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 22:45:47 2018 +0000
Revision:
14:a16cdcd098d7
Parent:
13:483b2b1a6471
Child:
15:9b2cfbaf1c12
"sys_thread_new number error"; TCP_PORT=80 redefine; tcp_port->port; char req_buf[] was not uesed, so deleted.; bool keep-alive was not uesed, so deleted.; stack size changed (char buffer[1024->256]); The error could be caused by stack overflow.

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 14:a16cdcd098d7 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 14:a16cdcd098d7 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 14:a16cdcd098d7 83 DEBUG_PRINT_LINE("A HTTP_SERVER has been inistantiated.");
aktk 0:cc483bea4fe3 84 }
aktk 0:cc483bea4fe3 85
aktk 0:cc483bea4fe3 86 HttpServer::~HttpServer()
aktk 0:cc483bea4fe3 87 {
aktk 0:cc483bea4fe3 88 }
aktk 0:cc483bea4fe3 89
aktk 0:cc483bea4fe3 90 bool HttpServer::init()
aktk 14:a16cdcd098d7 91 {
aktk 14:a16cdcd098d7 92 DEBUG_PRINT_LINE("The HTTP SERVER is being initiated");
aktk 14:a16cdcd098d7 93 // Ethernet Initialization
aktk 0:cc483bea4fe3 94 // Ethernet Connecting setup
aktk 14:a16cdcd098d7 95 if(net->connect()) {
aktk 1:3a1fe94c6e42 96 printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n");
aktk 0:cc483bea4fe3 97 return false;
aktk 0:cc483bea4fe3 98 } else {
aktk 14:a16cdcd098d7 99 printf("(HTTP_SERVER) IP Address is %s\r\n", net->get_ip_address());
aktk 0:cc483bea4fe3 100 }
aktk 14:a16cdcd098d7 101
aktk 0:cc483bea4fe3 102 // TCP Socket setup
aktk 0:cc483bea4fe3 103 // To open Server-side PORT
aktk 14:a16cdcd098d7 104 if(server.open(net) < 0) {
aktk 14:a16cdcd098d7 105 printf("(HTTP_SERVER) Error!@TCPSocketServer::open()\r\n");
aktk 14:a16cdcd098d7 106 return false;
aktk 14:a16cdcd098d7 107 } else {
aktk 14:a16cdcd098d7 108 printf("(HTTP_SERVER) TCP Server has successfully opened\r\n");
aktk 14:a16cdcd098d7 109 }
aktk 14:a16cdcd098d7 110 if(server.bind(port)< 0) {
aktk 1:3a1fe94c6e42 111 printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
aktk 0:cc483bea4fe3 112 return false;
aktk 0:cc483bea4fe3 113 } else {
aktk 1:3a1fe94c6e42 114 printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
aktk 0:cc483bea4fe3 115 }
aktk 0:cc483bea4fe3 116 // Server start listening Request from a web browser.
aktk 13:483b2b1a6471 117 if(server.listen(backlog) < 0) {
aktk 1:3a1fe94c6e42 118 printf("(HTTP_SERVER) tcp server listen failed.\r\n");
aktk 0:cc483bea4fe3 119 return false;
aktk 0:cc483bea4fe3 120 } else {
aktk 0:cc483bea4fe3 121 listening_flag = true;
aktk 1:3a1fe94c6e42 122 printf("(HTTP_SERVER) tcp server is listening...\r\n");
aktk 0:cc483bea4fe3 123 }
aktk 14:a16cdcd098d7 124
aktk 0:cc483bea4fe3 125 return true;
aktk 0:cc483bea4fe3 126 }
aktk 0:cc483bea4fe3 127
aktk 0:cc483bea4fe3 128 bool HttpServer::run()
aktk 0:cc483bea4fe3 129 {
aktk 14:a16cdcd098d7 130
aktk 0:cc483bea4fe3 131 DigitalOut led1(LED1);
aktk 0:cc483bea4fe3 132 DigitalOut led2(LED1);
aktk 14:a16cdcd098d7 133 bool socket_connection = false;
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 0:cc483bea4fe3 158 char* header_field_name = NULL;
aktk 0:cc483bea4fe3 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 14:a16cdcd098d7 164 DEBUG_PRINT_LINE("DEBUG MODE@Request Analysis");
aktk 14:a16cdcd098d7 165 switch(client_socket.recv(buffer, 255)) {
aktk 0:cc483bea4fe3 166 case 0:
aktk 10:4a48594c2f44 167 DEBUG_PRINT_LINE("recieved buffer is empty.");
aktk 0:cc483bea4fe3 168 msger.setStatusLine(400, "No Request");
aktk 10:4a48594c2f44 169 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 0:cc483bea4fe3 170 httpmethod = NULL;
aktk 0:cc483bea4fe3 171 filepath = NULL;
aktk 0:cc483bea4fe3 172 http_ver = NULL;
aktk 14:a16cdcd098d7 173 socket_connection = false;
aktk 0:cc483bea4fe3 174 break;
aktk 0:cc483bea4fe3 175 case -1:
aktk 10:4a48594c2f44 176 DEBUG_PRINT_LINE("failed to read data from client.");
aktk 0:cc483bea4fe3 177 msger.setStatusLine(500, "Internal Server Error");
aktk 10:4a48594c2f44 178 if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 0:cc483bea4fe3 179 httpmethod = NULL;
aktk 0:cc483bea4fe3 180 filepath = NULL;
aktk 0:cc483bea4fe3 181 http_ver = NULL;
aktk 14:a16cdcd098d7 182 socket_connection = false;
aktk 0:cc483bea4fe3 183 break;
aktk 0:cc483bea4fe3 184 default:
aktk 10:4a48594c2f44 185 DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer));
aktk 10:4a48594c2f44 186 DEBUG_PRINT_LINE("-->\r\n");
aktk 10:4a48594c2f44 187 DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
aktk 10:4a48594c2f44 188 // get HTTP method, File path, HTTP version
aktk 0:cc483bea4fe3 189 httpmethod = strtok(buffer," ");
aktk 0:cc483bea4fe3 190 filepath = strtok(NULL, " ");
aktk 0:cc483bea4fe3 191 http_ver = strtok(NULL, "\r\n");
aktk 10:4a48594c2f44 192 DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
aktk 10:4a48594c2f44 193 DEBUG_PRINT_LINE("file path: %s", filepath);
aktk 10:4a48594c2f44 194 DEBUG_PRINT_LINE("http ver : %s", http_ver);
aktk 0:cc483bea4fe3 195 break;
aktk 0:cc483bea4fe3 196 }
aktk 1:3a1fe94c6e42 197
aktk 0:cc483bea4fe3 198 //
aktk 0:cc483bea4fe3 199 // Response
aktk 0:cc483bea4fe3 200 //
aktk 0:cc483bea4fe3 201 if (strcmp(httpmethod,"GET") == 0 ) {
aktk 10:4a48594c2f44 202 DEBUG_PRINT_LINE("GET request incomming.");
aktk 0:cc483bea4fe3 203
aktk 0:cc483bea4fe3 204 // file calibration
aktk 10:4a48594c2f44 205 DEBUG_PRINT_LINE("file opening");
aktk 14:a16cdcd098d7 206 fhndl.open(filepath,"rb");
aktk 14:a16cdcd098d7 207 if(fhndl.arrival()) {
aktk 0:cc483bea4fe3 208 msger.setStatusLine(200, "OK");
aktk 14:a16cdcd098d7 209 if(msger.setHeaderField("Content-Length", fhndl.getFileSize())) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 10:4a48594c2f44 210 if(msger.setHeaderField("Connection", "keep-alive")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 0:cc483bea4fe3 211 } else {
aktk 10:4a48594c2f44 212 if(msger.setStatusLine(404, "NOT FOUND")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 10:4a48594c2f44 213 if(msger.setHeaderField("Connection", "Close")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 10:4a48594c2f44 214 DEBUG_PRINT_LINE("NOT FOUND");
aktk 0:cc483bea4fe3 215 }
aktk 14:a16cdcd098d7 216 if( !strcmp(fhndl.getSuffix(), "htm" ) ||
aktk 14:a16cdcd098d7 217 !strcmp(fhndl.getSuffix(), "HTM" ) ||
aktk 14:a16cdcd098d7 218 !strcmp(fhndl.getSuffix(), "html") ||
aktk 14:a16cdcd098d7 219 !strcmp(fhndl.getSuffix(), "HTML")) {
aktk 10:4a48594c2f44 220 if(msger.setHeaderField("Content-Type", "text/html")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 14:a16cdcd098d7 221 } else if( !strcmp(fhndl.getSuffix(), "js" )) {
aktk 10:4a48594c2f44 222 if(msger.setHeaderField("Content-Type", "text/javascript")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 14:a16cdcd098d7 223 } else if ( !strcmp(fhndl.getSuffix(), "ico" )) {
aktk 10:4a48594c2f44 224 if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 14:a16cdcd098d7 225 } else if ( !strcmp(fhndl.getSuffix(), "png" ) ||
aktk 14:a16cdcd098d7 226 !strcmp(fhndl.getSuffix(), "PNG" )) {
aktk 10:4a48594c2f44 227 if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 14:a16cdcd098d7 228 } else if ( !strcmp(fhndl.getSuffix(), "jpg" ) ||
aktk 14:a16cdcd098d7 229 !strcmp(fhndl.getSuffix(), "JPG" )) {
aktk 10:4a48594c2f44 230 if(msger.setHeaderField("Content-Type", "image/jpg")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 0:cc483bea4fe3 231 } else {
aktk 0:cc483bea4fe3 232 msger.setStatusLine(406, "not acceptable");
aktk 0:cc483bea4fe3 233 }
aktk 0:cc483bea4fe3 234
aktk 0:cc483bea4fe3 235 // Connection timeout field
aktk 10:4a48594c2f44 236 if(msger.setHeaderField("Keep-Alive", "timeouit=15")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
aktk 1:3a1fe94c6e42 237
aktk 0:cc483bea4fe3 238 // send response
aktk 14:a16cdcd098d7 239 msger.sendHTTPResponse(client_socket, fhndl);
aktk 0:cc483bea4fe3 240
aktk 0:cc483bea4fe3 241 //file close
aktk 14:a16cdcd098d7 242 if( fhndl.close()== 0)
aktk 10:4a48594c2f44 243 DEBUG_PRINT_LINE("file has closed");
aktk 0:cc483bea4fe3 244 else if(EOF)
aktk 10:4a48594c2f44 245 DEBUG_PRINT_LINE("failed to close the file");
aktk 14:a16cdcd098d7 246
aktk 7:184c6f1ace94 247 msger.resetHeader();
aktk 10:4a48594c2f44 248 DEBUG_PRINT_LINE("echo back done.");
aktk 7:184c6f1ace94 249 }
aktk 7:184c6f1ace94 250 if (httpmethod == NULL) {
aktk 14:a16cdcd098d7 251 msger.sendHTTPResponse(client_socket);
aktk 0:cc483bea4fe3 252 msger.resetHeader();
aktk 10:4a48594c2f44 253 DEBUG_PRINT_LINE("echo back done.");
aktk 14:a16cdcd098d7 254 socket_connection = false;
aktk 0:cc483bea4fe3 255 }
aktk 1:3a1fe94c6e42 256 printf("(HTTP_SERVER) Response to Request has done\r\n");
aktk 7:184c6f1ace94 257 //
aktk 7:184c6f1ace94 258 //
aktk 7:184c6f1ace94 259 //
aktk 0:cc483bea4fe3 260 }
aktk 1:3a1fe94c6e42 261 printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
aktk 14:a16cdcd098d7 262 client_socket.close();
aktk 0:cc483bea4fe3 263 led2 = false;
aktk 0:cc483bea4fe3 264 }
aktk 12:c926d680f339 265 server.close();
aktk 7:184c6f1ace94 266 listening_flag = false;
aktk 0:cc483bea4fe3 267 led1 = false;
aktk 0:cc483bea4fe3 268 return 0;
aktk 14:a16cdcd098d7 269
aktk 14:a16cdcd098d7 270 }