00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
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 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 static const char closed[] =   
00073 {0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
00074 static const char syn_rcvd[] = 
00075 {0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, 
00076  0x44,  0};
00077 static const char syn_sent[] = 
00078 {0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, 
00079  0x54,  0};
00080 static const char established[] = 
00081 {0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 
00082  0x45, 0x44, 0};
00083 static const char fin_wait_1[] = 
00084 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 
00085  0x54, 0x2d, 0x31, 0};
00086 static const char fin_wait_2[] = 
00087 {0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 
00088  0x54, 0x2d, 0x32, 0};
00089 static const char closing[] = 
00090 {0x43, 0x4c, 0x4f, 0x53, 0x49, 
00091  0x4e, 0x47, 0};
00092 static const char time_wait[] = 
00093 {0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, 
00094  0x49, 0x54, 0};
00095 static const char 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   
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, ((struct process *)p)->name, 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