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.13 2010/12/23 19:41:07 dak664 Exp $
00032  *
00033  */
00034 /* Line endings in git repository are LF instead of CR-LF ? */
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 #include <stdio.h>
00046 #include <string.h>
00047 
00048 #include "contiki-net.h"
00049 #include "httpd.h"
00050 #include "httpd-cgi.h"
00051 #include "httpd-fs.h"
00052 #include "httpd-fsdata.h"
00053 #include "lib/petsciiconv.h"
00054 
00055 #include "sensors.h"
00056 
00057 #define DEBUGLOGIC 0        //See httpd.c, if 1 must also set it there!
00058 #if DEBUGLOGIC
00059 #define uip_mss(...) 512
00060 #define uip_appdata TCPBUF
00061 extern char TCPBUF[512];
00062 #endif
00063 
00064 /* RADIOSTATS must also be set in clock.c and the radio driver */
00065 #if RF230BB
00066 #define RADIOSTATS 1
00067 #endif
00068 
00069 static struct httpd_cgi_call *calls = NULL;
00070 
00071 /*cgi function names*/
00072 #if HTTPD_FS_STATISTICS
00073 static const char   file_name[] HTTPD_STRING_ATTR = "file-stats";
00074 #endif
00075 static const char    tcp_name[] HTTPD_STRING_ATTR = "tcp-connections";
00076 static const char   proc_name[] HTTPD_STRING_ATTR = "processes";
00077 static const char sensor_name[] HTTPD_STRING_ATTR = "sensors";
00078 static const char   adrs_name[] HTTPD_STRING_ATTR = "addresses";
00079 static const char   nbrs_name[] HTTPD_STRING_ATTR = "neighbors";
00080 static const char   rtes_name[] HTTPD_STRING_ATTR = "routes";
00081 
00082 /*Process states for processes cgi*/
00083 static const char      closed[] HTTPD_STRING_ATTR = "CLOSED";
00084 static const char    syn_rcvd[] HTTPD_STRING_ATTR = "SYN-RCVD";
00085 static const char    syn_sent[] HTTPD_STRING_ATTR = "SYN-SENT";
00086 static const char established[] HTTPD_STRING_ATTR = "ESTABLISHED";
00087 static const char  fin_wait_1[] HTTPD_STRING_ATTR = "FIN-WAIT-1";
00088 static const char  fin_wait_2[] HTTPD_STRING_ATTR = "FIN-WAIT-2";
00089 static const char     closing[] HTTPD_STRING_ATTR = "CLOSING";
00090 static const char   time_wait[] HTTPD_STRING_ATTR = "TIME-WAIT";
00091 static const char    last_ack[] HTTPD_STRING_ATTR = "LAST-ACK";
00092 static const char        none[] HTTPD_STRING_ATTR = "NONE";
00093 static const char     running[] HTTPD_STRING_ATTR = "RUNNING";
00094 static const char      called[] HTTPD_STRING_ATTR = "CALLED";
00095 static const char *states[] = {
00096   closed,
00097   syn_rcvd,
00098   syn_sent,
00099   established,
00100   fin_wait_1,
00101   fin_wait_2,
00102   closing,
00103   time_wait,
00104   last_ack,
00105   none,
00106   running,
00107   called};
00108 
00109   static char sensor_temperature[12]="Not Enabled";
00110   static char sensor_extvoltage[12]="Not Enabled";
00111   static unsigned long last_tempupdate,last_extvoltageupdate;
00112   extern unsigned long seconds, sleepseconds;
00113 #if RADIOSTATS
00114   extern unsigned long radioontime;
00115   static unsigned long savedradioontime;
00116   extern uint8_t RF230_radio_on, rf230_last_rssi;
00117   extern uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
00118 #endif
00119   
00120 
00121 void
00122 web_set_temp(char *s)
00123 {
00124   strcpy(sensor_temperature, s);
00125 //  printf_P(PSTR("got temp"));
00126   last_tempupdate=seconds;
00127 }
00128 void
00129 web_set_voltage(char *s)
00130 {
00131   strcpy(sensor_extvoltage, s);
00132 //    printf_P(PSTR("got volts"));
00133   last_extvoltageupdate=seconds;
00134 }
00135 
00136 /*---------------------------------------------------------------------------*/
00137 static
00138 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
00139 {
00140   PSOCK_BEGIN(&s->sout);
00141   PSOCK_END(&s->sout);
00142 }
00143 /*---------------------------------------------------------------------------*/
00144 httpd_cgifunction
00145 httpd_cgi(char *name)
00146 {
00147   struct httpd_cgi_call *f;
00148 
00149   /* Find the matching name in the table, return the function. */
00150   for(f = calls; f != NULL; f = f->next) {
00151     if(httpd_strncmp(name, f->name, httpd_strlen(f->name)) == 0) {
00152       return f->function;
00153     }
00154   }
00155   return nullfunction;
00156 }
00157 
00158 #if HTTPD_FS_STATISTICS
00159 static char *thisfilename;
00160 /*---------------------------------------------------------------------------*/
00161 static unsigned short
00162 generate_file_stats(void *arg)
00163 {
00164   static const char httpd_cgi_filestat1[] HTTPD_STRING_ATTR = "<p class=right><br><br><i>This page has been sent %u times</i></div></body></html>";
00165   static const char httpd_cgi_filestat2[] HTTPD_STRING_ATTR = "<tr><td><a href=\"%s\">%s</a></td><td>%d</td>";
00166   static const char httpd_cgi_filestat3[] HTTPD_STRING_ATTR = "%5u";
00167   char tmp[20];
00168   struct httpd_fsdata_file_noconst *f,fram;
00169   uint16_t i;
00170   unsigned short numprinted;
00171 
00172   /* Transfer arg from whichever flash that contains the html file to RAM */
00173   httpd_fs_cpy(&tmp, (char *)arg, 20);
00174 
00175   /* Count for this page, with common page footer */
00176   if (tmp[0]=='.') {
00177     numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(thisfilename, 0));
00178 
00179   /* Count for all files */
00180   /* Note buffer will overflow if there are too many files! */
00181   } else if (tmp[0]=='*') {
00182     i=0;numprinted=0;
00183     for(f = (struct httpd_fsdata_file_noconst *)httpd_fs_get_root();
00184         f != NULL;
00185         f = (struct httpd_fsdata_file_noconst *)fram.next) {
00186 
00187       /* Get the linked list file entry into RAM from from wherever it is*/
00188       httpd_memcpy(&fram,f,sizeof(fram));
00189  
00190       /* Get the file name from whatever memory it is in */
00191       httpd_fs_cpy(&tmp, fram.name, sizeof(tmp));
00192 #if HTTPD_FS_STATISTICS==1
00193       numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, f->count);
00194 #elif HTTPD_FS_STATISTICS==2
00195       numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, httpd_filecount[i]);
00196 #endif
00197       i++;
00198     }
00199 
00200   /* Count for specified file */
00201   } else {
00202     numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat3, httpd_fs_open(tmp, 0));
00203   }
00204 #if DEBUGLOGIC
00205   return 0;
00206 #endif
00207   return numprinted;
00208 }
00209 /*---------------------------------------------------------------------------*/
00210 static
00211 PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
00212 {
00213 
00214   PSOCK_BEGIN(&s->sout);
00215 
00216   thisfilename=&s->filename[0]; //temporary way to pass filename to generate_file_stats
00217   
00218   PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) ptr);
00219   
00220   PSOCK_END(&s->sout);
00221 }
00222 #endif /*HTTPD_FS_STATISTICS*/
00223 /*---------------------------------------------------------------------------*/
00224 static unsigned short
00225 make_tcp_stats(void *arg)
00226 {
00227   static const char httpd_cgi_tcpstat1[] HTTPD_STRING_ATTR = "<tr align=\"center\"><td>%d</td><td>";
00228   static const char httpd_cgi_tcpstat2[] HTTPD_STRING_ATTR = "-%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n";
00229   struct uip_conn *conn;
00230   struct httpd_state *s = (struct httpd_state *)arg;
00231   char tstate[20];
00232   uint16_t numprinted;
00233 
00234   conn = &uip_conns[s->u.count];
00235 
00236   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_tcpstat1, uip_htons(conn->lport));
00237   numprinted += httpd_cgi_sprint_ip6(conn->ripaddr, uip_appdata + numprinted);
00238   httpd_strcpy(tstate,states[conn->tcpstateflags & UIP_TS_MASK]);
00239   numprinted +=  httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted,
00240                  httpd_cgi_tcpstat2,
00241                  uip_htons(conn->rport),
00242                  tstate,
00243                  conn->nrtx,
00244                  conn->timer,
00245                  (uip_outstanding(conn))? '*':' ',
00246                  (uip_stopped(conn))? '!':' ');
00247 
00248   return numprinted;
00249 }
00250 /*---------------------------------------------------------------------------*/
00251 static
00252 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
00253 {
00254   
00255   PSOCK_BEGIN(&s->sout);
00256 
00257   for(s->u.count = 0; s->u.count < UIP_CONNS; ++s->u.count) {
00258     if((uip_conns[s->u.count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
00259       PSOCK_GENERATOR_SEND(&s->sout, make_tcp_stats, s);
00260     }
00261   }
00262 
00263   PSOCK_END(&s->sout);
00264 }
00265 /*---------------------------------------------------------------------------*/
00266 static unsigned short
00267 make_processes(void *p)
00268 {
00269   static const char httpd_cgi_proc[] HTTPD_STRING_ATTR = "<tr align=\"center\"><td>%p</td><td>%s</td><td>%p</td><td>%s</td></tr>\r\n";
00270   char name[40],tstate[20];
00271 
00272   strncpy(name, PROCESS_NAME_STRING((struct process *)p), 40);
00273   petsciiconv_toascii(name, 40);
00274   httpd_strcpy(tstate,states[9 + ((struct process *)p)->state]);
00275   return httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_proc, p, name,
00276     *(char *)(&(((struct process *)p)->thread)),
00277 
00278     tstate);
00279 }
00280 /*---------------------------------------------------------------------------*/
00281 static
00282 PT_THREAD(processes(struct httpd_state *s, char *ptr))
00283 {
00284   PSOCK_BEGIN(&s->sout);
00285   for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
00286     PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
00287   }
00288   PSOCK_END(&s->sout);
00289 }
00290 /*---------------------------------------------------------------------------*/
00291 static const char httpd_cgi_addrh[] HTTPD_STRING_ATTR = "<code>";
00292 static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "</code>[Room for %u more]";
00293 static const char httpd_cgi_addrb[] HTTPD_STRING_ATTR = "<br>";
00294 static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "(none)<br>";
00295 extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
00296 extern uip_ds6_route_t uip_ds6_routing_table[];
00297 extern uip_ds6_netif_t uip_ds6_if;
00298 
00299 static unsigned short
00300 make_addresses(void *p)
00301 {
00302 uint8_t i,j=0;
00303 uint16_t numprinted;
00304   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00305   for (i=0; i<UIP_DS6_ADDR_NB;i++) {
00306     if (uip_ds6_if.addr_list[i].isused) {
00307       j++;
00308       numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, uip_appdata + numprinted);
00309       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb); 
00310     }
00311   }
00312 //if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00313   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf, UIP_DS6_ADDR_NB-j); 
00314   return numprinted;
00315 }
00316 /*---------------------------------------------------------------------------*/
00317 static
00318 PT_THREAD(addresses(struct httpd_state *s, char *ptr))
00319 {
00320   PSOCK_BEGIN(&s->sout);
00321 
00322   PSOCK_GENERATOR_SEND(&s->sout, make_addresses, s->u.ptr);
00323 
00324   PSOCK_END(&s->sout);
00325 }
00326 /*---------------------------------------------------------------------------*/ 
00327 static unsigned short
00328 make_neighbors(void *p)
00329 {
00330 uint8_t i,j=0;
00331 uint16_t numprinted;
00332   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00333   for (i=0; i<UIP_DS6_NBR_NB;i++) {
00334     if (uip_ds6_nbr_cache[i].isused) {
00335       j++;
00336       numprinted += httpd_cgi_sprint_ip6(uip_ds6_nbr_cache[i].ipaddr, uip_appdata + numprinted);
00337       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb); 
00338     }
00339   }
00340 //if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00341   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_NBR_NB-j);
00342   return numprinted;
00343 }
00344 /*---------------------------------------------------------------------------*/
00345 static
00346 PT_THREAD(neighbors(struct httpd_state *s, char *ptr))
00347 {
00348   PSOCK_BEGIN(&s->sout);
00349 
00350   PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, s->u.ptr);  
00351   
00352   PSOCK_END(&s->sout);
00353 }
00354 /*---------------------------------------------------------------------------*/                 
00355 static unsigned short
00356 make_routes(void *p)
00357 {
00358 static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via ";
00359 static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>";
00360 static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>";
00361 uint8_t i,j=0;
00362 uint16_t numprinted;
00363   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00364   for (i=0; i<UIP_DS6_ROUTE_NB;i++) {
00365     if (uip_ds6_routing_table[i].isused) {
00366       j++;
00367       numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].ipaddr, uip_appdata + numprinted);
00368       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, uip_ds6_routing_table[i].length);
00369       numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].nexthop, uip_appdata + numprinted);
00370       if(uip_ds6_routing_table[i].state.lifetime < 3600) {
00371          numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, uip_ds6_routing_table[i].state.lifetime);
00372       } else {
00373          numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes3);
00374       }
00375     }
00376   }
00377   if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00378   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j);
00379   return numprinted;
00380 }
00381 /*---------------------------------------------------------------------------*/
00382 static
00383 PT_THREAD(routes(struct httpd_state *s, char *ptr))
00384 {
00385   PSOCK_BEGIN(&s->sout);
00386  
00387   PSOCK_GENERATOR_SEND(&s->sout, make_routes, s->u.ptr); 
00388  
00389   PSOCK_END(&s->sout);
00390 }
00391 /*---------------------------------------------------------------------------*/
00392 static unsigned short
00393 generate_sensor_readings(void *arg)
00394 {
00395   uint16_t numprinted;
00396   uint16_t h,m,s;
00397   uint8_t p1;
00398   static const char httpd_cgi_sensor0[] HTTPD_STRING_ATTR = "[Updated %d seconds ago]<br><br>";
00399 //  static const char httpd_cgi_sensor1[] HTTPD_STRING_ATTR = "<em>Temperature:</em> %s<br>";
00400 //  static const char httpd_cgi_sensor2[] HTTPD_STRING_ATTR = "<em>Battery:</em> %s<br>";
00401   static const char httpd_cgi_sensr12[] HTTPD_STRING_ATTR = "<em>Temperature:</em> %s    <em>Battery:<em> %s<br>";
00402   static const char httpd_cgi_sensor3[] HTTPD_STRING_ATTR = "<em>Elapsed timer :</em> %02d:%02d:%02d<br>";
00403   static const char httpd_cgi_sensor4[] HTTPD_STRING_ATTR = "<em>Sleeping time :</em> %02d:%02d:%02d (%d%%)<br>";
00404 
00405   numprinted=0;
00406   if (last_tempupdate) {
00407     numprinted =httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_sensor0,seconds-last_tempupdate);
00408   }
00409 
00410 //  numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor1, sensor_temperature);
00411   numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensr12, sensor_temperature,sensor_extvoltage);
00412 
00413 #if 0
00414 //Measuring AVcc might be useful to check on battery condition but on ext power it's always 3v3
00415   ADMUX =0x1E;              //Select AREF as reference, measure 1.1 volt bandgap reference.
00416 //ADMUX =0x5E;              //Select AVCC as reference, measure 1.1 volt bandgap reference.
00417   ADCSRA=0x07;              //Enable ADC, not free running, interrupt disabled, clock divider  128 (62 KHz@ 8 MHz)
00418   ADCSRA|=1<<ADSC;          //Start throwaway conversion
00419   while (ADCSRA&(1<<ADSC)); //Wait till done
00420   ADCSRA|=1<<ADSC;          //Start another conversion
00421   while (ADCSRA&(1<<ADSC)); //Wait till done
00422   h=1131632UL/ADC;          //Get supply voltage
00423 #endif
00424 
00425  // numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor2, sensor_extvoltage);
00426 #if RADIOSTATS
00427   /* Remember radioontime for display below - slow connection might make it report longer than cpu ontime! */
00428   savedradioontime = radioontime;
00429 #endif
00430   h=seconds/3600;
00431   s=seconds-h*3600;
00432   m=s/60;
00433   s=s-m*60;
00434   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor3, h,m,s);
00435   if (sleepseconds) {
00436     p1=100UL*sleepseconds/seconds;
00437     h=sleepseconds/3600;
00438     s=sleepseconds-h*3600;
00439     m=s/60;
00440     s=s-m*60;
00441     numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor4, h,m,s,p1);
00442   }
00443   return numprinted;
00444 }
00445 #if RADIOSTATS
00446 /*---------------------------------------------------------------------------*/
00447 static unsigned short
00448 generate_radio_stats(void *arg)
00449 {
00450   uint16_t numprinted;
00451   uint16_t h,m,s;
00452   uint8_t p1,p2;
00453   static const char httpd_cgi_sensor10[] HTTPD_STRING_ATTR = "<em>Radio on time  :</em> %02d:%02d:%02d (%d.%02d%%)<br>";
00454   static const char httpd_cgi_sensor11[] HTTPD_STRING_ATTR = "<em>Packets:</em> Tx=%5d Rx=%5d TxL=%5d RxL=%5d RSSI=%2ddBm\n";
00455 
00456   s=(10000UL*savedradioontime)/seconds;
00457   p1=s/100;
00458   p2=s-p1*100;
00459   h=savedradioontime/3600;
00460   s=savedradioontime-h*3600;
00461   m=s/60;
00462   s=s-m*60;
00463 
00464   numprinted =httpd_snprintf((char *)uip_appdata             , uip_mss()             , httpd_cgi_sensor10,\
00465     h,m,s,p1,p2);
00466 
00467 #if RF230BB
00468   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00469     RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,-92+rf230_last_rssi);
00470 #else
00471   p1=0;
00472   radio_get_rssi_value(&p1);
00473   p1 = -91*3(p1-1);
00474   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00475     RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,p1);
00476 #endif
00477  
00478   return numprinted;
00479 }
00480 #endif
00481 /*---------------------------------------------------------------------------*/
00482 static
00483 PT_THREAD(sensor_readings(struct httpd_state *s, char *ptr))
00484 {
00485   PSOCK_BEGIN(&s->sout);
00486 
00487   PSOCK_GENERATOR_SEND(&s->sout, generate_sensor_readings, s);
00488 #if RADIOSTATS
00489   PSOCK_GENERATOR_SEND(&s->sout, generate_radio_stats, s);
00490 #endif
00491 
00492   
00493   PSOCK_END(&s->sout);
00494 }
00495 /*---------------------------------------------------------------------------*/
00496 void
00497 httpd_cgi_add(struct httpd_cgi_call *c)
00498 {
00499   struct httpd_cgi_call *l;
00500 
00501   c->next = NULL;
00502   if(calls == NULL) {
00503     calls = c;
00504   } else {
00505     for(l = calls; l->next != NULL; l = l->next);
00506     l->next = c;
00507   }
00508 }
00509 /*---------------------------------------------------------------------------*/
00510 
00511 #if HTTPD_FS_STATISTICS
00512 HTTPD_CGI_CALL(   file,   file_name,      file_stats);
00513 #endif
00514 HTTPD_CGI_CALL(    tcp,    tcp_name, tcp_stats      );
00515 HTTPD_CGI_CALL(   proc,   proc_name, processes      );
00516 HTTPD_CGI_CALL(   adrs,   adrs_name, addresses      );
00517 HTTPD_CGI_CALL(   nbrs,   nbrs_name, neighbors      );
00518 HTTPD_CGI_CALL(   rtes,   rtes_name, routes         );
00519 HTTPD_CGI_CALL(sensors, sensor_name, sensor_readings);
00520 
00521 void
00522 httpd_cgi_init(void)
00523 {
00524 #if HTTPD_FS_STATISTICS
00525   httpd_cgi_add(   &file);
00526 #endif
00527   httpd_cgi_add(    &tcp);
00528   httpd_cgi_add(   &proc);
00529   httpd_cgi_add(   &adrs);
00530   httpd_cgi_add(   &nbrs);
00531   httpd_cgi_add(   &rtes);
00532   httpd_cgi_add(&sensors);
00533 }
00534 /*---------------------------------------------------------------------------*/
00535 
00536 uint8_t httpd_cgi_sprint_ip6(uip_ip6addr_t addr, char * result)
00537         {
00538         unsigned char zerocnt = 0;
00539         unsigned char numprinted = 0;
00540         char * starting = result;
00541 
00542     unsigned char i = 0;
00543 
00544         while (numprinted < 8)
00545                 {
00546                 //Address is zero, have we used our ability to
00547                 //replace a bunch with : yet?
00548                 if ((addr.u16[i] == 0) && (zerocnt == 0))
00549                         {
00550                         //How mant zeros?
00551                         zerocnt = 0;
00552                         while(addr.u16[zerocnt + i] == 0)
00553                                 zerocnt++;
00554 
00555                         //just one, don't waste our zeros...
00556                         if (zerocnt == 1)
00557                                 {
00558                                 *result++ = '0';
00559                                 numprinted++;
00560                                 break;
00561                                 }
00562 
00563                         //Cool - can replace a bunch of zeros
00564                         i += zerocnt;
00565                         numprinted += zerocnt;
00566                         }
00567                 //Normal address, just print it
00568                 else
00569                         {
00570                         result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i])));
00571                         i++;
00572                         numprinted++;
00573                         }
00574 
00575                 //Don't print : on last one
00576                 if (numprinted != 8)
00577                         *result++ = ':';
00578                 }
00579 
00580     return (result - starting);
00581         }
00582