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 16 23:17:28 2018 +0000
Revision:
15:9b2cfbaf1c12
Parent:
14:a16cdcd098d7
Child:
16:c3920b5b8572
Defined functions for procedures of "Request Analysis" and "Response"

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 12:c926d680f339 3 #ifndef HTTP_SERVER_DEBUG
aktk 14:a16cdcd098d7 4 #define HTTP_SERVER_DEBUG
aktk 8:b013075de2e4 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 14:a16cdcd098d7 25 char req_buf[1024] was not uesed anywhere...
aktk 14:a16cdcd098d7 26 so it was deleted.
aktk 14:a16cdcd098d7 27
aktk 14:a16cdcd098d7 28 bool deep-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 0:cc483bea4fe3 103 // TCP Socket setup
aktk 0:cc483bea4fe3 104 // To open Server-side PORT
aktk 14:a16cdcd098d7 105 if(server.open(net) < 0) {
aktk 14:a16cdcd098d7 106 printf("(HTTP_SERVER) Error!@TCPSocketServer::open()\r\n");
aktk 14:a16cdcd098d7 107 return false;
aktk 14:a16cdcd098d7 108 } else {
aktk 14:a16cdcd098d7 109 printf("(HTTP_SERVER) TCP Server has successfully opened\r\n");
aktk 14:a16cdcd098d7 110 }
aktk 14:a16cdcd098d7 111 if(server.bind(port)< 0) {
aktk 1:3a1fe94c6e42 112 printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
aktk 0:cc483bea4fe3 113 return false;
aktk 0:cc483bea4fe3 114 } else {
aktk 1:3a1fe94c6e42 115 printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
aktk 0:cc483bea4fe3 116 }
aktk 0:cc483bea4fe3 117 // Server start listening Request from a web browser.
aktk 13:483b2b1a6471 118 if(server.listen(backlog) < 0) {
aktk 1:3a1fe94c6e42 119 printf("(HTTP_SERVER) tcp server listen failed.\r\n");
aktk 0:cc483bea4fe3 120 return false;
aktk 0:cc483bea4fe3 121 } else {
aktk 0:cc483bea4fe3 122 listening_flag = true;
aktk 1:3a1fe94c6e42 123 printf("(HTTP_SERVER) tcp server is listening...\r\n");
aktk 0:cc483bea4fe3 124 }
aktk 15:9b2cfbaf1c12 125
aktk 0:cc483bea4fe3 126 return true;
aktk 0:cc483bea4fe3 127 }
aktk 0:cc483bea4fe3 128
aktk 0:cc483bea4fe3 129 bool HttpServer::run()
aktk 0:cc483bea4fe3 130 {
aktk 15:9b2cfbaf1c12 131
aktk 0:cc483bea4fe3 132 DigitalOut led1(LED1);
aktk 0:cc483bea4fe3 133 DigitalOut led2(LED1);
aktk 0:cc483bea4fe3 134
aktk 14:a16cdcd098d7 135
aktk 14:a16cdcd098d7 136 DEBUG_PRINT_LINE("The HTTP SERVER is starting running");
aktk 0:cc483bea4fe3 137 while (listening_flag) {
aktk 0:cc483bea4fe3 138 led1 = true;
aktk 0:cc483bea4fe3 139 // blocking mode (never timeout)
aktk 0:cc483bea4fe3 140 // waiting client connection
aktk 1:3a1fe94c6e42 141 printf("(HTTP_SERVER) waiting connection\r\n");
aktk 14:a16cdcd098d7 142 if(server.accept(&client_socket, &client_address) < 0) {
aktk 1:3a1fe94c6e42 143 printf("(HTTP_SERVER) failed to accept connection.\r\n");
aktk 0:cc483bea4fe3 144 return -1;
aktk 0:cc483bea4fe3 145 } else {
aktk 14:a16cdcd098d7 146 printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",client_address.get_ip_address());
aktk 14:a16cdcd098d7 147 socket_connection = true;
aktk 0:cc483bea4fe3 148 led2 = true;
aktk 0:cc483bea4fe3 149 }
aktk 1:3a1fe94c6e42 150 // When conected
aktk 14:a16cdcd098d7 151 while (socket_connection) {
aktk 10:4a48594c2f44 152 printf("(HTTP_SERVER) connected\r\n");
aktk 1:3a1fe94c6e42 153
aktk 14:a16cdcd098d7 154 char buffer[256] = {0};
aktk 0:cc483bea4fe3 155 char* httpmethod = NULL;
aktk 0:cc483bea4fe3 156 char* filepath = NULL;
aktk 0:cc483bea4fe3 157 char* http_ver = NULL;
aktk 15:9b2cfbaf1c12 158 //char* header_field_name = NULL;
aktk 15:9b2cfbaf1c12 159 //char* header_field_val = NULL;
aktk 1:3a1fe94c6e42 160
aktk 0:cc483bea4fe3 161 //
aktk 0:cc483bea4fe3 162 // Request Analysis
aktk 0:cc483bea4fe3 163 //
aktk 15:9b2cfbaf1c12 164 analyzeRequest(buffer, 255, httpmethod, filepath, http_ver);
aktk 0:cc483bea4fe3 165 //
aktk 0:cc483bea4fe3 166 // Response
aktk 0:cc483bea4fe3 167 //
aktk 15:9b2cfbaf1c12 168 sendResponse(httpmethod, filepath, http_ver);
aktk 7:184c6f1ace94 169 //
aktk 7:184c6f1ace94 170 //
aktk 7:184c6f1ace94 171 //
aktk 0:cc483bea4fe3 172 }
aktk 1:3a1fe94c6e42 173 printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
aktk 14:a16cdcd098d7 174 client_socket.close();
aktk 0:cc483bea4fe3 175 led2 = false;
aktk 0:cc483bea4fe3 176 }
aktk 12:c926d680f339 177 server.close();
aktk 7:184c6f1ace94 178 listening_flag = false;
aktk 0:cc483bea4fe3 179 led1 = false;
aktk 0:cc483bea4fe3 180 return 0;
aktk 15:9b2cfbaf1c12 181
aktk 15:9b2cfbaf1c12 182 }
aktk 15:9b2cfbaf1c12 183
aktk 15:9b2cfbaf1c12 184 bool HttpServer::analyzeRequest(char* buffer, int buffer_size, char* httpmethod, char* filepath, char* http_ver)
aktk 15:9b2cfbaf1c12 185 {
aktk 15:9b2cfbaf1c12 186
aktk 15:9b2cfbaf1c12 187 DEBUG_PRINT_LINE("Request Analysis");
aktk 15:9b2cfbaf1c12 188 switch(client_socket.recv(buffer, buffer_size)) {
aktk 15:9b2cfbaf1c12 189 case 0:
aktk 15:9b2cfbaf1c12 190 DEBUG_PRINT_LINE("recieved buffer is empty.");
aktk 15:9b2cfbaf1c12 191 msger.setStatusLine(400, "No Request");
aktk 15:9b2cfbaf1c12 192 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 193 httpmethod = NULL;
aktk 15:9b2cfbaf1c12 194 filepath = NULL;
aktk 15:9b2cfbaf1c12 195 http_ver = NULL;
aktk 15:9b2cfbaf1c12 196 socket_connection = false;
aktk 15:9b2cfbaf1c12 197 break;
aktk 15:9b2cfbaf1c12 198 case -1:
aktk 15:9b2cfbaf1c12 199 DEBUG_PRINT_LINE("failed to read data from client.");
aktk 15:9b2cfbaf1c12 200 msger.setStatusLine(500, "Internal Server Error");
aktk 15:9b2cfbaf1c12 201 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 202 httpmethod = NULL;
aktk 15:9b2cfbaf1c12 203 filepath = NULL;
aktk 15:9b2cfbaf1c12 204 http_ver = NULL;
aktk 15:9b2cfbaf1c12 205 socket_connection = false;
aktk 15:9b2cfbaf1c12 206 break;
aktk 15:9b2cfbaf1c12 207 default:
aktk 15:9b2cfbaf1c12 208 DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer));
aktk 15:9b2cfbaf1c12 209 DEBUG_PRINT_LINE("-->\r\n");
aktk 15:9b2cfbaf1c12 210 DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
aktk 15:9b2cfbaf1c12 211 // get HTTP method, File path, HTTP version
aktk 15:9b2cfbaf1c12 212 httpmethod = strtok(buffer," ");
aktk 15:9b2cfbaf1c12 213 filepath = strtok(NULL, " ");
aktk 15:9b2cfbaf1c12 214 http_ver = strtok(NULL, "\r\n");
aktk 15:9b2cfbaf1c12 215 DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
aktk 15:9b2cfbaf1c12 216 DEBUG_PRINT_LINE("file path: %s", filepath);
aktk 15:9b2cfbaf1c12 217 DEBUG_PRINT_LINE("http ver : %s", http_ver);
aktk 15:9b2cfbaf1c12 218 break;
aktk 15:9b2cfbaf1c12 219 }
aktk 15:9b2cfbaf1c12 220 return true;
aktk 14:a16cdcd098d7 221 }
aktk 15:9b2cfbaf1c12 222
aktk 15:9b2cfbaf1c12 223 bool HttpServer::sendResponse(char* httpmethod, char*filepath, char* http_ver)
aktk 15:9b2cfbaf1c12 224 {
aktk 15:9b2cfbaf1c12 225 if (strcmp(httpmethod,"GET") == 0 ) {
aktk 15:9b2cfbaf1c12 226 DEBUG_PRINT_LINE("GET request incomming.");
aktk 15:9b2cfbaf1c12 227
aktk 15:9b2cfbaf1c12 228 // file calibration
aktk 15:9b2cfbaf1c12 229 DEBUG_PRINT_LINE("file opening");
aktk 15:9b2cfbaf1c12 230 fhndl.open(filepath,"rb");
aktk 15:9b2cfbaf1c12 231 if(fhndl.arrival()) {
aktk 15:9b2cfbaf1c12 232 msger.setStatusLine(200, "OK");
aktk 15:9b2cfbaf1c12 233 if(msger.setHeaderField("Content-Length", fhndl.getFileSize())) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 234 if(msger.setHeaderField("Connection", "keep-alive")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 235 } else {
aktk 15:9b2cfbaf1c12 236 if(msger.setStatusLine(404, "NOT FOUND")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 237 if(msger.setHeaderField("Connection", "Close")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 238 DEBUG_PRINT_LINE("NOT FOUND");
aktk 15:9b2cfbaf1c12 239 }
aktk 15:9b2cfbaf1c12 240 if( !strcmp(fhndl.getSuffix(), "htm" ) ||
aktk 15:9b2cfbaf1c12 241 !strcmp(fhndl.getSuffix(), "HTM" ) ||
aktk 15:9b2cfbaf1c12 242 !strcmp(fhndl.getSuffix(), "html") ||
aktk 15:9b2cfbaf1c12 243 !strcmp(fhndl.getSuffix(), "HTML")) {
aktk 15:9b2cfbaf1c12 244 if(msger.setHeaderField("Content-Type", "text/html")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 245 } else if( !strcmp(fhndl.getSuffix(), "js" )) {
aktk 15:9b2cfbaf1c12 246 if(msger.setHeaderField("Content-Type", "text/javascript")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 247 } else if ( !strcmp(fhndl.getSuffix(), "ico" )) {
aktk 15:9b2cfbaf1c12 248 if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 249 } else if ( !strcmp(fhndl.getSuffix(), "png" ) ||
aktk 15:9b2cfbaf1c12 250 !strcmp(fhndl.getSuffix(), "PNG" )) {
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(), "jpg" ) ||
aktk 15:9b2cfbaf1c12 253 !strcmp(fhndl.getSuffix(), "JPG" )) {
aktk 15:9b2cfbaf1c12 254 if(msger.setHeaderField("Content-Type", "image/jpg")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 255 } else {
aktk 15:9b2cfbaf1c12 256 msger.setStatusLine(406, "not acceptable");
aktk 15:9b2cfbaf1c12 257 }
aktk 15:9b2cfbaf1c12 258
aktk 15:9b2cfbaf1c12 259 // Connection timeout field
aktk 15:9b2cfbaf1c12 260 if(msger.setHeaderField("Keep-Alive", "timeouit=15")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 15:9b2cfbaf1c12 261
aktk 15:9b2cfbaf1c12 262 // send response
aktk 15:9b2cfbaf1c12 263 msger.sendHTTPResponse(client_socket, fhndl);
aktk 15:9b2cfbaf1c12 264
aktk 15:9b2cfbaf1c12 265 //file close
aktk 15:9b2cfbaf1c12 266 if( fhndl.close()== 0)
aktk 15:9b2cfbaf1c12 267 DEBUG_PRINT_LINE("file has closed");
aktk 15:9b2cfbaf1c12 268 else if(EOF)
aktk 15:9b2cfbaf1c12 269 DEBUG_PRINT_LINE("failed to close the file");
aktk 15:9b2cfbaf1c12 270
aktk 15:9b2cfbaf1c12 271 msger.resetHeader();
aktk 15:9b2cfbaf1c12 272 DEBUG_PRINT_LINE("echo back done.");
aktk 15:9b2cfbaf1c12 273 }
aktk 15:9b2cfbaf1c12 274 if (httpmethod == NULL) {
aktk 15:9b2cfbaf1c12 275 msger.sendHTTPResponse(client_socket);
aktk 15:9b2cfbaf1c12 276 msger.resetHeader();
aktk 15:9b2cfbaf1c12 277 DEBUG_PRINT_LINE("echo back done.");
aktk 15:9b2cfbaf1c12 278 socket_connection = false;
aktk 15:9b2cfbaf1c12 279 }
aktk 15:9b2cfbaf1c12 280 printf("(HTTP_SERVER) Response to Request has done\r\n");
aktk 15:9b2cfbaf1c12 281 }