Example of HTTPServer with additional features: * SNTPClient, DST rules * Link status indication * Local or SDCard-based WebServer * RPC-able class * Static and Dynamic HTML page

Dependencies:   mbed

HTTPDynamicPage.h

Committer:
iva2k
Date:
2010-01-12
Revision:
2:360fda42fefd
Parent:
0:886e4b3119ad

File content as of revision 2:360fda42fefd:

#ifndef HTTPDYNAMICPAGE_H
#define HTTPDYNAMICPAGE_H

#include "HTTPServer.h"

/**
 * A datastorage helper for the HTTPDynamicPage class.
 * Stores dynamically created page data and the size left to upload.
 */
class HTTPDynamicPageData : public HTTPData {
  public:
    HTTPDynamicPageData()
     : page_free(NULL), page(NULL), size(0), _left(0) {}
    virtual ~HTTPDynamicPageData() {
      if (page_free && page) {
          page_free(page);
      }
    }

    /** Pointer to garbage collection function (for freeing page data)
     * Should be set by callback function to a suitable free() if page is dynamically allocated
     */
    void (*page_free)(void *page);
    
    /** Pointer to the page data */
    char *page;
    
    /** Page data size
     * As long as the page is NULL terminated you don't have to tell the data length.
     * But if you want to send binary data you should tell us the size.
     */
    int size;

    /** Page data size left for the upload */
    int _left;
};

/**
 * This class Provide a Handler to send Static HTTP Pages from the bin file.
 */
class HTTPDynamicPage : public HTTPHandler {
  public:
    /**
     * Constructor takes the page path and the page callback function.
     */
    HTTPDynamicPage(const char *path, HTTPStatus page_fnc(HTTPConnection *con, HTTPDynamicPageData *pd))
     : HTTPHandler(path), _page_fnc(page_fnc) {
    }

    HTTPDynamicPage(HTTPServer *server, const char *path, HTTPStatus page_fnc(HTTPConnection *con, HTTPDynamicPageData *pd))
     : HTTPHandler(path), _page_fnc(page_fnc) {
      server->addHandler(this);
    }

  private:
    /**
     * This Dynamic Page is requested!
     * Prepare a datastorage helper "HTTPDynamicPageData", create the page and store in helper, then initialize remaining data size.
     * And return HTTP_OK if all ok.
     */
    virtual HTTPStatus init(HTTPConnection *con) const {
      HTTPDynamicPageData *data = new HTTPDynamicPageData();
      con->data = data;
      HTTPStatus status = _page_fnc(con, data);    // assigns data->page, data->size and optionally data->page_free
      if (!data->size && data->page)
          data->size = strlen(data->page);
      data->_left = data->size;
      con->setLength(data->size);
      return status;
    }

    /**
     * Send the maximum data out to the client. 
     * If the file is complete transmitted close connection by returning HTTP_SuccessEnded
     */
    virtual HTTPHandle send(HTTPConnection *con, int maximum) const {
      HTTPDynamicPageData *data = static_cast<HTTPDynamicPageData *>(con->data);
      int len = min(maximum, data->_left);
      err_t err;

      do {
        err = con->write((void*)&data->page[data->size - data->_left], len, 1);
        if (err == ERR_MEM) {
          len >>= 1;
        }
      } while(err == ERR_MEM && len > 1);
      if (err == ERR_OK) {
        data->_left -= len;
      }
      return (data->_left) ? HTTP_Success : HTTP_SuccessEnded;
    }

    HTTPStatus (*_page_fnc)(HTTPConnection *con, HTTPDynamicPageData *pd);
};

#endif