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 }