this will take a image from C328 serial camera and store those images in mbed flash as html and this html page is uploaded into the server at ip:192.168.1.2

Dependencies:   mbed

lwip/HTTPServer/HTTPRPC.h

Committer:
mitesh2patel
Date:
2010-12-15
Revision:
0:e1a0471e5ffb

File content as of revision 0:e1a0471e5ffb:

// HTTPRPC.h
// Modified by iva2k
// Improved URL string handling
//

#ifndef HTTPRPC_H
#define HTTPRPC_H

#include "HTTPServer.h"
#include "platform.h"
#ifdef MBED_RPC
#include "rpc.h"

#ifndef HTTPRPC_USE_URI_FIELDS
#define HTTPRPC_USE_URI_FIELDS 1
#endif

/**
 * A datastorage helper for the HTTPRPC class
 */
class HTTPRPCData : public HTTPData {
  public: char result[255];
};

/**
 * Thsi class enables you to make rpc calls to your mbed.
 * Furthermore it is a good example how to write a HTTPHandler for small data chunks.
 */
class HTTPRPC : public HTTPHandler {
  public:
    /**
     * We have to know the prefix for the RPCHandler.
     * A good default choice is /rpc so we made this default.
     */
    HTTPRPC(const char *path = "/rpc") : HTTPHandler(path) {}
    HTTPRPC(HTTPServer *server, const char *path = "/rpc") : HTTPHandler(path) { server->addHandler(this); }

  private:
    /**
     * If you need some Headerfeelds you have tor register the feelds here.
     */
//    virtual void reg(HTTPServer *svr) {
//      svr->registerField("Content-Length");
//    }

    /**
     * If a new RPCRequest Header is complete received the server will call this function.
     * This is the right place for preparing our datastructures.
     * Furthermore we will execute the rpc call and store the anwere.
     * But we will not send a response. This will be hapen in the send method.
     */
    virtual HTTPStatus init(HTTPConnection *con) const {
      HTTPRPCData *data = new HTTPRPCData();
      con->data = data;
      char *query = con->getURL()+strlen(_prefix);
      query = clean(query);
      rpc(query, data->result);

      const char *nfields = "Cache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GM";
      char *old = (char *)con->getHeaderFields();
      int oldlen = strlen(old);
      int atrlen = strlen(nfields);
      char *fields = new char[atrlen+oldlen+3];
      strcpy(fields,old);
      fields[oldlen+0] = '\r';
      fields[oldlen+1] = '\n';
      strcpy(&fields[oldlen+2], nfields);
      fields[atrlen+2+oldlen] = '\0';
      con->setHeaderFields(fields);
      if(*old) {
        delete old;
      }

      con->setLength(strlen(data->result));
      return HTTP_OK;
    }

    /**
     * If we got an POST request the send method will not be executed.
     * If we want to send data we have to trigger it the first time by ourself.
     * So we execute the send method.
     *
     * If the rpc call is the content of the POST body we would not be able to execute it.
     * Were parsing only the URL.
     */
    virtual HTTPHandle data(HTTPConnection *con, void *, int) const {
      return send(con, con->sndbuf());
    }

    /**
     * Send the result back to the client.
     * If we have not enought space wait for next time.
     */
    virtual HTTPHandle send(HTTPConnection *con, int maximum) const {
      HTTPRPCData *data = static_cast<HTTPRPCData *>(con->data);
      if(maximum>64) {
        con->write(data->result, con->getLength());
        return HTTP_SuccessEnded;
      } else {
        // To less memory.
        return HTTP_SenderMemory;
      }
    }

