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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTP_SERVER.cpp Source File

HTTP_SERVER.cpp

00001 #include "HTTP_SERVER.h"
00002 #include "string"
00003 //#ifndef HTTP_SERVER_DEBUG
00004 #define HTTP_SERVER_DEBUG
00005 //#endif
00006 /*
00007 LOG:
00008 "sys_thread_new number error" is occurred when an instance of this class is instantiated in main() in main.cpp
00009 This case wasn't occured with the APIs of mbed os 2.
00010 So, inserting some DEBUG_PRINT_LINE, and finding where is wrong.
00011 
00012 The error seems to be occurred in init() in the above case.
00013 
00014 TCP_PORT=80 redefine
00015 tcp_port->port
00016 
00017 The error seems to be occurred while ethernet->connect() is proceesing.
00018 
00019 The error seems to be caused by something wrong with stack.
00020 When modify (char* -> char) req_buf[1024] in the .h file,
00021 the error message became: "CMSIS-RTOS error: Stack underflow (status: 0x1, task ID: 0x10002678, task name: )"
00022 UNDERFLOW means that there is a value which is too fine(or high definition) to express.
00023 (Why was the type char*?)
00024 
00025 (char)req_buf[1024] was not uesed anywhere...
00026 so it was deleted.
00027 
00028 (bool)keep-alive was also not uesed so deleted it.
00029 
00030 After doing those above, the error massage was DERAYED but
00031 it even now occur.
00032 and when some array stack(such like char buffer[1024] -> [256])'s size was decreased,
00033 the message was more derayed.
00034 Therefore it can be thought that the error is causeed by stack overflow.
00035 */
00036 
00037 namespace HTTP_SERVER
00038 {
00039 void DEBUG_PRINT_NAME()
00040 {
00041 #ifdef HTTP_SERVER_DEBUG
00042     printf("(DEBUG LINE: HTTP_SERVER) ");
00043 #endif
00044 }
00045 
00046 void DEBUG_PRINT_LINE(const char* arg_line)
00047 {
00048 #ifdef HTTP_SERVER_DEBUG
00049     DEBUG_PRINT_NAME();
00050     printf(arg_line);
00051     printf("\r\n");
00052 #endif
00053 }
00054 template<typename T>
00055 void DEBUG_PRINT_LINE(const char* arg_line, T arg_t)
00056 {
00057 #ifdef HTTP_SERVER_DEBUG
00058     DEBUG_PRINT_NAME();
00059     printf(arg_line, arg_t);
00060     printf("\r\n");
00061 #endif
00062 }
00063 template<typename T1, typename T2>
00064 void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2)
00065 {
00066 #ifdef HTTP_SERVER_DEBUG
00067     DEBUG_PRINT_NAME();
00068     printf(arg_line, arg_t1, arg_t2);
00069     printf("\r\n");
00070 #endif
00071 }
00072 }
00073 using namespace HTTP_SERVER;
00074 
00075 HttpServer::HttpServer()
00076 {
00077     DEBUG_PRINT_LINE("=DEBUG MODE=");
00078     net = new EthernetInterface();
00079     port = TCP_PORT;
00080     backlog  = 1;
00081     //keep_alive = (false);
00082     listening_flag = (false);
00083     socket_connection = false;
00084     DEBUG_PRINT_LINE("A HTTP_SERVER has been inistantiated.");
00085 }
00086 
00087 HttpServer::~HttpServer()
00088 {
00089 }
00090 
00091 bool HttpServer::init()
00092 {
00093     DEBUG_PRINT_LINE("The HTTP SERVER is being initiated");
00094     //  Ethernet Initialization
00095     //  Ethernet Connecting setup
00096     if(net->connect()) {
00097         printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n");
00098         return false;
00099     } else {
00100         printf("(HTTP_SERVER) IP Address is %s\r\n", net->get_ip_address());
00101     }
00102 
00103     ftest.func();
00104     //  TCP Socket setup
00105     //  To open Server-side PORT
00106     if(server.open(net) < 0) {
00107         printf("(HTTP_SERVER) Error!@TCPSocketServer::open()\r\n");
00108         return false;
00109     } else {
00110         printf("(HTTP_SERVER) TCP Server has successfully opened\r\n");
00111     }
00112     if(server.bind(port)< 0) {
00113         printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
00114         return false;
00115     } else {
00116         printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
00117     }
00118     //  Server start listening Request from a web browser.
00119     if(server.listen(backlog) < 0) {
00120         printf("(HTTP_SERVER) tcp server listen failed.\r\n");
00121         return false;
00122     } else {
00123         listening_flag = true;
00124         printf("(HTTP_SERVER) tcp server is listening...\r\n");
00125     }
00126 
00127     return true;
00128 }
00129 
00130 bool HttpServer::run()
00131 {
00132 
00133     DigitalOut led1(LED1);
00134     DigitalOut led2(LED1);
00135 
00136 
00137     DEBUG_PRINT_LINE("The HTTP SERVER is starting running");
00138     while (listening_flag) {
00139         led1 = true;
00140         //  blocking mode (never timeout)
00141         //  waiting client connection
00142         printf("(HTTP_SERVER) waiting connection\r\n");
00143         if(server.accept(&client_socket, &client_address) < 0) {
00144             printf("(HTTP_SERVER) failed to accept connection.\r\n");
00145             return -1;
00146         } else {
00147             printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",client_address.get_ip_address());
00148             socket_connection = true;
00149             led2 = true;
00150         }
00151         //  When conected
00152         while (socket_connection) {
00153             printf("(HTTP_SERVER) connected\r\n");
00154 
00155             char buffer[1024]   = {0};
00156             char* httpmethod    = NULL;
00157             char* filepath      = NULL;
00158             char* http_ver      = NULL;
00159             //char* header_field_name = NULL;
00160             //char* header_field_val  = NULL;
00161 
00162             //
00163             //  Request Analysis
00164             //
00165             printf("(HTTP_SERVER) Request Analysis\r\n");
00166             analyzeRequest(buffer, 1023, httpmethod, filepath, http_ver);
00167             DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
00168             DEBUG_PRINT_LINE("file path:  %s", filepath);
00169             DEBUG_PRINT_LINE("http ver :  %s", http_ver);
00170             //
00171             //  Response
00172             //
00173             sendResponse(httpmethod, filepath, http_ver);
00174             //
00175             //
00176             //
00177         }
00178         printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
00179         client_socket.close();
00180         led2 = false;
00181     }
00182     server.close();
00183     listening_flag = false;
00184     led1 = false;
00185     return 0;
00186 
00187 }
00188 
00189 bool HttpServer::analyzeRequest(char* buffer, int buffer_size, char* &httpmethod, char* &filepath, char* &http_ver)
00190 {
00191 
00192     DEBUG_PRINT_LINE("Request Analysis");
00193     switch(client_socket.recv(buffer, buffer_size)) {
00194         case 0:
00195             DEBUG_PRINT_LINE("recieved buffer is empty.");
00196             msger.setStatusLine(400, "No Request");
00197             if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00198             httpmethod    = NULL;
00199             filepath      = NULL;
00200             http_ver      = NULL;
00201             socket_connection = false;
00202             break;
00203         case -1:
00204             DEBUG_PRINT_LINE("failed to read data from client.");
00205             msger.setStatusLine(500, "Internal Server Error");
00206             if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00207             httpmethod    = NULL;
00208             filepath      = NULL;
00209             http_ver      = NULL;
00210             socket_connection = false;
00211             break;
00212         default:
00213             DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer));
00214             DEBUG_PRINT_LINE("-->\r\n");
00215             DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
00216             //  get HTTP method, File path, HTTP version
00217             httpmethod = strtok(buffer," ");
00218             filepath = strtok(NULL, " ");
00219             http_ver = strtok(NULL, "\r\n");
00220             break;
00221     }
00222     return true;
00223 }
00224 
00225 bool HttpServer::sendResponse(char* httpmethod, char* filepath, char* http_ver)
00226 {
00227     if (strcmp(httpmethod,"GET") == 0 ) {
00228         DEBUG_PRINT_LINE("GET request incomming.");
00229 
00230         //  file calibration
00231         DEBUG_PRINT_LINE("file opening");
00232         DEBUG_PRINT_LINE("filepath: %s", filepath);
00233         fhndl.open(filepath,"rb");
00234         if(fhndl.arrival()) {
00235             msger.setStatusLine(200, "OK");
00236             if(msger.setHeaderField("Content-Length", fhndl.getFileSize()))     DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00237             if(msger.setHeaderField("Connection", "keep-alive"))                DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00238         } else {
00239             if(msger.setStatusLine(404, "NOT FOUND"))                           DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00240             if(msger.setHeaderField("Connection", "Close"))                     DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00241             DEBUG_PRINT_LINE("NOT FOUND");
00242         }
00243         if(         !strcmp(fhndl.getSuffix(), "htm" ) ||
00244                     !strcmp(fhndl.getSuffix(), "HTM" ) ||
00245                     !strcmp(fhndl.getSuffix(), "html") ||
00246                     !strcmp(fhndl.getSuffix(), "HTML")) {
00247             if(msger.setHeaderField("Content-Type", "text/html"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00248         } else if(  !strcmp(fhndl.getSuffix(), "js"  )) {
00249             if(msger.setHeaderField("Content-Type", "text/javascript"))         DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00250         } else if ( !strcmp(fhndl.getSuffix(), "ico" )) {
00251             if(msger.setHeaderField("Content-Type", "image/png"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00252         } else if ( !strcmp(fhndl.getSuffix(), "png" ) ||
00253                     !strcmp(fhndl.getSuffix(), "PNG" )) {
00254             if(msger.setHeaderField("Content-Type", "image/png"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00255         } else if ( !strcmp(fhndl.getSuffix(), "jpg" ) ||
00256                     !strcmp(fhndl.getSuffix(), "JPG" )) {
00257             if(msger.setHeaderField("Content-Type", "image/jpg"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00258         } else {
00259             msger.setStatusLine(406, "not acceptable");
00260         }
00261 
00262         //  Connection timeout field
00263         if(msger.setHeaderField("Keep-Alive", "timeouit=15"))                   DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
00264 
00265         //  send response
00266         msger.sendHTTPResponse(client_socket, fhndl);
00267 
00268         //file close
00269         if( fhndl.close()== 0)
00270             DEBUG_PRINT_LINE("file has closed");
00271         else if(EOF)
00272             DEBUG_PRINT_LINE("failed to close the file");
00273 
00274         msger.resetHeader();
00275         DEBUG_PRINT_LINE("echo back done.");
00276     }
00277     if (httpmethod == NULL) {
00278         msger.sendHTTPResponse(client_socket);
00279         msger.resetHeader();
00280         DEBUG_PRINT_LINE("echo back done.");
00281         socket_connection = false;
00282     }
00283     printf("(HTTP_SERVER) Response to Request has done\r\n");
00284     
00285     return true;
00286 }