Morgan Du
/
http-webserver-example
Webserver example for Nuvoton NuMaker boards and mbed OS 5.15 - HTTP 1.1 and multi-threaded.
Embed:
(wiki syntax)
Show/hide line numbers
http_server.h
00001 /* 00002 * PackageLicenseDeclared: Apache-2.0 00003 * Copyright (c) 2017 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef _HTTP_SERVER_ 00019 #define _HTTP_SERVER_ 00020 00021 #include "mbed.h" 00022 #include "http_request_parser.h" 00023 #include "http_response.h" 00024 #include "http_response_builder.h" 00025 00026 #ifndef HTTP_SERVER_MAX_CONCURRENT 00027 #define HTTP_SERVER_MAX_CONCURRENT 5 00028 #endif 00029 00030 typedef HttpResponse ParsedHttpRequest; 00031 00032 /** 00033 * \brief HttpServer implements the logic for setting up an HTTP server. 00034 */ 00035 class HttpServer { 00036 public: 00037 /** 00038 * HttpRequest Constructor 00039 * 00040 * @param[in] network The network interface 00041 */ 00042 HttpServer(NetworkInterface* network) { 00043 _network = network; 00044 } 00045 00046 ~HttpServer() { 00047 for (size_t ix = 0; ix < HTTP_SERVER_MAX_CONCURRENT; ix++) { 00048 if (socket_threads[ix]) { 00049 delete socket_threads[ix]; 00050 } 00051 } 00052 } 00053 00054 /** 00055 * Start running the server (it will run on it's own thread) 00056 */ 00057 nsapi_error_t start(uint16_t port, Callback<void(ParsedHttpRequest* request, TCPSocket* socket)> a_handler) { 00058 server = new TCPSocket(); 00059 00060 nsapi_error_t ret; 00061 00062 ret = server->open(_network); 00063 if (ret != NSAPI_ERROR_OK) { 00064 return ret; 00065 } 00066 00067 ret = server->bind(port); 00068 if (ret != NSAPI_ERROR_OK) { 00069 return ret; 00070 } 00071 00072 server->listen(HTTP_SERVER_MAX_CONCURRENT); // max. concurrent connections... 00073 00074 handler = a_handler; 00075 00076 main_thread.start(callback(this, &HttpServer::main)); 00077 00078 return NSAPI_ERROR_OK; 00079 } 00080 00081 private: 00082 00083 void receive_data() { 00084 // UNSAFE: should Mutex around it or something 00085 TCPSocket* socket = sockets.back(); 00086 00087 // needs to keep running until the socket gets closed 00088 while (1) { 00089 00090 ParsedHttpRequest* response = new ParsedHttpRequest(); 00091 HttpParser* parser = new HttpParser(response, HTTP_REQUEST); 00092 00093 // Set up a receive buffer (on the heap) 00094 uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE); 00095 00096 // TCPSocket::recv is called until we don't have any data anymore 00097 nsapi_size_or_error_t recv_ret; 00098 while ((recv_ret = socket->recv(recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) { 00099 // Pass the chunk into the http_parser 00100 size_t nparsed = parser->execute((const char*)recv_buffer, recv_ret); 00101 if (nparsed != recv_ret) { 00102 printf("Parsing failed... parsed %d bytes, received %d bytes\n", nparsed, recv_ret); 00103 recv_ret = -2101; 00104 break; 00105 } 00106 00107 if (response->is_message_complete()) { 00108 break; 00109 } 00110 } 00111 // error? 00112 if (recv_ret <= 0) { 00113 if (recv_ret < 0) { 00114 printf("Error reading from socket %d\n", recv_ret); 00115 } 00116 00117 // error = recv_ret; 00118 delete response; 00119 delete parser; 00120 free(recv_buffer); 00121 00122 // q; should we always break out of the thread or only if NO_SOCKET ? 00123 // should we delete socket here? the socket seems already gone... 00124 if (recv_ret < -3000 || recv_ret == 0) { 00125 return; 00126 } 00127 else { 00128 continue; 00129 } 00130 } 00131 00132 // When done, call parser.finish() 00133 parser->finish(); 00134 00135 // Free the receive buffer 00136 free(recv_buffer); 00137 00138 // Let user application handle the request, if user needs a handle to response they need to memcpy themselves 00139 if (recv_ret > 0) { 00140 handler(response, socket); 00141 } 00142 00143 // Free the response and parser 00144 delete response; 00145 delete parser; 00146 } 00147 } 00148 00149 void main() { 00150 while (1) { 00151 TCPSocket* clt_sock; // = new TCPSocket(); // Q: when should these be cleared? When not connected anymore? 00152 //SocketAddress clt_addr; 00153 nsapi_error_t accept_res; 00154 00155 //nsapi_error_t accept_res = server->accept(clt_sock, &clt_addr); 00156 clt_sock = server->accept(&accept_res); 00157 if (accept_res == NSAPI_ERROR_OK) { 00158 sockets.push_back(clt_sock); // so we can clear our disconnected sockets 00159 00160 // and start listening for events there 00161 Thread* t = new Thread(osPriorityNormal, 2048); 00162 t->start(callback(this, &HttpServer::receive_data)); 00163 00164 socket_thread_metadata_t* m = new socket_thread_metadata_t(); 00165 m->socket = clt_sock; 00166 m->thread = t; 00167 socket_threads.push_back(m); 00168 } 00169 else { 00170 //delete clt_sock; 00171 } 00172 00173 for (size_t ix = 0; ix < socket_threads.size(); ix++) { 00174 if (socket_threads[ix]->thread->get_state() == Thread::Deleted) { 00175 socket_threads[ix]->thread->terminate(); 00176 delete socket_threads[ix]->thread; 00177 //delete socket_threads[ix]->socket; // does this work on esp8266? 00178 socket_threads[ix]->socket->close(); 00179 socket_threads.erase(socket_threads.begin() + ix); // what if there are two? 00180 } 00181 } 00182 00183 } 00184 } 00185 00186 typedef struct { 00187 TCPSocket* socket; 00188 Thread* thread; 00189 } socket_thread_metadata_t; 00190 00191 TCPSocket* server; 00192 NetworkInterface* _network; 00193 Thread main_thread; 00194 vector<TCPSocket*> sockets; 00195 vector<socket_thread_metadata_t*> socket_threads; 00196 Callback<void(ParsedHttpRequest* request, TCPSocket* socket)> handler; 00197 }; 00198 00199 #endif // _HTTP_SERVER
Generated on Tue Jul 19 2022 01:00:46 by 1.7.2