Fork of HttpServer_snapshot_mbed-os library
Fork of HttpServer_snapshot_mbed-os by
HTTPServer.h@15:371fbad587ed, 2017-06-23 (annotated)
- Committer:
- dkato
- Date:
- Fri Jun 23 11:34:54 2017 +0000
- Revision:
- 15:371fbad587ed
- Parent:
- 13:d3571c244759
- Child:
- 16:13f082bef9a9
Added a function to notify the transfer completion of SnapshotHandler.
; Changed to process with a single task. This can be switched by compile switch.
;
Who changed what in which revision?
User | Revision | Line number | New 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> |
dkato | 15:371fbad587ed | 9 | static inline void http_server_debug_print(const char *format, ...) { |
dkato | 15:371fbad587ed | 10 | va_list args; |
dkato | 15:371fbad587ed | 11 | va_start(args, format); |
dkato | 15:371fbad587ed | 12 | vfprintf(stderr, format, args); |
dkato | 15:371fbad587ed | 13 | va_end(args); |
dkato | 15:371fbad587ed | 14 | } |
dkato | 15:371fbad587ed | 15 | #else |
dkato | 15:371fbad587ed | 16 | static inline void http_server_debug_print(const char *format, ...) {} |
yueee_yt | 4:1b6b021ee21d | 17 | #endif |
yueee_yt | 4:1b6b021ee21d | 18 | |
yueee_yt | 0:fdf9c2c5200f | 19 | #include <string> |
yueee_yt | 0:fdf9c2c5200f | 20 | using std::string; |
yueee_yt | 0:fdf9c2c5200f | 21 | |
yueee_yt | 0:fdf9c2c5200f | 22 | #include <map> |
yueee_yt | 0:fdf9c2c5200f | 23 | using std::map; |
yueee_yt | 0:fdf9c2c5200f | 24 | |
yueee_yt | 0:fdf9c2c5200f | 25 | #include "HTTPRequestHandler.h" |
yueee_yt | 0:fdf9c2c5200f | 26 | #include "rtos.h" |
yueee_yt | 0:fdf9c2c5200f | 27 | #include "mbed.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 | |
dkato | 11:0700755d64ae | 41 | map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocket* ), 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 | |
dkato | 11:0700755d64ae | 55 | bool getRequest(TCPSocket* 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++) { |
dkato | 11:0700755d64ae | 66 | ret = client->recv(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; |
dkato | 15:371fbad587ed | 82 | http_server_debug_print("Parsing request : %s\r\n", req); |
yueee_yt | 0:fdf9c2c5200f | 83 | ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path); |
yueee_yt | 0:fdf9c2c5200f | 84 | if(ret !=2) return false; |
yueee_yt | 0:fdf9c2c5200f | 85 | *meth = string(c_meth); |
yueee_yt | 0:fdf9c2c5200f | 86 | *path = string(c_path); |
yueee_yt | 0:fdf9c2c5200f | 87 | return true; |
yueee_yt | 0:fdf9c2c5200f | 88 | } |
yueee_yt | 0:fdf9c2c5200f | 89 | |
dkato | 11:0700755d64ae | 90 | void dispatchRequest(TCPSocket* client) |
yueee_yt | 0:fdf9c2c5200f | 91 | { |
yueee_yt | 0:fdf9c2c5200f | 92 | string path; |
yueee_yt | 0:fdf9c2c5200f | 93 | string meth; |
yueee_yt | 0:fdf9c2c5200f | 94 | HTTP_METH methCode; |
dkato | 15:371fbad587ed | 95 | http_server_debug_print("Dispatching req\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 96 | if( !getRequest(client,&path, &meth ) ) { |
dkato | 15:371fbad587ed | 97 | http_server_debug_print("dispatchRequest Invalid request\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 98 | return; //Invalid request |
yueee_yt | 0:fdf9c2c5200f | 99 | } |
yueee_yt | 0:fdf9c2c5200f | 100 | if( !meth.compare("GET") ) { |
dkato | 15:371fbad587ed | 101 | http_server_debug_print("dispatchRequest HTTP_GET\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 102 | methCode = HTTP_GET; |
yueee_yt | 0:fdf9c2c5200f | 103 | } else if( !meth.compare("POST") ) { |
dkato | 15:371fbad587ed | 104 | http_server_debug_print("dispatchRequest HTTP_POST\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 105 | methCode = HTTP_POST; |
yueee_yt | 0:fdf9c2c5200f | 106 | } else if( !meth.compare("HEAD") ) { |
dkato | 15:371fbad587ed | 107 | http_server_debug_print("dispatchRequest HTTP_HEAD\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 108 | methCode = HTTP_HEAD; |
yueee_yt | 0:fdf9c2c5200f | 109 | } else { |
dkato | 15:371fbad587ed | 110 | http_server_debug_print("dispatchRequest() Parse error\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 111 | return; |
yueee_yt | 0:fdf9c2c5200f | 112 | } |
dkato | 15:371fbad587ed | 113 | http_server_debug_print("Looking for a handler\r\n"); |
dkato | 11:0700755d64ae | 114 | map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*), handlersComp >::iterator it; |
yueee_yt | 0:fdf9c2c5200f | 115 | int root_len = 0; |
yueee_yt | 0:fdf9c2c5200f | 116 | for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) { |
dkato | 15:371fbad587ed | 117 | http_server_debug_print("Checking %s...\r\n", (*it).first.c_str()); |
yueee_yt | 0:fdf9c2c5200f | 118 | root_len = (*it).first.length(); |
yueee_yt | 0:fdf9c2c5200f | 119 | if ( root_len && |
yueee_yt | 0:fdf9c2c5200f | 120 | !path.compare( 0, root_len, (*it).first ) && |
yueee_yt | 0:fdf9c2c5200f | 121 | (path[root_len] == '/' || path[root_len] == '\0')) { |
dkato | 15:371fbad587ed | 122 | http_server_debug_print("Found (%s)\r\n", (*it).first.c_str()); |
yueee_yt | 0:fdf9c2c5200f | 123 | // Found! |
yueee_yt | 0:fdf9c2c5200f | 124 | break; // for |
yueee_yt | 0:fdf9c2c5200f | 125 | } |
yueee_yt | 0:fdf9c2c5200f | 126 | } |
yueee_yt | 0:fdf9c2c5200f | 127 | if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) { |
dkato | 15:371fbad587ed | 128 | http_server_debug_print("Using default handler\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 129 | it = m_lpHandlers.end(); |
yueee_yt | 0:fdf9c2c5200f | 130 | it--; //Get the last element |
yueee_yt | 0:fdf9c2c5200f | 131 | if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler |
yueee_yt | 0:fdf9c2c5200f | 132 | it = m_lpHandlers.end(); |
yueee_yt | 0:fdf9c2c5200f | 133 | root_len = 0; |
yueee_yt | 0:fdf9c2c5200f | 134 | } |
yueee_yt | 0:fdf9c2c5200f | 135 | if(it == m_lpHandlers.end()) { |
dkato | 15:371fbad587ed | 136 | http_server_debug_print("No handler found\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 137 | return; |
yueee_yt | 0:fdf9c2c5200f | 138 | } |
dkato | 15:371fbad587ed | 139 | http_server_debug_print("Handler found.\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 140 | HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client); |
yueee_yt | 0:fdf9c2c5200f | 141 | //**** client = NULL; //We don't own it anymore |
yueee_yt | 0:fdf9c2c5200f | 142 | switch(methCode) { |
yueee_yt | 0:fdf9c2c5200f | 143 | case HTTP_GET: |
yueee_yt | 0:fdf9c2c5200f | 144 | pHdlr->doGet(); |
yueee_yt | 0:fdf9c2c5200f | 145 | break; |
yueee_yt | 0:fdf9c2c5200f | 146 | case HTTP_POST: |
yueee_yt | 0:fdf9c2c5200f | 147 | pHdlr->doPost(); |
yueee_yt | 0:fdf9c2c5200f | 148 | break; |
yueee_yt | 0:fdf9c2c5200f | 149 | case HTTP_HEAD: |
yueee_yt | 0:fdf9c2c5200f | 150 | pHdlr->doHead(); |
yueee_yt | 0:fdf9c2c5200f | 151 | break; |
yueee_yt | 0:fdf9c2c5200f | 152 | } |
yueee_yt | 0:fdf9c2c5200f | 153 | delete pHdlr; |
dkato | 15:371fbad587ed | 154 | http_server_debug_print("(dispatcherRequest)return\r\n"); |
yueee_yt | 4:1b6b021ee21d | 155 | return ; |
yueee_yt | 0:fdf9c2c5200f | 156 | } |
yueee_yt | 0:fdf9c2c5200f | 157 | |
dkato | 15:371fbad587ed | 158 | #define THREAD_MAX 1 |
dkato | 15:371fbad587ed | 159 | |
dkato | 15:371fbad587ed | 160 | #if (THREAD_MAX > 1) |
dkato | 15:371fbad587ed | 161 | static Thread *threads[THREAD_MAX]; |
dkato | 15:371fbad587ed | 162 | static Thread *xthread; |
dkato | 15:371fbad587ed | 163 | |
dkato | 15:371fbad587ed | 164 | static void HTTPServerChild (TCPSocket* client) |
yueee_yt | 0:fdf9c2c5200f | 165 | { |
dkato | 15:371fbad587ed | 166 | http_server_debug_print("HTTPServerChiled Start......\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 167 | |
yueee_yt | 0:fdf9c2c5200f | 168 | for (;;) { |
dkato | 15:371fbad587ed | 169 | http_server_debug_print("(HTTPServer.h<HTTPServerChild>)Connection\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 170 | dispatchRequest(client); |
dkato | 15:371fbad587ed | 171 | http_server_debug_print("(HTTPServer.h<HTTPServerChild>)Close\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 172 | client->close(); |
yueee_yt | 0:fdf9c2c5200f | 173 | Thread::signal_wait(1); |
yueee_yt | 0:fdf9c2c5200f | 174 | } |
yueee_yt | 0:fdf9c2c5200f | 175 | } |
yueee_yt | 0:fdf9c2c5200f | 176 | |
dkato | 15:371fbad587ed | 177 | static void HTTPServerCloser (TCPSocket *client) |
yueee_yt | 0:fdf9c2c5200f | 178 | { |
yueee_yt | 0:fdf9c2c5200f | 179 | for (;;) { |
yueee_yt | 0:fdf9c2c5200f | 180 | client->close(); |
dkato | 15:371fbad587ed | 181 | http_server_debug_print("Close\r\n"); |
yueee_yt | 0:fdf9c2c5200f | 182 | Thread::signal_wait(1); |
yueee_yt | 0:fdf9c2c5200f | 183 | } |
yueee_yt | 0:fdf9c2c5200f | 184 | } |
yueee_yt | 0:fdf9c2c5200f | 185 | |
dkato | 15:371fbad587ed | 186 | void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal) |
yueee_yt | 0:fdf9c2c5200f | 187 | { |
yueee_yt | 0:fdf9c2c5200f | 188 | int i, t = 0; |
dkato | 11:0700755d64ae | 189 | TCPSocket clients[THREAD_MAX]; |
dkato | 11:0700755d64ae | 190 | TCPSocket xclient; |
yueee_yt | 0:fdf9c2c5200f | 191 | |
yueee_yt | 0:fdf9c2c5200f | 192 | for (i = 0; i < THREAD_MAX; i ++) { |
yueee_yt | 0:fdf9c2c5200f | 193 | threads[i] = NULL; |
yueee_yt | 0:fdf9c2c5200f | 194 | } |
yueee_yt | 0:fdf9c2c5200f | 195 | xthread = NULL; |
yueee_yt | 0:fdf9c2c5200f | 196 | |
dkato | 11:0700755d64ae | 197 | TCPServer server(net); |
yueee_yt | 0:fdf9c2c5200f | 198 | server.bind(port); |
yueee_yt | 0:fdf9c2c5200f | 199 | server.listen(); |
dkato | 15:371fbad587ed | 200 | http_server_debug_print("Wait for new connection...\r\n"); |
dkato | 13:d3571c244759 | 201 | |
yueee_yt | 0:fdf9c2c5200f | 202 | for (;;) { |
dkato | 15:371fbad587ed | 203 | http_server_debug_print("**Start Loop** \r\n"); |
yueee_yt | 0:fdf9c2c5200f | 204 | if (t >= 0) { |
dkato | 11:0700755d64ae | 205 | if(server.accept(&clients[t])==0) { |
yueee_yt | 0:fdf9c2c5200f | 206 | // fork child process |
yueee_yt | 0:fdf9c2c5200f | 207 | if (threads[t]) { |
yueee_yt | 0:fdf9c2c5200f | 208 | threads[t]->signal_set(1); |
yueee_yt | 0:fdf9c2c5200f | 209 | } else { |
dkato | 15:371fbad587ed | 210 | threads[t] = new Thread(priority, 1024 * 3); |
dkato | 13:d3571c244759 | 211 | threads[t]->start(callback(HTTPServerChild, &clients[t])); |
yueee_yt | 0:fdf9c2c5200f | 212 | } |
dkato | 15:371fbad587ed | 213 | http_server_debug_print("Forked %d\r\n", t); |
dkato | 15:371fbad587ed | 214 | } else { |
dkato | 15:371fbad587ed | 215 | Thread::wait(10); |
yueee_yt | 0:fdf9c2c5200f | 216 | } |
yueee_yt | 0:fdf9c2c5200f | 217 | } else { |
dkato | 11:0700755d64ae | 218 | if(server.accept(&xclient)==0) { |
yueee_yt | 0:fdf9c2c5200f | 219 | // closer process |
yueee_yt | 0:fdf9c2c5200f | 220 | if (xthread) { |
yueee_yt | 0:fdf9c2c5200f | 221 | xthread->signal_set(1); |
yueee_yt | 0:fdf9c2c5200f | 222 | } else { |
dkato | 15:371fbad587ed | 223 | xthread = new Thread(priority); |
dkato | 13:d3571c244759 | 224 | xthread->start(callback(HTTPServerCloser, &xclient)); |
yueee_yt | 0:fdf9c2c5200f | 225 | } |
dkato | 15:371fbad587ed | 226 | http_server_debug_print("Connection full\r\n"); |
dkato | 15:371fbad587ed | 227 | } else { |
dkato | 15:371fbad587ed | 228 | Thread::wait(10); |
yueee_yt | 0:fdf9c2c5200f | 229 | } |
yueee_yt | 0:fdf9c2c5200f | 230 | } |
yueee_yt | 0:fdf9c2c5200f | 231 | |
yueee_yt | 0:fdf9c2c5200f | 232 | t = -1; |
yueee_yt | 0:fdf9c2c5200f | 233 | for (i = 0; i < THREAD_MAX; i ++) { |
dkato | 6:d9e6379eefac | 234 | if ((threads[i] == NULL) |
dkato | 11:0700755d64ae | 235 | || ((threads[i]->get_state() == Thread::WaitingAnd))) { |
yueee_yt | 0:fdf9c2c5200f | 236 | if (t < 0) t = i; // next empty thread |
yueee_yt | 0:fdf9c2c5200f | 237 | } |
yueee_yt | 0:fdf9c2c5200f | 238 | } |
yueee_yt | 0:fdf9c2c5200f | 239 | } |
yueee_yt | 0:fdf9c2c5200f | 240 | } |
dkato | 15:371fbad587ed | 241 | |
dkato | 15:371fbad587ed | 242 | #else // THREAD_MAX == 1 |
dkato | 15:371fbad587ed | 243 | |
dkato | 15:371fbad587ed | 244 | void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal) |
dkato | 15:371fbad587ed | 245 | { |
dkato | 15:371fbad587ed | 246 | TCPSocket client; |
dkato | 15:371fbad587ed | 247 | |
dkato | 15:371fbad587ed | 248 | (void)priority; |
dkato | 15:371fbad587ed | 249 | |
dkato | 15:371fbad587ed | 250 | TCPServer server(net); |
dkato | 15:371fbad587ed | 251 | server.bind(port); |
dkato | 15:371fbad587ed | 252 | server.listen(); |
dkato | 15:371fbad587ed | 253 | http_server_debug_print("Wait for new connection...\r\n"); |
dkato | 15:371fbad587ed | 254 | |
dkato | 15:371fbad587ed | 255 | while (1) { |
dkato | 15:371fbad587ed | 256 | http_server_debug_print("**Start Loop** \r\n"); |
dkato | 15:371fbad587ed | 257 | if (server.accept(&client) == 0) { |
dkato | 15:371fbad587ed | 258 | dispatchRequest(&client); |
dkato | 15:371fbad587ed | 259 | client.close(); |
dkato | 15:371fbad587ed | 260 | } |
dkato | 15:371fbad587ed | 261 | } |
dkato | 15:371fbad587ed | 262 | } |
dkato | 15:371fbad587ed | 263 | |
dkato | 15:371fbad587ed | 264 | #endif |
dkato | 15:371fbad587ed | 265 | |
yueee_yt | 0:fdf9c2c5200f | 266 | #include "Handler/RPCHandler.h" |
yueee_yt | 0:fdf9c2c5200f | 267 | #include "Handler/FSHandler.h" |
yueee_yt | 0:fdf9c2c5200f | 268 | #include "Handler/SimpleHandler.h" |
dkato | 6:d9e6379eefac | 269 | #include "SnapshotHandler.h" |
yueee_yt | 0:fdf9c2c5200f | 270 | |
yueee_yt | 0:fdf9c2c5200f | 271 | #endif |