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@13:483b2b1a6471, 2018-03-04 (annotated)
- Committer:
- aktk
- Date:
- Sun Mar 04 19:08:36 2018 +0000
- Revision:
- 13:483b2b1a6471
- Parent:
- 12:c926d680f339
- Child:
- 14:a16cdcd098d7
add (int) backlog; add (uint16_t) tcp_port; rm enum{TCP_PORT}
Who changed what in which revision?
User | Revision | Line number | New 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 | 10:4a48594c2f44 | 4 | //#define DEBUG |
aktk | 8:b013075de2e4 | 5 | #endif |
aktk | 1:3a1fe94c6e42 | 6 | |
aktk | 10:4a48594c2f44 | 7 | namespace HTTP_SERVER |
aktk | 10:4a48594c2f44 | 8 | { |
aktk | 1:3a1fe94c6e42 | 9 | void DEBUG_PRINT_LINE(const char* arg_line) |
aktk | 1:3a1fe94c6e42 | 10 | { |
aktk | 12:c926d680f339 | 11 | #ifdef HTTP_SERVER_DEBUG |
aktk | 10:4a48594c2f44 | 12 | printf("(HTTP_SERVER) ") |
aktk | 10:4a48594c2f44 | 13 | printf(arg_line); |
aktk | 10:4a48594c2f44 | 14 | printf("\r\n"); |
aktk | 1:3a1fe94c6e42 | 15 | #endif |
aktk | 1:3a1fe94c6e42 | 16 | } |
aktk | 10:4a48594c2f44 | 17 | template<typename T> |
aktk | 10:4a48594c2f44 | 18 | void DEBUG_PRINT_LINE(const char* arg_line, T arg_t) |
aktk | 10:4a48594c2f44 | 19 | { |
aktk | 12:c926d680f339 | 20 | #ifdef HTTP_SERVER_DEBUG |
aktk | 10:4a48594c2f44 | 21 | printf("(HTTP_SERVER) "); |
aktk | 10:4a48594c2f44 | 22 | printf(arg_line, arg_t); |
aktk | 10:4a48594c2f44 | 23 | printf("\r\n"); |
aktk | 10:4a48594c2f44 | 24 | #endif |
aktk | 10:4a48594c2f44 | 25 | } |
aktk | 10:4a48594c2f44 | 26 | template<typename T1, typename T2> |
aktk | 10:4a48594c2f44 | 27 | void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2) |
aktk | 10:4a48594c2f44 | 28 | { |
aktk | 12:c926d680f339 | 29 | #ifdef HTTP_SERVER_DEBUG |
aktk | 10:4a48594c2f44 | 30 | printf("(HTTP_SERVER) "); |
aktk | 10:4a48594c2f44 | 31 | printf(arg_line, arg_t1, arg_t2); |
aktk | 10:4a48594c2f44 | 32 | printf("\r\n"); |
aktk | 10:4a48594c2f44 | 33 | #endif |
aktk | 10:4a48594c2f44 | 34 | } |
aktk | 10:4a48594c2f44 | 35 | } |
aktk | 10:4a48594c2f44 | 36 | using namespace HTTP_SERVER; |
aktk | 1:3a1fe94c6e42 | 37 | |
aktk | 0:cc483bea4fe3 | 38 | HttpServer::HttpServer() |
aktk | 0:cc483bea4fe3 | 39 | { |
aktk | 0:cc483bea4fe3 | 40 | keep_alive = (false); |
aktk | 0:cc483bea4fe3 | 41 | listening_flag = (false); |
aktk | 0:cc483bea4fe3 | 42 | req_buf[0] = '\0'; |
aktk | 13:483b2b1a6471 | 43 | tcp_port = 80; |
aktk | 13:483b2b1a6471 | 44 | backlog = 1; |
aktk | 0:cc483bea4fe3 | 45 | } |
aktk | 0:cc483bea4fe3 | 46 | |
aktk | 0:cc483bea4fe3 | 47 | HttpServer::~HttpServer() |
aktk | 0:cc483bea4fe3 | 48 | { |
aktk | 0:cc483bea4fe3 | 49 | } |
aktk | 0:cc483bea4fe3 | 50 | |
aktk | 0:cc483bea4fe3 | 51 | bool HttpServer::init() |
aktk | 0:cc483bea4fe3 | 52 | { |
aktk | 0:cc483bea4fe3 | 53 | |
aktk | 0:cc483bea4fe3 | 54 | // Ethernet Initialization |
aktk | 0:cc483bea4fe3 | 55 | // Ethernet Connecting setup |
aktk | 12:c926d680f339 | 56 | if(net.connect()) { |
aktk | 1:3a1fe94c6e42 | 57 | printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n"); |
aktk | 0:cc483bea4fe3 | 58 | return false; |
aktk | 0:cc483bea4fe3 | 59 | } else { |
aktk | 12:c926d680f339 | 60 | printf("(HTTP_SERVER) IP Address is %s\r\n", net.getIPAddress()); |
aktk | 0:cc483bea4fe3 | 61 | } |
aktk | 0:cc483bea4fe3 | 62 | // TCP Socket setup |
aktk | 0:cc483bea4fe3 | 63 | // To open Server-side PORT |
aktk | 13:483b2b1a6471 | 64 | if(server.bind(tcp_port)< 0) { |
aktk | 1:3a1fe94c6e42 | 65 | printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n"); |
aktk | 0:cc483bea4fe3 | 66 | return false; |
aktk | 0:cc483bea4fe3 | 67 | } else { |
aktk | 1:3a1fe94c6e42 | 68 | printf("(HTTP_SERVER) TCP Server has bounden!\r\n"); |
aktk | 0:cc483bea4fe3 | 69 | } |
aktk | 0:cc483bea4fe3 | 70 | // Server start listening Request from a web browser. |
aktk | 13:483b2b1a6471 | 71 | if(server.listen(backlog) < 0) { |
aktk | 1:3a1fe94c6e42 | 72 | printf("(HTTP_SERVER) tcp server listen failed.\r\n"); |
aktk | 0:cc483bea4fe3 | 73 | return false; |
aktk | 0:cc483bea4fe3 | 74 | } else { |
aktk | 0:cc483bea4fe3 | 75 | listening_flag = true; |
aktk | 1:3a1fe94c6e42 | 76 | printf("(HTTP_SERVER) tcp server is listening...\r\n"); |
aktk | 0:cc483bea4fe3 | 77 | } |
aktk | 0:cc483bea4fe3 | 78 | |
aktk | 0:cc483bea4fe3 | 79 | return true; |
aktk | 0:cc483bea4fe3 | 80 | } |
aktk | 0:cc483bea4fe3 | 81 | |
aktk | 0:cc483bea4fe3 | 82 | bool HttpServer::run() |
aktk | 0:cc483bea4fe3 | 83 | { |
aktk | 0:cc483bea4fe3 | 84 | DigitalOut led1(LED1); |
aktk | 0:cc483bea4fe3 | 85 | DigitalOut led2(LED1); |
aktk | 0:cc483bea4fe3 | 86 | |
aktk | 0:cc483bea4fe3 | 87 | while (listening_flag) { |
aktk | 0:cc483bea4fe3 | 88 | led1 = true; |
aktk | 0:cc483bea4fe3 | 89 | // blocking mode (never timeout) |
aktk | 0:cc483bea4fe3 | 90 | // waiting client connection |
aktk | 1:3a1fe94c6e42 | 91 | printf("(HTTP_SERVER) waiting connection\r\n"); |
aktk | 12:c926d680f339 | 92 | if(server.accept(tcpcon) < 0) { |
aktk | 1:3a1fe94c6e42 | 93 | printf("(HTTP_SERVER) failed to accept connection.\r\n"); |
aktk | 0:cc483bea4fe3 | 94 | return -1; |
aktk | 0:cc483bea4fe3 | 95 | } else { |
aktk | 12:c926d680f339 | 96 | printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",client.get_address()); |
aktk | 0:cc483bea4fe3 | 97 | led2 = true; |
aktk | 0:cc483bea4fe3 | 98 | } |
aktk | 1:3a1fe94c6e42 | 99 | // When conected |
aktk | 12:c926d680f339 | 100 | while(client.is_connected()) { |
aktk | 10:4a48594c2f44 | 101 | printf("(HTTP_SERVER) connected\r\n"); |
aktk | 1:3a1fe94c6e42 | 102 | |
aktk | 0:cc483bea4fe3 | 103 | char buffer[1024] = {0}; |
aktk | 0:cc483bea4fe3 | 104 | char* httpmethod = NULL; |
aktk | 0:cc483bea4fe3 | 105 | char* filepath = NULL; |
aktk | 0:cc483bea4fe3 | 106 | char* http_ver = NULL; |
aktk | 0:cc483bea4fe3 | 107 | char* header_field_name = NULL; |
aktk | 0:cc483bea4fe3 | 108 | char* header_field_val = NULL; |
aktk | 1:3a1fe94c6e42 | 109 | |
aktk | 0:cc483bea4fe3 | 110 | // |
aktk | 0:cc483bea4fe3 | 111 | // Request Analysis |
aktk | 0:cc483bea4fe3 | 112 | // |
aktk | 10:4a48594c2f44 | 113 | DEBUG_PRINT_LINE("DEBUG MODE"); |
aktk | 12:c926d680f339 | 114 | switch(client.receive(buffer, 1023)) { |
aktk | 0:cc483bea4fe3 | 115 | case 0: |
aktk | 10:4a48594c2f44 | 116 | DEBUG_PRINT_LINE("recieved buffer is empty."); |
aktk | 0:cc483bea4fe3 | 117 | msger.setStatusLine(400, "No Request"); |
aktk | 10:4a48594c2f44 | 118 | if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 0:cc483bea4fe3 | 119 | httpmethod = NULL; |
aktk | 0:cc483bea4fe3 | 120 | filepath = NULL; |
aktk | 0:cc483bea4fe3 | 121 | http_ver = NULL; |
aktk | 0:cc483bea4fe3 | 122 | break; |
aktk | 0:cc483bea4fe3 | 123 | case -1: |
aktk | 10:4a48594c2f44 | 124 | DEBUG_PRINT_LINE("failed to read data from client."); |
aktk | 0:cc483bea4fe3 | 125 | msger.setStatusLine(500, "Internal Server Error"); |
aktk | 10:4a48594c2f44 | 126 | if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 0:cc483bea4fe3 | 127 | httpmethod = NULL; |
aktk | 0:cc483bea4fe3 | 128 | filepath = NULL; |
aktk | 0:cc483bea4fe3 | 129 | http_ver = NULL; |
aktk | 0:cc483bea4fe3 | 130 | break; |
aktk | 0:cc483bea4fe3 | 131 | default: |
aktk | 10:4a48594c2f44 | 132 | DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer)); |
aktk | 10:4a48594c2f44 | 133 | DEBUG_PRINT_LINE("-->\r\n"); |
aktk | 10:4a48594c2f44 | 134 | DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer); |
aktk | 10:4a48594c2f44 | 135 | // get HTTP method, File path, HTTP version |
aktk | 0:cc483bea4fe3 | 136 | httpmethod = strtok(buffer," "); |
aktk | 0:cc483bea4fe3 | 137 | filepath = strtok(NULL, " "); |
aktk | 0:cc483bea4fe3 | 138 | http_ver = strtok(NULL, "\r\n"); |
aktk | 10:4a48594c2f44 | 139 | DEBUG_PRINT_LINE("httpmethod: %s", httpmethod); |
aktk | 10:4a48594c2f44 | 140 | DEBUG_PRINT_LINE("file path: %s", filepath); |
aktk | 10:4a48594c2f44 | 141 | DEBUG_PRINT_LINE("http ver : %s", http_ver); |
aktk | 0:cc483bea4fe3 | 142 | break; |
aktk | 0:cc483bea4fe3 | 143 | } |
aktk | 1:3a1fe94c6e42 | 144 | |
aktk | 0:cc483bea4fe3 | 145 | // |
aktk | 0:cc483bea4fe3 | 146 | // Response |
aktk | 0:cc483bea4fe3 | 147 | // |
aktk | 0:cc483bea4fe3 | 148 | if (strcmp(httpmethod,"GET") == 0 ) { |
aktk | 10:4a48594c2f44 | 149 | DEBUG_PRINT_LINE("GET request incomming."); |
aktk | 0:cc483bea4fe3 | 150 | |
aktk | 0:cc483bea4fe3 | 151 | // file calibration |
aktk | 10:4a48594c2f44 | 152 | DEBUG_PRINT_LINE("file opening"); |
aktk | 0:cc483bea4fe3 | 153 | fhandl.open(filepath,"rb"); |
aktk | 0:cc483bea4fe3 | 154 | if(fhandl.arrival()) { |
aktk | 0:cc483bea4fe3 | 155 | msger.setStatusLine(200, "OK"); |
aktk | 10:4a48594c2f44 | 156 | if(msger.setHeaderField("Content-Length", fhandl.getFileSize())) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 157 | if(msger.setHeaderField("Connection", "keep-alive")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 0:cc483bea4fe3 | 158 | } else { |
aktk | 10:4a48594c2f44 | 159 | if(msger.setStatusLine(404, "NOT FOUND")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 160 | if(msger.setHeaderField("Connection", "Close")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 161 | DEBUG_PRINT_LINE("NOT FOUND"); |
aktk | 0:cc483bea4fe3 | 162 | } |
aktk | 10:4a48594c2f44 | 163 | if( !strcmp(fhandl.getSuffix(), "htm" ) || |
aktk | 10:4a48594c2f44 | 164 | !strcmp(fhandl.getSuffix(), "HTM" ) || |
aktk | 10:4a48594c2f44 | 165 | !strcmp(fhandl.getSuffix(), "html") || |
aktk | 10:4a48594c2f44 | 166 | !strcmp(fhandl.getSuffix(), "HTML")){ |
aktk | 10:4a48594c2f44 | 167 | if(msger.setHeaderField("Content-Type", "text/html")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 168 | } else if( !strcmp(fhandl.getSuffix(), "js" )){ |
aktk | 10:4a48594c2f44 | 169 | if(msger.setHeaderField("Content-Type", "text/javascript")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 170 | } else if ( !strcmp(fhandl.getSuffix(), "ico" )){ |
aktk | 10:4a48594c2f44 | 171 | if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 172 | } else if ( !strcmp(fhandl.getSuffix(), "png" ) || |
aktk | 10:4a48594c2f44 | 173 | !strcmp(fhandl.getSuffix(), "PNG" )){ |
aktk | 10:4a48594c2f44 | 174 | if(msger.setHeaderField("Content-Type", "image/png")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 10:4a48594c2f44 | 175 | } else if ( !strcmp(fhandl.getSuffix(), "jpg" ) || |
aktk | 10:4a48594c2f44 | 176 | !strcmp(fhandl.getSuffix(), "JPG" )){ |
aktk | 10:4a48594c2f44 | 177 | if(msger.setHeaderField("Content-Type", "image/jpg")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 0:cc483bea4fe3 | 178 | } else { |
aktk | 0:cc483bea4fe3 | 179 | msger.setStatusLine(406, "not acceptable"); |
aktk | 0:cc483bea4fe3 | 180 | } |
aktk | 0:cc483bea4fe3 | 181 | |
aktk | 0:cc483bea4fe3 | 182 | // Connection timeout field |
aktk | 10:4a48594c2f44 | 183 | if(msger.setHeaderField("Keep-Alive", "timeouit=15")) DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 1:3a1fe94c6e42 | 184 | |
aktk | 0:cc483bea4fe3 | 185 | // send response |
aktk | 0:cc483bea4fe3 | 186 | msger.sendHTTPResponse(tcpcon, fhandl); |
aktk | 0:cc483bea4fe3 | 187 | |
aktk | 0:cc483bea4fe3 | 188 | //file close |
aktk | 7:184c6f1ace94 | 189 | if( fhandl.close()== 0) |
aktk | 10:4a48594c2f44 | 190 | DEBUG_PRINT_LINE("file has closed"); |
aktk | 0:cc483bea4fe3 | 191 | else if(EOF) |
aktk | 10:4a48594c2f44 | 192 | DEBUG_PRINT_LINE("failed to close the file"); |
aktk | 7:184c6f1ace94 | 193 | |
aktk | 7:184c6f1ace94 | 194 | msger.resetHeader(); |
aktk | 10:4a48594c2f44 | 195 | DEBUG_PRINT_LINE("echo back done."); |
aktk | 7:184c6f1ace94 | 196 | } |
aktk | 7:184c6f1ace94 | 197 | if (httpmethod == NULL) { |
aktk | 7:184c6f1ace94 | 198 | msger.sendHTTPResponse(tcpcon); |
aktk | 0:cc483bea4fe3 | 199 | msger.resetHeader(); |
aktk | 10:4a48594c2f44 | 200 | DEBUG_PRINT_LINE("echo back done."); |
aktk | 0:cc483bea4fe3 | 201 | } |
aktk | 1:3a1fe94c6e42 | 202 | printf("(HTTP_SERVER) Response to Request has done\r\n"); |
aktk | 7:184c6f1ace94 | 203 | // |
aktk | 7:184c6f1ace94 | 204 | // |
aktk | 7:184c6f1ace94 | 205 | // |
aktk | 0:cc483bea4fe3 | 206 | } |
aktk | 1:3a1fe94c6e42 | 207 | printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n"); |
aktk | 12:c926d680f339 | 208 | client.close(); |
aktk | 0:cc483bea4fe3 | 209 | led2 = false; |
aktk | 0:cc483bea4fe3 | 210 | } |
aktk | 12:c926d680f339 | 211 | server.close(); |
aktk | 7:184c6f1ace94 | 212 | listening_flag = false; |
aktk | 0:cc483bea4fe3 | 213 | led1 = false; |
aktk | 0:cc483bea4fe3 | 214 | return 0; |
aktk | 0:cc483bea4fe3 | 215 | } |