Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: WiFlyHTTPServer WiflyInterface mbed-rpc mbed-rtos mbed
Revision 1:40eadac4750b, committed 2013-06-26
- Comitter:
- leihen
- Date:
- Wed Jun 26 22:41:58 2013 +0000
- Parent:
- 0:9c6ebc97c758
- Commit message:
- UPdated the HTTPServer Library
Changed in this revision
--- a/HttpServer.cpp Wed Jun 26 21:13:55 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,477 +0,0 @@
-#include "mbed.h"
-#include "HttpServer.h"
-
-#define DEBUG
-#include "debug.h"
-
-
-#define EVENT_DATA_READY 0x05
-
-DigitalOut ledRX(LED4);
-
-
-typedef struct {
- char c;
-} message_t;
-
-Queue<char, 256> m_queue;
-
-typedef struct {
- const char* method;
- msg_t type;
-} methodType_t;
-
-const methodType_t supportedOps[] = {
- { "GET", msg_get },
- { "POST", msg_post },
- { "PUT", msg_put },
- { "HEAD", msg_head},
- { "CONNECT", msg_connect},
- { "DELETE", msg_delete},
- { "TRACE", msg_trace},
- { "OPTIONS", msg_options}
-};
-
-
-Queue<request_msg_t, 5> m_requestQueue; // Do not allow more than 5 concurrent requests
-MemoryPool<request_msg_t, 5> m_requestPool;
-
-map<string, string> messageHeaders;
-
-map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), HttpServer::handlersComp> HttpServer::m_lpHandlers;
-
-
-
-/* Constructor will create and initialize all objects excep the threads */
-HttpServer::HttpServer(PinName tx, PinName rx, PinName rst, PinName tcp_status, const char * ssid, const char * phrase, Security sec, Wifly::WiflyBaudrate_t baud)
- : Wifly(tx, rx, rst, tcp_status, ssid, phrase, sec, baud), m_listener(NULL), m_worker(NULL)
-{
- INFO("Initializing wifly\n");
- // Initialize the wifly wlan device
- reset();
-
- state.dhcp = true;
- INFO("Connecting to network...");
- // Try join the network
- while(!join()) {
- INFO("Failed to connect. Trying again\n");
- reset();
- }
- INFO("connected\n");
-}
-
-HttpServer::~HttpServer()
-{
- if (m_listener) {
- m_listener->terminate();
- delete m_listener;
- }
- if (m_worker) {
- m_worker->terminate();
- delete m_worker;
- }
-}
-
-
-bool HttpServer::start(int port)
-{
- // Bind to that port
- if (!bind(port)) {
- ERR("Failed to bind to port %d\n", port);
- return false;
- }
-
- // Start the child threads
- m_worker = new Thread(HttpServer::worker_thread, NULL, osPriorityAboveNormal, DEFAULT_STACK_SIZE*4);
- if (m_worker == NULL) {
- ERR("Failed to start server thread !\n");
- return false;
- }
-
- m_listener = new Thread(&HttpServer::listen_thread, NULL, osPriorityAboveNormal, DEFAULT_STACK_SIZE*2);
- if (m_listener == NULL) {
- ERR("Failed to start listener thread !\n");
- m_worker->terminate();
- delete m_worker;
- m_worker = NULL;
- return false;
- }
-
- return true;
-}
-
-
-
-
-
-bool HttpServer::bind(int port)
-{
- char cmd[20];
-
- // set TCP protocol
- setProtocol(TCP);
-
- // set local port
- sprintf(cmd, "set i l %d\r", port);
- if (!sendCommand(cmd, "AOK"))
- return false;
-
- // save
- if (!sendCommand("save\r", "Stor"))
- return false;
-
- // reboot
- reboot();
-
- // connect the network
- if (isDHCP()) {
- if (!sendCommand("join\r", "DHCP=ON", NULL, 10000))
- return false;
- } else {
- if (!sendCommand("join\r", "Associated", NULL, 10000))
- return false;
- }
-
- // exit
- exit();
-
- Thread::wait(200);
- flush();
-
- return true;
-}
-
-DigitalOut Led2(LED2);
-
-void HttpServer::handler_rx(void)
-{
- static char sequence = 0;
- //read characters
- while (wifi.readable()) {
- char c = LPC_UART3->RBR;
- ledRX = !ledRX;
- switch(sequence) {
- case 0 : if (c == 'G') sequence = 1; break;
- case 1 : if (c == 'E') sequence = 2; break;
- case 2 : if (c == 'T') sequence = 0; Led2 = !Led2;break;
- default: break;
- }
- m_queue.put((char*)(int)c);
- }
-}
-
-
-void HttpServer::attach_rx(bool callback)
-{
- if (!callback)
- wifi.attach(NULL);
- else
- wifi.attach(this, &HttpServer::handler_rx);
-}
-
-
-bool HttpServer::join()
-{
- return Wifly::join();
-}
-
-int HttpServer::send(const char * str, int len, const char * ACK, char * res, int timeout)
-{
- return Wifly::send(str, len, ACK, res, timeout);
-}
-
-request_msg_t* HttpServer::checkMessageReceived(char *data)
-{
- INFO("Checking for new HTTP request !\n");
- char *req = data;
- char *uri = NULL;
- char *ver = NULL;
- while( *data ) {
- if (*data == ' ') {
- *data = 0;
- if (uri == NULL) {
- uri = data+1;
- } else {
- ver = data+1;
- break;
- }
- }
- data++;
- }
-
- INFO("Detected : %s, %s, %s\n", req, uri, ver);
-
- if ((req != NULL) && (uri != NULL) && (ver != NULL) ) {
- for (int i = 0 ; i < sizeof(supportedOps) / sizeof(methodType_t) ; i++) {
- if (strcmp(supportedOps[i].method, req) == 0) {
- // found the request
- INFO("Request valid !!!\n");
- request_msg_t* pmsg = m_requestPool.alloc();
- pmsg->requestType = supportedOps[i].type;
- strncpy(pmsg->requestUri, uri, 255);
- return pmsg;
- }
- }
- }
-
- INFO("Invalid request \"%s\"\n", req);
- return NULL;
-}
-
-void HttpServer::processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue)
-{
- *fieldname = headerLine;
- *fieldvalue = NULL;
-
- while( *headerLine ) {
- if (*headerLine == ':') {
- *headerLine++ = 0;
- while(*headerLine == ' ') headerLine++;
- *fieldvalue = headerLine;
- return;
- }
- headerLine++;
- }
- return ;
-}
-
-
-void HttpServer::listenForRequests()
-{
- static char data[256];
- static int curPos = 0;
- int CRLF = 0;
- int m_openConnections = 0;
-
- request_msg_t *pMsg = NULL;
- INFO("Listener running\n");
- bool asteriskReceivedOnce = false;
- while(1) {
- osEvent evt = m_queue.get();
- if (evt.status == osEventMessage) {
- char c;
- c = (char)(int)evt.value.p;
- if ((c!='\n') && (c!='\r')) {
- data[curPos++] = c;
- data[curPos] = 0;
- }
- if (pMsg != NULL) { // request was detected and will further be processed completely
- // check for CRLF
- if (c == '\n') {
- CRLF++;
- INFO("<CR>(%d)", CRLF);
- if (CRLF == 2) { // all message headers received, so send message and be ready for new one
- CRLF = 0;
- // SPAWN MESSAGE
- INFO("REQUEST COMPLETE --> Handing over to worker thread !\n\n\n\n");
- m_requestQueue.put(pMsg);
- data[0] = 0;
- curPos = 0;
- asteriskReceivedOnce = false;
- pMsg = NULL;
- } else { // must be a new header
-// char *name, *value;
-// INFO("Processing Header !\"%s\"", data);
-/* processMessageHeader(data, &name, &value);
- if (strncmp(name, "Content-Length", 14 ) == 0) {
- // Data will be sent, be ready to receive
- } else {
- INFO("HEADER: Name=\"%s\", Value=\"%s\"", name, value);
- }
-*/ data[0] = 0;
- curPos = 0;
- }
- } else {
- if (c != '\r')
- CRLF = 0;
- else
- INFO("<LF>");
- }
- } else if (c == '*') {
- CRLF = 0;
- if (asteriskReceivedOnce) {
- // could be an open, close or read command
- if (curPos >= 6) { // only need to process if data is large enough
- if ( (data[curPos-6] == '*') && (data[curPos-5] == 'O') && (data[curPos-4] == 'P') && (data[curPos-3] == 'E') && (data[curPos-2] == 'N') && (data[curPos-1] == '*')) {
- // Add a connection
- INFO("New connection opened (%d)...\n", ++m_openConnections);
- data[0] = 0;
- curPos = 0;
- } else if ( (data[curPos-6] == '*') && (data[curPos-5] == 'C') && (data[curPos-4] == 'L') && (data[curPos-3] == 'O') && (data[curPos-2] == 'S') && (data[curPos-1] == '*')) {
- // close a connection
- INFO("Connection was closed ...(%d)\n", --m_openConnections);
- data[0] = 0;
- curPos = 0;
- }
- }
- asteriskReceivedOnce = false;
- } else { // set the indicator so that next time we'll check for valid connection commands
- asteriskReceivedOnce = true;
- }
- } else { // first make sure that when no asterisk is received the asteriskReceivedOnce flag will be reset on each newline
- if (c == '\n') {
- if (m_openConnections > 0) {
- // Check to see if we received a valid request
- pMsg = checkMessageReceived(data);
- if (pMsg == NULL) {
- // not received valid stuff, so discard
- INFO("Unrecognised data received : \"%s\"\n", data);
- } else {
- INFO("New request detected ! : \"%s\"\n", data);
- }
- } else {
- INFO("Unrecognised data detected : \"%s\"\n", data);
- }
- asteriskReceivedOnce = false;
- data[0] = 0;
- curPos = 0;
- CRLF = 1;
- }
- }
- }
-// else {
- Thread::yield();
-// }
- }
-}
-
-void HttpServer::serveRequests()
-{
- HTTPConnection::HTTPMessage *myMessage = new HTTPConnection::HTTPMessage;
-
- INFO("Server running\n");
-
- while(1) {
- INFO("Listening for new request !");
- osEvent evt = m_requestQueue.get();
- if (evt.status == osEventMessage) {
- request_msg_t* pMsg = (request_msg_t*)evt.value.p;
- m_worker->set_priority(osPriorityBelowNormal);
- Thread::yield();
- switch(pMsg->requestType) {
- case msg_get:
- INFO("Server received GET message !");
- myMessage->request = HTTP_RT_GET;
- myMessage->uri = pMsg->requestUri;
- HandleRequest(myMessage);
- Thread::yield();
- break;
-
- case msg_post:
- case msg_put:
- case msg_head:
- case msg_delete:
- case msg_trace:
- case msg_options:
- case msg_connect:
- default:
- break;
- }
- m_worker->set_priority(osPriorityNormal);
- m_requestPool.free(pMsg);
- }
- Thread::yield();
- }
-}
-
-bool HttpServer::parseRequest(char *request)
-{
- // dissect into : path, file[, [arg, value]1..N ] as "/path/file?arg1=val1&arg2=val2...
- // first check for questionmark sign to separate the file and path from any arguments
- char* path = request;
- char* file = NULL;
- char* arglist = NULL;
-
- char* lastPathSep = NULL;
- while(*request) {
- if (*request == '/' )
- lastPathSep = request;
- if (*request == '?') {
- *request++ = 0;
- arglist = request;
- }
- }
-
- if (arglist == NULL) {
- INFO("Request does not have parameters !");
- }
-
- if (lastPathSep == NULL)
- return false; // no path provided !!!!
-
- // now, whatever is provided to the left including the slash is the 'path', the part to the right is the file. caution: the file may be left blank !
- if (lastPathSep != 0) {
- // 2 cases to handle :
- // 1. : "/blah/" or "/blah/blub/" --> path = "/blah/", file = "index.html"
- // 2. : "/blah/blub" or "/blah/blub/blubber" --> path = "/blah/", file = "blub"
- } else {
- // 2 cases to handle :
- // 1. : "/" --> path = "/", file = "index.html"
- // 2. : "/blah" --> path = "/", file = "blah"
- }
- return true;
-}
-
-
-void HttpServer::listen_thread(const void *params)
-{
- HttpServer* pSvr = (HttpServer*)params;
-
- pSvr->listenForRequests();
-}
-
-void HttpServer::worker_thread(const void * params)
-{
- HttpServer* pSvr = (HttpServer*)params;
-
- pSvr->serveRequests();
-}
-
-
-
-
-static const char* szStdErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error 404</h1><P>This resource is not available<P></BODY></HTML>\r\n\r\n";
-
-void HttpServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg)
-{
- char echoHeader[256];
- sprintf(echoHeader,"HTTP/1.0 404 Fail\r\nConnection: close\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\n\n\r",strlen(szStdErrorPage));
-
- Wifly::getInstance()->sendData(echoHeader, strlen(echoHeader));
- Wifly::getInstance()->sendData((char*)szStdErrorPage, strlen(szStdErrorPage));
-}
-
-void HttpServer::HandleRequest(HTTPConnection::HTTPMessage* pmsg)
-{
- static std::string localPath;
- static std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp>::const_iterator it;
-
- INFO("Trying to handle request");
- // Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
- for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
- // check if this entries' path is fully contained at the beginning of the requested path
- std::string curpth = it->first;
-
- if (pmsg->uri.find(curpth) == 0) {
- // firts matching handler found, we just take it and we'll be happy
- localPath = pmsg->uri.substr(curpth.length());
- break;
- }
- }
-
- if (it == m_lpHandlers.end()) {
- // There is no such handler, so return invalid
- INFO("Webrequest left unhandled.");
-
- m_pErrorHandler(*pmsg);
- } else {
- // Valid handler was found
- INFO("Routing webrequest !");
- // Instantiate the handler object (handling will be done from withing the object's constructor
- HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), *pmsg);
- // now we can delete the object, because handling is completed.
- if (phdl != NULL)
- delete phdl;
- }
-}
-
--- a/HttpServer.h Wed Jun 26 21:13:55 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-#ifndef __HTTPSERVER_H__
-#define __HTTPSERVER_H__
-
-#include "Wifly.h"
-#include "rtos.h"
-#include "HTTPConnection.h"
-#include "HTTPRequestHandler.h"
-
-#include <string>
-#include <map>
-
-typedef enum {
- msg_get,
- msg_post,
- msg_head,
- msg_put,
- msg_delete,
- msg_trace,
- msg_options,
- msg_connect
-} msg_t;
-
-
-typedef struct {
- msg_t requestType;
- char requestUri[256];
-// map<string, string> messageHeaders;
-} request_msg_t;
-
-/** Typedefinition for a handler function
-*/
-typedef void (*HTTPRequestHandlerFunction)(HTTPConnection::HTTPMessage&);
-
-
-/** This is the non-blocking HTTP Server class. The idea behind this class is as follows:
- * the user may instantiate the class and initialize it. Once the server is setup and
- * listening, the server will stay in an endless loop and keep on listening for new
- * connections and for new HTTP requests. Once a request is received it will be placed
- * in a queue. The queue itself will be handled in a separate task.
- */
-class HttpServer : public Wifly
-{
- Thread *m_listener;
- Thread *m_worker;
-
- request_msg_t* checkMessageReceived(char *);
- void processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue);
-
- public:
- HttpServer(PinName tx, PinName rx, PinName reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec, Wifly::WiflyBaudrate_t baud = Wifly::Wifly_115200);
- ~HttpServer();
-
- bool start(int port);
-
- virtual void handler_rx(void);
- virtual void attach_rx(bool);
-
- virtual bool join();
- virtual int send(const char * str, int len, const char * ACK = NULL, char * res = NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
-
- public:
-
-
- /**
- * Structure which will allow to order the stored handlers according to their associated path.
- */
- struct handlersComp //Used to order handlers in the right way
- {
- bool operator() (const string& handler1, const string& handler2) const
- {
- //The first handler is longer than the second one
- if (handler1.length() > handler2.length())
- return true; //Returns true if handler1 is to appear before handler2
- else if (handler1.length() < handler2.length())
- return false;
- else //To avoid the == case, sort now by address
- return ((&handler1)>(&handler2));
- }
- };
- /** The standard error handler function.
- * @param msg : Request message data.
- * @param tcp : Socket to be used for responding.
- */
- static void StdErrorHandler(HTTPConnection::HTTPMessage& msg);
-
-
- /** Internal function which processes a request and which will try to find the matching handler function
- * for the given request. Please note that the function will search through the list of handlers, iterating
- * from longest to shortest \c paths. If the registered \c path is a subset of the request the associated
- * handler is considered as being a match.
- * @param msg : Request message data. Contains the requested logical \c uri.
- * @param tcp : Socket to be used for communication with the client.
- */
- void HandleRequest(HTTPConnection::HTTPMessage* msg);
-
- /** Map of handler objects. Can be any object derived from \ref HTTPRequestHeader. Use the \ref addHandler function
- * to register new handler objects.
- */
- static map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp> m_lpHandlers;
-
- /**
- * Adds a request handler to the handlers list. You will have to use one of the existing implementations.
- * With each handler a \c uri or \c path is associated. Whenever a request is received the server will
- * walk through all registered handlers and check which \c path is matching.
- * @param T : class which will be instanciated to serve these requests for the associated \b path.
- * @param path : request uri starting with this \c path will be served using this handler.
- */
- template<typename T>
- void addHandler(const char* path)
- { m_lpHandlers[path] = &T::create; }
-
- /**
- * Replaces the standard error Handler. The error Handler will be called everytime a request is not
- * matching any of the registered \c paths or \c uris.
- * @param hdlFunc: User specified handler function which will be used in error conditions.
- */
- void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
- { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }
- HTTPRequestHandlerFunction m_pErrorHandler;
-
- protected:
- bool bind(int port);
- void listenForRequests();
- void serveRequests();
-
- bool parseRequest(char *request);
-
- static void listen_thread(const void * parms);
- static void worker_thread(const void * parms);
-};
-
-#endif // __HTTPSERVER_H__
\ No newline at end of file
--- a/WiFlyHTTPServer.lib Wed Jun 26 21:13:55 2013 +0000 +++ b/WiFlyHTTPServer.lib Wed Jun 26 22:41:58 2013 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/leihen/code/WiFlyHTTPServer/#93ff322420b0 +http://mbed.org/users/leihen/code/WiFlyHTTPServer/#7f9fbfc18623