Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

/opentcp/http/http_server.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053  
00067 #include<inet/datatypes.h>
00068 #include<inet/globalvariables.h>
00069 #include<inet/debug.h>
00070 #include<inet/system.h>
00071 #include<inet/tcp_ip.h>
00072 #include<inet/http/http_server.h>
00073 
00074 
00075 UINT8 https_enabled = 0; 
00083 struct http_server_state https[NO_OF_HTTP_SESSIONS];
00084 
00093 INT8 https_init(void)
00094 {
00095         UINT8 i;
00096         INT8 soch;
00097 
00098 
00099         for( i=0; i<NO_OF_HTTP_SESSIONS; i++)
00100         {
00101                 https[i].state = HTTPS_STATE_FREE;
00102                 https[i].ownersocket = 0;
00103                 https[i].fstart = 0;
00104                 https[i].fpoint = 0;
00105                 https[i].flen  = 0;
00106                 https[i].funacked = 0;
00107                 
00108                 soch =  tcp_getsocket(TCP_TYPE_SERVER, TCP_TOS_NORMAL, TCP_DEF_TOUT, https_eventlistener);
00109                 
00110                 if(soch < 0)
00111                 {
00112                         DEBUGOUT("HTTP Server uncapable of getting socket\r\n");
00113                         RESET_SYSTEM();
00114                         /*return(-1);*/
00115                 }
00116                 
00117                 https[i].ownersocket = soch;
00118                 
00119                 kick_WD();
00120                 
00121                 soch = tcp_listen(https[i].ownersocket, HTTPS_SERVERPORT);
00122                 
00123                 if(soch < 0)
00124                 {
00125                         DEBUGOUT("HTTP Server uncapable of setting socket to listening mode\r\n");
00126                         RESET_SYSTEM();
00127                         /*return(-1);*/
00128                 }               
00129                 
00130         
00131         } 
00132         
00133         https_enabled  = 1;
00134         
00135         return(i);      
00136         
00137 }
00138 
00139 
00140 /********************************************************************************
00141 Function:               https_run
00142 
00143 Parameters:             void    
00144                                 
00145 Return val:             void
00146                                 
00147 Date:                   13.10.2002
00148 
00149 Desc:                   This function is main 'thread' of HTTP server program
00150                                 and should be called periodically from main loop.
00151 *********************************************************************************/
00152 
00153 void https_run (void)
00154 {
00155         UINT8 i;
00156         INT16 len;
00157         static UINT8 ses = 0;
00158         
00159         if( https_enabled == 0)
00160                 return;
00161                 
00162         /* Walk thru all sessions untill we found something to send or so       */
00163         
00164         for(i=0; i<NO_OF_HTTP_SESSIONS; i++)
00165         {
00166                 kick_WD();
00167                 
00168                 if(ses >= NO_OF_HTTP_SESSIONS)
00169                         ses = 0;
00170 
00171                 /* Keep sockets listening       */
00172                 
00173                 if(tcp_getstate(https[ses].ownersocket) < TCP_STATE_LISTENING)
00174                 {
00175                         tcp_listen(https[ses].ownersocket, HTTPS_SERVERPORT);
00176                         ses++;
00177                         continue;       
00178                 }
00179 
00180                 if(https[ses].state != HTTPS_STATE_ACTIVE)
00181                 {
00182                         ses++;
00183                         continue;
00184                 }
00185                 
00186                 if(https[ses].funacked != 0)
00187                 {
00188                         ses++;
00189                         continue;               
00190                 }
00191                 
00192                 if(https[ses].fstart == 0)
00193                 {
00194                         ses++;
00195                         continue;               
00196                 }               
00197                 
00198                 /* End of data? */
00199                 
00200                 if( https[ses].fpoint >= https[ses].flen)
00201                 {
00202                         tcp_close(https[ses].ownersocket);
00203                         tcp_abort(https[ses].ownersocket);
00204                         https_deletesession(ses);
00205                         
00206                         ses++;
00207                         
00208                         return;                 
00209                 
00210                 }
00211                 
00212                 /* More data to send    */
00213                 
00214                 len = https_loadbuffer(ses, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET);
00215                         
00216                 if(len<0)
00217                         return;
00218                         
00219                 len = tcp_send(https[ses].ownersocket, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, len); 
00220                 
00221                 if(len<0)
00222                 {
00223                         tcp_close(https[ses].ownersocket);
00224                         https_deletesession(ses);
00225                         
00226                         ses++;
00227 
00228                         return;                 
00229                 
00230                 }
00231                 
00232                 https[ses].funacked = len;
00233                 
00234                 
00235                 /* Serve another session on next run    */
00236                 
00237                 ses++;
00238                 
00239                 return;         
00240                 
00241         
00242         }       
00243         
00244         
00245 
00246 
00247 }
00248 
00249 /********************************************************************************
00250 Function:               https_eventlistener
00251 
00252 Parameters:             INT8 cbhandle - handle to TCP socket where event is coming from 
00253                                 UINT8 event - type of event
00254                                 UINT32 par1 - parameter the meaning of depends on event
00255                                 UINT32 par2 - parameter the meaning of depends on event
00256                                 
00257 Return val:             INT32 - depends on event but usually (-1) is error of some
00258                                                 kind and positive reply means OK
00259                                 
00260 Date:                   13.10.2002
00261 
00262 Desc:                   This function is given to TCP socket as function pointer to be
00263                                 used by TCP engine to make callbacks to inform about events
00264                                 on TCP e.g. arriving data. 
00265 *********************************************************************************/
00266 
00267 
00268 INT32 https_eventlistener (INT8 cbhandle, UINT8 event, UINT32 par1, UINT32 par2)
00269 {
00270         /* This function is called by TCP stack to inform about events  */
00271         
00272         INT16   i;
00273         INT16   session;
00274                 
00275         if( https_enabled == 0)
00276                 return(-1);
00277         
00278         if(cbhandle < 0)
00279                 return(-1);     
00280                 
00281         /* Search for rigth session     */
00282         
00283         session = https_searchsession(cbhandle);        
00284         
00285         switch( event )
00286         {
00287         
00288                 case TCP_EVENT_CONREQ:
00289                 
00290                         /* Do we have a session for requesting socket?  */
00291                         
00292                         if(session < 0)
00293                                 return(-1);
00294 
00295                         
00296                         /* Try to get new session       */
00297                         
00298                         session = https_bindsession(cbhandle);
00299                         
00300                         if(session < 0)                 /* No resources */
00301                                 return(-1);
00302 
00303                         
00304                         return(1);
00305         
00306                 case TCP_EVENT_ABORT:
00307                 
00308                         if(session < 0)
00309                                 return(1);
00310                         
00311                         https_deletesession((UINT8)session);            
00312                         
00313                         return(1);
00314                 
00315                 case TCP_EVENT_CONNECTED:
00316                 
00317                         if(session < 0)
00318                                 return(-1);
00319                 
00320                         https_activatesession((UINT8)session);
00321                         
00322                         return(1);
00323                         
00324                 case TCP_EVENT_CLOSE:
00325                 
00326                         if(session < 0)
00327                                 return(-1);
00328                         
00329                         https_deletesession((UINT8)session);            
00330                         
00331                         return(1);              
00332                 
00333                         
00334                 case TCP_EVENT_ACK:
00335                 
00336                         if(session < 0)
00337                                 return(-1);
00338                 
00339                         https[session].fpoint += https[session].funacked;
00340                         https[session].funacked = 0;
00341                 
00342                         return(1);
00343                         
00344                 case TCP_EVENT_DATA:
00345                 
00346                         /* Check for GET request        */
00347                         
00348                         if(session < 0)
00349                                 return(-1);
00350                         
00351                         if(https[session].fstart == 0)
00352                         {
00353                                 if(par1 <= 3)
00354                                         return(1);
00355                                 
00356                                 /* Check for GET        */
00357                                 
00358                                 if(RECEIVE_NETWORK_B() != 'G')
00359                                         return(1);
00360                                 if(RECEIVE_NETWORK_B() != 'E')
00361                                         return(1);      
00362                                 if(RECEIVE_NETWORK_B() != 'T')
00363                                         return(1);                      
00364                                         
00365                                 par1 -= 3;
00366                                 
00367                                 /* Search for '/'       */
00368                                 
00369                                 for(i=0; i<par1; i++)
00370                                 {
00371                                         if(RECEIVE_NETWORK_B() == '/')
00372                                         {
00373                                                 i++;
00374                                                 break;
00375                                         }
00376                                 }               
00377                                 
00378                                 par1 -= i;
00379                                 
00380                                 /* Calculate Hash       */
00381                                 
00382                                 i = https_calculatehash(par1);  
00383                                 
00384                                 if(i < 0)
00385                                 {
00386                                         /* Invalid GET  */
00387                                         return(1);
00388                                 }       
00389                                 
00390                                 /* Get FileRef  */
00391                                 
00392                                 i = https_findfile((UINT8)i, (UINT8)session);
00393                                                 
00394                                 
00395                                 return(1);              
00396                                 
00397                         
00398                         }
00399                 
00400                 
00401                         return(1);
00402                 
00403                         
00404                 case TCP_EVENT_REGENERATE:
00405                 
00406                         if(session < 0)
00407                                 return(-1);
00408                 
00409                         if(https[session].state != HTTPS_STATE_ACTIVE)
00410                                 return(-1);
00411                 
00412                         i = https_loadbuffer(session, &net_buf[TCP_APP_OFFSET], (UINT16)par1);
00413                         
00414                         if(i<0)
00415                                 return(-1);
00416                         
00417                         tcp_send(https[session].ownersocket, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i);     
00418                 
00419                         return(i);
00420         
00421         
00422                 default:
00423                         return(-1);
00424         }       
00425 
00426 }
00427 
00428 
00429 void https_deletesession (UINT8 ses)
00430 {
00431         https[ses].state = HTTPS_STATE_FREE;
00432         https[ses].fstart = 0;
00433         https[ses].fpoint = 0;
00434         https[ses].flen  = 0;
00435         https[ses].funacked = 0;
00436 
00437 }
00438 
00439 INT16 https_searchsession (UINT8 soch)
00440 {
00441         UINT8 i;
00442         
00443         for(i=0; i<NO_OF_HTTP_SESSIONS; i++)
00444         {
00445                 if(https[i].ownersocket == soch)
00446                         return(i);
00447                 
00448         }
00449         
00450         return(-1);
00451 
00452 }
00453 
00454 INT16 https_bindsession (UINT8 soch)
00455 {
00456         UINT8 i;
00457         
00458         for(i=0; i<NO_OF_HTTP_SESSIONS; i++)
00459         {
00460                 if(https[i].ownersocket == soch)
00461                 {
00462                         if(https[i].state == HTTPS_STATE_FREE)
00463                         {
00464                                 https[i].state = HTTPS_STATE_RESERVED;
00465                                 return(i);
00466                         }                       
00467                 }       
00468                 
00469         }
00470         
00471         
00472         return(-1);
00473 
00474 }
00475 
00476 void https_activatesession (UINT8 ses)
00477 {
00478         https[ses].state = HTTPS_STATE_ACTIVE;
00479 
00480 }
00481 
00482 /* read two encoded bytes from HTTP URI and return
00483  * decoded byte
00484  */
00485 UINT8 https_read_encoded(void)
00486 {
00487         UINT8 temp,ch;
00488         
00489         temp = RECEIVE_NETWORK_B();
00490         if((temp>='0')&&(temp<='9')){
00491                 ch = (temp-'0')<<4;
00492         }else{
00493                 if((temp>='a')&&(temp<='f')){
00494                         ch = (temp-'a'+10)<<4;
00495                 }else{
00496                         ch = (temp-'A'+10)<<4;
00497                 }
00498         }
00499                 
00500         temp = RECEIVE_NETWORK_B();
00501         if((temp>='0')&&(temp<='9')){
00502                 ch |= (temp-'0');
00503         }else{
00504                 if((temp>='a')&&(temp<='f')){
00505                         ch |= (temp-'a'+10);
00506                 }else{
00507                         ch |= (temp-'A'+10);
00508                 }
00509         }
00510         return ch;
00511 }
00512 
00513 INT16 https_calculatehash (UINT32 len)
00514 {
00515         UINT8 hash=0;
00516         UINT8 ch;
00517         UINT8 i;
00518         
00519         
00520         /* Read Max 60 characters */
00521         
00522         if(len > 60)
00523                 len = 60;
00524         
00525         for( i=0; i<len; i++)
00526         {
00527                 ch = RECEIVE_NETWORK_B();
00528                 
00529                 if( ch ==' ')   /* End reached?                 */
00530                         break;
00531                 
00532                 /* encoded HTTP URI ? */
00533                 if( ch == '%'){
00534                         ch = https_read_encoded();
00535 
00536                         /* is this UNICODE char encoded? (for now allow only
00537                          * one byte encoded UNICODE chars)
00538                          */
00539                         if( ( ch & 0xe0 ) == 0xc0){
00540                                 /* yes */
00541                                 ch = ( ch & 0x1F ) << 6; 
00542                                 RECEIVE_NETWORK_B();    /* skip first % */
00543                                 ch |= (https_read_encoded() & 0x3F);
00544                         }
00545                 }
00546 
00547                 hash *= 37;
00548                 hash += ch;
00549         
00550         }
00551         
00552         if(i==len)
00553                 return(-1);
00554         
00555         /* construct address for Hash table */
00556         
00557         if(hash == 0)           /* User asked defaul file       */
00558         {
00559                 /* Set hash to index.html value */
00560                 
00561                 hash = 0x0B;
00562         
00563         }
00564         
00565         /* Now we have hash value calculated            */
00566         
00567         return( hash );
00568 
00569 }
00570 
00571 

Generated on Sun Aug 3 20:32:59 2003 for OpenTCP by doxygen1.2.18