Definition in file BasicWEB.c.
#include <stdio.h>
#include <string.h>
#include "conf_eth.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "serial.h"
#include "portmacro.h"
#include "lwip/api.h"
#include "lwip/tcpip.h"
#include "lwip/memp.h"
#include "lwip/stats.h"
#include "netif/loopif.h"
#include "ctrl_access.h"
#include "fsaccess.h"
#include "config_file.h"
#include "ethernet.h"
#include "supervisor.h"
#include "shell.h"
#include "datalog.h"
#include "defaultpage.htm.h"
#include "tracedump.h"
#include "BasicWEB.h"
Go to the source code of this file.
Defines | |
#define | ERR_BUFFER_SIZE 512 |
#define | ERR_DIR "errors" |
#define | HTTP_CONFIG_FILE "A:/CFG/http.txt" |
#define | webCONN_TIMEOUT 5000 |
#define | webHTTP_CONNECTION_PRIORITY (CTRLPANEL_WEB_SERVER_PRIORITY+1) |
#define | webHTTP_CONNECTION_STACK_SIZE 384 |
#define | webHTTP_NB_CONN 1 |
#define | webHTTP_PORT ( 80 ) |
#define | webMAX_DATA_TO_SEND webNB_SECTOR_TO_SEND * FS_SIZE_OF_SECTOR |
#define | webNB_SECTOR_TO_SEND 4 |
#define | webSERVER_FOLDER "A:/WEB/" |
#define | webSERVER_PROTOCOL "HTTP/1.1" |
#define | webSERVER_SOFTWARE "AVR32 UC3 WEB SERVER" |
#define | webSHORT_DELAY ( 10 ) |
Typedefs | |
typedef ssize_t(* | pf_read_src )(int fd, void *buf, size_t count) |
Functions | |
eExecStatus | e_webserver_cmd_get_config (eModId xModId, signed short FsNavId, int ac, signed portCHAR *av[], signed portCHAR **ppcStringReply) |
The get webserver config command: get the config fields value of http port Takes no parameter. | |
eExecStatus | e_webserver_cmd_set_config (eModId xModId, signed short FsNavId, int ac, signed portCHAR *av[], signed portCHAR **ppcStringReply) |
The set webserver config command: set the http port. Takes one parameter : port=ppppp. | |
portTASK_FUNCTION (prvweb_ProcessSingleConnection, pvParameters) | |
process an incoming connection parse the request and close/delete the connection | |
portTASK_FUNCTION (vBasicWEBServer, pvParameters) | |
WEB server main task check for incoming connection and process it. | |
portTASK_FUNCTION_PROTO (prvweb_ProcessSingleConnection, pvParameters) | |
static unsigned portLONG | prulweb_BuildErrorBody (portCHAR *response, int s, char *title, const char *text) |
build the static error page body | |
static unsigned portLONG | prulweb_BuildErrorTail (portCHAR *response) |
build the static error page tail | |
static unsigned portLONG | prulweb_BuildHeaders (portCHAR *response, int s, char *title, char *extra_header, char *me, char *mt) |
build the HTTP header | |
static ssize_t | prv_read_default_page (int fd, void *buf, size_t count) |
Copy part of the Default html page to another buffer. | |
static void | prvweb_ParseCGIRequest (struct netconn *pxNetCon, char *request) |
parse the CGI request and send it to the shell | |
static void | prvweb_ParseHTMLRequest (struct netconn *pxNetCon) |
parse the incoming request parse the HTML request and send file or execute CGI request | |
static void | prvweb_SendErrorPage (struct netconn *pxNetCon, int s, char *extra_header, const char *text) |
send the static error page | |
static void | prvweb_SendFile (struct netconn *pxNetCon, char *filename) |
parse the file request and send the requested file to the host | |
Variables | |
static portSHORT | sCurrentNbHTTPConn = 0 |
xTaskHandle | tTaskHandle [webHTTP_NB_CONN] = { NULL } |
static unsigned int | webHttpPort = 0 |
static size_t | x_default_page_len |
xSemaphoreHandle | xCFGMutex |
The CFG system mutex. | |
static xSemaphoreHandle | xMutexNbHTTPConn |
xSemaphoreHandle | xWEBMutex |
#define ERR_BUFFER_SIZE 512 |
The error buffer size for error page
Definition at line 142 of file BasicWEB.c.
Referenced by prvweb_SendErrorPage().
#define ERR_DIR "errors" |
Definition at line 120 of file BasicWEB.c.
#define HTTP_CONFIG_FILE "A:/CFG/http.txt" |
The config file location
Definition at line 139 of file BasicWEB.c.
Referenced by e_webserver_cmd_set_config(), and portTASK_FUNCTION().
#define webCONN_TIMEOUT 5000 |
The max timeout before killing all pending tasks (ms)
Definition at line 151 of file BasicWEB.c.
#define webHTTP_CONNECTION_PRIORITY (CTRLPANEL_WEB_SERVER_PRIORITY+1) |
The priority of a http connection.
Definition at line 130 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
#define webHTTP_CONNECTION_STACK_SIZE 384 |
The stack size of a http connection task
Definition at line 133 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
#define webHTTP_NB_CONN 1 |
The max number of simultaneous http connection.
Definition at line 127 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
#define webHTTP_PORT ( 80 ) |
The port on which we listen.
Definition at line 111 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
#define webMAX_DATA_TO_SEND webNB_SECTOR_TO_SEND * FS_SIZE_OF_SECTOR |
The max amount of fat data to try to send
Definition at line 148 of file BasicWEB.c.
Referenced by prv_read_default_page(), and prvweb_SendFile().
#define webNB_SECTOR_TO_SEND 4 |
The max number of sector to try to send
Definition at line 145 of file BasicWEB.c.
Referenced by prvweb_SendFile().
#define webSERVER_FOLDER "A:/WEB/" |
The folder were server files are
Definition at line 136 of file BasicWEB.c.
Referenced by prvweb_ParseHTMLRequest().
#define webSERVER_PROTOCOL "HTTP/1.1" |
The server protocol.
Definition at line 114 of file BasicWEB.c.
Referenced by prulweb_BuildHeaders().
#define webSERVER_SOFTWARE "AVR32 UC3 WEB SERVER" |
The server software name.
Definition at line 124 of file BasicWEB.c.
Referenced by prulweb_BuildErrorTail(), and prulweb_BuildHeaders().
#define webSHORT_DELAY ( 10 ) |
typedef ssize_t(* pf_read_src)(int fd, void *buf, size_t count) |
Definition at line 156 of file BasicWEB.c.
eExecStatus e_webserver_cmd_get_config | ( | eModId | xModId, | |
signed short | FsNavId, | |||
int | ac, | |||
signed portCHAR * | av[], | |||
signed portCHAR ** | ppcStringReply | |||
) |
The get webserver config command: get the config fields value of http port Takes no parameter.
xModId | Input. The module that is calling this function. | |
FsNavId | Ignored. | |
ac | Input. The argument counter. For this command, should be 1. | |
av | Input. The argument vector. | |
ppcStringReply | Input/Output. The response string. If Input is NULL, no response string will be output. Else a malloc for the response string is performed here; the caller must free this string. |
Definition at line 404 of file BasicWEB.c.
References SHELL_ERRMSG_MEMALLOC, SHELL_EXECSTATUS_KO, SHELL_EXECSTATUS_OK, sprintf(), and webHttpPort.
Referenced by e_syscmds_cmd_get_config().
00407 { 00408 if(ppcStringReply != NULL) 00409 { 00410 /* allocate a buffer for answer */ 00411 *ppcStringReply = (signed portCHAR *)pvPortMalloc(15); 00412 if( NULL == *ppcStringReply ) 00413 { 00414 *ppcStringReply = (signed portCHAR *)SHELL_ERRMSG_MEMALLOC; 00415 return( SHELL_EXECSTATUS_KO ); 00416 } 00417 /* get HTTP port and add it to the buffer */ 00418 sprintf((char *)*ppcStringReply,"port=%u\r\n", webHttpPort); 00419 /* no error, return */ 00420 return( SHELL_EXECSTATUS_OK ); 00421 } 00422 return( SHELL_EXECSTATUS_KO ); 00423 }
eExecStatus e_webserver_cmd_set_config | ( | eModId | xModId, | |
signed short | FsNavId, | |||
int | ac, | |||
signed portCHAR * | av[], | |||
signed portCHAR ** | ppcStringReply | |||
) |
The set webserver config command: set the http port. Takes one parameter : port=ppppp.
xModId | Input. The module that is calling this function. | |
FsNavId | Ignored. | |
ac | Input. The argument counter. For this command, should be 1. | |
av | Input. The argument vector. | |
ppcStringReply | Input/Output. The response string. If Input is NULL, no response string will be output. Else a malloc for the response string is performed here; the caller must free this string. |
Definition at line 364 of file BasicWEB.c.
References config_file_set_value(), HTTP_CONFIG_FILE, SHELL_ERRMSG_CONFIGERROR, SHELL_EXECSTATUS_KO, SHELL_EXECSTATUS_OK, and SHELL_MSG_REBOOT.
Referenced by e_syscmds_cmd_set_config().
00367 { 00368 if (config_file_set_value(HTTP_CONFIG_FILE, ac, av) != 0) 00369 { 00370 if(ppcStringReply != NULL) 00371 { 00372 *ppcStringReply = (signed portCHAR *)SHELL_ERRMSG_CONFIGERROR; 00373 } 00374 return( SHELL_EXECSTATUS_KO ); 00375 } 00376 if(ppcStringReply != NULL) 00377 { 00378 /* allocate a buffer for answer */ 00379 *ppcStringReply = (signed portCHAR *)pvPortMalloc( strlen( SHELL_MSG_REBOOT ) +1 ); // Alloc 00380 if( NULL != *ppcStringReply ) 00381 { 00382 strcpy( (char *)*ppcStringReply, SHELL_MSG_REBOOT ); 00383 } 00384 } 00385 return( SHELL_EXECSTATUS_OK ); 00386 }
portTASK_FUNCTION | ( | prvweb_ProcessSingleConnection | , | |
pvParameters | ||||
) |
process an incoming connection parse the request and close/delete the connection
Definition at line 431 of file BasicWEB.c.
References prvweb_ParseHTMLRequest(), sCurrentNbHTTPConn, tTaskHandle, webHTTP_NB_CONN, webSHORT_DELAY, x_supervisor_SemaphoreGive(), xMutexNbHTTPConn, and xWEBMutex.
00432 { 00433 struct netconn * pxNewConnection; 00434 portSHORT i; 00435 portLONG err_count; 00436 /* 00437 while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); 00438 sCurrentNbHTTPConn++; 00439 // Release the mutex. 00440 xSemaphoreGive( xMutexNbHTTPConn ); 00441 */ 00442 00443 pxNewConnection = ( struct netconn *)pvParameters; 00444 prvweb_ParseHTMLRequest( pxNewConnection ); 00445 00446 // Since we cannot know when the client has closed the connection(lwIP bug), 00447 // we set a 1000ms delay (the time for the file transfer to end), then we close 00448 // the connection ourselves. 00449 // NOTE FOR IMPROVMENTS: we could set this delay depending on the amount of 00450 // data that was sent to the client(the more the longer). 00451 vTaskDelay( 50 ); 00452 err_count = 4; 00453 while( netconn_close( pxNewConnection ) != ERR_OK ) 00454 { 00455 if (--err_count == 0) break; 00456 vTaskDelay( webSHORT_DELAY ); 00457 } 00458 00459 //vTaskDelay( 100 ); 00460 err_count = 4; 00461 while( netconn_delete( pxNewConnection ) != ERR_OK ) 00462 { 00463 if (--err_count == 0) break; 00464 vTaskDelay( webSHORT_DELAY ); 00465 } 00466 // netconn_close( pxNewConnection ); 00467 // netconn_delete( pxNewConnection ); 00468 while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); 00469 for (i = 0 ; i < webHTTP_NB_CONN ; i++) 00470 { 00471 if (tTaskHandle[i] == xTaskGetCurrentTaskHandle()) 00472 { 00473 tTaskHandle[i] = NULL; 00474 break; 00475 } 00476 } 00477 sCurrentNbHTTPConn--; 00478 00479 // Release the xWEBMutex if there are no other active connections. 00480 if( 0 == sCurrentNbHTTPConn ) 00481 { 00482 x_supervisor_SemaphoreGive( xWEBMutex ); 00483 } 00484 00485 // Release the mutex. 00486 xSemaphoreGive( xMutexNbHTTPConn ); 00487 00488 vTaskDelete(NULL); 00489 /* nothing after delete task : this will not be reached */ 00490 }
portTASK_FUNCTION | ( | vBasicWEBServer | , | |
pvParameters | ||||
) |
WEB server main task check for incoming connection and process it.
Definition at line 221 of file BasicWEB.c.
References config_file_get_value(), HTTP_CONFIG_FILE, pcDefaultPage, prvweb_SendErrorPage(), sCurrentNbHTTPConn, TRACE_COM2, tTaskHandle, webHTTP_CONNECTION_PRIORITY, webHTTP_CONNECTION_STACK_SIZE, webHTTP_NB_CONN, webHTTP_PORT, webHttpPort, webSHORT_DELAY, x_default_page_len, x_supervisor_SemaphoreGive(), x_supervisor_SemaphoreTake(), xCFGMutex, xMutexNbHTTPConn, and xWEBMutex.
00222 { 00223 struct netconn *pxHTTPListener, *pxNewConnection; 00224 portCHAR token[6]; 00225 portSHORT TaskIdx; 00226 portLONG err_count; 00227 00228 00229 /* initialize current nb connection */ 00230 sCurrentNbHTTPConn = 0; 00231 vSemaphoreCreateBinary( xMutexNbHTTPConn ); 00232 00233 x_default_page_len = strlen( pcDefaultPage ); 00234 00235 /* HTTP configuration. */ 00236 // Get the xCFGMutex. 00237 if( pdFALSE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) 00238 { 00239 // Failed to get the CFG mutex, use the default HTTP config. 00240 webHttpPort = webHTTP_PORT; 00241 } 00242 // Mutex has been taken 00243 else 00244 { 00245 // get the field value for port number 00246 if (config_file_get_value(HTTP_CONFIG_FILE, "port" , token) >= 0) 00247 { 00248 sscanf(token, "%u", &webHttpPort); 00249 } 00250 // if it does not exist, use the default value 00251 else 00252 { 00253 webHttpPort = webHTTP_PORT; 00254 } 00255 // Release the xCFGMutex. 00256 x_supervisor_SemaphoreGive( xCFGMutex ); 00257 } 00258 00259 // Create a new tcp connection handle 00260 pxHTTPListener = netconn_new( NETCONN_TCP ); 00261 netconn_bind(pxHTTPListener, NULL, webHttpPort ); 00262 netconn_listen( pxHTTPListener ); 00263 // Loop forever 00264 for( ;; ) 00265 { 00266 /* Wait for a first connection. */ 00267 pxNewConnection = netconn_accept(pxHTTPListener); 00268 if(pxNewConnection != NULL) 00269 { 00270 /* read the nb of connection, no need to use Mutex */ 00271 while( webHTTP_NB_CONN == sCurrentNbHTTPConn ) 00272 { 00273 vTaskDelay( webSHORT_DELAY ); 00274 } 00275 00276 // Take the xWEBMutex if there are no active connections. 00277 if( 0 == sCurrentNbHTTPConn ) 00278 { 00279 if( pdFALSE == x_supervisor_SemaphoreTake( xWEBMutex, 0 ) ) 00280 { 00281 prvweb_SendErrorPage( pxNewConnection, 503, "", "AVR32 UC3 Web server under maintenance." ); 00282 // Close the connection. 00283 vTaskDelay( 50 ); 00284 err_count = 4; 00285 while( netconn_close( pxNewConnection ) != ERR_OK ) 00286 { 00287 if (--err_count == 0) break; 00288 vTaskDelay( webSHORT_DELAY ); 00289 } 00290 err_count = 4; 00291 while( netconn_delete( pxNewConnection ) != ERR_OK ) 00292 { 00293 if (--err_count == 0) break; 00294 vTaskDelay( webSHORT_DELAY ); 00295 } 00296 continue; 00297 } 00298 } 00299 00300 // Find an available spot in the tTaskHandle[] array. 00301 // We're sure to find one because sCurrentNbHTTPConn < webHTTP_NB_CONN. 00302 TaskIdx = 0; 00303 while( NULL != tTaskHandle[TaskIdx] ) TaskIdx++; 00304 00305 while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); 00306 sCurrentNbHTTPConn++; 00307 // Release the mutex. 00308 xSemaphoreGive( xMutexNbHTTPConn ); 00309 00310 // TRACE_COM2( "nb http conn:%d",sCurrentNbHTTPConn ); 00311 00312 if( xTaskCreate( prvweb_ProcessSingleConnection, 00313 ( signed portCHAR * )"WCONN", 00314 webHTTP_CONNECTION_STACK_SIZE, pxNewConnection, 00315 webHTTP_CONNECTION_PRIORITY, 00316 &tTaskHandle[TaskIdx] ) != pdPASS) 00317 { 00318 TRACE_COM2( "xTaskCreate() alloc error" ); 00319 00320 /* delete connection */ 00321 err_count = 4; 00322 while( netconn_close( pxNewConnection ) != ERR_OK ) 00323 { 00324 if (--err_count == 0) break; 00325 vTaskDelay( webSHORT_DELAY ); 00326 } 00327 err_count = 4; 00328 while( netconn_delete( pxNewConnection ) != ERR_OK ) 00329 { 00330 if (--err_count == 0) break; 00331 vTaskDelay( webSHORT_DELAY ); 00332 } 00333 00334 while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); 00335 sCurrentNbHTTPConn--; 00336 // Release the xWEBMutex if there are no active connections. 00337 if( 0 == sCurrentNbHTTPConn ) 00338 { 00339 x_supervisor_SemaphoreGive( xWEBMutex ); 00340 } 00341 // Release the mutex. 00342 xSemaphoreGive( xMutexNbHTTPConn ); 00343 }// end if task not created 00344 }// end if new connection 00345 }// end infinite loop 00346 }
portTASK_FUNCTION_PROTO | ( | prvweb_ProcessSingleConnection | , | |
pvParameters | ||||
) |
static unsigned portLONG prulweb_BuildErrorBody | ( | portCHAR * | response, | |
int | s, | |||
char * | title, | |||
const char * | text | |||
) | [static] |
build the static error page body
response | Input/Output. the buffer to store data. | |
s | Input. The error code. | |
title | Input. title of the error page. | |
text | Input. text to display in the error page. |
Definition at line 931 of file BasicWEB.c.
References sprintf().
Referenced by prvweb_SendErrorPage().
00932 { 00933 unsigned portLONG retsize = 0; 00934 00935 /* Send built-in error page. */ 00936 retsize = sprintf(response, "<HTML><HEAD>"); 00937 retsize += sprintf(&response[retsize], "<TITLE>%d %s</TITLE></HEAD>", s, title); 00938 retsize += sprintf(&response[retsize], "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#FF8C00\" VLINK=\"#FF8C00\">"); 00939 retsize += sprintf(&response[retsize], "<H1>%d %s</H1>", s, title); 00940 retsize += sprintf(&response[retsize], "<H3>%s</H3>", text ); 00941 return (retsize); 00942 }
static unsigned portLONG prulweb_BuildErrorTail | ( | portCHAR * | response | ) | [static] |
build the static error page tail
response | Input/Output. the buffer to store data. |
Definition at line 949 of file BasicWEB.c.
References sprintf(), vEthernetGetIPAddr(), and webSERVER_SOFTWARE.
Referenced by prvweb_SendErrorPage().
00950 { 00951 unsigned portLONG retsize = 0; 00952 portCHAR buff[15]; 00953 vEthernetGetIPAddr(buff); 00954 retsize = sprintf(response, "<HR><ADDRESS><A HREF=\"http://%s\">", buff); 00955 retsize += sprintf(&response[retsize], "%s</A></ADDRESS></BODY></HTML>", webSERVER_SOFTWARE ); 00956 return (retsize); 00957 }
static unsigned portLONG prulweb_BuildHeaders | ( | portCHAR * | response, | |
int | s, | |||
char * | title, | |||
char * | extra_header, | |||
char * | me, | |||
char * | mt | |||
) | [static] |
build the HTTP header
response | Input/Output. the buffer to store data. | |
s | Input. The page code (200, 404, etc). | |
title | Input. title of the page. | |
extra_header | Input. text to display in the error page. | |
me | Input. MIME encoding, if used. | |
mt | Input. MIME type if used. |
Definition at line 969 of file BasicWEB.c.
References sprintf(), webSERVER_PROTOCOL, and webSERVER_SOFTWARE.
Referenced by prvweb_ParseCGIRequest(), prvweb_SendErrorPage(), and prvweb_SendFile().
00970 { 00971 unsigned portLONG retsize = 0; 00972 portLONG s100; 00973 00974 retsize = sprintf( response, "%s %d %s\r\n", webSERVER_PROTOCOL, s, title ); 00975 retsize += sprintf( &response[retsize], "Server: %s\r\n", webSERVER_SOFTWARE ); 00976 s100 = s / 100; 00977 // if ( s100 != 2 && s100 != 3 ) 00978 if ( s100 != 3 ) 00979 { 00980 retsize += sprintf( &response[retsize], "Cache-Control: no-cache,no-store\r\n" ); 00981 } 00982 if ( extra_header != (char*) 0 && extra_header[0] != '\0' ) 00983 { 00984 retsize += sprintf( &response[retsize], "%s\r\n", extra_header ); 00985 } 00986 if ( me != (char*) 0 && me[0] != '\0' ) 00987 { 00988 retsize += sprintf(&response[retsize], "Content-Encoding: %s\r\n", me ); 00989 } 00990 if ( mt != (char*) 0 && mt[0] != '\0' ) 00991 { 00992 retsize += sprintf( &response[retsize], "Content-Type: %s\r\n", mt ); 00993 } 00994 retsize += sprintf( &response[retsize], "Connection: close\r\n\r\n" ); 00995 00996 return (retsize); 00997 }
static ssize_t prv_read_default_page | ( | int | fd, | |
void * | buf, | |||
size_t | count | |||
) | [static] |
Copy part of the Default html page to another buffer.
fd | Input. file descriptor. Ignored. | |
buf | Input/ouput. Destination memory ptr. | |
count | Input. Amount of bytes to read. |
Definition at line 732 of file BasicWEB.c.
References pcDefaultPage, webMAX_DATA_TO_SEND, and x_default_page_len.
Referenced by prvweb_SendFile().
00733 { 00734 const char *pcOffset; 00735 00736 00737 // WARNING NOTE: this implementation assumes that the default page len is < 2*webMAX_DATA_TO_SEND. 00738 if( x_default_page_len >= ( 2*webMAX_DATA_TO_SEND ) ) 00739 return( -1 ); 00740 else 00741 { 00742 if( x_default_page_len >= webMAX_DATA_TO_SEND ) 00743 pcOffset = pcDefaultPage + ( ( webMAX_DATA_TO_SEND == count ) 00744 ? 0 : ( ( FS_SIZE_OF_SECTOR <= count ) 00745 ? webMAX_DATA_TO_SEND : ( x_default_page_len - count ) ) ); 00746 else 00747 pcOffset = pcDefaultPage + ( ( FS_SIZE_OF_SECTOR <= count ) 00748 ? 0 : ( x_default_page_len - count ) ); 00749 memcpy( buf, pcOffset, count ); 00750 return( count ); 00751 } 00752 }
static void prvweb_ParseCGIRequest | ( | struct netconn * | pxNetCon, | |
char * | request | |||
) | [static] |
parse the CGI request and send it to the shell
pxNetCon | Input. The netconn to use to send and receive data. | |
request | Input. The incoming CGI request. |
Definition at line 606 of file BasicWEB.c.
References NAKED_TRACE_COM2, prulweb_BuildHeaders(), Shell_exec(), SHELL_EXECSTATUS_OK, and SYS_MODID_HTTP.
Referenced by prvweb_ParseHTMLRequest().
00607 { 00608 portCHAR cgi_present = FALSE, loop; 00609 signed portCHAR * pcStringCmd; 00610 signed portCHAR * CurrentChar; 00611 signed portCHAR * pcStringReply; 00612 eExecStatus xExeStatus; 00613 portCHAR *pcResp_data; 00614 portLONG header_size; 00615 00616 /* when entering this function, path contains : 00617 command.cgi?arg1=val1&arg2=val2 00618 it should be command arg1=val1 arg2=val2 after parsing operation */ 00619 00620 /* allocate command space */ 00621 pcStringCmd = pvPortMalloc( 100 ); 00622 if (pcStringCmd != NULL) 00623 { 00624 00625 loop = TRUE; 00626 CurrentChar = pcStringCmd; 00627 while (loop) 00628 { 00629 switch (*request) 00630 { 00631 case '.': 00632 { 00633 if (cgi_present == FALSE) 00634 { 00635 cgi_present = TRUE; 00636 request += strlen(".cgi"); 00637 } 00638 else 00639 { 00640 *CurrentChar++ = *request++; 00641 } 00642 break; 00643 } 00644 /* move ? and & to space */ 00645 case '?': 00646 case '&': 00647 *CurrentChar++ = ' '; 00648 request++; 00649 break; 00650 case '%': 00651 /* move %20 to space */ 00652 if ((*(request+1) == '2') && (*(request+2) == '0')) 00653 { 00654 *CurrentChar++ = ' '; 00655 request += 3; 00656 } 00657 /* keep %22 */ 00658 else if ((*(request+1) == '2') && (*(request+2) == '2')) 00659 { 00660 *CurrentChar++ = '"'; 00661 request += 3; 00662 } 00663 /* else keep the % symbol */ 00664 else 00665 { 00666 *CurrentChar++ = *request++; 00667 } 00668 break; 00669 case '\r': 00670 case '\n': 00671 case '\0': 00672 case ' ': 00673 *CurrentChar = '\0'; 00674 loop = FALSE; 00675 break; 00676 default: 00677 *CurrentChar++ = *request++; 00678 break; 00679 } 00680 } 00681 00682 /* send command to the shell, no error control for this module */ 00683 xExeStatus = Shell_exec(pcStringCmd, SYS_MODID_HTTP, -1, &pcStringReply); 00684 /* free buffer */ 00685 vPortFree(pcStringCmd); 00686 00687 if (pcStringReply != NULL) 00688 { 00689 pcResp_data = pvPortMalloc( 130 + strlen( (char *)pcStringReply ) ); // 130(header size) + sizeof( reply ) 00690 if( NULL == pcResp_data ) 00691 { 00692 if( SHELL_EXECSTATUS_OK == xExeStatus ) 00693 { 00694 vPortFree(pcStringReply); 00695 } 00696 NAKED_TRACE_COM2( "ParseCGIRequest(): reply mem alloc failed" ); 00697 // Avoid returning an error page so that the remote web browser keeps 00698 // on trying. 00699 return; 00700 } 00701 /* add the header */ 00702 header_size = prulweb_BuildHeaders( pcResp_data, 200, "OK", "", "", "text/html"); 00703 // Add the data. 00704 strcpy( pcResp_data + header_size, (char *)pcStringReply ); 00705 if( SHELL_EXECSTATUS_OK == xExeStatus ) 00706 { 00707 vPortFree(pcStringReply); 00708 } 00709 00710 /* send the response to network */ 00711 netconn_write(pxNetCon, pcResp_data, (u16_t)strlen( pcResp_data ), NETCONN_COPY ); 00712 vPortFree( pcResp_data ); 00713 } 00714 } 00715 else 00716 { 00717 NAKED_TRACE_COM2( "ParseCGIRequest(): request mem alloc failed" ); 00718 // Avoid returning an error page so that the remote web browser keeps on trying. 00719 } 00720 }
static void prvweb_ParseHTMLRequest | ( | struct netconn * | pxNetCon | ) | [static] |
parse the incoming request parse the HTML request and send file or execute CGI request
pxNetCon | Input. The netconn to use to send and receive data. |
Definition at line 498 of file BasicWEB.c.
References MAX_FILE_PATH_LENGTH, NAKED_TRACE_COM2, prvweb_ParseCGIRequest(), prvweb_SendErrorPage(), prvweb_SendFile(), sprintf(), and webSERVER_FOLDER.
Referenced by portTASK_FUNCTION().
00499 { 00500 struct netbuf *pxRxBuffer; 00501 portCHAR *pcRxString; 00502 portCHAR *file; 00503 portCHAR *path; 00504 portCHAR *protocol; 00505 unsigned portSHORT Length; 00506 00507 00508 /* We expect to immediately get data. */ 00509 pxRxBuffer = netconn_recv( pxNetCon ); 00510 00511 if( pxRxBuffer != NULL ) 00512 { 00513 /* Where is the data? */ 00514 netbuf_data( pxRxBuffer, (void *) &pcRxString, &Length ); 00515 /* Parse the first line of the request. */ 00516 if ( pcRxString == (char*) 0 ) 00517 { 00518 NAKED_TRACE_COM2( "ParseHTMLRequest(): empty request" ); 00519 prvweb_SendErrorPage( pxNetCon, 400, "", "Wrong request : no action submitted." ); 00520 goto delete_buffer; 00521 } 00522 /* get first occurence of space char or \t or \n or \r */ 00523 path = strpbrk( pcRxString, " \t\n\r" ); 00524 if ( path == (char*) 0 ) 00525 { 00526 NAKED_TRACE_COM2( "ParseHTMLRequest(): parse error" ); 00527 prvweb_SendErrorPage( pxNetCon, 400, "", "Can't parse request." ); 00528 goto delete_buffer; 00529 } 00530 *path++ = '\0'; 00531 protocol = strpbrk( path, " \t\r\n" ); 00532 *protocol++ = '\0'; 00533 /* Is this a GET? */ 00534 if( !strncmp( pcRxString, "GET", 3 ) ) 00535 { 00536 if ( path[0] != '/' ) 00537 { 00538 NAKED_TRACE_COM2( "ParseHTMLRequest(): wrong request" ); 00539 prvweb_SendErrorPage( pxNetCon, 400, "", "Wrong request." ); 00540 goto delete_buffer; 00541 } 00542 /* if there is a ?, this is a CGI request */ 00543 protocol = strpbrk( path, "?" ); 00544 if (protocol != NULL) 00545 { 00546 /* parse the CGI request */ 00547 prvweb_ParseCGIRequest(pxNetCon, &path[1]); 00548 goto delete_buffer; 00549 } 00550 else 00551 { 00552 /* a file has been requested */ 00553 file = (portCHAR *)pvPortMalloc((MAX_FILE_PATH_LENGTH * 2) + 4); 00554 if( NULL == file ) 00555 { 00556 NAKED_TRACE_COM2( "ParseHTMLRequest(): mem alloc failed" ); 00557 prvweb_SendErrorPage( pxNetCon, 400, "", "Memory allocation failed." ); 00558 goto delete_buffer; 00559 } 00560 /* add web directory structure */ 00561 sprintf(file,webSERVER_FOLDER); 00562 strcat(file,&(path[1])); 00563 /* check filename, if none, send index.htm */ 00564 if ( file[sizeof(webSERVER_FOLDER)-1] == '\0' ) 00565 { 00566 strcat(file,"index.htm"); 00567 } 00568 /* go to the file transfer */ 00569 prvweb_SendFile( pxNetCon, file ); 00570 vPortFree(file); 00571 } 00572 } 00573 /* Is this a POST? */ 00574 else if( !strncmp( pcRxString, "POST", 4 ) ) 00575 { 00576 NAKED_TRACE_COM2( "ParseHTMLRequest(): POST request not supported" ); 00577 prvweb_SendErrorPage( pxNetCon, 400, "", "POST request not supported for now." ); 00578 } 00579 /* Is this a HEAD? */ 00580 else if( !strncmp( pcRxString, "HEAD", 4 ) ) 00581 { 00582 NAKED_TRACE_COM2( "ParseHTMLRequest(): HEAD request not supported" ); 00583 prvweb_SendErrorPage( pxNetCon, 400, "", "HEAD request not supported for now." ); 00584 } 00585 /* We don't handle anything else. */ 00586 else 00587 { 00588 NAKED_TRACE_COM2( "ParseHTMLRequest(): unexpected request" ); 00589 prvweb_SendErrorPage( pxNetCon, 400, "", "Can't parse request." ); 00590 } 00591 } 00592 else 00593 { 00594 NAKED_TRACE_COM2( "ParseHTMLRequest(): nothing rxed" ); 00595 } 00596 delete_buffer: // netbuf_delete() handles the case when pxRxBuffer == NULL 00597 netbuf_delete( pxRxBuffer ); 00598 }
static void prvweb_SendErrorPage | ( | struct netconn * | pxNetCon, | |
int | s, | |||
char * | extra_header, | |||
const char * | text | |||
) | [static] |
send the static error page
pxNetCon | Input. The netconn to use to send and receive data. | |
s | Input. The error code. | |
extra_header | Input. data to push in the error answer. | |
text | Input. text to display in the error page. |
Definition at line 886 of file BasicWEB.c.
References ERR_BUFFER_SIZE, NAKED_TRACE_COM2, prulweb_BuildErrorBody(), prulweb_BuildErrorTail(), and prulweb_BuildHeaders().
Referenced by portTASK_FUNCTION(), prvweb_ParseHTMLRequest(), and prvweb_SendFile().
00887 { 00888 portCHAR* title; 00889 unsigned portLONG size; 00890 portCHAR * err_data; 00891 00892 err_data = (portCHAR *)pvPortMalloc(ERR_BUFFER_SIZE); 00893 if( NULL == err_data ) 00894 { 00895 NAKED_TRACE_COM2( "prvweb_SendErrorPage(): mem alloc failed" ); 00896 return; 00897 } 00898 /* Write the status line. */ 00899 switch ( s ) 00900 { 00901 case 400: title = "Bad Request"; break; 00902 case 401: title = "Unauthorized"; break; 00903 case 403: title = "Forbidden"; break; 00904 case 404: title = "Not Found"; break; 00905 case 408: title = "Request Timeout"; break; 00906 case 500: title = "Internal Error"; break; 00907 case 501: title = "Not Implemented"; break; 00908 case 503: title = "Service Unavailable"; break; 00909 default: title = "Something"; break; 00910 } 00911 /* add the header */ 00912 size = prulweb_BuildHeaders(err_data, s, title, extra_header, "", "text/html"); 00913 /* add the body */ 00914 size += prulweb_BuildErrorBody(&err_data[size], s, title, text ); 00915 /* add the tail */ 00916 size += prulweb_BuildErrorTail(&err_data[size]); 00917 /* send the response to network */ 00918 netconn_write(pxNetCon, err_data, size, NETCONN_COPY ); 00919 /* free the buffer */ 00920 vPortFree(err_data); 00921 }
static void prvweb_SendFile | ( | struct netconn * | pxNetCon, | |
char * | filename | |||
) | [static] |
parse the file request and send the requested file to the host
pxNetCon | Input. The netconn to use to send and receive data. | |
filename | Input. The incoming filename. |
Definition at line 761 of file BasicWEB.c.
References NAKED_TRACE_COM2, prulweb_BuildHeaders(), prv_read_default_page(), prvweb_SendErrorPage(), webMAX_DATA_TO_SEND, webNB_SECTOR_TO_SEND, and x_default_page_len.
Referenced by prvweb_ParseHTMLRequest().
00762 { 00763 portLONG size, header_size; 00764 portLONG fd = -1; 00765 portCHAR *resp_data; 00766 unsigned portSHORT i; 00767 err_t error; 00768 pf_read_src pfread = read; // Set the default read to a file read. 00769 00770 // NAKED_TRACE_COM2( "SendFile(): %s", filename ); 00771 00772 /* allocate response */ 00773 resp_data = (portCHAR *)pvPortMalloc(webMAX_DATA_TO_SEND); 00774 00775 if (resp_data != NULL) 00776 { 00777 /* add the header */ 00778 header_size = prulweb_BuildHeaders(resp_data, 200, "OK", "", "", "text/html"); 00779 00780 if ((fd = open((const char *)filename, O_RDONLY)) < 0) 00781 { 00782 // Set the read function to read from the pcDefaultPage 00783 pfread = prv_read_default_page; 00784 size = x_default_page_len; 00785 NAKED_TRACE_COM2( "SendFile(): file not found. Default page len:%d", x_default_page_len ); 00786 } 00787 else /* get the file size */ 00788 { 00789 size = fsaccess_file_get_size(fd); 00790 } 00791 00792 /* check if file should be sent in a single frame */ 00793 if ( size <= (webMAX_DATA_TO_SEND - header_size)) 00794 { 00795 /* get the data from filesystem */ 00796 if( pfread(fd,&resp_data[header_size],size) != size) 00797 { 00798 NAKED_TRACE_COM2( "SendFile(): short file read access error" ); 00799 prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." ); 00800 goto quit_send_page; 00801 } 00802 /* send the response to network */ 00803 error = netconn_write(pxNetCon, resp_data, (u16_t)(header_size + size), NETCONN_COPY ); 00804 if (error != 0) 00805 { 00806 NAKED_TRACE_COM2( "SendFile(): short file nw write error" ); 00807 goto quit_send_page; 00808 } 00809 } 00810 else 00811 { 00812 /* send the header */ 00813 error = netconn_write(pxNetCon, resp_data, header_size, NETCONN_COPY ); 00814 if (error != 0) 00815 { 00816 NAKED_TRACE_COM2( "SendFile(): long file hdr nw write error" ); 00817 goto quit_send_page; 00818 } 00819 00820 /* try to send the biggest frame contained in the file */ 00821 for (i = webNB_SECTOR_TO_SEND ; i > 0 ; i--) 00822 { 00823 /* get sectors of maximum size */ 00824 while(size > i * FS_SIZE_OF_SECTOR) 00825 { 00826 /* get the data from filesystem */ 00827 if( pfread(fd,resp_data, i * FS_SIZE_OF_SECTOR) != i * FS_SIZE_OF_SECTOR) 00828 { 00829 NAKED_TRACE_COM2( "SendFile(): long file read access error" ); 00830 prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." ); 00831 goto quit_send_page; 00832 } 00833 00834 /* send the response to network */ 00835 error = netconn_write(pxNetCon, resp_data, (u16_t)(i * FS_SIZE_OF_SECTOR), NETCONN_COPY ); 00836 if (error != 0) 00837 { 00838 NAKED_TRACE_COM2( "SendFile(): long file nw write error" ); 00839 goto quit_send_page; 00840 } 00841 00842 size -= (i * FS_SIZE_OF_SECTOR); 00843 } 00844 } 00845 /* finish with the few data remaining (less than 1 sector)*/ 00846 if ( size > 0 ) 00847 { 00848 /* get the data from filesystem */ 00849 if( pfread(fd,resp_data,size) != size) 00850 { 00851 NAKED_TRACE_COM2( "SendFile(): long file end read access error" ); 00852 prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." ); 00853 goto quit_send_page; 00854 } 00855 /* send the response to network */ 00856 error = netconn_write(pxNetCon, resp_data, (u16_t)size, NETCONN_COPY ); 00857 if (error != 0) 00858 { 00859 NAKED_TRACE_COM2( "SendFile(): long file end nw write error" ); 00860 goto quit_send_page; 00861 } 00862 } 00863 } 00864 }// end if response != NULL 00865 else 00866 { 00867 NAKED_TRACE_COM2( "SendFile(): mem alloc failed" ); 00868 __asm__ __volatile__ ("nop"); 00869 } 00870 quit_send_page: 00871 // vPortFree() handles the case where resp_data==NULL 00872 vPortFree(resp_data); 00873 /* close the file */ 00874 // close() handles the case where fd is an invalid file descriptor. 00875 close(fd); 00876 }
portSHORT sCurrentNbHTTPConn = 0 [static] |
Current nb of HTTP connections.
Definition at line 180 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
xTaskHandle tTaskHandle[webHTTP_NB_CONN] = { NULL } |
The handlers for connection tasks.
Definition at line 189 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
unsigned int webHttpPort = 0 [static] |
HTTP port for server.
Definition at line 183 of file BasicWEB.c.
Referenced by e_webserver_cmd_get_config(), and portTASK_FUNCTION().
size_t x_default_page_len [static] |
The size of the default contant html page.
Definition at line 192 of file BasicWEB.c.
Referenced by portTASK_FUNCTION(), prv_read_default_page(), and prvweb_SendFile().
xSemaphoreHandle xCFGMutex |
xSemaphoreHandle xMutexNbHTTPConn [static] |
Mutex to access the current_nb_http_conn variable.
Definition at line 186 of file BasicWEB.c.
Referenced by portTASK_FUNCTION().
xSemaphoreHandle xWEBMutex |
The Web server system mutex.
Definition at line 193 of file supervisor.c.
Referenced by e_supervisor_switch_to_maintenance_mode(), portTASK_FUNCTION(), and prv_v_common_leave_UsbDevice_mode().