BasicWEB.c File Reference


Detailed Description

Basic WEB Server for AVR32 UC3.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

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 Documentation

#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 )

Delay on close error.

Definition at line 117 of file BasicWEB.c.

Referenced by portTASK_FUNCTION().


Typedef Documentation

typedef ssize_t(* pf_read_src)(int fd, void *buf, size_t count)

Definition at line 156 of file BasicWEB.c.


Function Documentation

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.

Note:
This function must be of the type pfShellCmd defined by the shell module.
Parameters:
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.
Returns:
the status of the command execution.

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.

Note:
This function must be of the type pfShellCmd defined by the shell module.
Parameters:
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.
Returns:
the status of the command execution.

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

Note:
Input. The netconn to use to send and receive data.

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

Parameters:
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

Parameters:
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

Parameters:
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.

Parameters:
fd Input. file descriptor. Ignored.
buf Input/ouput. Destination memory ptr.
count Input. Amount of bytes to read.
Returns:
amount of data read (or -1 if error)

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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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 }


Variable Documentation

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

The CFG system mutex.

The CFG system mutex.

Definition at line 203 of file supervisor.c.

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().


Generated on Fri Feb 19 02:22:42 2010 for AVR32 - Control Panel demonstration. by  doxygen 1.5.5