Main Page | Modules | File List | Related Pages

webport.c

00001 /*
00002  * Copyright (C) 2002 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this
00014  *    software must display the following acknowledgement:
00015  *
00016  *    This product includes software developed by egnite Software GmbH
00017  *    and its contributors.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00023  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00035 /*
00036  * $Log$
00037  */
00038 
00039 #define MYMAC   0x00, 0x06, 0x98, 0x00, 0x00, 0x00
00040 #define MYIP    "192.168.192.100"
00041 #define MYMASK  "255.255.255.0"
00042 
00043 
00044 #include <string.h>
00045 #include <stdio.h>
00046 #include <io.h>
00047 
00048 #ifdef ETHERNUT2
00049 #include <dev/lanc111.h>
00050 #else
00051 #include <dev/nicrtl.h>
00052 #endif
00053 #include <dev/debug.h>
00054 #include <dev/urom.h>
00055 
00056 #include <sys/version.h>
00057 #include <sys/confnet.h>
00058 #include <sys/thread.h>
00059 #include <sys/timer.h>
00060 #include <sys/heap.h>
00061 
00062 #include <dev/nicrtl.h>
00063 #include <netinet/sostream.h>
00064 #include <arpa/inet.h>
00065 
00066 #include <pro/dhcp.h>
00067 #include <pro/httpd.h>
00068 
00069 #include "webport.h"
00070 
00071 #define NUTDEBUG
00072 
00073 #ifdef NUTDEBUG
00074 #include <sys/osdebug.h>
00075 #include <net/netdebug.h>
00076 #endif
00077 
00078 /*!
00079  * \addtogroup xgWebPort
00080  */
00081 /*@{*/
00082 
00083 /*!
00084  * \brief CPU reset macro.
00085  *
00086  * Start all over on fatal initialization errors.
00087  */
00088 #define JUMP_RESET asm volatile("cli\n\tcall 0\n\t" ::)
00089 
00090 /*!
00091  * \brief Process a single HTTP request.
00092  *
00093  * This routine performs the whole cycle of a HTTP request.
00094  *
00095  * - Creating a socket.
00096  * - Listening on the defined port.
00097  * - Processing the request.
00098  * - Closing the socket.
00099  */
00100 void Service(void)
00101 {
00102     TCPSOCKET *sock;    /* TCP socket pointer. */
00103     FILE *stream;       /* TCP stream. */
00104 
00105     /*
00106      * Let the Nut/OS library create a TCP socket for us.
00107      */
00108     if((sock = NutTcpCreateSocket()) != 0) {
00109 
00110         /*
00111          * Listen on the port defined in webport.h.
00112          */
00113         if(NutTcpAccept(sock, HTTP_PORT) == 0) {
00114 
00115             /*
00116              * The Nut/OS memory manager dynamically allocates
00117              * and releases SRAM space. In this application
00118              * most memory is used by incoming telegrams and
00119              * the socket interface. If the available space
00120              * becomes low, we sleep for 200 milliseconds and
00121              * try again. This way we will always leave some
00122              * RAM for more important parts of the system.
00123              * The watermark is defined in webport.h.
00124              */
00125             while(NutHeapAvailable() < LOW_MEM_MARK)
00126                 NutSleep(200);
00127 
00128             /*
00129              * Create a stream from the socket, so we can use stdio.
00130              */
00131             if((stream = _fdopen((int) sock, "r+b")) != 0) {
00132                 /*
00133                  * Process http request and close the stream when done.
00134                  */
00135                 NutHttpProcessRequest(stream);
00136                 fclose(stream);
00137             }
00138         }
00139 
00140         /*
00141          * Close the socket.
00142          */
00143         NutTcpCloseSocket(sock);
00144     }
00145 }
00146 
00147 /*! \fn ServiceThread(void *arg)
00148  * \brief Background thread to process HTTP requests.
00149  *
00150  * This thread calls Service() in an endless loop.
00151  */
00152 THREAD(ServiceThread, arg)
00153 {
00154     /*
00155      * Loop endless for connections.
00156      */
00157     for(;;) 
00158         Service();
00159 }
00160 
00161 /*!
00162  * \brief Main entry of our application.
00163  *
00164  * Nut/OS automatically calls this entry after initialization.
00165  * 
00166  * This routine will do all required initialization, start some
00167  * background threads and then process incoming HTTP requests together 
00168  * with the concurrently running background threads.
00169  */
00170 int main(void)
00171 {
00172     u_char i;
00173     u_char mac[] = { MYMAC };
00174 
00175 #ifdef NUTDEBUG
00176     u_long baud = 115200;
00177 
00178     /*
00179      * Initialize the uart device.
00180      */
00181     NutRegisterDevice(&devDebug0, 0, 0);
00182     freopen("uart0", "w", stdout);
00183     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00184     printf("\n\nNut/OS %s Webport Daemon...", NutVersionString());
00185 
00186     NutTraceTcp(stdout, 0);
00187     NutTraceOs(stdout, 0);
00188     NutTraceHeap(stdout, 0);
00189     NutSleep(2000);
00190 #endif
00191 
00192     /*
00193      * Register Ethernet controller.
00194      */
00195     if(NutRegisterDevice(&DEV_ETHER, 0x8300, 5)) {
00196 #ifdef NUTDEBUG
00197         puts("registering NIC failed");
00198 #endif
00199     }
00200 
00201     /*
00202      * LAN configuration using EEPROM values or DHCP/ARP method.
00203      * If it fails, use fixed values.
00204      */
00205     if (NutDhcpIfConfig("eth0", mac, 60000)) {
00206         u_long ip_addr = inet_addr(MYIP);
00207         u_long ip_mask = inet_addr(MYMASK);
00208 
00209 #ifdef NUTDEBUG
00210         puts("No DHCP");
00211 #endif
00212         NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
00213     }
00214 #ifdef NUTDEBUG
00215     puts("started");
00216     if(confnet.cdn_cip_addr)
00217         printf("ip addr %s\n", inet_ntoa(confnet.cdn_cip_addr));
00218     else
00219         printf("ip addr %s\n", inet_ntoa(confnet.cdn_ip_addr));
00220     printf("ip mask %s\n", inet_ntoa(confnet.cdn_ip_mask));
00221     printf("ip gate %s\n", inet_ntoa(confnet.cdn_gateway));
00222 #endif
00223 
00224     /*
00225      * Register our device for the file system.
00226      */
00227     NutRegisterDevice(&devUrom, 0, 0);
00228 
00229     /*
00230      * Register our CGI routines.
00231      */
00232     if(NutRegisterCgi(PORT_CONTROL_CGI, CpuPortControl))
00233         JUMP_RESET;
00234     if(NutRegisterCgi(PORT_STATUS_CGI, CpuPortStatus))
00235         JUMP_RESET;
00236     if(NutRegisterCgi(RELAY_CONTROL_CGI, SpiRelayControl))
00237         JUMP_RESET;
00238     if(NutRegisterCgi(OPTO_STATUS_CGI, SpiOptoStatus))
00239         JUMP_RESET;
00240 
00241     /*
00242      * Start a defined number of concurrent background
00243      * threads. The more threads we have running, the
00244      * more connections we can handle concurrently.
00245      * However, each thread occupies some additional
00246      * RAM.
00247      */
00248     for(i = 0; i < NUM_HTTP_THREADS - 1; i++) {
00249         char *thname = "httpd0";
00250         thname[5] = '0' + i;
00251         NutThreadCreate(thname, ServiceThread, 0, HTTP_THREAD_STACK);
00252     }
00253 
00254     /*
00255      * Loop endless for connections.
00256      */
00257     for(;;) 
00258         Service();
00259 }
00260 
00261 /*@}*/

© 2002-2004 by egnite Software GmbH - visit http://www.ethernut.de/