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
HTTP_SERVER.cpp
- Committer:
- aktk
- Date:
- 2018-03-19
- Revision:
- 16:c3920b5b8572
- Parent:
- 15:9b2cfbaf1c12
- Child:
- 17:ce5845164001
File content as of revision 16:c3920b5b8572:
#include "HTTP_SERVER.h" #include "string" //#ifndef HTTP_SERVER_DEBUG #define HTTP_SERVER_DEBUG //#endif /* LOG: "sys_thread_new number error" is occurred when an instance of this class is instantiated in main() in main.cpp This case wasn't occured with the APIs of mbed os 2. So, inserting some DEBUG_PRINT_LINE, and finding where is wrong. The error seems to be occurred in init() in the above case. TCP_PORT=80 redefine tcp_port->port The error seems to be occurred while ethernet->connect() is proceesing. The error seems to be caused by something wrong with stack. When modify (char* -> char) req_buf[1024] in the .h file, the error message became: "CMSIS-RTOS error: Stack underflow (status: 0x1, task ID: 0x10002678, task name: )" UNDERFLOW means that there is a value which is too fine(or high definition) to express. (Why was the type char*?) char req_buf[1024] was not uesed anywhere... so it was deleted. bool keep-alive was also not uesed so deleted it. After doing those above, the error massage was DERAYED but it even now occur. and when some array stack(such like char buffer[1024] -> [256])'s size was decreased, the message was more derayed. Therefore it can be thought that the error is causeed by stack overflow. */ namespace HTTP_SERVER { void DEBUG_PRINT_NAME() { #ifdef HTTP_SERVER_DEBUG printf("(DEBUG LINE: HTTP_SERVER) "); #endif } void DEBUG_PRINT_LINE(const char* arg_line) { #ifdef HTTP_SERVER_DEBUG DEBUG_PRINT_NAME(); printf(arg_line); printf("\r\n"); #endif } template<typename T> void DEBUG_PRINT_LINE(const char* arg_line, T arg_t) { #ifdef HTTP_SERVER_DEBUG DEBUG_PRINT_NAME(); printf(arg_line, arg_t); printf("\r\n"); #endif } template<typename T1, typename T2> void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2) { #ifdef HTTP_SERVER_DEBUG DEBUG_PRINT_NAME(); printf(arg_line, arg_t1, arg_t2); printf("\r\n"); #endif } } using namespace HTTP_SERVER; HttpServer::HttpServer() { DEBUG_PRINT_LINE("=DEBUG MODE="); net = new EthernetInterface(); port = TCP_PORT; backlog = 1; //keep_alive = (false); listening_flag = (false); socket_connection = false; DEBUG_PRINT_LINE("A HTTP_SERVER has been inistantiated."); } HttpServer::~HttpServer() { } bool HttpServer::init() { DEBUG_PRINT_LINE("The HTTP SERVER is being initiated"); // Ethernet Initialization // Ethernet Connecting setup if(net->connect()) { printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n"); return false; } else { printf("(HTTP_SERVER) IP Address is %s\r\n", net->get_ip_address()); } // TCP Socket setup // To open Server-side PORT if(server.open(net) < 0) { printf("(HTTP_SERVER) Error!@TCPSocketServer::open()\r\n"); return false; } else { printf("(HTTP_SERVER) TCP Server has successfully opened\r\n"); } if(server.bind(port)< 0) { printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n"); return false; } else { printf("(HTTP_SERVER) TCP Server has bounden!\r\n"); } // Server start listening Request from a web browser. if(server.listen(backlog) < 0) { printf("(HTTP_SERVER) tcp server listen failed.\r\n"); return false; } else { listening_flag = true; printf("(HTTP_SERVER) tcp server is listening...\r\n"); } return true; } bool HttpServer::run() { DigitalOut led1(LED1); DigitalOut led2(LED1); DEBUG_PRINT_LINE("The HTTP SERVER is starting running"); while (listening_flag) { led1 = true; // blocking mode (never timeout) // waiting client connection printf("(HTTP_SERVER) waiting connection\r\n"); if(server.accept(&client_socket, &client_address) < 0) { printf("(HTTP_SERVER) failed to accept connection.\r\n"); return -1; } else { printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",client_address.get_ip_address()); socket_connection = true; led2 = true; } // When conected while (socket_connection) { printf("(HTTP_SERVER) connected\r\n"); char buffer[1024] = {0}; char* httpmethod = NULL; char* filepath = NULL; char* http_ver = NULL; //char* header_field_name = NULL; //char* header_field_val = NULL; // // Request Analysis // printf("(HTTP_SERVER) Request Analysis\r\n"); analyzeRequest(buffer, 1023, httpmethod, filepath, http_ver); DEBUG_PRINT_LINE("httpmethod: %s", httpmethod); DEBUG_PRINT_LINE("file path: %s", filepath); DEBUG_PRINT_LINE("http ver : %s", http_ver); // // Response // sendResponse(httpmethod, filepath, http_ver); // // // } printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n"); client_socket.close(); led2 = false; } server.close(); listening_flag = false; led1 = false; return 0; } bool HttpServer::analyzeRequest(char* buffer, int buffer_size, char* &httpmethod, char* &filepath, char* &http_ver) { DEBUG_PRINT_LINE("Request Analysis"); switch(client_socket.recv(buffer, buffer_size)) { case 0: DEBUG_PRINT_LINE("recieved buffer is empty."); msger.setStatusLine(400, "No Request"); if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); httpmethod = NULL; filepath = NULL; http_ver = NULL; socket_connection = false; break; case -1: DEBUG_PRINT_LINE("failed to read data from client."); msger.setStatusLine(500, "Internal Server Error"); if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); httpmethod = NULL; filepath = NULL; http_ver = NULL; socket_connection = false; break; default: DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer)); DEBUG_PRINT_LINE("-->\r\n"); DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer); // get HTTP method, File path, HTTP version httpmethod = strtok(buffer," "); filepath = strtok(NULL, " "); http_ver = strtok(NULL, "\r\n"); break; } return true; } bool HttpServer::sendResponse(char* httpmethod, char* filepath, char* http_ver) { if (strcmp(httpmethod,"GET") == 0 ) { DEBUG_PRINT_LINE("GET request incomming."); // file calibration DEBUG_PRINT_LINE("file opening"); DEBUG_PRINT_LINE("filepath: %s", filepath); fhndl.open(filepath,"rb");///////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(fhndl.arrival()) { msger.setStatusLine(200, "OK"); if(msger.setHeaderField("Content-Length", fhndl.getFileSize())) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); if(msger.setHeaderField("Connection", "keep-alive")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else { if(msger.setStatusLine(404, "NOT FOUND")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); if(msger.setHeaderField("Connection", "Close")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); DEBUG_PRINT_LINE("NOT FOUND"); } if( !strcmp(fhndl.getSuffix(), "htm" ) || !strcmp(fhndl.getSuffix(), "HTM" ) || !strcmp(fhndl.getSuffix(), "html") || !strcmp(fhndl.getSuffix(), "HTML")) { if(msger.setHeaderField("Content-Type", "text/html")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else if( !strcmp(fhndl.getSuffix(), "js" )) { if(msger.setHeaderField("Content-Type", "text/javascript")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else if ( !strcmp(fhndl.getSuffix(), "ico" )) { if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else if ( !strcmp(fhndl.getSuffix(), "png" ) || !strcmp(fhndl.getSuffix(), "PNG" )) { if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else if ( !strcmp(fhndl.getSuffix(), "jpg" ) || !strcmp(fhndl.getSuffix(), "JPG" )) { if(msger.setHeaderField("Content-Type", "image/jpg")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); } else { msger.setStatusLine(406, "not acceptable"); } // Connection timeout field if(msger.setHeaderField("Keep-Alive", "timeouit=15")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); // send response msger.sendHTTPResponse(client_socket, fhndl); //file close if( fhndl.close()== 0) DEBUG_PRINT_LINE("file has closed"); else if(EOF) DEBUG_PRINT_LINE("failed to close the file"); msger.resetHeader(); DEBUG_PRINT_LINE("echo back done."); } if (httpmethod == NULL) { msger.sendHTTPResponse(client_socket); msger.resetHeader(); DEBUG_PRINT_LINE("echo back done."); socket_connection = false; } printf("(HTTP_SERVER) Response to Request has done\r\n"); return true; }