1 /** 2 * \addtogroup httpd 3 * @{ 4 */ 5 6 /** 7 * \file 8 * Web server script interface 9 * \author 10 * Adam Dunkels <[email protected]> 11 * 12 */ 13 14 /* 15 * Copyright (c) 2001-2006, Adam Dunkels. 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. The name of the author may not be used to endorse or promote 27 * products derived from this software without specific prior 28 * written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * 42 * This file is part of the uIP TCP/IP stack. 43 * 44 * $Id: httpd-cgi.c,v 1.2 2006/06/11 21:46:37 adam Exp $ 45 * 46 */ 47 48 #include "uip.h" 49 #include "psock.h" 50 #include "httpd.h" 51 #include "httpd-cgi.h" 52 #include "httpd-fs.h" 53 54 #include <stdio.h> 55 #include <string.h> 56 57 HTTPD_CGI_CALL(file, "file-stats", file_stats); 58 HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats); 59 HTTPD_CGI_CALL(net, "net-stats", net_stats); 60 61 static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, NULL }; 62 63 /*---------------------------------------------------------------------------*/ 64 static 65 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr)) 66 { 67 PSOCK_BEGIN(&s->sout); 68 PSOCK_END(&s->sout); 69 } 70 /*---------------------------------------------------------------------------*/ 71 httpd_cgifunction 72 httpd_cgi(char *name) 73 { 74 const struct httpd_cgi_call **f; 75 76 /* Find the matching name in the table, return the function. */ 77 for(f = calls; *f != NULL; ++f) { 78 if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) { 79 return (*f)->function; 80 } 81 } 82 return nullfunction; 83 } 84 /*---------------------------------------------------------------------------*/ 85 static unsigned short 86 generate_file_stats(void *arg) 87 { 88 char *f = (char *)arg; 89 return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f)); 90 } 91 /*---------------------------------------------------------------------------*/ 92 static 93 PT_THREAD(file_stats(struct httpd_state *s, char *ptr)) 94 { 95 PSOCK_BEGIN(&s->sout); 96 97 PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1); 98 99 PSOCK_END(&s->sout); 100 } 101 /*---------------------------------------------------------------------------*/ 102 static const char closed[] = /* "CLOSED",*/ 103 {0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0}; 104 static const char syn_rcvd[] = /* "SYN-RCVD",*/ 105 {0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, 106 0x44, 0}; 107 static const char syn_sent[] = /* "SYN-SENT",*/ 108 {0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, 109 0x54, 0}; 110 static const char established[] = /* "ESTABLISHED",*/ 111 {0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 112 0x45, 0x44, 0}; 113 static const char fin_wait_1[] = /* "FIN-WAIT-1",*/ 114 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 115 0x54, 0x2d, 0x31, 0}; 116 static const char fin_wait_2[] = /* "FIN-WAIT-2",*/ 117 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 118 0x54, 0x2d, 0x32, 0}; 119 static const char closing[] = /* "CLOSING",*/ 120 {0x43, 0x4c, 0x4f, 0x53, 0x49, 121 0x4e, 0x47, 0}; 122 static const char time_wait[] = /* "TIME-WAIT,"*/ 123 {0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, 124 0x49, 0x54, 0}; 125 static const char last_ack[] = /* "LAST-ACK"*/ 126 {0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, 127 0x4b, 0}; 128 129 static const char *states[] = { 130 closed, 131 syn_rcvd, 132 syn_sent, 133 established, 134 fin_wait_1, 135 fin_wait_2, 136 closing, 137 time_wait, 138 last_ack}; 139 140 141 static unsigned short 142 generate_tcp_stats(void *arg) 143 { 144 struct uip_conn *conn; 145 struct httpd_state *s = (struct httpd_state *)arg; 146 147 conn = &uip_conns[s->count]; 148 return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, 149 "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n", 150 htons(conn->lport), 151 htons(conn->ripaddr[0]) >> 8, 152 htons(conn->ripaddr[0]) & 0xff, 153 htons(conn->ripaddr[1]) >> 8, 154 htons(conn->ripaddr[1]) & 0xff, 155 htons(conn->rport), 156 states[conn->tcpstateflags & UIP_TS_MASK], 157 conn->nrtx, 158 conn->timer, 159 (uip_outstanding(conn))? '*':' ', 160 (uip_stopped(conn))? '!':' '); 161 } 162 /*---------------------------------------------------------------------------*/ 163 static 164 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr)) 165 { 166 167 PSOCK_BEGIN(&s->sout); 168 169 for(s->count = 0; s->count < UIP_CONNS; ++s->count) { 170 if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { 171 PSOCK_GENERATOR_SEND(&s->sout, generate_tcp_stats, s); 172 } 173 } 174 175 PSOCK_END(&s->sout); 176 } 177 /*---------------------------------------------------------------------------*/ 178 static unsigned short 179 generate_net_stats(void *arg) 180 { 181 struct httpd_state *s = (struct httpd_state *)arg; 182 return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, 183 "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]); 184 } 185 186 static 187 PT_THREAD(net_stats(struct httpd_state *s, char *ptr)) 188 { 189 PSOCK_BEGIN(&s->sout); 190 191 #if UIP_STATISTICS 192 193 for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); 194 ++s->count) { 195 PSOCK_GENERATOR_SEND(&s->sout, generate_net_stats, s); 196 } 197 198 #endif /* UIP_STATISTICS */ 199 200 PSOCK_END(&s->sout); 201 } 202 /*---------------------------------------------------------------------------*/ 203 /** @} */ 204