Embedded WebSockets Experiment

Dependencies:   mbed MD5

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPFS.h Source File

HTTPFS.h

00001 #ifndef HTTPFILESYSTEM_H
00002 #define HTTPFILESYSTEM_H
00003 
00004 #include "mbed.h"
00005 
00006 #include "HTTPServer.h"
00007 
00008 #define HTTP_BUFFER_SIZE 700
00009 #define FILENAMELANGTH 100
00010 
00011 /**
00012  * This class will store the data which are required for an request.
00013  * We are not in every case able to return all data at once, that means we have to store
00014  * the actual level of transmission.
00015  */
00016 class HTTPFileSystemData : public HTTPData {
00017   public:
00018     int fleft;
00019     int bleft;
00020     int offset;
00021     FILE *file;
00022     char buffer[HTTP_BUFFER_SIZE];
00023     
00024     virtual ~HTTPFileSystemData() {
00025       if(file) {
00026         fclose(file);
00027         file = 0;
00028       }
00029     }
00030 };
00031 
00032 /**
00033  * This class will deliver files form the virtual file system.
00034  * Furthermore it is a simple example how to implement an HTTPHandler for big data requests.
00035  */
00036 class HTTPFileSystemHandler : public HTTPHandler {
00037   public:
00038     /**
00039      * Create a new HTTPFileSzstemHandler.
00040      * @param prefix The Prefix is the URL Proefix in witch the Handler will work.
00041      * @param dir The Prefix will be directly mappt on the dir.
00042      */
00043     HTTPFileSystemHandler(const char *path, const char *dir) : HTTPHandler(path), _dir(dir) {}
00044     HTTPFileSystemHandler(HTTPServer *server, const char *path, const char *dir) : HTTPHandler(path), _dir(dir) { server->addHandler(this); }
00045 
00046   private:
00047     /**
00048      * Check if a requested file exists.
00049      * If it exists open it and store the data back in the HTTPConnection.
00050      * We would not store connection specific data into the Handler.
00051      * If the file exists and we cann serve a page return HTTP_OK else HTTP_NotFound.
00052      * @param con The Connection which will be handled.
00053      */
00054     virtual HTTPStatus init(HTTPConnection *con) const {
00055       char filename[FILENAMELANGTH];
00056       HTTPFileSystemData *data = new HTTPFileSystemData();
00057       printf("FS: %s\n", con->getURL());
00058       snprintf(filename, FILENAMELANGTH, "%s%s\0", _dir, con->getURL() + strlen(_prefix));
00059       
00060       printf("filename: %s\n", filename);
00061       
00062       data->file = fopen(filename, "r");
00063       if(!data->file) {
00064         delete data;
00065         return HTTP_NotFound;
00066       }
00067       data->fleft  = fleft(data->file);
00068       data->bleft  = 0;
00069       data->offset = 0;
00070       
00071       con->data = data;
00072       con->setLength(data->fleft);
00073       loadFromFile(con);
00074       return HTTP_OK;
00075     }
00076 
00077     /**
00078      * Send the maximum available data chunk to the Client.
00079      * If it is the last chunk close connection by returning HTTP_SuccessEnded
00080      * @param con The connection to handle
00081      * @param maximum The maximal available sendbuffer size.
00082      * @return HTTP_Success when mor data is available or HTTP_SuccessEnded when the file is complete.
00083      */
00084     virtual HTTPHandle send(HTTPConnection *con, int maximum) const {
00085       HTTPFileSystemData *data = static_cast<HTTPFileSystemData *>(con->data);
00086       err_t err;
00087       u16_t len = min(data->bleft, maximum);
00088       if(len) {
00089         do {
00090           err = con->write(
00091             &data->buffer[data->offset], len, (((!data->fleft)&&(data->bleft==len))? 
00092             (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE) : (TCP_WRITE_FLAG_COPY)));
00093           if(err == ERR_MEM) {
00094             len /= 2;
00095           }
00096         } while (err == ERR_MEM && len > 1);  
00097   
00098         if(err == ERR_OK) {
00099           data->offset += len;
00100           data->bleft  -= len;
00101         }
00102       }
00103       return loadFromFile(con);
00104     }
00105 
00106     /**
00107      * Returns the left size of a file.
00108      * @param fd The filehandler of which we want to know the filesize.
00109      * @return The filesize of fd.
00110      */
00111     long fleft(FILE *fd) const {
00112       long len, cur;
00113       cur = ftell(fd);
00114       fseek(fd, 0, SEEK_END);
00115       len = ftell(fd);
00116       fseek(fd, cur, SEEK_SET);
00117       return len;
00118     }
00119     
00120     /**
00121      * Fill the buffer if the buffer is empty.
00122      * If the file is complete close the filehandler and return HTTP_SuccessEnded.
00123      */
00124     HTTPHandle loadFromFile(HTTPConnection *con) const {
00125       HTTPFileSystemData *data = static_cast<HTTPFileSystemData *>(con->data);
00126       if(!data->bleft) {
00127         if(data->fleft) {
00128           int len = fread(&data->buffer[0], sizeof(char), HTTP_BUFFER_SIZE, data->file);
00129           data->fleft -= len;
00130           data->bleft  = len;
00131           data->offset = 0;
00132         } else {
00133           if(data->file) {
00134             fclose(data->file);
00135             data->file = 0;
00136           }
00137           return HTTP_SuccessEnded;
00138         }
00139       }
00140       return HTTP_Success;
00141     }
00142     
00143     /** The Directory which will replace the prefix of the URL */
00144     const char *_dir;
00145 };
00146 
00147 #endif