HttpServer Library for "mbed-os" which added a snapshot handler.

Dependents:   GR-PEACH-webcam GR-Boards_WebCamera GR-Boards_WebCamera GR-Boards_WebCamera

Fork of HttpServer_snapshot by Renesas

Committer:
dkato
Date:
Wed Jun 07 05:53:36 2017 +0000
Revision:
13:d3571c244759
Parent:
11:0700755d64ae
Child:
15:371fbad587ed
SnapshotHandler can register multiple paths.

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