Adaptation of the HttpServer by user yueee_yt. This version has improved handling of the HTTP headers (**NOTE**: There are limitations with this implementation and it is not fully functional. Use it only as a starting point.)

Dependents:   DMSupport DMSupport DMSupport DMSupport

Fork of DM_HttpServer by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Tue Dec 02 15:04:43 2014 +0000
Revision:
6:7b3320c34654
Parent:
4:1b6b021ee21d
Child:
10:c1c8276af541
Fixed stack sizes so that FSHandler works. Changed printfs to RtosLog. Changed sprintf to snprintf to prevent overwrite.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yueee_yt 4:1b6b021ee21d 1 //#define _DEBUG_ALL
yueee_yt 4:1b6b021ee21d 2
yueee_yt 0:fdf9c2c5200f 3 #ifndef HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 4 #define HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 5
yueee_yt 4:1b6b021ee21d 6 #ifdef _DEBUG_ALL
yueee_yt 4:1b6b021ee21d 7 #define _DEBUG_HTTP_SERVER_H
yueee_yt 4:1b6b021ee21d 8 #endif
yueee_yt 4:1b6b021ee21d 9
yueee_yt 0:fdf9c2c5200f 10 #include <string>
yueee_yt 0:fdf9c2c5200f 11 using std::string;
yueee_yt 0:fdf9c2c5200f 12
yueee_yt 0:fdf9c2c5200f 13 #include <map>
yueee_yt 0:fdf9c2c5200f 14 using std::map;
yueee_yt 0:fdf9c2c5200f 15
yueee_yt 0:fdf9c2c5200f 16 #include "HTTPRequestHandler.h"
yueee_yt 0:fdf9c2c5200f 17 #include "rtos.h"
yueee_yt 0:fdf9c2c5200f 18 #include "mbed.h"
yueee_yt 0:fdf9c2c5200f 19 #include "EthernetInterface.h"
yueee_yt 0:fdf9c2c5200f 20 //#include "HTTPRequestDispatcher.h"
yueee_yt 0:fdf9c2c5200f 21
yueee_yt 0:fdf9c2c5200f 22 //#include "dbg/dbg.h"
yueee_yt 0:fdf9c2c5200f 23
yueee_yt 0:fdf9c2c5200f 24 #define THREAD_MAX 5
yueee_yt 0:fdf9c2c5200f 25 Thread *threads[THREAD_MAX];
yueee_yt 0:fdf9c2c5200f 26 Thread *xthread;
yueee_yt 0:fdf9c2c5200f 27 //#include "HTTPServer2.h"
yueee_yt 0:fdf9c2c5200f 28
yueee_yt 0:fdf9c2c5200f 29 struct handlersComp { //Used to order handlers in the right way
yueee_yt 0:fdf9c2c5200f 30 bool operator() (const string& handler1, const string& handler2) const {
yueee_yt 0:fdf9c2c5200f 31 //The first handler is longer than the second one
yueee_yt 0:fdf9c2c5200f 32 if (handler1.length() > handler2.length())
yueee_yt 0:fdf9c2c5200f 33 return true; //Returns true if handler1 is to appear before handler2
yueee_yt 0:fdf9c2c5200f 34 else if (handler1.length() < handler2.length())
yueee_yt 0:fdf9c2c5200f 35 return false;
yueee_yt 0:fdf9c2c5200f 36 else //To avoid the == case, sort now by address
yueee_yt 0:fdf9c2c5200f 37 return ((&handler1)>(&handler2));
yueee_yt 0:fdf9c2c5200f 38 }
yueee_yt 0:fdf9c2c5200f 39 };
yueee_yt 0:fdf9c2c5200f 40
yueee_yt 0:fdf9c2c5200f 41 map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers;
yueee_yt 0:fdf9c2c5200f 42 template<typename T>
yueee_yt 0:fdf9c2c5200f 43 void HTTPServerAddHandler(const char* path) //Template decl in header
yueee_yt 0:fdf9c2c5200f 44 {
yueee_yt 0:fdf9c2c5200f 45 m_lpHandlers[path] = &T::inst;
yueee_yt 0:fdf9c2c5200f 46 }
yueee_yt 0:fdf9c2c5200f 47
yueee_yt 0:fdf9c2c5200f 48 void ListenThread(void const *args);
yueee_yt 0:fdf9c2c5200f 49 enum HTTP_METH {
yueee_yt 0:fdf9c2c5200f 50 HTTP_GET,
yueee_yt 0:fdf9c2c5200f 51 HTTP_POST,
yueee_yt 0:fdf9c2c5200f 52 HTTP_HEAD
yueee_yt 0:fdf9c2c5200f 53 };
yueee_yt 0:fdf9c2c5200f 54
yueee_yt 0:fdf9c2c5200f 55 bool getRequest(TCPSocketConnection* client,string* path, string* meth)
yueee_yt 0:fdf9c2c5200f 56 {
yueee_yt 0:fdf9c2c5200f 57 char req[128];
yueee_yt 0:fdf9c2c5200f 58 char c_path[128];
yueee_yt 0:fdf9c2c5200f 59 char c_meth[128];
yueee_yt 0:fdf9c2c5200f 60 const int maxLen = 128;
yueee_yt 0:fdf9c2c5200f 61 char* p = req;
yueee_yt 0:fdf9c2c5200f 62 //Read Line
yueee_yt 0:fdf9c2c5200f 63 int ret;
yueee_yt 0:fdf9c2c5200f 64 int len = 0;
yueee_yt 0:fdf9c2c5200f 65 for(int i = 0; i < maxLen - 1; i++) {
yueee_yt 0:fdf9c2c5200f 66 ret = client->receive(p, 1);
yueee_yt 0:fdf9c2c5200f 67 if(!ret) {
yueee_yt 0:fdf9c2c5200f 68 break;
yueee_yt 0:fdf9c2c5200f 69 }
yueee_yt 0:fdf9c2c5200f 70 if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) {
yueee_yt 0:fdf9c2c5200f 71 p--;
yueee_yt 0:fdf9c2c5200f 72 len-=2;
yueee_yt 0:fdf9c2c5200f 73 break;
yueee_yt 0:fdf9c2c5200f 74 } else if( *p=='\n' ) {
yueee_yt 0:fdf9c2c5200f 75 len--;
yueee_yt 0:fdf9c2c5200f 76 break;
yueee_yt 0:fdf9c2c5200f 77 }
yueee_yt 0:fdf9c2c5200f 78 p++;
yueee_yt 0:fdf9c2c5200f 79 len++;
yueee_yt 0:fdf9c2c5200f 80 }
yueee_yt 0:fdf9c2c5200f 81 *p = 0;
yueee_yt 4:1b6b021ee21d 82 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 83 printf("Parsing request : %s\r\n", req);
yueee_yt 4:1b6b021ee21d 84 #endif
yueee_yt 0:fdf9c2c5200f 85 ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
yueee_yt 0:fdf9c2c5200f 86 if(ret !=2) return false;
yueee_yt 0:fdf9c2c5200f 87 *meth = string(c_meth);
yueee_yt 0:fdf9c2c5200f 88 *path = string(c_path);
yueee_yt 0:fdf9c2c5200f 89 return true;
yueee_yt 0:fdf9c2c5200f 90 }
yueee_yt 0:fdf9c2c5200f 91
yueee_yt 0:fdf9c2c5200f 92 void dispatchRequest(TCPSocketConnection* client)
yueee_yt 0:fdf9c2c5200f 93 {
yueee_yt 0:fdf9c2c5200f 94 string path;
yueee_yt 0:fdf9c2c5200f 95 string meth;
yueee_yt 0:fdf9c2c5200f 96 HTTP_METH methCode;
yueee_yt 4:1b6b021ee21d 97 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 98 printf("Dispatching req\r\n");
yueee_yt 4:1b6b021ee21d 99 #endif
yueee_yt 0:fdf9c2c5200f 100 if( !getRequest(client,&path, &meth ) ) {
yueee_yt 4:1b6b021ee21d 101 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 102 printf("dispatchRequest Invalid request\r\n");
yueee_yt 4:1b6b021ee21d 103 #endif
yueee_yt 0:fdf9c2c5200f 104 //close();
yueee_yt 0:fdf9c2c5200f 105 return; //Invalid request
yueee_yt 0:fdf9c2c5200f 106 }
yueee_yt 0:fdf9c2c5200f 107 if( !meth.compare("GET") ) {
yueee_yt 4:1b6b021ee21d 108 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 109 printf("dispatchRequest HTTP_GET\r\n");
yueee_yt 4:1b6b021ee21d 110 #endif
yueee_yt 0:fdf9c2c5200f 111 methCode = HTTP_GET;
yueee_yt 0:fdf9c2c5200f 112 } else if( !meth.compare("POST") ) {
yueee_yt 4:1b6b021ee21d 113 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 114 printf("dispatchRequest HTTP_POST\r\n");
yueee_yt 4:1b6b021ee21d 115 #endif
yueee_yt 0:fdf9c2c5200f 116 methCode = HTTP_POST;
yueee_yt 0:fdf9c2c5200f 117 } else if( !meth.compare("HEAD") ) {
yueee_yt 4:1b6b021ee21d 118 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 119 printf("dispatchRequest HTTP_HEAD\r\n");
yueee_yt 4:1b6b021ee21d 120 #endif
yueee_yt 0:fdf9c2c5200f 121 methCode = HTTP_HEAD;
yueee_yt 0:fdf9c2c5200f 122 } else {
yueee_yt 4:1b6b021ee21d 123 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 124 printf("dispatchRequest() Parse error\r\n");
yueee_yt 4:1b6b021ee21d 125 #endif
yueee_yt 0:fdf9c2c5200f 126 //close(); //Parse error
yueee_yt 0:fdf9c2c5200f 127 return;
yueee_yt 0:fdf9c2c5200f 128 }
yueee_yt 4:1b6b021ee21d 129 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 130 printf("Looking for a handler\r\n");
yueee_yt 4:1b6b021ee21d 131 #endif
yueee_yt 0:fdf9c2c5200f 132 map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it;
yueee_yt 0:fdf9c2c5200f 133 int root_len = 0;
yueee_yt 0:fdf9c2c5200f 134 for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) {
yueee_yt 4:1b6b021ee21d 135 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 136 printf("Checking %s...\r\n", (*it).first.c_str());
yueee_yt 4:1b6b021ee21d 137 #endif
yueee_yt 0:fdf9c2c5200f 138 root_len = (*it).first.length();
yueee_yt 0:fdf9c2c5200f 139 if ( root_len &&
yueee_yt 0:fdf9c2c5200f 140 !path.compare( 0, root_len, (*it).first ) &&
yueee_yt 0:fdf9c2c5200f 141 (path[root_len] == '/' || path[root_len] == '\0')) {
yueee_yt 4:1b6b021ee21d 142 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 143 printf("Found (%s)\r\n", (*it).first.c_str());
yueee_yt 4:1b6b021ee21d 144 #endif
yueee_yt 0:fdf9c2c5200f 145 // Found!
yueee_yt 0:fdf9c2c5200f 146 break; // for
yueee_yt 0:fdf9c2c5200f 147 }
yueee_yt 0:fdf9c2c5200f 148 }
yueee_yt 0:fdf9c2c5200f 149 if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) {
yueee_yt 4:1b6b021ee21d 150 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 151 printf("Using default handler\r\n");
yueee_yt 4:1b6b021ee21d 152 #endif
yueee_yt 0:fdf9c2c5200f 153 it = m_lpHandlers.end();
yueee_yt 0:fdf9c2c5200f 154 it--; //Get the last element
yueee_yt 0:fdf9c2c5200f 155 if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
yueee_yt 0:fdf9c2c5200f 156 it = m_lpHandlers.end();
yueee_yt 0:fdf9c2c5200f 157 root_len = 0;
yueee_yt 0:fdf9c2c5200f 158 }
yueee_yt 0:fdf9c2c5200f 159 if(it == m_lpHandlers.end()) {
yueee_yt 4:1b6b021ee21d 160 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 161 printf("No handler found\r\n");
yueee_yt 4:1b6b021ee21d 162 #endif
yueee_yt 0:fdf9c2c5200f 163 return;
yueee_yt 0:fdf9c2c5200f 164 }
yueee_yt 4:1b6b021ee21d 165 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 166 printf("Handler found.\r\n");
yueee_yt 4:1b6b021ee21d 167 #endif
yueee_yt 0:fdf9c2c5200f 168 HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client);
yueee_yt 0:fdf9c2c5200f 169 //**** client = NULL; //We don't own it anymore
yueee_yt 0:fdf9c2c5200f 170 switch(methCode) {
yueee_yt 0:fdf9c2c5200f 171 case HTTP_GET:
yueee_yt 0:fdf9c2c5200f 172 pHdlr->doGet();
yueee_yt 0:fdf9c2c5200f 173 break;
yueee_yt 0:fdf9c2c5200f 174 case HTTP_POST:
yueee_yt 0:fdf9c2c5200f 175 pHdlr->doPost();
yueee_yt 0:fdf9c2c5200f 176 break;
yueee_yt 0:fdf9c2c5200f 177 case HTTP_HEAD:
yueee_yt 0:fdf9c2c5200f 178 pHdlr->doHead();
yueee_yt 0:fdf9c2c5200f 179 break;
yueee_yt 0:fdf9c2c5200f 180 }
yueee_yt 0:fdf9c2c5200f 181 delete pHdlr;
yueee_yt 4:1b6b021ee21d 182 // delete client;
yueee_yt 4:1b6b021ee21d 183 // delete m_pTCPSocketConnection;
yueee_yt 4:1b6b021ee21d 184 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 4:1b6b021ee21d 185 printf("(dispatcherRequest)return\r\n");
yueee_yt 4:1b6b021ee21d 186 #endif
yueee_yt 4:1b6b021ee21d 187 return ;
yueee_yt 0:fdf9c2c5200f 188 }
yueee_yt 0:fdf9c2c5200f 189
yueee_yt 0:fdf9c2c5200f 190 void HTTPServerChild (void const *arg)
yueee_yt 0:fdf9c2c5200f 191 {
yueee_yt 4:1b6b021ee21d 192 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 193 printf("HTTPServerChiled Start......\r\n");
yueee_yt 4:1b6b021ee21d 194 #endif
yueee_yt 0:fdf9c2c5200f 195 TCPSocketConnection* client = (TCPSocketConnection*)arg;
yueee_yt 0:fdf9c2c5200f 196
yueee_yt 0:fdf9c2c5200f 197 for (;;) {
yueee_yt 4:1b6b021ee21d 198 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 199 printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 200 #endif
yueee_yt 0:fdf9c2c5200f 201 dispatchRequest(client);
yueee_yt 4:1b6b021ee21d 202 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 203 printf("(HTTPServer.h<HTTPServerChild>)Close %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 204 #endif
yueee_yt 0:fdf9c2c5200f 205 client->close();
yueee_yt 0:fdf9c2c5200f 206 client->reset_address();
yueee_yt 0:fdf9c2c5200f 207 //delete client;
yueee_yt 0:fdf9c2c5200f 208 Thread::signal_wait(1);
yueee_yt 0:fdf9c2c5200f 209 }
yueee_yt 0:fdf9c2c5200f 210 }
yueee_yt 0:fdf9c2c5200f 211
yueee_yt 0:fdf9c2c5200f 212 void HTTPServerCloser (void const *arg)
yueee_yt 0:fdf9c2c5200f 213 {
yueee_yt 0:fdf9c2c5200f 214 TCPSocketConnection *client = (TCPSocketConnection*)arg;
yueee_yt 0:fdf9c2c5200f 215
yueee_yt 0:fdf9c2c5200f 216 for (;;) {
yueee_yt 0:fdf9c2c5200f 217 client->close();
yueee_yt 4:1b6b021ee21d 218 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 219 printf("Close %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 220 #endif
yueee_yt 0:fdf9c2c5200f 221 Thread::signal_wait(1);
yueee_yt 0:fdf9c2c5200f 222 }
yueee_yt 0:fdf9c2c5200f 223 }
yueee_yt 0:fdf9c2c5200f 224
yueee_yt 0:fdf9c2c5200f 225 void HTTPServerStart(int port = 80)
yueee_yt 0:fdf9c2c5200f 226 {
yueee_yt 0:fdf9c2c5200f 227 int i, t = 0;
yueee_yt 0:fdf9c2c5200f 228 TCPSocketConnection clients[THREAD_MAX];
yueee_yt 0:fdf9c2c5200f 229 TCPSocketConnection xclient;
yueee_yt 0:fdf9c2c5200f 230
yueee_yt 0:fdf9c2c5200f 231 for (i = 0; i < THREAD_MAX; i ++) {
yueee_yt 0:fdf9c2c5200f 232 threads[i] = NULL;
yueee_yt 0:fdf9c2c5200f 233 }
yueee_yt 0:fdf9c2c5200f 234 xthread = NULL;
yueee_yt 0:fdf9c2c5200f 235
yueee_yt 0:fdf9c2c5200f 236 TCPSocketServer server;
yueee_yt 0:fdf9c2c5200f 237 server.bind(port);
yueee_yt 0:fdf9c2c5200f 238 server.listen();
yueee_yt 4:1b6b021ee21d 239 // server.set_blocking(false);
yueee_yt 4:1b6b021ee21d 240 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 241 printf("Wait for new connection...\r\n");
yueee_yt 4:1b6b021ee21d 242 #endif
yueee_yt 0:fdf9c2c5200f 243 for (;;) {
yueee_yt 4:1b6b021ee21d 244 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 245 printf("**Start Loop** \r\n");
yueee_yt 4:1b6b021ee21d 246 #endif
yueee_yt 0:fdf9c2c5200f 247 if (t >= 0) {
yueee_yt 0:fdf9c2c5200f 248 if(server.accept(clients[t])==0) {
yueee_yt 0:fdf9c2c5200f 249 // fork child process
yueee_yt 0:fdf9c2c5200f 250 if (threads[t]) {
yueee_yt 0:fdf9c2c5200f 251 threads[t]->signal_set(1);
yueee_yt 0:fdf9c2c5200f 252 } else {
embeddedartists 6:7b3320c34654 253 threads[t] = new Thread(HTTPServerChild, (void*)&clients[t], osPriorityNormal, DEFAULT_STACK_SIZE*2);
yueee_yt 0:fdf9c2c5200f 254 }
yueee_yt 4:1b6b021ee21d 255 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 256 printf("Forked %d\r\n", t);
yueee_yt 4:1b6b021ee21d 257 #endif
yueee_yt 0:fdf9c2c5200f 258 }
yueee_yt 0:fdf9c2c5200f 259 } else {
yueee_yt 0:fdf9c2c5200f 260 if(server.accept(xclient)==0) {
yueee_yt 0:fdf9c2c5200f 261 // closer process
yueee_yt 0:fdf9c2c5200f 262 if (xthread) {
yueee_yt 0:fdf9c2c5200f 263 xthread->signal_set(1);
yueee_yt 0:fdf9c2c5200f 264 } else {
embeddedartists 6:7b3320c34654 265 xthread = new Thread(HTTPServerCloser, (void*)&xclient, osPriorityNormal, DEFAULT_STACK_SIZE*2);
yueee_yt 0:fdf9c2c5200f 266 }
yueee_yt 4:1b6b021ee21d 267 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 268 printf("Connection full\r\n");
yueee_yt 4:1b6b021ee21d 269 #endif
yueee_yt 0:fdf9c2c5200f 270 }
yueee_yt 0:fdf9c2c5200f 271 }
yueee_yt 0:fdf9c2c5200f 272
yueee_yt 0:fdf9c2c5200f 273 t = -1;
yueee_yt 0:fdf9c2c5200f 274 for (i = 0; i < THREAD_MAX; i ++) {
yueee_yt 0:fdf9c2c5200f 275 if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) {
yueee_yt 0:fdf9c2c5200f 276 if (t < 0) t = i; // next empty thread
yueee_yt 0:fdf9c2c5200f 277 }
yueee_yt 0:fdf9c2c5200f 278 }
yueee_yt 4:1b6b021ee21d 279 // Thread::wait(100);
yueee_yt 0:fdf9c2c5200f 280 }
yueee_yt 0:fdf9c2c5200f 281 }
yueee_yt 0:fdf9c2c5200f 282 #include "Handler/RPCHandler.h"
yueee_yt 0:fdf9c2c5200f 283 #include "Handler/FSHandler.h"
yueee_yt 0:fdf9c2c5200f 284 #include "Handler/SimpleHandler.h"
yueee_yt 0:fdf9c2c5200f 285
yueee_yt 0:fdf9c2c5200f 286 #endif