    inline bool is_hex(const char a) const {
        return (a>='0' && a<='9') || (a>='A' && a<='F') || (a>='a' && a<='f');
    }
    inline char hex_nib(const char a) const {
        return 0xf & (
          (a>='0' && a<='9') ? (a-'0'   ) :
          (a>='A' && a<='F') ? (a-'A'+10) :
          (a>='a' && a<='f') ? (a-'a'+10) : 0
        );
    }
    inline char hex_byte(const char *str) const {
        return (hex_nib(*str) << 4) | hex_nib(*(str+1));
    }
    /**
     * To reduce memory usage we sodify the URL directly
     * and replace '%20',',','+','=' with spaces.
     */
//    mutable char _buf[1024];
    inline char *clean(char *str) const {
      char *in = str;
//      char *out = _buf;
      char *out = str;    // this will do conversions in-place.
      bool inquotes=false;
      bool backslash=false;
      bool hasquery=false;
      bool cantquery=false;
        // cantquery=true will indicate that the URI already has symbols 
        // incompatible with query, so it disables checking for query.
#if HTTPRPC_USE_URI_FIELDS
      bool infield=false;
//      bool rpcquery=false;
      char *field=out;
#endif

printf("\r\nDEBUG HTTPRPC::clean() IN=:%s:\r\n",str);
      while (*in) {
#if HTTPRPC_USE_URI_FIELDS
        // Check if URI has query part
        // in form "/rpc/obj/method?arg1=val1&arg2=val2&arg3=val3"
        if (!inquotes && !cantquery && !hasquery && *in == '?') {
          hasquery = true;
          *out = ' '; out++;  // delimit base URI part
          infield = true; in++; field=in; continue;
          // New field started. Do nothing yet
        }
        // Check if URI with query part is delimited
        if (!inquotes && !infield && hasquery && *in == '&') {
          *out = ' '; out++;  // delimit current arg
          infield = true; in++; field=in; continue;
          // New field started
        }
        if (infield) {
          // Process the query - skip till '='
          // Also check if it is in form "/rpc/obj/method?val1&val2&val3"
          if (!inquotes && *in == '&') {
            // modified query - catch up
            while (field<in) {
              *out = *field;
              if (*field=='%' && is_hex(*(field+1)) && is_hex(*(field+2)) ) {
                *out = hex_byte(++field);
                field++;    // field is incremented by 2 total
              }
              if (!backslash && *out == '"') { inquotes = !inquotes; }
              backslash = inquotes && !backslash && (*out == '\\');

              out++;
              field++;
            }
            
            *out = ' '; out++;  // delimit current arg
            infield = true; in++; field=in; continue;
            // New field started
          } else
          if (!inquotes && *in == '=') {
            infield = false;
            *in = '\0';  // this will mark the field name
printf("    - field: %s\r\n", field);
// FIXME: here we have a field/arg name. Can we use it to reorder the arguments for the rpc?

          } else {
            // Keep tracking quotes
            char tmp = *in;
            if (*in=='%' && is_hex(*(in+1)) && is_hex(*(in+2)) ) {
              tmp = hex_byte(++in);
              in++;    // in is incremented by 2 total
            }
            if (!backslash && tmp == '"') { inquotes = !inquotes; }
            backslash = inquotes && !backslash && (tmp == '\\');
          }
        } else
#endif    // HTTPRPC_USE_URI_FIELDS
        {
          // Keep processing the stream
          *out = *in;

          if (*in=='%' && is_hex(*(in+1)) && is_hex(*(in+2)) ) {
            *out = hex_byte(++in);
            in++;    // in is incremented by 2 total
            cantquery = !hasquery;   // any %-encoded before '?' means it can't be a query
          } else
          if (!inquotes && !hasquery && (*in==',' || *in=='+' || *in=='=')) {
            *out = ' ';
//            cantquery = !hasquery;   // any non-query delimiter disallows URI query
          }
          if (!backslash && *out == '"') { inquotes = !inquotes; }
          backslash = inquotes && !backslash && (*out == '\\');

          out++;
        }

        in++;
      } // while

#if HTTPRPC_USE_URI_FIELDS
      if (infield) {
        // modified query last arg - catch up
        while (field < in) {
          *out = *field;
          if (*field=='%' && is_hex(*(field+1)) && is_hex(*(field+2)) ) {
            *out = hex_byte(++field);
            field++;    // field is incremented by 2 total
          }
          if (!backslash && *out == '"') { inquotes = !inquotes; }
          backslash = inquotes && !backslash && (*out == '\\');

          out++;
          field++;
        }
      }
#endif    // HTTPRPC_USE_URI_FIELDS

      hasquery = cantquery; // only removes compiler warning
      *out = '\0';

//      out = _buf;
      out = str;
printf("DEBUG HTTPRPC::clean() OUT=:%s:\r\n", out);
      return out;
    }
};
#endif

#endif