Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed
HTTPServer.cpp
00001 #include "HTTPServer.h" 00002 #include "NetServer.h" 00003 00004 using namespace std; 00005 using namespace mbed; 00006 00007 //unsigned int gconnections = 0; 00008 00009 unsigned int mbed::hash(unsigned char *str) { 00010 unsigned int hash = 5381; 00011 int c; 00012 while((c = *(str++))!=(unsigned char)'\0') { 00013 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 00014 } 00015 return hash; 00016 } 00017 00018 HTTPConnection::HTTPConnection(HTTPServer *pparent, struct tcp_pcb *pcb) 00019 : TCPConnection(pparent, pcb), request_incomplete(true), data(NULL), 00020 request_handler(NULL), request_status(HTTP_NotFound), parent(pparent), 00021 _request_url(NULL), _request_type(0), _request_headerfields(NULL), 00022 _request_length(0), _request_arg_key(NULL), _request_arg_value(NULL), 00023 _request_arg_state(0), emptypolls(0) { 00024 _timeout_max = pparent->timeout(); 00025 } 00026 00027 HTTPConnection::~HTTPConnection() { 00028 deleteRequest(); 00029 emptypolls = NetServer::time(); 00030 } 00031 00032 const char *HTTPConnection::getField(char *key) const { 00033 unsigned int h = hash((unsigned char *)key); 00034 return _request_fields.find(h)->second; 00035 } 00036 00037 void HTTPConnection::addField(char *key, char *value) { 00038 unsigned int h = hash((unsigned char *)key); 00039 if(parent->isField(h)) { 00040 _request_fields.insert( make_pair(h, value)); 00041 } 00042 } 00043 00044 void HTTPConnection::send() { 00045 int i = sndbuf(); 00046 if(!request_incomplete&&i) { 00047 switch(request_handler->send(this, i)) { 00048 case HTTP_SuccessEnded: 00049 case HTTP_Failed: { 00050 deleteRequest(); 00051 release_callbacks(); 00052 NetServer::get()->free(this); 00053 close(); 00054 } break; 00055 default: 00056 emptypolls = NetServer::time(); 00057 break; 00058 } 00059 } else { 00060 if(NetServer::time() - emptypolls > _timeout_max) { 00061 release_callbacks(); 00062 NetServer::get()->free(this); 00063 close(); 00064 } 00065 } 00066 } 00067 00068 void HTTPConnection::store(void *d, struct pbuf *p) { 00069 int len = p->len-(((int)d)-((int)p->payload)); 00070 do { 00071 switch(request_handler->data(this, d, len)) { 00072 case HTTP_SuccessEnded: 00073 case HTTP_Failed: { 00074 deleteRequest(); 00075 release_callbacks(); 00076 NetServer::get()->free(this); 00077 close(); 00078 } break; 00079 default: 00080 break; 00081 } 00082 p = p->next; 00083 if(p) { 00084 len = p->len; 00085 d = static_cast<char *>(p->payload); 00086 } 00087 } while(_request_type&&p); 00088 } 00089 00090 void HTTPConnection::err(err_t err) { 00091 printf("Error\n"); 00092 release_callbacks(); 00093 NetServer::get()->free(this); 00094 } 00095 00096 err_t HTTPConnection::poll() { 00097 send(); 00098 return ERR_OK; 00099 } 00100 00101 err_t HTTPConnection::sent(u16_t len) { 00102 return poll(); 00103 } 00104 00105 err_t HTTPConnection::recv(struct pbuf *q, err_t err) { 00106 struct pbuf *p = q; 00107 int i; 00108 char *data; 00109 if(err == ERR_OK && p != NULL) { 00110 /* Inform TCP that we have taken the data. */ 00111 recved(p->tot_len); 00112 data = static_cast<char *>(p->payload); 00113 00114 // :1 00115 // Looking if it's GET, POST, 00116 // Followup from an incomplete request Header, 00117 // POST data or just crap (DEL, HEAD ...). 00118 if(!_request_type&&(strncmp(data, "GET ", 4) == 0)) { 00119 _request_type = GET; // Need :2 00120 } else if(!_request_type&&(strncmp(data, "POST ", 5) == 0)) { 00121 _request_type = POST; // Need :2 00122 } else if(_request_type&&request_incomplete) { 00123 getFields(&p, &data); // Need :3 00124 } else if(_request_type == POST) { 00125 // Followup (Data) // Exits 00126 data = static_cast<char *>(p->payload); 00127 store(data, p); 00128 emptypolls = NetServer::time(); 00129 pbuf_free(q); 00130 data = NULL; 00131 return ERR_OK; 00132 } else { 00133 pbuf_free(q); // Exits 00134 data = NULL; 00135 return ERR_OK; 00136 } 00137 00138 // :2 00139 // Processing first POST or GET Packet 00140 // need :3 v--- If its 0 we have followup header data. 00141 if(_request_type&&!_request_url) { 00142 char *pagename = (char *)(data + _request_type); 00143 for(i = _request_type; i < p->len; i++) { 00144 if((data[i] == ' ') || (data[i] == '\r') || (data[i] == '\n')) { 00145 data[i] = 0; 00146 data = &data[i+1]; 00147 break; 00148 } 00149 } 00150 emptypolls = NetServer::time(); 00151 00152 if((pagename[0] == '/') && (pagename[1] == 0)) { 00153 pagename = "/index.htm"; 00154 } 00155 00156 i = strlen(pagename); 00157 _request_url = new char[i+1]; 00158 memcpy(_request_url, pagename, i); 00159 _request_url[i] = '\0'; 00160 getFields(&p, &data); 00161 } 00162 // :3 00163 // Send or store the first amoungh of data. 00164 // Only when the message is complete. 00165 if(!request_incomplete) { 00166 emptypolls = NetServer::time(); 00167 // Find the right handler 00168 if(!request_handler) { 00169 request_handler = parent->handle(this); 00170 request_status = request_handler->init(this); 00171 } 00172 i = strlen(_request_headerfields) + 120; 00173 char *buf = new char[i]; 00174 sprintf(buf, "HTTP/1.1 %d OK\r\nServer:mbed embedded%s%d%s\r\nConnection: Close\r\n\r\n", request_status, 00175 (_request_length?"\r\nContent-Length: ":""),_request_length, 00176 getHeaderFields()); 00177 i = strlen(buf); 00178 if(sndbuf()>i) { 00179 if(request_status==HTTP_NotFound) { 00180 const char *msg = { 00181 "HTTP/1.1 404 Not Found\r\nServer:mbed embedded\r\n" 00182 "Content-Type: text/html\r\n" 00183 "Content-Length: 163\r\n" 00184 "\r\n" 00185 "<html>\r\n" 00186 "<header>\r\n" 00187 "<title>File not found<title>\r\n" 00188 "</header>\r\n" 00189 "<body>\r\n" 00190 "<h1>HTTP 404</h1>\r\n" 00191 "<p>The file you requested was not found on this mbed. </p>\r\n" 00192 "</body>\r\n" 00193 "</html>\r\n" 00194 }; 00195 00196 write((void *)msg, strlen(msg), 0); 00197 deleteRequest(); 00198 } else { 00199 write(buf, i, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE)); 00200 if(_request_type == POST) { 00201 store(data, p); 00202 } else { 00203 send(); 00204 } 00205 } 00206 } 00207 delete buf; 00208 } 00209 00210 // Exits 00211 pbuf_free(q); 00212 data = NULL; 00213 } else { 00214 release_callbacks(); 00215 NetServer::get()->free(this); 00216 close(); 00217 } 00218 return ERR_OK; 00219 } 00220 00221 void HTTPConnection::getFields(struct pbuf **q, char **d) { 00222 if(parent->fields.empty()) { 00223 while((*q)&&request_incomplete) { 00224 unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); 00225 for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { 00226 if((*((char *)((*d)-0))=='\n')&&(*((char *)((*d)-1))=='\r')&& 00227 (*((char *)((*d)-2))=='\n')&&(*((char *)((*d)-3))=='\r')) { 00228 request_incomplete = false; 00229 (*d) += 1; 00230 break; 00231 } 00232 } 00233 if(request_incomplete) { 00234 (*q) = (*q)->next; 00235 if((*q)) { 00236 (*d) = static_cast<char *>((*q)->payload); 00237 } 00238 } 00239 } 00240 } else { 00241 char *kb = *d, *ke = NULL, *vb = *d, *ve = NULL; 00242 while((*q)&&request_incomplete) { 00243 unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); 00244 for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { 00245 switch(**d) { 00246 case ' ': switch(_request_arg_state) { 00247 case 1: case 2: _request_arg_state = 2; break; 00248 case 3: _request_arg_state = 3; break; 00249 default: _request_arg_state = 0; break; 00250 } break; 00251 case ':': switch(_request_arg_state) { 00252 default: _request_arg_state = 2; break; 00253 case 3: _request_arg_state = 3; break; 00254 } break; 00255 case '\r': switch(_request_arg_state) { 00256 default: _request_arg_state = 4; break; 00257 case 5: case 6: _request_arg_state = 6; break; 00258 } break; 00259 case '\n': switch(_request_arg_state) { 00260 default: _request_arg_state = 4; break; 00261 case 4: case 5: _request_arg_state = 5; break; 00262 case 6: _request_arg_state = 7; break; 00263 } break; 00264 default: switch(_request_arg_state) { 00265 default: _request_arg_state = 1; break; 00266 case 2: case 3: _request_arg_state = 3; break; 00267 } break; 00268 } 00269 switch(_request_arg_state) { 00270 case 0: kb = (*d)+1; break; //PreKey 00271 case 1: ke = (*d); break; //Key 00272 case 2: vb = (*d)+1; break; //PreValue 00273 case 3: ve = (*d); break; //Value 00274 default: break; 00275 case 7: request_incomplete = false; break; 00276 case 5: { 00277 int oldkey = (_request_arg_key)?strlen(_request_arg_key):0; 00278 int oldval = (_request_arg_value)?strlen(_request_arg_value):0; 00279 int keylen =(ke&&kb)?ke-kb+1:0; 00280 int vallen = (ve&&vb)?ve-vb+1:0; 00281 char *key = new char[oldkey+keylen]; 00282 char *val = new char[oldval+vallen]; 00283 if(_request_arg_key&&oldkey) { 00284 strncpy(key, _request_arg_key, oldkey); 00285 } 00286 if(_request_arg_value&&oldval) { 00287 strncpy(val, _request_arg_value, oldval); 00288 } 00289 if(kb&&keylen) { 00290 strncpy(&key[oldkey], kb, keylen); 00291 } 00292 if(vb&&vallen) { 00293 strncpy(&val[oldval], vb, vallen); 00294 } 00295 key[oldkey+keylen] = 0; 00296 val[oldval+vallen] = 0; 00297 // printf("'%s':='%s'\n", key, val); 00298 addField(key, val); 00299 kb = vb = (*d)+1; 00300 ke = ve = NULL; 00301 if(_request_arg_key) { 00302 delete _request_arg_key; 00303 _request_arg_key = NULL; 00304 } 00305 if(_request_arg_value) { 00306 delete _request_arg_value; 00307 _request_arg_value = NULL; 00308 } 00309 delete key; 00310 } break; 00311 } 00312 } 00313 } 00314 switch(_request_arg_state) { 00315 case 0: break; // PreKey 00316 case 5: break; // n-rec 00317 case 6: break; // 2r-rec 00318 default: break; 00319 case 1: case 2: { // Key // PreValue 00320 int keylen =(kb)?(*d)-kb+1:0; 00321 _request_arg_key = new char[keylen]; 00322 strncpy(_request_arg_key, kb, keylen+1); 00323 _request_arg_key[keylen] = 0; 00324 } break; 00325 case 3: case 4: { // Value // r-rec 00326 int keylen =(ke&&kb)?ke-kb+1:0; 00327 int vallen = (vb)?(*d)-vb+1:0; 00328 _request_arg_key = new char[keylen]; 00329 _request_arg_value = new char[vallen]; 00330 strncpy(_request_arg_key, kb, keylen+1); 00331 strncpy(_request_arg_value, vb, vallen+1); 00332 _request_arg_key[keylen] = 0; 00333 _request_arg_value[vallen] = 0; 00334 } break; 00335 } 00336 if(request_incomplete) { 00337 (*q) = (*q)->next; 00338 if((*q)) { 00339 (*d) = static_cast<char *>((*q)->payload); 00340 } 00341 } 00342 } 00343 } 00344 00345 HTTPServer::HTTPServer(unsigned short port) 00346 : TCPListener(port), _timeout_max(60000) { 00347 } 00348 00349 HTTPServer::HTTPServer(const char *hostname, struct ip_addr ip, struct ip_addr nm, struct ip_addr gw, struct ip_addr dns, unsigned short port) 00350 : TCPListener(port), _timeout_max(60000) { 00351 NetServer *net = NULL; 00352 if(ip.addr != ip_addr_any.addr && nm.addr != ip_addr_any.addr && gw.addr != ip_addr_any.addr) { 00353 net = NetServer::create(ip, nm, gw); 00354 if(dns.addr != ip_addr_any.addr) { 00355 net->setDNS1(dns); 00356 } 00357 } else if(hostname) { 00358 net = NetServer::create(); 00359 } 00360 if(hostname) { 00361 net->setHostname(hostname); 00362 } 00363 } 00364 00365 void HTTPConnection::deleteRequest() { 00366 for(map<unsigned int, char *>::iterator iter = _request_fields.begin(); 00367 iter!=_request_fields.end();iter++) { 00368 delete iter->second; 00369 } 00370 _request_fields.clear(); 00371 if(data) {delete data; data = NULL; }; 00372 00373 if(_request_type) { 00374 delete _request_headerfields; 00375 delete _request_arg_key; 00376 delete _request_arg_value; 00377 if(_request_url) { 00378 delete _request_url; 00379 _request_url = NULL; 00380 } 00381 } 00382 _request_type = 0; 00383 request_incomplete = true; 00384 } 00385
Generated on Tue Jul 12 2022 19:17:23 by 1.7.2