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:
Fri Sep 13 02:08:33 2019 +0000
Revision:
18:673d663a1ed7
Parent:
17:6b7076372285
Add macro HTTP_SERVER_THREAD_MAX (default 1)

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>
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);
dkato 17:6b7076372285 67 if(ret <= 0) {
dkato 17:6b7076372285 68 return false;
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 18:673d663a1ed7 158 #ifndef HTTP_SERVER_THREAD_MAX
dkato 18:673d663a1ed7 159 #define HTTP_SERVER_THREAD_MAX 1
dkato 18:673d663a1ed7 160 #endif
dkato 15:371fbad587ed 161
dkato 18:673d663a1ed7 162 #if (HTTP_SERVER_THREAD_MAX > 1)
dkato 18:673d663a1ed7 163 static Thread *threads[HTTP_SERVER_THREAD_MAX];
dkato 18:673d663a1ed7 164 static bool soket_rady[HTTP_SERVER_THREAD_MAX];
dkato 18:673d663a1ed7 165 static TCPSocket * clients[HTTP_SERVER_THREAD_MAX];
dkato 15:371fbad587ed 166
dkato 16:16289b6ec82a 167 static void HTTPServerChild (void* param)
yueee_yt 0:fdf9c2c5200f 168 {
dkato 16:16289b6ec82a 169 bool* p_rady = &soket_rady[(int)param];
yueee_yt 0:fdf9c2c5200f 170
dkato 16:16289b6ec82a 171 while (1) {
dkato 17:6b7076372285 172 ThisThread::flags_wait_all(1);
dkato 17:6b7076372285 173 TCPSocket* client = clients[(int)param];
yueee_yt 0:fdf9c2c5200f 174 dispatchRequest(client);
yueee_yt 0:fdf9c2c5200f 175 client->close();
dkato 16:16289b6ec82a 176 *p_rady = true;
yueee_yt 0:fdf9c2c5200f 177 }
yueee_yt 0:fdf9c2c5200f 178 }
yueee_yt 0:fdf9c2c5200f 179
dkato 15:371fbad587ed 180 void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal)
yueee_yt 0:fdf9c2c5200f 181 {
dkato 16:16289b6ec82a 182 int i;
dkato 17:6b7076372285 183 TCPSocket server;
yueee_yt 0:fdf9c2c5200f 184
dkato 18:673d663a1ed7 185 for (i = 0; i < HTTP_SERVER_THREAD_MAX; i++) {
dkato 16:16289b6ec82a 186 soket_rady[i] = true;
dkato 16:16289b6ec82a 187 threads[i] = new Thread(priority, 1024 * 3);
dkato 16:16289b6ec82a 188 threads[i]->start(callback(HTTPServerChild, (void *)i));
yueee_yt 0:fdf9c2c5200f 189 }
yueee_yt 0:fdf9c2c5200f 190
dkato 17:6b7076372285 191 server.open(net);
yueee_yt 0:fdf9c2c5200f 192 server.bind(port);
yueee_yt 0:fdf9c2c5200f 193 server.listen();
dkato 15:371fbad587ed 194 http_server_debug_print("Wait for new connection...\r\n");
dkato 13:d3571c244759 195
dkato 16:16289b6ec82a 196 while (1) {
dkato 16:16289b6ec82a 197 while (1) {
dkato 18:673d663a1ed7 198 for (i = 0; i < HTTP_SERVER_THREAD_MAX; i++) {
dkato 16:16289b6ec82a 199 if (soket_rady[i] != false) {
dkato 16:16289b6ec82a 200 break;
yueee_yt 0:fdf9c2c5200f 201 }
yueee_yt 0:fdf9c2c5200f 202 }
dkato 18:673d663a1ed7 203 if (i < HTTP_SERVER_THREAD_MAX) {
dkato 16:16289b6ec82a 204 break;
yueee_yt 0:fdf9c2c5200f 205 }
dkato 16:16289b6ec82a 206 ThisThread::sleep_for(5);
yueee_yt 0:fdf9c2c5200f 207 }
yueee_yt 0:fdf9c2c5200f 208
dkato 17:6b7076372285 209 clients[i] = server.accept();
dkato 17:6b7076372285 210 if (clients[i] != NULL) {
dkato 16:16289b6ec82a 211 // fork child process
dkato 16:16289b6ec82a 212 soket_rady[i] = false;
dkato 17:6b7076372285 213 threads[i]->flags_set(1);
yueee_yt 0:fdf9c2c5200f 214 }
yueee_yt 0:fdf9c2c5200f 215 }
yueee_yt 0:fdf9c2c5200f 216 }
dkato 15:371fbad587ed 217
dkato 18:673d663a1ed7 218 #else // HTTP_SERVER_THREAD_MAX == 1
dkato 15:371fbad587ed 219
dkato 15:371fbad587ed 220 void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal)
dkato 15:371fbad587ed 221 {
dkato 17:6b7076372285 222 TCPSocket server;
dkato 17:6b7076372285 223 TCPSocket * p_client;
dkato 15:371fbad587ed 224
dkato 15:371fbad587ed 225 (void)priority;
dkato 15:371fbad587ed 226
dkato 17:6b7076372285 227 server.open(net);
dkato 15:371fbad587ed 228 server.bind(port);
dkato 15:371fbad587ed 229 server.listen();
dkato 15:371fbad587ed 230 http_server_debug_print("Wait for new connection...\r\n");
dkato 15:371fbad587ed 231
dkato 15:371fbad587ed 232 while (1) {
dkato 17:6b7076372285 233 p_client = server.accept();
dkato 17:6b7076372285 234 if (p_client != NULL) {
dkato 17:6b7076372285 235 dispatchRequest(p_client);
dkato 17:6b7076372285 236 p_client->close();
dkato 15:371fbad587ed 237 }
dkato 15:371fbad587ed 238 }
dkato 15:371fbad587ed 239 }
dkato 15:371fbad587ed 240
dkato 15:371fbad587ed 241 #endif
dkato 15:371fbad587ed 242
yueee_yt 0:fdf9c2c5200f 243 #include "Handler/RPCHandler.h"
yueee_yt 0:fdf9c2c5200f 244 #include "Handler/FSHandler.h"
yueee_yt 0:fdf9c2c5200f 245 #include "Handler/SimpleHandler.h"
dkato 6:d9e6379eefac 246 #include "SnapshotHandler.h"
yueee_yt 0:fdf9c2c5200f 247
yueee_yt 0:fdf9c2c5200f 248 #endif