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