00001
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #if (HTTP_USED == 1)
00062
00063
00064
00065 #include <stdio.h>
00066 #include <string.h>
00067
00068 #include "conf_eth.h"
00069
00070
00071 #include "FreeRTOS.h"
00072 #include "task.h"
00073 #include "semphr.h"
00074 #include "serial.h"
00075
00076
00077
00078 #include "portmacro.h"
00079
00080
00081 #include "lwip/api.h"
00082 #include "lwip/tcpip.h"
00083 #include "lwip/memp.h"
00084 #include "lwip/stats.h"
00085 #include "netif/loopif.h"
00086
00087
00088 #include "ctrl_access.h"
00089 #include "fsaccess.h"
00090 #include "config_file.h"
00091
00092
00093 #include "ethernet.h"
00094
00095
00096 #include "supervisor.h"
00097 #include "shell.h"
00098 #include "datalog.h"
00099
00100
00101 #include "defaultpage.htm.h"
00102
00103
00104 #include "tracedump.h"
00105
00106 #include "BasicWEB.h"
00107
00108
00109
00111 #define webHTTP_PORT ( 80 )
00112
00114 #define webSERVER_PROTOCOL "HTTP/1.1"
00115
00117 #define webSHORT_DELAY ( 10 )
00118
00119 #ifndef ERR_DIR
00120 #define ERR_DIR "errors"
00121 #endif
00122
00124 #define webSERVER_SOFTWARE "AVR32 UC3 WEB SERVER"
00125
00127 #define webHTTP_NB_CONN 1 // 3
00128
00130 #define webHTTP_CONNECTION_PRIORITY (CTRLPANEL_WEB_SERVER_PRIORITY+1)
00131
00133 #define webHTTP_CONNECTION_STACK_SIZE 384 // 256 // 512?
00134
00136 #define webSERVER_FOLDER "A:/WEB/"
00137
00139 #define HTTP_CONFIG_FILE "A:/CFG/http.txt"
00140
00142 #define ERR_BUFFER_SIZE 512
00143
00145 #define webNB_SECTOR_TO_SEND 4
00146
00148 #define webMAX_DATA_TO_SEND webNB_SECTOR_TO_SEND * FS_SIZE_OF_SECTOR
00149
00151 #define webCONN_TIMEOUT 5000
00152
00153
00154
00155
00156 typedef ssize_t (*pf_read_src)( int fd, void *buf, size_t count );
00157
00158
00159 static void prvweb_ParseHTMLRequest( struct netconn *pxNetCon );
00160
00161
00162 static void prvweb_SendFile( struct netconn *pxNetCon, char* filename );
00163
00164
00165 static void prvweb_ParseCGIRequest( struct netconn *pxNetCon, char* path );
00166
00167
00168 static void prvweb_SendErrorPage( struct netconn *pxNetCon, int s, char* extra_header, const char* text );
00169
00170
00171 static unsigned portLONG prulweb_BuildErrorBody(portCHAR * response, int s, char* title, const char* text );
00172
00173
00174 static unsigned portLONG prulweb_BuildErrorTail(portCHAR * response);
00175
00176
00177 static unsigned portLONG prulweb_BuildHeaders(portCHAR * response, int s, char* title, char* extra_header, char* me, char* mt);
00178
00180 static portSHORT sCurrentNbHTTPConn = 0;
00181
00183 static unsigned int webHttpPort = 0;
00184
00186 static xSemaphoreHandle xMutexNbHTTPConn;
00187
00189 xTaskHandle tTaskHandle[webHTTP_NB_CONN] = { NULL };
00190
00192 static size_t x_default_page_len;
00193
00195 extern xSemaphoreHandle xWEBMutex;
00196
00198 extern xSemaphoreHandle xCFGMutex;
00199
00200
00201
00202
00203 portTASK_FUNCTION_PROTO( prvweb_ProcessSingleConnection, pvParameters );
00204
00205
00206 #if configCTRLPANEL_TRACE == 1
00207
00210 void v_basicweb_trace( void )
00211 {
00212 NAKED_TRACE_COM2( "BASICWEB:<%d>", sCurrentNbHTTPConn );
00213 }
00214 #endif
00215
00216
00221 portTASK_FUNCTION( vBasicWEBServer, pvParameters )
00222 {
00223 struct netconn *pxHTTPListener, *pxNewConnection;
00224 portCHAR token[6];
00225 portSHORT TaskIdx;
00226 portLONG err_count;
00227
00228
00229
00230 sCurrentNbHTTPConn = 0;
00231 vSemaphoreCreateBinary( xMutexNbHTTPConn );
00232
00233 x_default_page_len = strlen( pcDefaultPage );
00234
00235
00236
00237 if( pdFALSE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) )
00238 {
00239
00240 webHttpPort = webHTTP_PORT;
00241 }
00242
00243 else
00244 {
00245
00246 if (config_file_get_value(HTTP_CONFIG_FILE, "port" , token) >= 0)
00247 {
00248 sscanf(token, "%u", &webHttpPort);
00249 }
00250
00251 else
00252 {
00253 webHttpPort = webHTTP_PORT;
00254 }
00255
00256 x_supervisor_SemaphoreGive( xCFGMutex );
00257 }
00258
00259
00260 pxHTTPListener = netconn_new( NETCONN_TCP );
00261 netconn_bind(pxHTTPListener, NULL, webHttpPort );
00262 netconn_listen( pxHTTPListener );
00263
00264 for( ;; )
00265 {
00266
00267 pxNewConnection = netconn_accept(pxHTTPListener);
00268 if(pxNewConnection != NULL)
00269 {
00270
00271 while( webHTTP_NB_CONN == sCurrentNbHTTPConn )
00272 {
00273 vTaskDelay( webSHORT_DELAY );
00274 }
00275
00276
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
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
00301
00302 TaskIdx = 0;
00303 while( NULL != tTaskHandle[TaskIdx] ) TaskIdx++;
00304
00305 while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE );
00306 sCurrentNbHTTPConn++;
00307
00308 xSemaphoreGive( xMutexNbHTTPConn );
00309
00310
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
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
00337 if( 0 == sCurrentNbHTTPConn )
00338 {
00339 x_supervisor_SemaphoreGive( xWEBMutex );
00340 }
00341
00342 xSemaphoreGive( xMutexNbHTTPConn );
00343 }
00344 }
00345 }
00346 }
00347
00364 eExecStatus e_webserver_cmd_set_config( eModId xModId, signed short FsNavId,
00365 int ac, signed portCHAR *av[],
00366 signed portCHAR **ppcStringReply )
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
00379 *ppcStringReply = (signed portCHAR *)pvPortMalloc( strlen( SHELL_MSG_REBOOT ) +1 );
00380 if( NULL != *ppcStringReply )
00381 {
00382 strcpy( (char *)*ppcStringReply, SHELL_MSG_REBOOT );
00383 }
00384 }
00385 return( SHELL_EXECSTATUS_OK );
00386 }
00387
00404 eExecStatus e_webserver_cmd_get_config( eModId xModId, signed short FsNavId,
00405 int ac, signed portCHAR *av[],
00406 signed portCHAR **ppcStringReply )
00407 {
00408 if(ppcStringReply != NULL)
00409 {
00410
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
00418 sprintf((char *)*ppcStringReply,"port=%u\r\n", webHttpPort);
00419
00420 return( SHELL_EXECSTATUS_OK );
00421 }
00422 return( SHELL_EXECSTATUS_KO );
00423 }
00424
00431 portTASK_FUNCTION( prvweb_ProcessSingleConnection, pvParameters )
00432 {
00433 struct netconn * pxNewConnection;
00434 portSHORT i;
00435 portLONG err_count;
00436
00437
00438
00439
00440
00441
00442
00443 pxNewConnection = ( struct netconn *)pvParameters;
00444 prvweb_ParseHTMLRequest( pxNewConnection );
00445
00446
00447
00448
00449
00450
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
00460 err_count = 4;
00461 while( netconn_delete( pxNewConnection ) != ERR_OK )
00462 {
00463 if (--err_count == 0) break;
00464 vTaskDelay( webSHORT_DELAY );
00465 }
00466
00467
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
00480 if( 0 == sCurrentNbHTTPConn )
00481 {
00482 x_supervisor_SemaphoreGive( xWEBMutex );
00483 }
00484
00485
00486 xSemaphoreGive( xMutexNbHTTPConn );
00487
00488 vTaskDelete(NULL);
00489
00490 }
00491
00498 static void prvweb_ParseHTMLRequest( struct netconn *pxNetCon )
00499 {
00500 struct netbuf *pxRxBuffer;
00501 portCHAR *pcRxString;
00502 portCHAR *file;
00503 portCHAR *path;
00504 portCHAR *protocol;
00505 unsigned portSHORT Length;
00506
00507
00508
00509 pxRxBuffer = netconn_recv( pxNetCon );
00510
00511 if( pxRxBuffer != NULL )
00512 {
00513
00514 netbuf_data( pxRxBuffer, (void *) &pcRxString, &Length );
00515
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
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
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
00543 protocol = strpbrk( path, "?" );
00544 if (protocol != NULL)
00545 {
00546
00547 prvweb_ParseCGIRequest(pxNetCon, &path[1]);
00548 goto delete_buffer;
00549 }
00550 else
00551 {
00552
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
00561 sprintf(file,webSERVER_FOLDER);
00562 strcat(file,&(path[1]));
00563
00564 if ( file[sizeof(webSERVER_FOLDER)-1] == '\0' )
00565 {
00566 strcat(file,"index.htm");
00567 }
00568
00569 prvweb_SendFile( pxNetCon, file );
00570 vPortFree(file);
00571 }
00572 }
00573
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
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
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:
00597 netbuf_delete( pxRxBuffer );
00598 }
00599
00606 static void prvweb_ParseCGIRequest( struct netconn *pxNetCon, char* request )
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
00617
00618
00619
00620
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
00645 case '?':
00646 case '&':
00647 *CurrentChar++ = ' ';
00648 request++;
00649 break;
00650 case '%':
00651
00652 if ((*(request+1) == '2') && (*(request+2) == '0'))
00653 {
00654 *CurrentChar++ = ' ';
00655 request += 3;
00656 }
00657
00658 else if ((*(request+1) == '2') && (*(request+2) == '2'))
00659 {
00660 *CurrentChar++ = '"';
00661 request += 3;
00662 }
00663
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
00683 xExeStatus = Shell_exec(pcStringCmd, SYS_MODID_HTTP, -1, &pcStringReply);
00684
00685 vPortFree(pcStringCmd);
00686
00687 if (pcStringReply != NULL)
00688 {
00689 pcResp_data = pvPortMalloc( 130 + strlen( (char *)pcStringReply ) );
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
00698
00699 return;
00700 }
00701
00702 header_size = prulweb_BuildHeaders( pcResp_data, 200, "OK", "", "", "text/html");
00703
00704 strcpy( pcResp_data + header_size, (char *)pcStringReply );
00705 if( SHELL_EXECSTATUS_OK == xExeStatus )
00706 {
00707 vPortFree(pcStringReply);
00708 }
00709
00710
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
00719 }
00720 }
00721
00722
00732 static ssize_t prv_read_default_page( int fd, void *buf, size_t count )
00733 {
00734 const char *pcOffset;
00735
00736
00737
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 }
00753
00754
00761 static void prvweb_SendFile( struct netconn *pxNetCon, char* filename )
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;
00769
00770
00771
00772
00773 resp_data = (portCHAR *)pvPortMalloc(webMAX_DATA_TO_SEND);
00774
00775 if (resp_data != NULL)
00776 {
00777
00778 header_size = prulweb_BuildHeaders(resp_data, 200, "OK", "", "", "text/html");
00779
00780 if ((fd = open((const char *)filename, O_RDONLY)) < 0)
00781 {
00782
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
00788 {
00789 size = fsaccess_file_get_size(fd);
00790 }
00791
00792
00793 if ( size <= (webMAX_DATA_TO_SEND - header_size))
00794 {
00795
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
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
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
00821 for (i = webNB_SECTOR_TO_SEND ; i > 0 ; i--)
00822 {
00823
00824 while(size > i * FS_SIZE_OF_SECTOR)
00825 {
00826
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
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
00846 if ( size > 0 )
00847 {
00848
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
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 }
00865 else
00866 {
00867 NAKED_TRACE_COM2( "SendFile(): mem alloc failed" );
00868 __asm__ __volatile__ ("nop");
00869 }
00870 quit_send_page:
00871
00872 vPortFree(resp_data);
00873
00874
00875 close(fd);
00876 }
00877
00886 static void prvweb_SendErrorPage(struct netconn *pxNetCon, int s, char* extra_header, const char* text )
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
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
00912 size = prulweb_BuildHeaders(err_data, s, title, extra_header, "", "text/html");
00913
00914 size += prulweb_BuildErrorBody(&err_data[size], s, title, text );
00915
00916 size += prulweb_BuildErrorTail(&err_data[size]);
00917
00918 netconn_write(pxNetCon, err_data, size, NETCONN_COPY );
00919
00920 vPortFree(err_data);
00921 }
00922
00931 static unsigned portLONG prulweb_BuildErrorBody(portCHAR * response, int s, char* title, const char* text )
00932 {
00933 unsigned portLONG retsize = 0;
00934
00935
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 }
00943
00949 static unsigned portLONG prulweb_BuildErrorTail( portCHAR * response )
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 }
00958
00969 static unsigned portLONG prulweb_BuildHeaders(portCHAR * response, int s, char * title, char* extra_header, char* me, char* mt )
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
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 }
00998
00999 #endif