Contiki 2.6

httpd-cgi.c

00001 /*
00002  * Copyright (c) 2001, Adam Dunkels.
00003  * All rights reserved. 
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions 
00007  * are met: 
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. The name of the author may not be used to endorse or promote
00014  *    products derived from this software without specific prior
00015  *    written permission.  
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00018  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00021  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00023  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00025  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00028  *
00029  * This file is part of the uIP TCP/IP stack.
00030  *
00031  * $Id: httpd-cgi.c,v 1.2 2010/10/19 18:29:05 adamdunkels Exp $
00032  *
00033  */
00034 
00035 /*
00036  * This file includes functions that are called by the web server
00037  * scripts. The functions takes no argument, and the return value is
00038  * interpreted as follows. A zero means that the function did not
00039  * complete and should be invoked for the next packet as well. A
00040  * non-zero value indicates that the function has completed and that
00041  * the web server should move along to the next script line.
00042  *
00043  */
00044 
00045 
00046 #include "contiki-net.h"
00047 #include "httpd.h"
00048 #include "httpd-cgi.h"
00049 #include "httpd-fs.h"
00050 
00051 #include "lib/petsciiconv.h"
00052 
00053 #include <stdio.h>
00054 #include <string.h>
00055 
00056 
00057 static struct httpd_cgi_call *calls = NULL;
00058 
00059 /*struct cgifunction {
00060   char *name;
00061   httpd_cgifunction function;
00062 };
00063 
00064 static struct cgifunction cgitab[] = {
00065   {"file-stats", file_stats},
00066   {"tcp-connections", tcp_stats},
00067   {"processes", processes},
00068   {NULL, NULL}
00069   };*/
00070 
00071 
00072 static const char closed[] =   /*  "CLOSED",*/
00073 {0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
00074 static const char syn_rcvd[] = /*  "SYN-RCVD",*/
00075 {0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, 
00076  0x44,  0};
00077 static const char syn_sent[] = /*  "SYN-SENT",*/
00078 {0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, 
00079  0x54,  0};
00080 static const char established[] = /*  "ESTABLISHED",*/
00081 {0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 
00082  0x45, 0x44, 0};
00083 static const char fin_wait_1[] = /*  "FIN-WAIT-1",*/
00084 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 
00085  0x54, 0x2d, 0x31, 0};
00086 static const char fin_wait_2[] = /*  "FIN-WAIT-2",*/
00087 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 
00088  0x54, 0x2d, 0x32, 0};
00089 static const char closing[] = /*  "CLOSING",*/
00090 {0x43, 0x4c, 0x4f, 0x53, 0x49, 
00091  0x4e, 0x47, 0};
00092 static const char time_wait[] = /*  "TIME-WAIT,"*/
00093 {0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, 
00094  0x49, 0x54, 0};
00095 static const char last_ack[] = /*  "LAST-ACK"*/
00096 {0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, 
00097  0x4b, 0};
00098 static const char none[] = "NONE";
00099 static const char init[] = "INIT";
00100 static const char running[] = "RUNNING";
00101 static const char needs_poll[] = "NEEDS POLL";
00102 
00103 static const char *states[] = {
00104   closed,
00105   syn_rcvd,
00106   syn_sent,
00107   established,
00108   fin_wait_1,
00109   fin_wait_2,
00110   closing,
00111   time_wait,
00112   last_ack,
00113   none,
00114   init,
00115   running,
00116   needs_poll};
00117   
00118 
00119 /*---------------------------------------------------------------------------*/
00120 static
00121 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
00122 {
00123   PSOCK_BEGIN(&s->sout);  
00124   PSOCK_END(&s->sout);
00125 }
00126 /*---------------------------------------------------------------------------*/
00127 httpd_cgifunction
00128 httpd_cgi(char *name)
00129 {
00130   struct httpd_cgi_call *f;
00131 
00132   /* Find the matching name in the table, return the function. */
00133   for(f = calls; f != NULL; f = f->next) {
00134     if(strncmp(f->name, name, strlen(f->name)) == 0) {
00135       return f->function;
00136     }
00137   }
00138   return nullfunction;
00139 }
00140 /*---------------------------------------------------------------------------*/
00141 static unsigned short
00142 generate_file_stats(void *arg)
00143 {
00144   char *f = (char *)arg;
00145   return sprintf((char *)uip_appdata, "%5u", httpd_fs_count(f));
00146 }
00147 /*---------------------------------------------------------------------------*/
00148 static
00149 PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
00150 {
00151   PSOCK_BEGIN(&s->sout);
00152 
00153   PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) (strchr(ptr, ' ') + 1));
00154   
00155   PSOCK_END(&s->sout);
00156 }
00157 /*---------------------------------------------------------------------------*/
00158 static unsigned short
00159 make_tcp_stats(void *arg)
00160 {
00161   struct uip_conn *conn;
00162   struct httpd_state *s = (struct httpd_state *)arg;
00163     
00164   conn = &uip_conns[s->u.count];
00165   return sprintf((char *)uip_appdata,
00166                  "<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",
00167                  uip_htons(conn->lport),
00168                  conn->ripaddr.u8[0],
00169                  conn->ripaddr.u8[1],
00170                  conn->ripaddr.u8[2],
00171                  conn->ripaddr.u8[3],
00172                  uip_htons(conn->rport),
00173                  states[conn->tcpstateflags & UIP_TS_MASK],
00174                  conn->nrtx,
00175                  conn->timer,
00176                  (uip_outstanding(conn))? '*':' ',
00177                  (uip_stopped(conn))? '!':' ');
00178 }
00179 /*---------------------------------------------------------------------------*/
00180 static
00181 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
00182 {
00183   
00184   PSOCK_BEGIN(&s->sout);
00185 
00186   for(s->u.count = 0; s->u.count < UIP_CONNS; ++s->u.count) {   
00187     if((uip_conns[s->u.count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
00188       PSOCK_GENERATOR_SEND(&s->sout, make_tcp_stats, s);
00189     }
00190   }
00191 
00192   PSOCK_END(&s->sout);
00193 }
00194 /*---------------------------------------------------------------------------*/
00195 static unsigned short
00196 make_processes(void *p)
00197 {
00198   char name[40];
00199 
00200   strncpy(name, PROCESS_NAME_STRING((struct process *)p), 40);
00201   petsciiconv_toascii(name, 40);
00202 
00203   return sprintf((char *)uip_appdata,
00204                  "<tr align=\"center\"><td>%p</td><td>%s</td><td>%p</td><td>%s</td></tr>\r\n",
00205                  p, name,
00206                  (char *)((struct process *)p)->thread,
00207                  states[9 + ((struct process *)p)->state]);
00208 }
00209 /*---------------------------------------------------------------------------*/
00210 static
00211 PT_THREAD(processes(struct httpd_state *s, char *ptr))
00212 {
00213   PSOCK_BEGIN(&s->sout);
00214   for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
00215     PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
00216   }
00217   PSOCK_END(&s->sout);
00218 }
00219 /*---------------------------------------------------------------------------*/
00220 void
00221 httpd_cgi_add(struct httpd_cgi_call *c)
00222 {
00223   struct httpd_cgi_call *l;
00224 
00225   c->next = NULL;
00226   if(calls == NULL) {
00227     calls = c;
00228   } else {
00229     for(l = calls; l->next != NULL; l = l->next);
00230     l->next = c;
00231   }
00232 }
00233 /*---------------------------------------------------------------------------*/
00234 
00235 HTTPD_CGI_CALL(file, "file-stats", file_stats);
00236 HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats);
00237 HTTPD_CGI_CALL(proc, "processes", processes);
00238 
00239 void
00240 httpd_cgi_init(void)
00241 {
00242   httpd_cgi_add(&file);
00243   httpd_cgi_add(&tcp);
00244   httpd_cgi_add(&proc);
00245 }
00246 /*---------------------------------------------------------------------------*/