📄 httpserv.c
字号:
#endif static prog_char tfmt2[] = "<TD>%s:%u</TD><TD>"; static prog_char foot[] = "</TABLE></BODY></HTML>"; static prog_char st_listen[] = "LISTEN"; static prog_char st_synsent[] = "SYNSENT"; static prog_char st_synrcvd[] = "SYNRCVD"; static prog_char st_estab[] = "<FONT COLOR=#CC0000>ESTABL</FONT>"; static prog_char st_finwait1[] = "FINWAIT1"; static prog_char st_finwait2[] = "FINWAIT2"; static prog_char st_closewait[] = "CLOSEWAIT"; static prog_char st_closing[] = "CLOSING"; static prog_char st_lastack[] = "LASTACK"; static prog_char st_timewait[] = "TIMEWAIT"; static prog_char st_closed[] = "CLOSED"; static prog_char st_unknown[] = "UNKNOWN"; prog_char *st_P; extern TCPSOCKET *tcpSocketList; TCPSOCKET *ts; NutHttpSendHeaderTop(stream, req, 200, "Ok"); NutHttpSendHeaderBot(stream, html_mt, -1); /* Send HTML header. */ fputs_P(head, stream); for (ts = tcpSocketList; ts; ts = ts->so_next) { switch (ts->so_state) { case TCPS_LISTEN: st_P = st_listen; break; case TCPS_SYN_SENT: st_P = st_synsent; break; case TCPS_SYN_RECEIVED: st_P = st_synrcvd; break; case TCPS_ESTABLISHED: st_P = st_estab; break; case TCPS_FIN_WAIT_1: st_P = st_finwait1; break; case TCPS_FIN_WAIT_2: st_P = st_finwait2; break; case TCPS_CLOSE_WAIT: st_P = st_closewait; break; case TCPS_CLOSING: st_P = st_closing; break; case TCPS_LAST_ACK: st_P = st_lastack; break; case TCPS_TIME_WAIT: st_P = st_timewait; break; case TCPS_CLOSED: st_P = st_closed; break; default: st_P = st_unknown; break; } /* * Fixed a bug reported by Zhao Weigang. */ fprintf_P(stream, tfmt1, (uptr_t) ts, inet_ntoa(ts->so_local_addr), ntohs(ts->so_local_port)); fprintf_P(stream, tfmt2, inet_ntoa(ts->so_remote_addr), ntohs(ts->so_remote_port)); fputs_P(st_P, stream); fputs("</TD></TR>\r\n", stream); fflush(stream); } fputs_P(foot, stream); fflush(stream); return 0;}/* * CGI Sample: Proccessing a form. * * This routine must have been registered by NutRegisterCgi() and is * automatically called by NutHttpProcessRequest() when the client * request the URL 'cgi-bin/form.cgi'. * * Thanks to Tom Boettger, who provided this sample for ICCAVR. */int ShowForm(FILE * stream, REQUEST * req){ static prog_char html_head[] = "<HTML><BODY><BR><H1>Form Result</H1><BR><BR>"; static prog_char html_body[] = "<BR><BR><p><a href=\"../index.html\">return to main</a></BODY></HTML></p>"; NutHttpSendHeaderTop(stream, req, 200, "Ok"); NutHttpSendHeaderBot(stream, html_mt, -1); /* Send HTML header. */ fputs_P(html_head, stream); if (req->req_query) { char *name; char *value; int i; int count; count = NutHttpGetParameterCount(req); /* Extract count parameters. */ for (i = 0; i < count; i++) { name = NutHttpGetParameterName(req, i); value = NutHttpGetParameterValue(req, i); /* Send the parameters back to the client. */#ifdef __IMAGECRAFT__ fprintf(stream, "%s: %s<BR>\r\n", name, value);#else fprintf_P(stream, PSTR("%s: %s<BR>\r\n"), name, value);#endif } } fputs_P(html_body, stream); fflush(stream); return 0;}/*! \fn Service(void *arg) * \brief HTTP service thread. * * The endless loop in this thread waits for a client connect, * processes the HTTP request and disconnects. Nut/Net doesn't * support a server backlog. If one client has established a * connection, further connect attempts will be rejected. * Typically browsers open more than one connection in order * to load images concurrently. So we run this routine by * several threads. * */THREAD(Service, arg){ TCPSOCKET *sock; FILE *stream; u_char id = (u_char) ((uptr_t) arg); /* * Now loop endless for connections. */ for (;;) { /* * Create a socket. */ if ((sock = NutTcpCreateSocket()) == 0) { printf("[%u] Creating socket failed\n", id); NutSleep(5000); continue; } /* * Listen on port 80. This call will block until we get a connection * from a client. */ NutTcpAccept(sock, 80);#if defined(__AVR__) printf("[%u] Connected, %u bytes free\n", id, NutHeapAvailable());#else printf("[%u] Connected, %lu bytes free\n", id, NutHeapAvailable());#endif /* * Wait until at least 8 kByte of free RAM is available. This will * keep the client connected in low memory situations. */#if defined(__AVR__) while (NutHeapAvailable() < 8192) {#else while (NutHeapAvailable() < 4096) {#endif printf("[%u] Low mem\n", id); NutSleep(1000); } /* * Associate a stream with the socket so we can use standard I/O calls. */ if ((stream = _fdopen((int) ((uptr_t) sock), "r+b")) == 0) { printf("[%u] Creating stream device failed\n", id); } else { /* * This API call saves us a lot of work. It will parse the * client's HTTP request, send any requested file from the * registered file system or handle CGI requests by calling * our registered CGI routine. */ NutHttpProcessRequest(stream); /* * Destroy the virtual stream device. */ fclose(stream); } /* * Close our socket. */ NutTcpCloseSocket(sock); printf("[%u] Disconnected\n", id); }}/*! * \brief Main application routine. * * Nut/OS automatically calls this entry after initialization. */int main(void){ u_long baud = 115200; u_char i; /* * Initialize the uart device. */ NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); NutSleep(200); printf("\n\nNut/OS %s HTTP Daemon...", NutVersionString());#ifdef NUTDEBUG NutTraceTcp(stdout, 0); NutTraceOs(stdout, 0); NutTraceHeap(stdout, 0); NutTracePPP(stdout, 0);#endif /* * Register Ethernet controller. */ if (NutRegisterDevice(&DEV_ETHER, 0, 0)) { puts("Registering device failed"); } /* * LAN configuration using EEPROM values or DHCP/ARP method. * If it fails, use fixed values. */ if (NutDhcpIfConfig("eth0", 0, 60000)) { u_char mac[] = { MYMAC }; u_long ip_addr = inet_addr(MYIP); u_long ip_mask = inet_addr(MYMASK); puts("EEPROM/DHCP/ARP config failed"); NutNetIfConfig("eth0", mac, ip_addr, ip_mask); } printf("%s ready\n", inet_ntoa(confnet.cdn_ip_addr)); /* * Register our device for the file system. */ NutRegisterDevice(&devUrom, 0, 0); /* * Register our CGI sample. This will be called * by http://host/cgi-bin/test.cgi?anyparams */ NutRegisterCgi("test.cgi", ShowQuery); /* * Register some CGI samples, which display interesting * system informations. */ NutRegisterCgi("threads.cgi", ShowThreads); NutRegisterCgi("timers.cgi", ShowTimers); NutRegisterCgi("sockets.cgi", ShowSockets); /* * Finally a CGI example to process a form. */ NutRegisterCgi("form.cgi", ShowForm); /* * Protect the cgi-bin directory with * user and password. */ NutRegisterAuth("cgi-bin", "root:root"); /* * Register SSI and ASP handler */ NutRegisterSsi(); NutRegisterAsp(); NutRegisterAspCallback(ASPCallback); /* * Start four server threads. */ for (i = 1; i <= 4; i++) { char *thname = "httpd0"; thname[5] = '0' + i; NutThreadCreate(thname, Service, (void *) (uptr_t) i, NUT_THREAD_MAINSTACK); } /* * We could do something useful here, like serving a watchdog. */ NutThreadSetPriority(254); for (;;) NutSleep(60000);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -