httpd.c

Go to the documentation of this file.
00001 /*##############################################################################
00002 
00003 nIP - Testapplication
00004 
00005 File        : httpd.c
00006 
00007 Description : Simple Web Server
00008 
00009 Copyright notice:
00010 
00011 Copyright (C) 2005 -
00012 Andreas Dittrich, dittrich@informatik.hu-berlin.de
00013 Jon Kowal, kowal@informatik.hu-berlin.de
00014 
00015 This program is free software; you can redistribute it and/or
00016 modify it under the terms of the GNU General Public License
00017 as published by the Free Software Foundation; either version 2
00018 of the License, or (at your option) any later version.
00019 
00020 This program is distributed in the hope that it will be useful,
00021 but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023 GNU General Public License for more details.
00024 
00025 You should have received a copy of the GNU General Public License
00026 along with this program; if not, write to the Free Software
00027 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00028 
00029 #############################################################################*/
00030 
00031 #include "httpd.h"
00032 #include "dispatcher.h"
00033 #include "inet.h"
00034 #include "os_core.h"
00035 #include "nip_error.h"
00036 #include "net/net_if.h"
00037 #include "net/tcp.h"
00038 #include "net/numbers.h"
00039 #include "app/ports.h"
00040 #include "app/dns_sd.h"
00041 
00042 #if HTTPD_ENABLE == 1
00043 
00044 nip_tcp_sock_id_t        http_listensock;
00045 nip_tcp_sock_id_t        http_opensock = NIP_TCP_NO_SOCKET;
00046 
00047 
00048 void httpd_start( void )
00049 {
00050         struct nip_tcp_sock_addr sockaddr;
00051 
00052         // open tcp socket
00053         nip_memset( &sockaddr, 0, sizeof( struct nip_tcp_sock_addr ) );
00054         sockaddr.port = NIP_TCP_PORT_HTTP;
00055         http_listensock = nip_tcp_socket( &sockaddr, NIP_TCP_SOCK_FLG_LISTENING );
00056 }
00057 
00058 void httpd_check( void )
00059 {
00060         nip_mem_size_t      size;
00061         uint8_t             buf;
00062         uint8_t             p;
00063         static uint8_t      found_addr;
00064         static http_state_t state;
00065         static uint8_t      nl_pos; /* characters parsed since newline */
00066         static struct http_parser parser[HTTP_PARSER_COUNT] = {
00067                                                 {0, 6, (uint8_t*)"GET /A"  },
00068                                                 {0, 6, (uint8_t*)"GET /B"  },
00069                                                 {0, 2, (uint8_t*)"\r\n"}};
00070 #if (NIP_DNSSD_ENABLE == 1)
00071         nip_dnssd_id_t srv_id = NIP_DNSSD_NO_SERVICE;
00072         uint8_t *instance_name = (uint8_t*)"\x07""Boogie!";
00073         uint8_t *service_name  = (uint8_t*)"\x05""_http""\x04""_tcp";
00074         uint8_t *txt_records   = (uint8_t*)"\x07""path=/B";
00075         nip_mem_ptr_t  in_mem_ptr;
00076         nip_mem_ptr_t  srv_mem_ptr;
00077         nip_mem_ptr_t  txt_mem_ptr;
00078 #endif /*NIP_DNSSD_ENABLE*/
00079 
00080 #if (NIP_DNSSD_ENABLE == 1)
00081         // register service
00082         if ( srv_id == NIP_DNSSD_NO_SERVICE )
00083         {
00084                 in_mem_ptr.id  = NIP_MEM_NULL;
00085                 in_mem_ptr.ptr = instance_name;
00086         //                      instance_name[0] = 3;
00087                 srv_mem_ptr.id  = NIP_MEM_NULL;
00088                 srv_mem_ptr.ptr = service_name;
00089         //                      service_name[0] = 7;
00090         //                      service_name[8] = 4;
00091                 txt_mem_ptr.id  = NIP_MEM_NULL;
00092                 txt_mem_ptr.ptr = txt_records;
00093         //                      txt_records[0]  = 8;
00094                 srv_id = nip_dnssd_register( &in_mem_ptr, &srv_mem_ptr, &txt_mem_ptr,8, NIP_TCP_PORT_HTTP, 0, 0 );
00095         }
00096 #endif /*NIP_DNSSD_ENABLE*/
00097 
00098         // check for new connections if we're not already serving one
00099         if ( http_opensock == NIP_TCP_NO_SOCKET )
00100         {
00101                 http_opensock = nip_tcp_accept( http_listensock );
00102                 if ( http_opensock != NIP_TCP_NO_SOCKET )
00103                 {
00104                         nl_pos        = 0;
00105                         parser[0].pos = 0;
00106                         parser[1].pos = 0;
00107                         parser[2].pos = 0;
00108                         state         = HTTP_STAT_ADDR;
00109                 }
00110         }
00111 
00112         if ( http_opensock != NIP_TCP_NO_SOCKET )
00113         {
00114                 // check for incoming data
00115                 size = nip_tcp_read( http_opensock, &buf, 1 );
00116 
00117                 // connection closed by remote peer?
00118                 /// @todo include some kind of timeout after which stale connections
00119                 /// are being reset so we won't be locked forever by broken http-clients.
00120                 if ( size == 0 && nip_error != NIP_E_AGAIN )
00121                 {
00122                         // close connectin
00123                         if ( state != HTTP_STAT_CLOSE )
00124                                 nip_tcp_close( http_opensock );
00125 
00126                         http_opensock = NIP_TCP_NO_SOCKET;
00127                 }
00128                 // received data?
00129                 else if ( size > 0 && state != HTTP_STAT_CLOSE )
00130                 {
00131                         // increment distance to previous newline
00132                         nl_pos++;
00133                         p = 0;
00134                         do
00135                         {
00136                                 ///@todo check for header lines that are longer than 255 and would
00137                                 /// therefor cause counter overflows.
00138                                 // scan for header end
00139                                 if ( buf == parser[p].s[parser[p].pos] )
00140                                         parser[p].pos++;
00141                                 else
00142                                         parser[p].pos = 0;
00143 
00144                                 // check address
00145                                 if ( state == HTTP_STAT_ADDR
00146                                   && p <= HTTP_ADDR_PARSER
00147                                   && parser[p].pos == parser[p].sz )
00148                                 {
00149                                         state = HTTP_STAT_200;
00150                                         found_addr = p;
00151                                 }
00152 
00153                                 // parse for newlines
00154                                 if ( p == HTTP_NL_PARSER && parser[p].pos == 2 )
00155                                 {
00156                                         // address should have been on line 1
00157                                         if ( state == HTTP_STAT_ADDR )
00158                                                 state = HTTP_STAT_404;
00159 
00160                                         if ( nl_pos == parser[p].pos )
00161                                                 goto header_done;
00162 
00163                                         parser[p].pos = 0;
00164                                         nl_pos = 0;
00165                                 }
00166 
00167                         }
00168                         while ( ++p < HTTP_PARSER_COUNT );
00169 
00170                 }
00171         }
00172 
00173         goto quit;
00174 
00175         header_done:
00176 
00177         /// @todo perform checks on nip_tcp_write() operations
00178         if ( state == HTTP_STAT_404 )
00179         {
00180                 nip_tcp_write( http_opensock, (uint8_t*)"HTTP/1.0 404\r\ncontent-type:text/html\r\n\r\n", 40 );
00181                 nip_tcp_write( http_opensock, (uint8_t*)"<h1>404 Not Found</h1>", 22 );
00182         }
00183 
00184         if ( state == HTTP_STAT_200 )
00185         {
00186                 /// @todo add site processing here
00187                 nip_tcp_write( http_opensock, (uint8_t*)"HTTP/1.0 200\r\ncontent-type:", 27 );
00188                 if ( found_addr == 0 )
00189                 {
00190                         nip_tcp_write( http_opensock, (uint8_t*)"text/plain\r\n\r\n", 14);
00191                         buf = 250;
00192                         nip_tcp_write( http_opensock, &buf, 1 );
00193                 }
00194                 else if ( found_addr == 1 )
00195                         nip_tcp_write( http_opensock, (uint8_t*)"text/html\r\n\r\n<h1>Ooh Yes!! Boogie!!</h1>", 40 );
00196         }
00197 
00198         nip_tcp_close( http_opensock );
00199         state = HTTP_STAT_CLOSE;
00200 
00201         quit:
00202                 return;
00203 }
00204 
00205 #endif

Generated on Thu Jul 10 01:09:29 2008 for NIP by  doxygen 1.5.5