Passed tests on Raven 1284p in 3 seconds with 56KB program memory disk
[contiki-2.x.git] / apps / webserver / httpd-cgi.c
blobfdf4ccd18167a672ed68617a2dd1acdc9486ce87
1 /*
2 * Copyright (c) 2001, Adam Dunkels.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior
15 * written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * This file is part of the uIP TCP/IP stack.
31 * $Id: httpd-cgi.c,v 1.14 2008/10/14 11:07:57 adamdunkels Exp $
36 * This file includes functions that are called by the web server
37 * scripts. The functions takes no argument, and the return value is
38 * interpreted as follows. A zero means that the function did not
39 * complete and should be invoked for the next packet as well. A
40 * non-zero value indicates that the function has completed and that
41 * the web server should move along to the next script line.
45 #include <stdio.h>
46 #include <string.h>
48 #include "contiki-net.h"
49 #include "httpd.h"
50 #include "httpd-cgi.h"
51 #include "httpd-fs.h"
53 #include "lib/petsciiconv.h"
55 static struct httpd_cgi_call *calls = NULL;
57 static const char closed[] = /* "CLOSED",*/
58 {0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
59 static const char syn_rcvd[] = /* "SYN-RCVD",*/
60 {0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56,
61 0x44, 0};
62 static const char syn_sent[] = /* "SYN-SENT",*/
63 {0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e,
64 0x54, 0};
65 static const char established[] = /* "ESTABLISHED",*/
66 {0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49,
67 0x53, 0x48, 0x45, 0x44, 0};
68 static const char fin_wait_1[] = /* "FIN-WAIT-1",*/
69 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
70 0x54, 0x2d, 0x31, 0};
71 static const char fin_wait_2[] = /* "FIN-WAIT-2",*/
72 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
73 0x54, 0x2d, 0x32, 0};
74 static const char closing[] = /* "CLOSING",*/
75 {0x43, 0x4c, 0x4f, 0x53, 0x49,
76 0x4e, 0x47, 0};
77 static const char time_wait[] = /* "TIME-WAIT,"*/
78 {0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41,
79 0x49, 0x54, 0};
80 static const char last_ack[] = /* "LAST-ACK"*/
81 {0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43,
82 0x4b, 0};
83 static const char none[] = /* "NONE"*/
84 {0x4e, 0x4f, 0x4e, 0x45, 0};
85 static const char running[] = /* "RUNNING"*/
86 {0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47,
87 0};
88 static const char called[] = /* "CALLED"*/
89 {0x43, 0x41, 0x4c, 0x4c, 0x45, 0x44, 0};
90 static const char file_name[] = /* "file-stats"*/
91 {0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
92 0x61, 0x74, 0x73, 0};
93 static const char tcp_name[] = /* "tcp-connections"*/
94 {0x74, 0x63, 0x70, 0x2d, 0x63, 0x6f, 0x6e,
95 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
96 0x73, 0};
97 static const char proc_name[] = /* "processes"*/
98 {0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
99 0x65, 0x73, 0};
101 static const char *states[] = {
102 closed,
103 syn_rcvd,
104 syn_sent,
105 established,
106 fin_wait_1,
107 fin_wait_2,
108 closing,
109 time_wait,
110 last_ack,
111 none,
112 running,
113 called};
115 /*---------------------------------------------------------------------------*/
116 static
117 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
119 PSOCK_BEGIN(&s->sout);
120 PSOCK_END(&s->sout);
122 /*---------------------------------------------------------------------------*/
123 httpd_cgifunction
124 httpd_cgi(char *name)
126 struct httpd_cgi_call *f;
128 /* Find the matching name in the table, return the function. */
129 for(f = calls; f != NULL; f = f->next) {
130 if(strncmp(f->name, name, strlen(f->name)) == 0) {
131 return f->function;
134 return nullfunction;
136 /*---------------------------------------------------------------------------*/
137 static unsigned short
138 generate_file_stats(void *arg)
140 char *f = (char *)arg;
141 return snprintf((char *)uip_appdata, uip_mss(), "%5u", httpd_fs_count(f));
143 /*---------------------------------------------------------------------------*/
144 static
145 PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
147 PSOCK_BEGIN(&s->sout);
149 PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) (strchr(ptr, ' ') + 1));
151 PSOCK_END(&s->sout);
153 /*---------------------------------------------------------------------------*/
154 static unsigned short
155 make_tcp_stats(void *arg)
157 struct uip_conn *conn;
158 struct httpd_state *s = (struct httpd_state *)arg;
160 conn = &uip_conns[s->u.count];
161 return snprintf((char *)uip_appdata, uip_mss(),
162 "<tr align=\"center\"><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",
163 htons(conn->lport),
164 conn->ripaddr.u8[0],
165 conn->ripaddr.u8[1],
166 conn->ripaddr.u8[2],
167 conn->ripaddr.u8[3],
168 htons(conn->rport),
169 states[conn->tcpstateflags & UIP_TS_MASK],
170 conn->nrtx,
171 conn->timer,
172 (uip_outstanding(conn))? '*':' ',
173 (uip_stopped(conn))? '!':' ');
175 /*---------------------------------------------------------------------------*/
176 static
177 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
180 PSOCK_BEGIN(&s->sout);
182 for(s->u.count = 0; s->u.count < UIP_CONNS; ++s->u.count) {
183 if((uip_conns[s->u.count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
184 PSOCK_GENERATOR_SEND(&s->sout, make_tcp_stats, s);
188 PSOCK_END(&s->sout);
190 /*---------------------------------------------------------------------------*/
191 static unsigned short
192 make_processes(void *p)
194 char name[40];
196 strncpy(name, ((struct process *)p)->name, 40);
197 petsciiconv_toascii(name, 40);
199 return snprintf((char *)uip_appdata, uip_mss(),
200 "<tr align=\"center\"><td>%p</td><td>%s</td><td>%p</td><td>%s</td></tr>\r\n",
201 p, name,
202 *((char **)&(((struct process *)p)->thread)),
203 states[9 + ((struct process *)p)->state]);
205 /*---------------------------------------------------------------------------*/
206 static
207 PT_THREAD(processes(struct httpd_state *s, char *ptr))
209 PSOCK_BEGIN(&s->sout);
210 for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
211 PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
213 PSOCK_END(&s->sout);
215 /*---------------------------------------------------------------------------*/
216 void
217 httpd_cgi_add(struct httpd_cgi_call *c)
219 struct httpd_cgi_call *l;
221 c->next = NULL;
222 if(calls == NULL) {
223 calls = c;
224 } else {
225 for(l = calls; l->next != NULL; l = l->next);
226 l->next = c;
229 /*---------------------------------------------------------------------------*/
231 HTTPD_CGI_CALL(file, file_name, file_stats);
232 HTTPD_CGI_CALL(tcp, tcp_name, tcp_stats);
233 HTTPD_CGI_CALL(proc, proc_name, processes);
235 void
236 httpd_cgi_init(void)
238 httpd_cgi_add(&file);
239 httpd_cgi_add(&tcp);
240 httpd_cgi_add(&proc);
242 /*---------------------------------------------------------------------------*/