httpd/httpserv.c

Simple multithreaded HTTP daemon.

00001 /*
00002  * Copyright (C) 2001-2004 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. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00095 /* 
00096  * Unique MAC address of the Ethernut Board. 
00097  *
00098  * Ignored if EEPROM contains a valid configuration.
00099  */
00100 #define MY_MAC  "\x00\x06\x98\x30\x00\x35"
00101 
00102 /* 
00103  * Unique IP address of the Ethernut Board. 
00104  *
00105  * Ignored if DHCP is used. 
00106  */
00107 #define MY_IPADDR "192.168.192.35"
00108 
00109 /* 
00110  * IP network mask of the Ethernut Board.
00111  *
00112  * Ignored if DHCP is used. 
00113  */
00114 #define MY_IPMASK "255.255.255.0"
00115 
00116 /* 
00117  * Gateway IP address for the Ethernut Board.
00118  *
00119  * Ignored if DHCP is used. 
00120  */
00121 #define MY_IPGATE "192.168.192.1"
00122 
00123 /* ICCAVR Demo is limited. Try to use the bare minimum. */
00124 #if !defined(__IMAGECRAFT__)
00125 
00126 /* Wether we should use DHCP. */
00127 #define USE_DHCP
00128 /* Wether we should run a discovery responder. */
00129 #define USE_DISCOVERY
00130 /* Wether to use PHAT file system. */
00131 //#define USE_PHAT
00132 
00133 #endif /* __IMAGECRAFT__ */
00134 
00135 
00136 #ifdef USE_PHAT
00137 
00138 #if defined(ETHERNUT3)
00139 
00140 /* Ethernut 3 file system. */
00141 #define MY_FSDEV       devPhat0
00142 #define MY_FSDEV_NAME  "PHAT0" 
00143 
00144 /* Ethernut 3 block device interface. */
00145 #define MY_BLKDEV      devNplMmc0
00146 #define MY_BLKDEV_NAME "MMC0"
00147 
00148 #elif defined(AT91SAM7X_EK)
00149 
00150 /* SAM7X-EK file system. */
00151 #define MY_FSDEV       devPhat0
00152 #define MY_FSDEV_NAME  "PHAT0" 
00153 
00154 /* SAM7X-EK block device interface. */
00155 #define MY_BLKDEV      devAt91SpiMmc0
00156 #define MY_BLKDEV_NAME "MMC0"
00157 
00158 #elif defined(AT91SAM9260_EK)
00159 
00160 /* SAM9260-EK file system. */
00161 #define MY_FSDEV       devPhat0
00162 #define MY_FSDEV_NAME  "PHAT0" 
00163 
00164 /* SAM9260-EK block device interface. */
00165 #define MY_BLKDEV      devAt91Mci0
00166 #define MY_BLKDEV_NAME "MCI0"
00167 
00168 #endif
00169 #endif /* USE_PHAT */
00170 
00171 #ifndef MY_FSDEV
00172 #define MY_FSDEV        devUrom
00173 #endif
00174 
00175 #ifdef MY_FSDEV_NAME
00176 #define MY_HTTPROOT     MY_FSDEV_NAME ":/" 
00177 #endif
00178 
00179 
00180 #include <cfg/os.h>
00181 
00182 #include <string.h>
00183 #include <io.h>
00184 #include <fcntl.h>
00185 
00186 #include <dev/board.h>
00187 #include <dev/urom.h>
00188 #include <dev/nplmmc.h>
00189 #include <dev/sbimmc.h>
00190 #include <fs/phatfs.h>
00191 
00192 #include <sys/version.h>
00193 #include <sys/thread.h>
00194 #include <sys/timer.h>
00195 #include <sys/heap.h>
00196 #include <sys/confnet.h>
00197 #include <sys/socket.h>
00198 
00199 #include <arpa/inet.h>
00200 #include <net/route.h>
00201 
00202 #include <pro/httpd.h>
00203 #include <pro/dhcp.h>
00204 #include <pro/ssi.h>
00205 #include <pro/asp.h>
00206 #include <pro/discover.h>
00207 
00208 #ifdef NUTDEBUG
00209 #include <sys/osdebug.h>
00210 #include <net/netdebug.h>
00211 #endif
00212 
00213 static char *html_mt = "text/html";
00214 
00215 
00216 /**************************************************************/
00217 /*  ASPCallback                                               */
00218 /*                                                            */
00219 /* This routine must have been registered by                  */
00220 /* NutRegisterAspCallback() and is automatically called by    */
00221 /* NutHttpProcessFileRequest() when the server process a page */
00222 /* with an asp function.                                      */
00223 /*                                                            */
00224 /* Return 0 on success, -1 otherwise.                         */
00225 /**************************************************************/
00226 
00227 
00228 static int ASPCallback (char *pASPFunction, FILE *stream)
00229 {
00230     if (strcmp(pASPFunction, "usr_date") == 0) {
00231         fprintf(stream, "Dummy example: 01.01.2005");
00232         return(0);
00233     }
00234 
00235     if (strcmp(pASPFunction, "usr_time") == 0) {
00236         fprintf(stream, "Dummy example: 12:15:02");
00237         return(0);
00238     }
00239 
00240     return (-1);
00241 }
00242 
00243 /*
00244  * CGI Sample: Show request parameters.
00245  *
00246  * See httpd.h for REQUEST structure.
00247  *
00248  * This routine must have been registered by NutRegisterCgi() and is
00249  * automatically called by NutHttpProcessRequest() when the client
00250  * request the URL 'cgi-bin/test.cgi'.
00251  */
00252 static int ShowQuery(FILE * stream, REQUEST * req)
00253 {
00254     char *cp;
00255     /*
00256      * This may look a little bit weird if you are not used to C programming
00257      * for flash microcontrollers. The special type 'prog_char' forces the
00258      * string literals to be placed in flash ROM. This saves us a lot of
00259      * precious RAM.
00260      */
00261     static prog_char head[] = "<HTML><HEAD><TITLE>Parameters</TITLE></HEAD><BODY><H1>Parameters</H1>";
00262     static prog_char foot[] = "</BODY></HTML>";
00263     static prog_char req_fmt[] = "Method: %s<BR>\r\nVersion: HTTP/%d.%d<BR>\r\nContent length: %d<BR>\r\n";
00264     static prog_char url_fmt[] = "URL: %s<BR>\r\n";
00265     static prog_char query_fmt[] = "Argument: %s<BR>\r\n";
00266     static prog_char type_fmt[] = "Content type: %s<BR>\r\n";
00267     static prog_char cookie_fmt[] = "Cookie: %s<BR>\r\n";
00268     static prog_char auth_fmt[] = "Auth info: %s<BR>\r\n";
00269     static prog_char agent_fmt[] = "User agent: %s<BR>\r\n";
00270 
00271     /* These useful API calls create a HTTP response for us. */
00272     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00273     NutHttpSendHeaderBot(stream, html_mt, -1);
00274 
00275     /* Send HTML header. */
00276     fputs_P(head, stream);
00277 
00278     /*
00279      * Send request parameters.
00280      */
00281     switch (req->req_method) {
00282     case METHOD_GET:
00283         cp = "GET";
00284         break;
00285     case METHOD_POST:
00286         cp = "POST";
00287         break;
00288     case METHOD_HEAD:
00289         cp = "HEAD";
00290         break;
00291     default:
00292         cp = "UNKNOWN";
00293         break;
00294     }
00295     fprintf_P(stream, req_fmt, cp, req->req_version / 10, req->req_version % 10, req->req_length);
00296     if (req->req_url)
00297         fprintf_P(stream, url_fmt, req->req_url);
00298     if (req->req_query)
00299         fprintf_P(stream, query_fmt, req->req_query);
00300     if (req->req_type)
00301         fprintf_P(stream, type_fmt, req->req_type);
00302     if (req->req_cookie)
00303         fprintf_P(stream, cookie_fmt, req->req_cookie);
00304     if (req->req_auth)
00305         fprintf_P(stream, auth_fmt, req->req_auth);
00306     if (req->req_agent)
00307         fprintf_P(stream, agent_fmt, req->req_agent);
00308 
00309     /* Send HTML footer and flush output buffer. */
00310     fputs_P(foot, stream);
00311     fflush(stream);
00312 
00313     return 0;
00314 }
00315 
00316 /*
00317  * CGI Sample: Show list of threads.
00318  *
00319  * This routine must have been registered by NutRegisterCgi() and is
00320  * automatically called by NutHttpProcessRequest() when the client
00321  * request the URL 'cgi-bin/threads.cgi'.
00322  */
00323 static int ShowThreads(FILE * stream, REQUEST * req)
00324 {
00325     static prog_char head[] = "<HTML><HEAD><TITLE>Threads</TITLE></HEAD><BODY><H1>Threads</H1>\r\n"
00326         "<TABLE BORDER><TR><TH>Handle</TH><TH>Name</TH><TH>Priority</TH><TH>Status</TH><TH>Event<BR>Queue</TH><TH>Timer</TH><TH>Stack-<BR>pointer</TH><TH>Free<BR>Stack</TH></TR>\r\n";
00327 #if defined(__AVR__)
00328     static prog_char tfmt[] =
00329         "<TR><TD>%04X</TD><TD>%s</TD><TD>%u</TD><TD>%s</TD><TD>%04X</TD><TD>%04X</TD><TD>%04X</TD><TD>%u</TD><TD>%s</TD></TR>\r\n";
00330 #else
00331     static prog_char tfmt[] =
00332         "<TR><TD>%08lX</TD><TD>%s</TD><TD>%u</TD><TD>%s</TD><TD>%08lX</TD><TD>%08lX</TD><TD>%08lX</TD><TD>%lu</TD><TD>%s</TD></TR>\r\n";
00333 #endif
00334     static prog_char foot[] = "</TABLE></BODY></HTML>";
00335     static char *thread_states[] = { "TRM", "<FONT COLOR=#CC0000>RUN</FONT>", "<FONT COLOR=#339966>RDY</FONT>", "SLP" };
00336     NUTTHREADINFO *tdp = nutThreadList;
00337 
00338     /* Send HTTP response. */
00339     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00340     NutHttpSendHeaderBot(stream, html_mt, -1);
00341 
00342     /* Send HTML header. */
00343     fputs_P(head, stream);
00344     for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
00345         fprintf_P(stream, tfmt, (uptr_t) tdp, tdp->td_name, tdp->td_priority,
00346                   thread_states[tdp->td_state], (uptr_t) tdp->td_queue, (uptr_t) tdp->td_timer,
00347                   (uptr_t) tdp->td_sp, (uptr_t) tdp->td_sp - (uptr_t) tdp->td_memory,
00348                   *((u_long *) tdp->td_memory) != DEADBEEF ? "Corr" : "OK");
00349     }
00350     fputs_P(foot, stream);
00351     fflush(stream);
00352 
00353     return 0;
00354 }
00355 
00356 /*
00357  * CGI Sample: Show list of timers.
00358  *
00359  * This routine must have been registered by NutRegisterCgi() and is
00360  * automatically called by NutHttpProcessRequest() when the client
00361  * request the URL 'cgi-bin/timers.cgi'.
00362  */
00363 static int ShowTimers(FILE * stream, REQUEST * req)
00364 {
00365     static prog_char head[] = "<HTML><HEAD><TITLE>Timers</TITLE></HEAD><BODY><H1>Timers</H1>\r\n";
00366     static prog_char thead[] =
00367         "<TABLE BORDER><TR><TH>Handle</TH><TH>Countdown</TH><TH>Tick Reload</TH><TH>Callback<BR>Address</TH><TH>Callback<BR>Argument</TH></TR>\r\n";
00368 #if defined(__AVR__)
00369     static prog_char tfmt[] = "<TR><TD>%04X</TD><TD>%lu</TD><TD>%lu</TD><TD>%04X</TD><TD>%04X</TD></TR>\r\n";
00370 #else
00371     static prog_char tfmt[] = "<TR><TD>%08lX</TD><TD>%lu</TD><TD>%lu</TD><TD>%08lX</TD><TD>%08lX</TD></TR>\r\n";
00372 #endif
00373     static prog_char foot[] = "</TABLE></BODY></HTML>";
00374     NUTTIMERINFO *tnp;
00375     u_long ticks_left;
00376 
00377     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00378     NutHttpSendHeaderBot(stream, html_mt, -1);
00379 
00380     /* Send HTML header. */
00381     fputs_P(head, stream);
00382     if ((tnp = nutTimerList) != 0) {
00383         fputs_P(thead, stream);
00384         ticks_left = 0;
00385         while (tnp) {
00386             ticks_left += tnp->tn_ticks_left;
00387             fprintf_P(stream, tfmt, (uptr_t) tnp, ticks_left, tnp->tn_ticks, (uptr_t) tnp->tn_callback, (uptr_t) tnp->tn_arg);
00388             tnp = tnp->tn_next;
00389         }
00390     }
00391 
00392     fputs_P(foot, stream);
00393     fflush(stream);
00394 
00395     return 0;
00396 }
00397 
00398 /*
00399  * CGI Sample: Show list of sockets.
00400  *
00401  * This routine must have been registered by NutRegisterCgi() and is
00402  * automatically called by NutHttpProcessRequest() when the client
00403  * request the URL 'cgi-bin/sockets.cgi'.
00404  */
00405 static int ShowSockets(FILE * stream, REQUEST * req)
00406 {
00407     /* String literals are kept in flash ROM. */
00408     static prog_char head[] = "<HTML><HEAD><TITLE>Sockets</TITLE></HEAD>"
00409         "<BODY><H1>Sockets</H1>\r\n"
00410         "<TABLE BORDER><TR><TH>Handle</TH><TH>Type</TH><TH>Local</TH><TH>Remote</TH><TH>Status</TH></TR>\r\n";
00411 #if defined(__AVR__)
00412     static prog_char tfmt1[] = "<TR><TD>%04X</TD><TD>TCP</TD><TD>%s:%u</TD>";
00413 #else
00414     static prog_char tfmt1[] = "<TR><TD>%08lX</TD><TD>TCP</TD><TD>%s:%u</TD>";
00415 #endif
00416     static prog_char tfmt2[] = "<TD>%s:%u</TD><TD>";
00417     static prog_char foot[] = "</TABLE></BODY></HTML>";
00418     static prog_char st_listen[] = "LISTEN";
00419     static prog_char st_synsent[] = "SYNSENT";
00420     static prog_char st_synrcvd[] = "SYNRCVD";
00421     static prog_char st_estab[] = "<FONT COLOR=#CC0000>ESTABL</FONT>";
00422     static prog_char st_finwait1[] = "FINWAIT1";
00423     static prog_char st_finwait2[] = "FINWAIT2";
00424     static prog_char st_closewait[] = "CLOSEWAIT";
00425     static prog_char st_closing[] = "CLOSING";
00426     static prog_char st_lastack[] = "LASTACK";
00427     static prog_char st_timewait[] = "TIMEWAIT";
00428     static prog_char st_closed[] = "CLOSED";
00429     static prog_char st_unknown[] = "UNKNOWN";
00430     prog_char *st_P;
00431     extern TCPSOCKET *tcpSocketList;
00432     TCPSOCKET *ts;
00433 
00434     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00435     NutHttpSendHeaderBot(stream, html_mt, -1);
00436 
00437     /* Send HTML header. */
00438     fputs_P(head, stream);
00439     for (ts = tcpSocketList; ts; ts = ts->so_next) {
00440         switch (ts->so_state) {
00441         case TCPS_LISTEN:
00442             st_P = (prog_char *) st_listen;
00443             break;
00444         case TCPS_SYN_SENT:
00445             st_P = (prog_char *) st_synsent;
00446             break;
00447         case TCPS_SYN_RECEIVED:
00448             st_P = (prog_char *) st_synrcvd;
00449             break;
00450         case TCPS_ESTABLISHED:
00451             st_P = (prog_char *) st_estab;
00452             break;
00453         case TCPS_FIN_WAIT_1:
00454             st_P = (prog_char *) st_finwait1;
00455             break;
00456         case TCPS_FIN_WAIT_2:
00457             st_P = (prog_char *) st_finwait2;
00458             break;
00459         case TCPS_CLOSE_WAIT:
00460             st_P = (prog_char *) st_closewait;
00461             break;
00462         case TCPS_CLOSING:
00463             st_P = (prog_char *) st_closing;
00464             break;
00465         case TCPS_LAST_ACK:
00466             st_P = (prog_char *) st_lastack;
00467             break;
00468         case TCPS_TIME_WAIT:
00469             st_P = (prog_char *) st_timewait;
00470             break;
00471         case TCPS_CLOSED:
00472             st_P = (prog_char *) st_closed;
00473             break;
00474         default:
00475             st_P = (prog_char *) st_unknown;
00476             break;
00477         }
00478         /*
00479          * Fixed a bug reported by Zhao Weigang.
00480          */
00481         fprintf_P(stream, tfmt1, (uptr_t) ts, inet_ntoa(ts->so_local_addr), ntohs(ts->so_local_port));
00482         fprintf_P(stream, tfmt2, inet_ntoa(ts->so_remote_addr), ntohs(ts->so_remote_port));
00483         fputs_P(st_P, stream);
00484         fputs("</TD></TR>\r\n", stream);
00485         fflush(stream);
00486     }
00487 
00488     fputs_P(foot, stream);
00489     fflush(stream);
00490 
00491     return 0;
00492 }
00493 
00494 /*
00495  * CGI Sample: Proccessing a form.
00496  *
00497  * This routine must have been registered by NutRegisterCgi() and is
00498  * automatically called by NutHttpProcessRequest() when the client
00499  * request the URL 'cgi-bin/form.cgi'.
00500  *
00501  * Thanks to Tom Boettger, who provided this sample for ICCAVR.
00502  */
00503 int ShowForm(FILE * stream, REQUEST * req)
00504 {
00505     static prog_char html_head[] = "<HTML><BODY><BR><H1>Form Result</H1><BR><BR>";
00506     static prog_char html_body[] = "<BR><BR><p><a href=\"../index.html\">return to main</a></BODY></HTML></p>";
00507 
00508     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00509     NutHttpSendHeaderBot(stream, html_mt, -1);
00510 
00511     /* Send HTML header. */
00512     fputs_P(html_head, stream);
00513 
00514     if (req->req_query) {
00515         char *name;
00516         char *value;
00517         int i;
00518         int count;
00519 
00520         count = NutHttpGetParameterCount(req);
00521         /* Extract count parameters. */
00522         for (i = 0; i < count; i++) {
00523             name = NutHttpGetParameterName(req, i);
00524             value = NutHttpGetParameterValue(req, i);
00525 
00526             /* Send the parameters back to the client. */
00527 
00528 #ifdef __IMAGECRAFT__
00529             fprintf(stream, "%s: %s<BR>\r\n", name, value);
00530 #else
00531             fprintf_P(stream, PSTR("%s: %s<BR>\r\n"), name, value);
00532 #endif
00533         }
00534     }
00535 
00536     fputs_P(html_body, stream);
00537     fflush(stream);
00538 
00539     return 0;
00540 }
00541 
00554 THREAD(Service, arg)
00555 {
00556     TCPSOCKET *sock;
00557     FILE *stream;
00558     u_char id = (u_char) ((uptr_t) arg);
00559 
00560     /*
00561      * Now loop endless for connections.
00562      */
00563     for (;;) {
00564 
00565         /*
00566          * Create a socket.
00567          */
00568         if ((sock = NutTcpCreateSocket()) == 0) {
00569             printf("[%u] Creating socket failed\n", id);
00570             NutSleep(5000);
00571             continue;
00572         }
00573 
00574         /*
00575          * Listen on port 80. This call will block until we get a connection
00576          * from a client.
00577          */
00578         NutTcpAccept(sock, 80);
00579 #if defined(__AVR__)
00580         printf("[%u] Connected, %u bytes free\n", id, NutHeapAvailable());
00581 #else
00582         printf("[%u] Connected, %lu bytes free\n", id, NutHeapAvailable());
00583 #endif
00584 
00585         /*
00586          * Wait until at least 8 kByte of free RAM is available. This will
00587          * keep the client connected in low memory situations.
00588          */
00589 #if defined(__AVR__)
00590         while (NutHeapAvailable() < 8192) {
00591 #else
00592         while (NutHeapAvailable() < 4096) {
00593 #endif
00594             printf("[%u] Low mem\n", id);
00595             NutSleep(1000);
00596         }
00597 
00598         /*
00599          * Associate a stream with the socket so we can use standard I/O calls.
00600          */
00601         if ((stream = _fdopen((int) ((uptr_t) sock), "r+b")) == 0) {
00602             printf("[%u] Creating stream device failed\n", id);
00603         } else {
00604             /*
00605              * This API call saves us a lot of work. It will parse the
00606              * client's HTTP request, send any requested file from the
00607              * registered file system or handle CGI requests by calling
00608              * our registered CGI routine.
00609              */
00610             NutHttpProcessRequest(stream);
00611 
00612             /*
00613              * Destroy the virtual stream device.
00614              */
00615             fclose(stream);
00616         }
00617 
00618         /*
00619          * Close our socket.
00620          */
00621         NutTcpCloseSocket(sock);
00622         printf("[%u] Disconnected\n", id);
00623     }
00624 }
00625 
00631 int main(void)
00632 {
00633     u_long baud = 115200;
00634     u_char i;
00635 
00636     /*
00637      * Initialize the uart device.
00638      */
00639     NutRegisterDevice(&DEV_DEBUG, 0, 0);
00640     freopen(DEV_DEBUG_NAME, "w", stdout);
00641     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00642     NutSleep(200);
00643     printf("\n\nNut/OS %s HTTP Daemon...", NutVersionString());
00644 
00645 #ifdef NUTDEBUG
00646     NutTraceTcp(stdout, 0);
00647     NutTraceOs(stdout, 0);
00648     NutTraceHeap(stdout, 0);
00649     NutTracePPP(stdout, 0);
00650 #endif
00651 
00652     /*
00653      * Register Ethernet controller.
00654      */
00655     if (NutRegisterDevice(&DEV_ETHER, 0, 0)) {
00656         puts("Registering device failed");
00657     }
00658 
00659     printf("Configure %s...", DEV_ETHER_NAME);
00660     if (NutNetLoadConfig(DEV_ETHER_NAME)) {
00661         u_char mac[] = MY_MAC;
00662 
00663         printf("initial boot...");
00664 #ifdef USE_DHCP
00665         if (NutDhcpIfConfig(DEV_ETHER_NAME, mac, 60000)) 
00666 #endif
00667         {
00668             u_long ip_addr = inet_addr(MY_IPADDR);
00669             u_long ip_mask = inet_addr(MY_IPMASK);
00670             u_long ip_gate = inet_addr(MY_IPGATE);
00671 
00672             printf("No DHCP...");
00673             if (NutNetIfConfig(DEV_ETHER_NAME, mac, ip_addr, ip_mask) == 0) {
00674                 /* Without DHCP we had to set the default gateway manually.*/
00675                 if(ip_gate) {
00676                     printf("hard coded gate...");
00677                     NutIpRouteAdd(0, 0, ip_gate, &DEV_ETHER);
00678                 }
00679                 puts("OK");
00680             }
00681             else {
00682                 puts("failed");
00683             }
00684         }
00685     }
00686     else {
00687 #ifdef USE_DHCP
00688         if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
00689             puts("failed");
00690         }
00691         else {
00692             puts("OK");
00693         }
00694 #else
00695         if (NutNetIfConfig(DEV_ETHER_NAME, 0, 0, confnet.cdn_ip_mask)) {
00696             puts("failed");
00697         }
00698         else {
00699             puts("OK");
00700         }
00701 #endif
00702     }
00703     printf("%s ready\n", inet_ntoa(confnet.cdn_ip_addr));
00704 
00705 #ifdef USE_DISCOVERY
00706     NutRegisterDiscovery((u_long)-1, 0, DISF_INITAL_ANN);
00707 #endif
00708 
00709     /*
00710      * Register our device for the file system.
00711      */
00712     NutRegisterDevice(&MY_FSDEV, 0, 0);
00713 
00714 #ifdef MY_BLKDEV
00715     /* Register block device. */
00716     printf("Registering block device '" MY_BLKDEV_NAME "'...");
00717     if (NutRegisterDevice(&MY_BLKDEV, 0, 0)) {
00718         puts("failed");
00719         for (;;);
00720     }
00721     puts("OK");
00722 
00723     /* Mount partition. */
00724     printf("Mounting block device '" MY_BLKDEV_NAME ":1/" MY_FSDEV_NAME "'...");
00725     if (_open(MY_BLKDEV_NAME ":1/" MY_FSDEV_NAME, _O_RDWR | _O_BINARY) == -1) {
00726         puts("failed");
00727         for (;;);
00728     }
00729     puts("OK");
00730 #endif
00731 
00732 #ifdef MY_HTTPROOT
00733     /* Register root path. */
00734     printf("Registering HTTP root '" MY_HTTPROOT "'...");
00735     if (NutRegisterHttpRoot(MY_HTTPROOT)) {
00736         puts("failed");
00737         for (;;);
00738     }
00739     puts("OK");
00740 #endif
00741 
00742     /*
00743      * Register our CGI sample. This will be called
00744      * by http://host/cgi-bin/test.cgi?anyparams
00745      */
00746     NutRegisterCgi("test.cgi", ShowQuery);
00747 
00748     /*
00749      * Register some CGI samples, which display interesting
00750      * system informations.
00751      */
00752     NutRegisterCgi("threads.cgi", ShowThreads);
00753     NutRegisterCgi("timers.cgi", ShowTimers);
00754     NutRegisterCgi("sockets.cgi", ShowSockets);
00755 
00756     /*
00757      * Finally a CGI example to process a form.
00758      */
00759     NutRegisterCgi("form.cgi", ShowForm);
00760 
00761     /*
00762      * Protect the cgi-bin directory with
00763      * user and password.
00764      */
00765     NutRegisterAuth("cgi-bin", "root:root");
00766 
00767     /*
00768      * Register SSI and ASP handler
00769      */
00770     NutRegisterSsi();
00771     NutRegisterAsp();
00772     NutRegisterAspCallback(ASPCallback);
00773     /*
00774      * Start four server threads.
00775      */
00776     for (i = 1; i <= 4; i++) {
00777         char thname[] = "httpd0";
00778 
00779         thname[5] = '0' + i;
00780         NutThreadCreate(thname, Service, (void *) (uptr_t) i, NUT_THREAD_MAINSTACK);
00781     }
00782 
00783     /*
00784      * We could do something useful here, like serving a watchdog.
00785      */
00786     NutThreadSetPriority(254);
00787     for (;;) {
00788         NutSleep(60000);
00789     }
00790 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/