NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FSHandler.cpp Source File

FSHandler.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "FSHandler.h"
00025 
00026 //#define __DEBUG
00027 #include "dbg/dbg.h"
00028 
00029 #define CHUNK_SIZE 128
00030 
00031 #define DEFAULT_PAGE "/index.htm"
00032 
00033 FSHandler::FSHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket), m_err404(false)
00034 {}
00035 
00036 FSHandler::~FSHandler()
00037 {
00038   if(m_fp)
00039     fclose(m_fp);
00040   DBG("\r\nHandler destroyed\r\n");
00041 }
00042 
00043 //static init
00044 map<string,string> FSHandler::m_lFsPath = map<string,string>();
00045 
00046 void FSHandler::mount(const string& fsPath, const string& rootPath)
00047 {
00048   m_lFsPath[rootPath]=fsPath;
00049 }
00050 
00051 void FSHandler::doGet()
00052 {
00053   DBG("\r\nIn FSHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str());
00054   //FIXME: Translate path to local/path
00055   string checkedRootPath = rootPath();
00056   if(checkedRootPath.empty())
00057     checkedRootPath="/";
00058   string filePath = m_lFsPath[checkedRootPath];
00059   if (path().size() > 1)
00060   {
00061     filePath += path();
00062   }
00063   else
00064   {
00065     filePath += DEFAULT_PAGE;
00066   }
00067   
00068   DBG("Trying to open %s\n", filePath.c_str());
00069 
00070   m_fp = fopen(filePath.c_str(), "r"); //FIXME: if null, error 404
00071   
00072   if(!m_fp)
00073   {
00074     m_err404 = true;
00075     setErrCode(404);
00076     const char* msg = "File not found.";
00077     setContentLen(strlen(msg));
00078     respHeaders()["Content-Type"] = "text/html";
00079     respHeaders()["Connection"] = "close";
00080     writeData(msg,strlen(msg)); //Only send header
00081     DBG("\r\nExit FSHandler::doGet() w Error 404\r\n");
00082     return;
00083   }
00084     
00085   //Seek EOF to get length
00086   fseek(m_fp, 0, SEEK_END);
00087   setContentLen( ftell(m_fp) );
00088   fseek(m_fp, 0, SEEK_SET); //Goto SOF
00089 
00090   respHeaders()["Connection"] = "close";
00091   onWriteable();
00092   DBG("\r\nExit SimpleHandler::doGet()\r\n");
00093 }
00094 
00095 void FSHandler::doPost()
00096 {
00097 
00098 }
00099 
00100 void FSHandler::doHead()
00101 {
00102 
00103 }
00104 
00105 void FSHandler::onReadable() //Data has been read
00106 {
00107 
00108 }
00109 
00110 void FSHandler::onWriteable() //Data has been written & buf is free
00111 {
00112   DBG("\r\nFSHandler::onWriteable() event\r\n");
00113   if(m_err404)
00114   {
00115     //Error has been served, now exit
00116     close();
00117     return;
00118   }
00119   
00120   static char rBuf[CHUNK_SIZE];
00121   while(true)
00122   {
00123     int len = fread(rBuf, 1, CHUNK_SIZE, m_fp);
00124     if(len>0)
00125     {
00126       int writtenLen = writeData(rBuf, len);
00127       if(writtenLen < 0) //Socket error
00128       {
00129         DBG("FSHandler: Socket error %d\n", writtenLen);
00130         if(writtenLen == TCPSOCKET_MEM)
00131         {
00132           fseek(m_fp, -len, SEEK_CUR);
00133           return; //Wait for the queued TCP segments to be transmitted
00134         }
00135         else
00136         {
00137           //This is a critical error
00138           close();
00139           return; 
00140         }
00141       }
00142       else if(writtenLen < len) //Short write, socket's buffer is full
00143       {
00144         fseek(m_fp, writtenLen - len, SEEK_CUR);
00145         return;
00146       }
00147     }
00148     else
00149     {
00150       close(); //Data written, we can close the connection
00151       return;
00152     }
00153   }
00154 }
00155 
00156 void FSHandler::onClose() //Connection is closing
00157 {
00158   if(m_fp)
00159     fclose(m_fp);
00160 }