Fork of HttpServer_snapshot_mbed-os library

Fork of HttpServer_snapshot_mbed-os by Renesas

Committer:
fxanhkhoa
Date:
Sat Sep 30 08:36:29 2017 +0000
Revision:
16:13f082bef9a9
Parent:
15:371fbad587ed
Renesas GR Peach ASEAN Contest

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