HTTP File Server using SD Card for Arch Max

Dependencies:   EthernetInterface SDFileSystem mbed-rtos mbed

Fork of HTTP_SDcard_file_server by Ivan Georgiev

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "EthernetInterface.h"
00003 #include "SDFileSystem.h"
00004 
00005 #define EnDebugMSG  false //true-> print debug message to PC USB terminal, false->not print
00006 #include "filelib.h"
00007 
00008 #define IP      "192.168.100.100"
00009 #define MASK    "255.255.255.0"
00010 #define GATEWAY "192.168.100.1"
00011 #define PORT    80
00012 
00013 Serial pc (USBTX,USBRX);    // tx, rx
00014 SDFileSystem sd(SD_MOSI, SD_MISO, SD_SCK, SD_CS, "wfs"); // the pinout on the mbed
00015 
00016 char sMethod[7];
00017 char sURL[250];
00018 char sProtocol[8];
00019 
00020 EthernetInterface eth;
00021 
00022 TCPSocketServer svr;
00023 bool serverIsListened = false;
00024 
00025 TCPSocketConnection client;
00026 bool clientIsConnected = false;
00027 
00028 char sentBuffer[1608] = {}; // 2*536=1072, 3*536=1608, 4*536=2144   !1500
00029 char line_response[256]= {0};
00030 char file_path[256] = {0};
00031 
00032 DigitalOut led1(LED1); //server listning status
00033 DigitalOut led2(LED2); //socket connecting status
00034 
00035 Ticker ledTick;
00036 
00037 void ledTickfunc()
00038 {
00039     if(serverIsListened)  {
00040         led1 = !led1;
00041     } else {
00042         led1 = false;
00043     }
00044 }
00045 
00046 void send_HTTP_header(char* protocol, int code, char* title, char* mime_type, long long lengthBody)
00047 {
00048     snprintf(line_response, sizeof(line_response),"%s %d %s\r\n", protocol, code, title );
00049     snprintf(sentBuffer, sizeof(sentBuffer),"%s",line_response);
00050 
00051     if ( mime_type != NULL ) {
00052         snprintf(line_response, sizeof(line_response), "Content-Type: %s\r\n", mime_type );
00053         snprintf(sentBuffer, sizeof(sentBuffer), "%s%s",sentBuffer,line_response);    //append to sentBuffer
00054     }
00055     if ( lengthBody >= 0 ) {
00056         snprintf(line_response, sizeof(line_response), "Content-Length: %lld\r\n", lengthBody );
00057         snprintf(sentBuffer, sizeof(sentBuffer), "%s%s",sentBuffer,line_response);    //append to sentBuffer
00058     }
00059     snprintf(line_response, sizeof(line_response), "Connection: close\r\n" );
00060     snprintf(sentBuffer, sizeof(sentBuffer),"%s%s\r\n",sentBuffer,line_response);    //append to sentBuffer
00061 
00062     if (EnDebugMSG)
00063         printf("\n-->sent Header--\n");
00064 
00065     client.send_all(sentBuffer,strlen(sentBuffer));
00066     if (EnDebugMSG) {
00067         printf(sentBuffer);
00068         printf("\n--end Header-- bytes:%d",strlen(sentBuffer));
00069     }
00070     Thread::wait(200);  //200ms important for browser!
00071 }
00072 
00073 void send_HTML_line(char* line, unsigned int length_line)
00074 {
00075     client.send_all(line,length_line);
00076     if (EnDebugMSG)
00077         printf("\n-->send HTML line:\n%s ...Ok!",line);
00078     Thread::wait(10);
00079 }
00080 
00081 void send_HTML_error( int status_code, char* title, char* body_text)
00082 {
00083     send_HTTP_header("HTTP/1.1", status_code, title, "text/html", -1);
00084     if (EnDebugMSG)
00085         printf("\n-->send_error...\n");
00086     sentBuffer[0]=NULL; //clear buffer
00087     sprintf(line_response, "<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<title>%d %s</title>\r\n</head>\r\n", status_code, title);
00088     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00089     sprintf(line_response, "<body><center><h2><center>%d %s</center></h2>\r\n",status_code, title );
00090     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00091     sprintf(line_response, "%s\r\n", body_text );
00092     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00093     sprintf(line_response, "<p>mbed HTTP File Server</p>\r\n</center></body></html>\r\n");
00094     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00095     send_HTML_line(sentBuffer, strlen(sentBuffer));
00096 }
00097 
00098 int send_file(char *path_file)
00099 {
00100     char *mime_type = {0};
00101     unsigned int bytes_for_send=0;
00102     long long filesize, all_send_bytes = 0;
00103 
00104     mime_type =  get_mime_type( path_file );
00105     snprintf(file_path, sizeof(file_path),"/wfs/%s",path_file);
00106     if (EnDebugMSG) {
00107         printf("\n-->from send_file:%s",file_path);
00108         printf("\n-->from send_file mime type:%s",mime_type);
00109     }
00110 
00111     if (Mystat(path_file, &myStatBuf)) { //fault with file
00112         send_HTML_error( 403, "Forbidden", "403 - File access forbidden.");
00113         return 403;
00114     }
00115     FILE* fp = NULL;
00116     fp = fopen(file_path,"r");
00117     if (fp==NULL ) {
00118         send_HTML_error( 403, "Forbidden", "403 - File access forbidden.");
00119         return 403;
00120     }
00121 
00122     filesize = myStatBuf.st_size;
00123     send_HTTP_header("HTTP/1.1", 200, "Ok", mime_type, myStatBuf.st_size);
00124     //binary send
00125     all_send_bytes=0;
00126     while(filesize)  {  //check for EOF !feof(fp)
00127         bytes_for_send = filesize;
00128         if (bytes_for_send > sizeof(sentBuffer)) {
00129             bytes_for_send = sizeof(sentBuffer);
00130         }
00131         fread (sentBuffer,1,bytes_for_send,fp);
00132         filesize -= bytes_for_send;
00133         if (EnDebugMSG)
00134             printf("\n---bytes_for_send...%d",bytes_for_send);
00135         client.send_all(sentBuffer,bytes_for_send);
00136         //Thread::wait(10);
00137         all_send_bytes += bytes_for_send;
00138     }
00139     if (EnDebugMSG)
00140         printf("\n---buffer fill end - all ...%lld", all_send_bytes);
00141     //binary send
00142 
00143     sprintf(line_response, "\r\n");
00144     client.send_all(line_response,strlen(line_response));
00145     if ( fp != NULL )
00146         fclose(fp);
00147     //Thread::wait(10);
00148     return 0;
00149 }
00150 
00151 int send_directory(char *path)
00152 {
00153     char process_name[64]= {0};
00154 
00155     char posOfLastSlash;
00156     char *pLS;
00157 
00158     struct dirent *p;
00159     struct sMystat sb;
00160     struct tm *timeinfo;
00161     char timeBuf[40];
00162 
00163     if (EnDebugMSG)
00164         printf("\n-->from send_directory:%s",path);
00165     snprintf(file_path,sizeof(file_path),"/wfs%s",path);
00166     DIR *d = opendir(file_path);
00167     if (EnDebugMSG && d!=NULL)
00168         printf("\n-->from send_directory:%s ...open OK",file_path);
00169     if (d==NULL) {   //error open dir
00170         send_HTML_error( 403, "Forbidden", "403 - Directory access forbidden.");
00171         return -1;
00172     }
00173     send_HTTP_header("HTTP/1.1", 200, "Ok",NULL, -1);
00174     sentBuffer[0]=NULL;
00175     sprintf(line_response,"<!DOCTYPE html>\r\n<html>\n<head><title>Index of %s</title>\n",path);
00176     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00177 
00178     sprintf(line_response,"<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\"></head>\n");
00179     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00180 
00181 
00182     sprintf(line_response,"<body><center>\n<h3>Index of %s</h3>\n", path);
00183     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00184     send_HTML_line(sentBuffer, strlen(sentBuffer));
00185 //begin table
00186     sentBuffer[0]=NULL; //clear buffer
00187     sprintf(line_response,"<table border=\"0\">\n");
00188     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00189     sprintf(line_response,"<tr><th align=\"left\" width=\"200\">Name</th><th align=\"right\" width=\"100\">Size(bytes)</th><th align=\"right\" width=\"200\">Date/Time</th></tr>\n");
00190     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00191 //begin table
00192 
00193     pLS=strrchr(path,'/');
00194     posOfLastSlash=pLS-path+1;
00195     if (EnDebugMSG)
00196         printf("\r\n>>posOfLastSlash=%d",posOfLastSlash);
00197     snprintf(process_name,posOfLastSlash+1,"%s",path);
00198     if (EnDebugMSG)
00199         printf("\r\n>>process_name=%s",process_name);
00200     sprintf(line_response,"<tr><td align=\"left\"><a href=\"%s\">../</a></td></tr>\n",process_name);
00201     snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00202     while((p = readdir(d)) != NULL) {
00203         if (EnDebugMSG)
00204             printf("\n   :%s",p->d_name);
00205         sprintf(file_path,"%s/%s",path,p->d_name);
00206         Mystat( file_path, &sb );
00207         if (get_dirInfo(file_path)==0 ) { //this is directory path
00208             if (EnDebugMSG)
00209                 printf("\nDIR");
00210             sprintf(line_response, "<tr><td align=\"left\"><a href=\"%s\">%s</a><br></td></tr>\n",file_path,p->d_name);
00211             if (strlen(line_response)>(sizeof(sentBuffer)-strlen(sentBuffer))) { //buffer must be sent
00212                 send_HTML_line(sentBuffer, strlen(sentBuffer));
00213                 sentBuffer[0]=NULL; //clear buffer
00214             }
00215             snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00216 
00217         } else {    //this is file
00218             if (EnDebugMSG)
00219                 printf("\nFILE");
00220             timeinfo = localtime (&sb.st_mtime);
00221             //strftime(timeBuf,40, "%I:%M:%S %p (%Y/%m/%d)\r\n", localtime(&sb.st_mtime));
00222             strftime(timeBuf, 40, "%c", timeinfo);
00223             sprintf(line_response, "<tr><td align=\"left\"><a href=\"%s\">%s</a></td><td align=\"right\">%lld</td><td align=\"right\">%s</td></tr>\n", file_path, p->d_name,(long long) sb.st_size,timeBuf);    // asctime(timeinfo) );
00224 
00225             if (strlen(line_response)>(sizeof(sentBuffer)-strlen(sentBuffer))) { //buffer must be sent
00226                 send_HTML_line(sentBuffer, strlen(sentBuffer));
00227                 sentBuffer[0]=NULL; //clear buffer
00228             }
00229             snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer
00230         }
00231     }
00232     send_HTML_line(sentBuffer, strlen(sentBuffer));
00233     closedir(d);
00234 
00235     sprintf(line_response, "</table>\n<br><h4>mbed HTTP File Server</h4>\n</center></body></html>\n");
00236     send_HTML_line(line_response, strlen(line_response));
00237 
00238     return 0;
00239 }
00240 
00241 void parseHTTPRequest(char* buffer)
00242 {
00243     char spacePos;
00244     char *tmpBuffer;
00245     spacePos = strcspn(buffer, " ") + 1;   //position of first space character
00246     snprintf(sMethod, spacePos,"%s", buffer);
00247 
00248     //get Protocol
00249     tmpBuffer=&(buffer[spacePos]);   //move pointer to buffer (delete Method)
00250     spacePos = strcspn(tmpBuffer, "\r\n") + 1;
00251     tmpBuffer[spacePos]='\0';    //set end of string ...cut
00252     sprintf(sProtocol, "%s", strrchr(tmpBuffer,' '));  //get string after last (space )
00253     printf("\r\nsProtocol:%s", tmpBuffer);
00254     buffer = &(sProtocol[1]);  //cut first character (space)
00255     sprintf(sProtocol, "%s", buffer);
00256 
00257     //get URL
00258     snprintf(sURL,strlen(tmpBuffer)-strlen(sProtocol),"%s\r\n", tmpBuffer);   //URL is between Method and Protocol
00259 
00260     printf("\nParse Method:%s",sMethod);
00261     printf("\nParse URL:%s",sURL);
00262     printf("\nParse PROTOCOL:%s",sProtocol);
00263     printf("\n\r\n");
00264 }
00265 
00266 int processHTTP(char* sMethod, char* sURL, char* sProtocol)
00267 {
00268     int gdi, gfi;   //status of get_dir_info(xxx), and get_file_info(xxx)
00269 
00270     if (strcmp(sMethod,"GET")!=0) {
00271         send_HTML_error( 501, "501 Not Implemented", "501 - The server either does not recognize the request method");
00272         return 501;
00273     }
00274     if (sURL[0]!= '/') {
00275         send_HTML_error( 400, "Bad Request", "400 - The request cannot be fulfilled due to bad syntax.");
00276         return 400;
00277     }
00278     if (sURL[strlen(sURL)-1]=='/') {
00279         sURL[strlen(sURL)-1]=sURL[strlen(sURL)];  //delete last symbol
00280         if (EnDebugMSG)
00281             printf("\n delete last:%s",sURL);
00282     }
00283     gdi= get_dirInfo(sURL);
00284     gfi= get_fileInfo(sURL);
00285     if (gfi!=0) {   //!=0 file not found
00286         if (gdi==0) { //0-ok this is directory
00287             return send_directory(sURL);
00288         }
00289         if (EnDebugMSG)
00290             printf("\n404-br File not found or...(Fresult is:%d)",gfi);
00291         send_HTML_error( 404, "Not Found","404 - The requested resource could not be found.");
00292         return 404;
00293     } else {    //==0  found
00294         if (gdi==0)  //0-ok this is directory
00295             return send_directory(sURL);
00296         else
00297             return send_file(sURL);
00298     }
00299 }
00300 
00301 int main()
00302 {
00303     printf("\r\n---- HTTP Server ----\r\n");
00304 
00305     ledTick.attach(&ledTickfunc,0.5);
00306     //ledTick.detach();
00307     //setup ethernet interface
00308     eth.init(); //Use DHCP
00309     // eth.init(IP,MASK,GATEWAY);  //IP,mask,Gateway
00310     eth.connect();
00311     printf("IP Address is %s\n\r", eth.getIPAddress());
00312 
00313     //setup tcp socket
00314     if(svr.bind(PORT)< 0) {
00315         printf("tcp server bind failed.\n\r");
00316         return -1;
00317     } else {
00318         printf("tcp server bind successed.\n\r");
00319         serverIsListened = true;
00320     }
00321 
00322     if(svr.listen(1) < 0) {
00323         printf("tcp server listen failed.\n\r");
00324         return -1;
00325     } else {
00326         printf("tcp server is listening...\n\r");
00327     }
00328 
00329     //listening for http GET request
00330     while (serverIsListened) {
00331         //blocking mode(never timeout)
00332         if(svr.accept(client)<0) {
00333             printf("failed to accept connection.\n\r");
00334         } else {
00335             //client.set_blocking(false,5000);    //5000=5sec
00336             printf("connection success!\n\rIP: %s\n\r",client.get_address());
00337             clientIsConnected = true;
00338             led2 = true;
00339             while(clientIsConnected) {
00340                 char buffer[1024] = {};
00341                 switch(client.receive(buffer, 1023)) {
00342                     case 0:
00343                         printf("recieved buffer is empty.\n\r");
00344                         clientIsConnected = false;
00345                         break;
00346                     case -1:
00347                         printf("failed to read data from client.\n\r");
00348                         clientIsConnected = false;
00349                         break;
00350                     default:
00351                         printf("Recieved Data: %d\n\r\n\r%.*s\n\r",strlen(buffer),strlen(buffer),buffer);
00352                         parseHTTPRequest(buffer);
00353                         //if(buffer[0] == 'G' && buffer[1] == 'E' && buffer[2] == 'T' ) {
00354                         if (strcmp(sMethod, "GET" ) == 0 ) {
00355                             printf("GET request incomming.\n\r");
00356                             processHTTP(sMethod, sURL, sProtocol);
00357                             clientIsConnected = false;
00358                         }//if get
00359                         break;
00360                 }   //switch
00361                 //ledTick.attach(&ledTickfunc,0.5);
00362             }//while
00363             printf("close connection.\n\rHTTP server is listening...\n\r\n");
00364             client.close();
00365             Thread::wait(50);
00366             led2 = false;
00367         }
00368     }
00369 
00370 }