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 #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
00065 #if RF230BB
00066 #define RADIOSTATS 1
00067 #endif
00068
00069 static struct httpd_cgi_call *calls = NULL;
00070
00071
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
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
00126 last_tempupdate=seconds;
00127 }
00128 void
00129 web_set_voltage(char *s)
00130 {
00131 strcpy(sensor_extvoltage, s);
00132
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
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 u16_t i;
00170 unsigned short numprinted;
00171
00172
00173 httpd_fs_cpy(&tmp, (char *)arg, 20);
00174
00175
00176 if (tmp[0]=='.') {
00177 numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(thisfilename, 0));
00178
00179
00180
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
00188 httpd_memcpy(&fram,f,sizeof(fram));
00189
00190
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
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];
00217
00218 PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) ptr);
00219
00220 PSOCK_END(&s->sout);
00221 }
00222 #endif
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, ((struct process *)p)->name, 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
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
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
00400
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
00411 numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensr12, sensor_temperature,sensor_extvoltage);
00412
00413 #if 0
00414
00415 ADMUX =0x1E;
00416
00417 ADCSRA=0x07;
00418 ADCSRA|=1<<ADSC;
00419 while (ADCSRA&(1<<ADSC));
00420 ADCSRA|=1<<ADSC;
00421 while (ADCSRA&(1<<ADSC));
00422 h=1131632UL/ADC;
00423 #endif
00424
00425
00426 #if RADIOSTATS
00427
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
00547
00548 if ((addr.u16[i] == 0) && (zerocnt == 0))
00549 {
00550
00551 zerocnt = 0;
00552 while(addr.u16[zerocnt + i] == 0)
00553 zerocnt++;
00554
00555
00556 if (zerocnt == 1)
00557 {
00558 *result++ = '0';
00559 numprinted++;
00560 break;
00561 }
00562
00563
00564 i += zerocnt;
00565 numprinted += zerocnt;
00566 }
00567
00568 else
00569 {
00570 result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i])));
00571 i++;
00572 numprinted++;
00573 }
00574
00575
00576 if (numprinted != 8)
00577 *result++ = ':';
00578 }
00579
00580 return (result - starting);
00581 }
00582