The lib with which to make LPC1768 a simple HTTP server. This have not yet implemented. fopen() DOESN'T WORK after EthernetInterface::connect() is called as using mbed-os 5.4~. See also https://os.mbed.com/questions/80658/HardFault-occurs-when-fopen-is-called-af/ or https://github.com/ARMmbed/mbed-os/issues/6578 and https://github.com/ARMmbed/mbed-os/issues/6624

Fork of HTTP_SERVER by Akifumi Takahashi

Committer:
aktk
Date:
Fri Mar 23 07:40:26 2018 +0000
Revision:
18:ad5c461905bd
Parent:
17:ce5845164001
rename: Filehandler.h -> FileHandler.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aktk 0:cc483bea4fe3 1 #include "HTTP_SERVER.h"
aktk 1:3a1fe94c6e42 2 #include "string"
aktk 16:c3920b5b8572 3 //#ifndef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 4 #define HTTP_SERVER_DEBUG
aktk 16:c3920b5b8572 5 //#endif
aktk 14:a16cdcd098d7 6 /*
aktk 14:a16cdcd098d7 7 LOG:
aktk 14:a16cdcd098d7 8 "sys_thread_new number error" is occurred when an instance of this class is instantiated in main() in main.cpp
aktk 14:a16cdcd098d7 9 This case wasn't occured with the APIs of mbed os 2.
aktk 15:9b2cfbaf1c12 10 So, inserting some DEBUG_PRINT_LINE, and finding where is wrong.
aktk 14:a16cdcd098d7 11
aktk 14:a16cdcd098d7 12 The error seems to be occurred in init() in the above case.
aktk 14:a16cdcd098d7 13
aktk 14:a16cdcd098d7 14 TCP_PORT=80 redefine
aktk 14:a16cdcd098d7 15 tcp_port->port
aktk 14:a16cdcd098d7 16
aktk 14:a16cdcd098d7 17 The error seems to be occurred while ethernet->connect() is proceesing.
aktk 14:a16cdcd098d7 18
aktk 14:a16cdcd098d7 19 The error seems to be caused by something wrong with stack.
aktk 14:a16cdcd098d7 20 When modify (char* -> char) req_buf[1024] in the .h file,
aktk 14:a16cdcd098d7 21 the error message became: "CMSIS-RTOS error: Stack underflow (status: 0x1, task ID: 0x10002678, task name: )"
aktk 14:a16cdcd098d7 22 UNDERFLOW means that there is a value which is too fine(or high definition) to express.
aktk 14:a16cdcd098d7 23 (Why was the type char*?)
aktk 14:a16cdcd098d7 24
aktk 17:ce5845164001 25 (char)req_buf[1024] was not uesed anywhere...
aktk 14:a16cdcd098d7 26 so it was deleted.
aktk 14:a16cdcd098d7 27
aktk 17:ce5845164001 28 (bool)keep-alive was also not uesed so deleted it.
aktk 14:a16cdcd098d7 29
aktk 15:9b2cfbaf1c12 30 After doing those above, the error massage was DERAYED but
aktk 14:a16cdcd098d7 31 it even now occur.
aktk 14:a16cdcd098d7 32 and when some array stack(such like char buffer[1024] -> [256])'s size was decreased,
aktk 14:a16cdcd098d7 33 the message was more derayed.
aktk 14:a16cdcd098d7 34 Therefore it can be thought that the error is causeed by stack overflow.
aktk 14:a16cdcd098d7 35 */
aktk 1:3a1fe94c6e42 36
aktk 10:4a48594c2f44 37 namespace HTTP_SERVER
aktk 10:4a48594c2f44 38 {
aktk 14:a16cdcd098d7 39 void DEBUG_PRINT_NAME()
aktk 14:a16cdcd098d7 40 {
aktk 14:a16cdcd098d7 41 #ifdef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 42 printf("(DEBUG LINE: HTTP_SERVER) ");
aktk 14:a16cdcd098d7 43 #endif
aktk 14:a16cdcd098d7 44 }
aktk 14:a16cdcd098d7 45
aktk 1:3a1fe94c6e42 46 void DEBUG_PRINT_LINE(const char* arg_line)
aktk 1:3a1fe94c6e42 47 {
aktk 12:c926d680f339 48 #ifdef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 49 DEBUG_PRINT_NAME();
aktk 10:4a48594c2f44 50 printf(arg_line);
aktk 10:4a48594c2f44 51 printf("\r\n");
aktk 1:3a1fe94c6e42 52 #endif
aktk 1:3a1fe94c6e42 53 }
aktk 10:4a48594c2f44 54 template<typename T>
aktk 10:4a48594c2f44 55 void DEBUG_PRINT_LINE(const char* arg_line, T arg_t)
aktk 10:4a48594c2f44 56 {
aktk 12:c926d680f339 57 #ifdef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 58 DEBUG_PRINT_NAME();
aktk 10:4a48594c2f44 59 printf(arg_line, arg_t);
aktk 10:4a48594c2f44 60 printf("\r\n");
aktk 10:4a48594c2f44 61 #endif
aktk 10:4a48594c2f44 62 }
aktk 10:4a48594c2f44 63 template<typename T1, typename T2>
aktk 10:4a48594c2f44 64 void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2)
aktk 10:4a48594c2f44 65 {
aktk 12:c926d680f339 66 #ifdef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 67 DEBUG_PRINT_NAME();
aktk 10:4a48594c2f44 68 printf(arg_line, arg_t1, arg_t2);
aktk 10:4a48594c2f44 69 printf("\r\n");
aktk 10:4a48594c2f44 70 #endif
aktk 10:4a48594c2f44 71 }
aktk 10:4a48594c2f44 72 }
aktk 10:4a48594c2f44 73 using namespace HTTP_SERVER;
aktk 1:3a1fe94c6e42 74
aktk 0:cc483bea4fe3 75 HttpServer::HttpServer()
aktk 0:cc483bea4fe3 76 {
aktk 14:a16cdcd098d7 77 DEBUG_PRINT_LINE("=DEBUG MODE=");
aktk 14:a16cdcd098d7 78 net = new EthernetInterface();
aktk 14:a16cdcd098d7 79 port = TCP_PORT;
aktk 14:a16cdcd098d7 80 backlog = 1;
aktk 14:a16cdcd098d7 81 //keep_alive = (false);
aktk 0:cc483bea4fe3 82 listening_flag = (false);
aktk 15:9b2cfbaf1c12 83 socket_connection = false;
aktk 14:a16cdcd098d7 84 DEBUG_PRINT_LINE("A HTTP_SERVER has been inistantiated.");
aktk 0:cc483bea4fe3 85 }
aktk 0:cc483bea4fe3 86
aktk 0:cc483bea4fe3 87 HttpServer::~HttpServer()
aktk 0:cc483bea4fe3 88 {
aktk 0:cc483bea4fe3 89 }
aktk 0:cc483bea4fe3 90
aktk 0:cc483bea4fe3 91 bool HttpServer::init()
aktk 15:9b2cfbaf1c12 92 {
aktk 14:a16cdcd098d7 93 DEBUG_PRINT_LINE("The HTTP SERVER is being initiated");
aktk 14:a16cdcd098d7 94 // Ethernet Initialization
aktk 0:cc483bea4fe3 95 // Ethernet Connecting setup
aktk 14:a16cdcd098d7 96 if(net->connect()) {
aktk 1:3a1fe94c6e42 97 printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n");
aktk 0:cc483bea4fe3 98 return false;
aktk 0:cc483bea4fe3 99 } else {
aktk 14:a16cdcd098d7 100 printf("(HTTP_SERVER) IP Address is %s\r\n", net->get_ip_address());
aktk 0:cc483bea4fe3 101 }
aktk 15:9b2cfbaf1c12 102
aktk 17:ce5845164001 103 ftest.func();
aktk 0:cc483bea4fe3 104 // TCP Socket setup
aktk 0:cc483bea4fe3 105 // To open Server-side PORT
aktk 14:a16cdcd098d7 106 if(server.open(net) < 0) {
aktk 14:a16cdcd098d7 107 printf("(HTTP_SERVER) Error!@TCPSocketServer::open()\r\n");
aktk 14:a16cdcd098d7 108 return false;
aktk 14:a16cdcd098d7 109 } else {
aktk 14:a16cdcd098d7 110 printf("(HTTP_SERVER) TCP Server has successfully opened\r\n");
aktk 14:a16cdcd098d7 111 }
aktk 14:a16cdcd098d7 112 if(server.bind(port)< 0) {
aktk 1:3a1fe94c6e42 113 printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
aktk 0:cc483bea4fe3 114 return false;
aktk 0:cc483bea4fe3 115 } else {
aktk 1:3a1fe94c6e42 116 printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
aktk 0:cc483bea4fe3 117 }
aktk 0:cc483bea4fe3 118 // Server start listening Request from a web browser.
aktk 13:483b2b1a6471 119 if(server.listen(backlog) < 0) {
aktk 1:3a1fe94c6e42 120 printf("(HTTP_SERVER) tcp server listen failed.\r\n");
aktk 0:cc483bea4fe3 121 return false;
aktk 0:cc483bea4fe3 122 } else {
aktk 0:cc483bea4fe3 123 listening_flag = true;
aktk 1:3a1fe94c6e42 124 printf("(HTTP_SERVER) tcp server is listening...\r\n");
aktk 0:cc483bea4fe3 125 }
aktk 15:9b2cfbaf1c12 126
aktk 0:cc483bea4fe3 127 return true;
aktk 0:cc483bea4fe3 128 }
aktk 0:cc483bea4fe3 129
aktk 0:cc483bea4fe3 130 bool HttpServer::run()
aktk 0:cc483bea4fe3 131 {
aktk 15:9b2cfbaf1c12 132
aktk 0:cc483bea4fe3 133 DigitalOut led1(LED1);
aktk 0:cc483bea4fe3 134 DigitalOut led2(LED1);
aktk 0:cc483bea4fe3 135
aktk 14:a16cdcd098d7 136
aktk 14:a16cdcd098d7 137 DEBUG_PRINT_LINE("The HTTP SERVER is starting running");
aktk 0:cc483bea4fe3 138 while (listening_flag) {
aktk 0:cc483bea4fe3 139 led1 = true;
aktk 0:cc483bea4fe3 140 // blocking mode (never timeout)
aktk 0:cc483bea4fe3 141 // waiting client connection
aktk 1:3a1fe94c6e42 142 printf("(HTTP_SERVER) waiting connection\r\n");
aktk 14:a16cdcd098d7 143 if(server.accept(&client_socket, &client_address) < 0) {
aktk 1:3a1fe94c6e42 144 printf("(HTTP_SERVER) failed to accept connection.\r\n");
aktk 0:cc483bea4fe3 145 return -1;
aktk 0:cc483bea4fe3 146 } else {
aktk 14:a16cdcd098d7 147 printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",client_address.get_ip_address());
aktk 14:a16cdcd098d7 148 socket_connection = true;
aktk 0:cc483bea4fe3 149 led2 = true;
aktk 0:cc483bea4fe3 150 }
aktk 1:3a1fe94c6e42 151 // When conected
aktk 14:a16cdcd098d7 152 while (socket_connection) {
aktk 10:4a48594c2f44 153 printf("(HTTP_SERVER) connected\r\n");
aktk 1:3a1fe94c6e42 154
aktk 16:c3920b5b8572 155 char buffer[1024] = {0};
aktk 0:cc483bea4fe3 156 char* httpmethod = NULL;
aktk 0:cc483bea4fe3 157 char* filepath = NULL;
aktk 0:cc483bea4fe3 158 char* http_ver = NULL;
aktk 15:9b2cfbaf1c12 159 //char* header_field_name = NULL;
aktk 15:9b2cfbaf1c12 160 //char* header_field_val = NULL;
aktk 1:3a1fe94c6e42 161
aktk 0:cc483bea4fe3 162 //
aktk 0:cc483bea4fe3 163 // Request Analysis
aktk 0:cc483bea4fe3 164 //
aktk 16:c3920b5b8572 165 printf("(HTTP_SERVER) Request Analysis\r\n");
aktk 16:c3920b5b8572 166 analyzeRequest(buffer, 1023, httpmethod, filepath, http_ver);
aktk 16:c3920b5b8572 167 DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
aktk 16:c3920b5b8572 168 DEBUG_PRINT_LINE("file path: %s", filepath);
aktk 16:c3920b5b8572 169 DEBUG_PRINT_LINE("http ver : %s", http_ver);
aktk 0:cc483bea4fe3 170 //
aktk 0:cc483bea4fe3 171 // Response
aktk 0:cc483bea4fe3 172 //
aktk 15:9b2cfbaf1c12 173 sendResponse(httpmethod, filepath, http_ver);
aktk 7:184c6f1ace94 174 //
aktk 7:184c6f1ace94 175 //
aktk 7:184c6f1ace94 176 //
aktk 0:cc483bea4fe3 177 }
aktk 1:3a1fe94c6e42 178 printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
aktk 14:a16cdcd098d7 179 client_socket.close();
aktk 0:cc483bea4fe3 180 led2 = false;
aktk 0:cc483bea4fe3 181 }
aktk 12:c926d680f339 182 server.close();
aktk 7:184c6f1ace94 183 listening_flag = false;
aktk 0:cc483bea4fe3 184 led1 = false;
aktk 0:cc483bea4fe3 185 return 0;
aktk 15:9b2cfbaf1c12 186
aktk 15:9b2cfbaf1c12 187 }
aktk 15:9b2cfbaf1c12 188
aktk 16:c3920b5b8572 189 bool HttpServer::analyzeRequest(char* buffer, int buffer_size, char* &httpmethod, char* &filepath, char* &http_ver)
aktk 15:9b2cfbaf1c12 190 {
aktk 15:9b2cfbaf1c12 191
aktk 15:9b2cfbaf1c12 192 DEBUG_PRINT_LINE("Request Analysis");
aktk 15:9b2cfbaf1c12 193 switch(client_socket.recv(buffer, buffer_size)) {
aktk 15:9b2cfbaf1c12 194 case 0:
aktk 15:9b2cfbaf1c12 195 DEBUG_PRINT_LINE("recieved buffer is empty.");
aktk 15:9b2cfbaf1c12 196 msger.setStatusLine(400, "No Request");
aktk 15:9b2cfbaf1c12 197 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 198 httpmethod = NULL;
aktk 15:9b2cfbaf1c12 199 filepath = NULL;
aktk 15:9b2cfbaf1c12 200 http_ver = NULL;
aktk 15:9b2cfbaf1c12 201 socket_connection = false;
aktk 15:9b2cfbaf1c12 202 break;
aktk 15:9b2cfbaf1c12 203 case -1:
aktk 15:9b2cfbaf1c12 204 DEBUG_PRINT_LINE("failed to read data from client.");
aktk 15:9b2cfbaf1c12 205 msger.setStatusLine(500, "Internal Server Error");
aktk 15:9b2cfbaf1c12 206 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 207 httpmethod = NULL;
aktk 15:9b2cfbaf1c12 208 filepath = NULL;
aktk 15:9b2cfbaf1c12 209 http_ver = NULL;
aktk 15:9b2cfbaf1c12 210 socket_connection = false;
aktk 15:9b2cfbaf1c12 211 break;
aktk 15:9b2cfbaf1c12 212 default:
aktk 15:9b2cfbaf1c12 213 DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer));
aktk 15:9b2cfbaf1c12 214 DEBUG_PRINT_LINE("-->\r\n");
aktk 15:9b2cfbaf1c12 215 DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
aktk 15:9b2cfbaf1c12 216 // get HTTP method, File path, HTTP version
aktk 15:9b2cfbaf1c12 217 httpmethod = strtok(buffer," ");
aktk 15:9b2cfbaf1c12 218 filepath = strtok(NULL, " ");
aktk 15:9b2cfbaf1c12 219 http_ver = strtok(NULL, "\r\n");
aktk 15:9b2cfbaf1c12 220 break;
aktk 15:9b2cfbaf1c12 221 }
aktk 15:9b2cfbaf1c12 222 return true;
aktk 14:a16cdcd098d7 223 }
aktk 15:9b2cfbaf1c12 224
aktk 16:c3920b5b8572 225 bool HttpServer::sendResponse(char* httpmethod, char* filepath, char* http_ver)
aktk 15:9b2cfbaf1c12 226 {
aktk 15:9b2cfbaf1c12 227 if (strcmp(httpmethod,"GET") == 0 ) {
aktk 15:9b2cfbaf1c12 228 DEBUG_PRINT_LINE("GET request incomming.");
aktk 15:9b2cfbaf1c12 229
aktk 15:9b2cfbaf1c12 230 // file calibration
aktk 15:9b2cfbaf1c12 231 DEBUG_PRINT_LINE("file opening");
aktk 16:c3920b5b8572 232 DEBUG_PRINT_LINE("filepath: %s", filepath);
aktk 17:ce5845164001 233 fhndl.open(filepath,"rb");
aktk 15:9b2cfbaf1c12 234 if(fhndl.arrival()) {
aktk 15:9b2cfbaf1c12 235 msger.setStatusLine(200, "OK");
aktk 15:9b2cfbaf1c12 236 if(msger.setHeaderField("Content-Length", fhndl.getFileSize())) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 237 if(msger.setHeaderField("Connection", "keep-alive")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 238 } else {
aktk 15:9b2cfbaf1c12 239 if(msger.setStatusLine(404, "NOT FOUND")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 240 if(msger.setHeaderField("Connection", "Close")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 241 DEBUG_PRINT_LINE("NOT FOUND");
aktk 15:9b2cfbaf1c12 242 }
aktk 15:9b2cfbaf1c12 243 if( !strcmp(fhndl.getSuffix(), "htm" ) ||
aktk 15:9b2cfbaf1c12 244 !strcmp(fhndl.getSuffix(), "HTM" ) ||
aktk 15:9b2cfbaf1c12 245 !strcmp(fhndl.getSuffix(), "html") ||
aktk 15:9b2cfbaf1c12 246 !strcmp(fhndl.getSuffix(), "HTML")) {
aktk 15:9b2cfbaf1c12 247 if(msger.setHeaderField("Content-Type", "text/html")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 248 } else if( !strcmp(fhndl.getSuffix(), "js" )) {
aktk 15:9b2cfbaf1c12 249 if(msger.setHeaderField("Content-Type", "text/javascript")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 250 } else if ( !strcmp(fhndl.getSuffix(), "ico" )) {
aktk 15:9b2cfbaf1c12 251 if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 252 } else if ( !strcmp(fhndl.getSuffix(), "png" ) ||
aktk 15:9b2cfbaf1c12 253 !strcmp(fhndl.getSuffix(), "PNG" )) {
aktk 15:9b2cfbaf1c12 254 if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 255 } else if ( !strcmp(fhndl.getSuffix(), "jpg" ) ||
aktk 15:9b2cfbaf1c12 256 !strcmp(fhndl.getSuffix(), "JPG" )) {
aktk 15:9b2cfbaf1c12 257 if(msger.setHeaderField("Content-Type", "image/jpg")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 258 } else {
aktk 15:9b2cfbaf1c12 259 msger.setStatusLine(406, "not acceptable");
aktk 15:9b2cfbaf1c12 260 }
aktk 15:9b2cfbaf1c12 261
aktk 15:9b2cfbaf1c12 262 // Connection timeout field
aktk 15:9b2cfbaf1c12 263 if(msger.setHeaderField("Keep-Alive", "timeouit=15")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 264
aktk 15:9b2cfbaf1c12 265 // send response
aktk 15:9b2cfbaf1c12 266 msger.sendHTTPResponse(client_socket, fhndl);
aktk 15:9b2cfbaf1c12 267
aktk 15:9b2cfbaf1c12 268 //file close
aktk 15:9b2cfbaf1c12 269 if( fhndl.close()== 0)
aktk 15:9b2cfbaf1c12 270 DEBUG_PRINT_LINE("file has closed");
aktk 15:9b2cfbaf1c12 271 else if(EOF)
aktk 15:9b2cfbaf1c12 272 DEBUG_PRINT_LINE("failed to close the file");
aktk 15:9b2cfbaf1c12 273
aktk 15:9b2cfbaf1c12 274 msger.resetHeader();
aktk 15:9b2cfbaf1c12 275 DEBUG_PRINT_LINE("echo back done.");
aktk 15:9b2cfbaf1c12 276 }
aktk 15:9b2cfbaf1c12 277 if (httpmethod == NULL) {
aktk 15:9b2cfbaf1c12 278 msger.sendHTTPResponse(client_socket);
aktk 15:9b2cfbaf1c12 279 msger.resetHeader();
aktk 15:9b2cfbaf1c12 280 DEBUG_PRINT_LINE("echo back done.");
aktk 15:9b2cfbaf1c12 281 socket_connection = false;
aktk 15:9b2cfbaf1c12 282 }
aktk 15:9b2cfbaf1c12 283 printf("(HTTP_SERVER) Response to Request has done\r\n");
aktk 16:c3920b5b8572 284
aktk 16:c3920b5b8572 285 return true;
aktk 15:9b2cfbaf1c12 286 }