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 #include <util/delay.h>
00035 #define delay_us( us ) ( _delay_us( ( us ) ) )
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <stdio.h>
00047 #include <string.h>
00048
00049 #include "contiki-net.h"
00050 #include "httpd.h"
00051 #include "httpd-cgi.h"
00052 #include "httpd-fs.h"
00053 #include "httpd-fsdata.h"
00054 #include "lib/petsciiconv.h"
00055
00056 #include "sensors.h"
00057
00058 #define DEBUGLOGIC 0 //See httpd.c, if 1 must also set it there!
00059 #if DEBUGLOGIC
00060 #define uip_mss(...) 512
00061 #define uip_appdata TCPBUF
00062 extern char TCPBUF[512];
00063 #endif
00064
00065
00066 #if RF230BB
00067 #define RADIOSTATS 1
00068 #endif
00069
00070 static struct httpd_cgi_call *calls = NULL;
00071
00072
00073 #if HTTPD_FS_STATISTICS
00074 static const char file_name[] HTTPD_STRING_ATTR = "file-stats";
00075 #endif
00076 static const char tcp_name[] HTTPD_STRING_ATTR = "tcp-connections";
00077 static const char proc_name[] HTTPD_STRING_ATTR = "processes";
00078 static const char sensor_name[] HTTPD_STRING_ATTR = "sensors";
00079 static const char adrs_name[] HTTPD_STRING_ATTR = "addresses";
00080 static const char nbrs_name[] HTTPD_STRING_ATTR = "neighbors";
00081 static const char rtes_name[] HTTPD_STRING_ATTR = "routes";
00082
00083
00084 static const char closed[] HTTPD_STRING_ATTR = "CLOSED";
00085 static const char syn_rcvd[] HTTPD_STRING_ATTR = "SYN-RCVD";
00086 static const char syn_sent[] HTTPD_STRING_ATTR = "SYN-SENT";
00087 static const char established[] HTTPD_STRING_ATTR = "ESTABLISHED";
00088 static const char fin_wait_1[] HTTPD_STRING_ATTR = "FIN-WAIT-1";
00089 static const char fin_wait_2[] HTTPD_STRING_ATTR = "FIN-WAIT-2";
00090 static const char closing[] HTTPD_STRING_ATTR = "CLOSING";
00091 static const char time_wait[] HTTPD_STRING_ATTR = "TIME-WAIT";
00092 static const char last_ack[] HTTPD_STRING_ATTR = "LAST-ACK";
00093 static const char none[] HTTPD_STRING_ATTR = "NONE";
00094 static const char running[] HTTPD_STRING_ATTR = "RUNNING";
00095 static const char called[] HTTPD_STRING_ATTR = "CALLED";
00096 static const char *states[] = {
00097 closed,
00098 syn_rcvd,
00099 syn_sent,
00100 established,
00101 fin_wait_1,
00102 fin_wait_2,
00103 closing,
00104 time_wait,
00105 last_ack,
00106 none,
00107 running,
00108 called};
00109
00110 static char sensor_temperature[12]="Not Enabled";
00111 static char sensor_extvoltage[12]="Not Enabled";
00112
00113 extern unsigned long seconds, sleepseconds;
00114 #if RADIOSTATS
00115 extern unsigned long radioontime;
00116 static unsigned long savedradioontime;
00117 extern uint8_t RF230_radio_on, rf230_last_rssi;
00118 extern uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
00119 #endif
00120
00121 #if 0
00122 void
00123 web_set_temp(char *s)
00124 {
00125 strcpy(sensor_temperature, s);
00126 last_tempupdate=seconds;
00127 }
00128 void
00129 web_set_voltage(char *s)
00130 {
00131 strcpy(sensor_extvoltage, s);
00132 last_extvoltageupdate=seconds;
00133 }
00134 #endif
00135
00136 static
00137 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
00138 {
00139 PSOCK_BEGIN(&s->sout);
00140 PSOCK_END(&s->sout);
00141 }
00142
00143 httpd_cgifunction
00144 httpd_cgi(char *name)
00145 {
00146 struct httpd_cgi_call *f;
00147
00148
00149 for(f = calls; f != NULL; f = f->next) {
00150 if(httpd_strncmp(name, f->name, httpd_strlen(f->name)) == 0) {
00151 return f->function;
00152 }
00153 }
00154 return nullfunction;
00155 }
00156
00157 #if HTTPD_FS_STATISTICS
00158 static char *thisfilename;
00159
00160 static unsigned short
00161 generate_file_stats(void *arg)
00162 {
00163 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>";
00164 static const char httpd_cgi_filestat2[] HTTPD_STRING_ATTR = "<tr><td><a href=\"%s\">%s</a></td><td>%d</td>";
00165 static const char httpd_cgi_filestat3[] HTTPD_STRING_ATTR = "%5u";
00166 char tmp[20];
00167 struct httpd_fsdata_file_noconst *f,fram;
00168 u16_t i;
00169 unsigned short numprinted;
00170
00171
00172 httpd_fs_cpy(&tmp, (char *)arg, 20);
00173
00174
00175 if (tmp[0]=='.') {
00176 numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(thisfilename, 0));
00177
00178
00179
00180 } else if (tmp[0]=='*') {
00181 i=0;numprinted=0;
00182 for(f = (struct httpd_fsdata_file_noconst *)httpd_fs_get_root();
00183 f != NULL;
00184 f = (struct httpd_fsdata_file_noconst *)fram.next) {
00185
00186
00187 httpd_memcpy(&fram,f,sizeof(fram));
00188
00189
00190 httpd_fs_cpy(&tmp, fram.name, sizeof(tmp));
00191 #if HTTPD_FS_STATISTICS==1
00192 numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, f->count);
00193 #elif HTTPD_FS_STATISTICS==2
00194 numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, httpd_filecount[i]);
00195 #endif
00196 i++;
00197 }
00198
00199
00200 } else {
00201 numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat3, httpd_fs_open(tmp, 0));
00202 }
00203 #if DEBUGLOGIC
00204 return 0;
00205 #endif
00206 return numprinted;
00207 }
00208
00209 static
00210 PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
00211 {
00212
00213 PSOCK_BEGIN(&s->sout);
00214
00215 thisfilename=&s->filename[0];
00216
00217 PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) ptr);
00218
00219 PSOCK_END(&s->sout);
00220 }
00221 #endif
00222
00223 static unsigned short
00224 make_tcp_stats(void *arg)
00225 {
00226 static const char httpd_cgi_tcpstat1[] HTTPD_STRING_ATTR = "<tr align=\"center\"><td>%d</td><td>";
00227 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";
00228 struct uip_conn *conn;
00229 struct httpd_state *s = (struct httpd_state *)arg;
00230 char tstate[20];
00231 uint16_t numprinted;
00232
00233 conn = &uip_conns[s->u.count];
00234
00235 numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_tcpstat1, uip_htons(conn->lport));
00236 numprinted += httpd_cgi_sprint_ip6(conn->ripaddr, uip_appdata + numprinted);
00237 httpd_strcpy(tstate,states[conn->tcpstateflags & UIP_TS_MASK]);
00238 numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted,
00239 httpd_cgi_tcpstat2,
00240 uip_htons(conn->rport),
00241 tstate,
00242 conn->nrtx,
00243 conn->timer,
00244 (uip_outstanding(conn))? '*':' ',
00245 (uip_stopped(conn))? '!':' ');
00246
00247 return numprinted;
00248 }
00249
00250 static
00251 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
00252 {
00253
00254 PSOCK_BEGIN(&s->sout);
00255
00256 for(s->u.count = 0; s->u.count < UIP_CONNS; ++s->u.count) {
00257 if((uip_conns[s->u.count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
00258 PSOCK_GENERATOR_SEND(&s->sout, make_tcp_stats, s);
00259 }
00260 }
00261
00262 PSOCK_END(&s->sout);
00263 }
00264
00265 static unsigned short
00266 make_processes(void *p)
00267 {
00268 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";
00269 char name[40],tstate[20];
00270
00271 strncpy(name, ((struct process *)p)->name, 40);
00272 petsciiconv_toascii(name, 40);
00273 httpd_strcpy(tstate,states[9 + ((struct process *)p)->state]);
00274 return httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_proc, p, name,
00275 *(char *)(&(((struct process *)p)->thread)),
00276
00277 tstate);
00278 }
00279
00280 static
00281 PT_THREAD(processes(struct httpd_state *s, char *ptr))
00282 {
00283 PSOCK_BEGIN(&s->sout);
00284 for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
00285 PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
00286 }
00287 PSOCK_END(&s->sout);
00288 }
00289
00290 static const char httpd_cgi_addrh[] HTTPD_STRING_ATTR = "<code>";
00291 static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "</code>[Room for %u more]";
00292 static const char httpd_cgi_addrb[] HTTPD_STRING_ATTR = "<br>";
00293 static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "(none)<br>";
00294 extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
00295 extern uip_ds6_route_t uip_ds6_routing_table[];
00296 extern uip_ds6_netif_t uip_ds6_if;
00297
00298 static unsigned short
00299 make_addresses(void *p)
00300 {
00301 uint8_t i,j=0;
00302 uint16_t numprinted;
00303 numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00304 for (i=0; i<UIP_DS6_ADDR_NB;i++) {
00305 if (uip_ds6_if.addr_list[i].isused) {
00306 j++;
00307 numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, uip_appdata + numprinted);
00308 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb);
00309 }
00310 }
00311
00312 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf, UIP_DS6_ADDR_NB-j);
00313 return numprinted;
00314 }
00315
00316 static
00317 PT_THREAD(addresses(struct httpd_state *s, char *ptr))
00318 {
00319 PSOCK_BEGIN(&s->sout);
00320
00321 PSOCK_GENERATOR_SEND(&s->sout, make_addresses, s->u.ptr);
00322
00323 PSOCK_END(&s->sout);
00324 }
00325
00326 static unsigned short
00327 make_neighbors(void *p)
00328 {
00329 uint8_t i,j=0;
00330 uint16_t numprinted;
00331 numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00332 for (i=0; i<UIP_DS6_NBR_NB;i++) {
00333 if (uip_ds6_nbr_cache[i].isused) {
00334 j++;
00335 numprinted += httpd_cgi_sprint_ip6(uip_ds6_nbr_cache[i].ipaddr, uip_appdata + numprinted);
00336 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb);
00337 }
00338 }
00339
00340 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_NBR_NB-j);
00341 return numprinted;
00342 }
00343
00344 static
00345 PT_THREAD(neighbors(struct httpd_state *s, char *ptr))
00346 {
00347 PSOCK_BEGIN(&s->sout);
00348
00349 PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, s->u.ptr);
00350
00351 PSOCK_END(&s->sout);
00352 }
00353
00354 static unsigned short
00355 make_routes(void *p)
00356 {
00357 static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via ";
00358 static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>";
00359 static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>";
00360 uint8_t i,j=0;
00361 uint16_t numprinted;
00362 numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00363 for (i=0; i<UIP_DS6_ROUTE_NB;i++) {
00364 if (uip_ds6_routing_table[i].isused) {
00365 j++;
00366 numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].ipaddr, uip_appdata + numprinted);
00367 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, uip_ds6_routing_table[i].length);
00368 numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].nexthop, uip_appdata + numprinted);
00369 if(uip_ds6_routing_table[i].state.lifetime < 3600) {
00370 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, uip_ds6_routing_table[i].state.lifetime);
00371 } else {
00372 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes3);
00373 }
00374 }
00375 }
00376 if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00377 numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j);
00378 return numprinted;
00379 }
00380
00381 static
00382 PT_THREAD(routes(struct httpd_state *s, char *ptr))
00383 {
00384 PSOCK_BEGIN(&s->sout);
00385
00386 PSOCK_GENERATOR_SEND(&s->sout, make_routes, s->u.ptr);
00387
00388 PSOCK_END(&s->sout);
00389 }
00390
00391 static unsigned short
00392 generate_sensor_readings(void *arg)
00393 {
00394 uint16_t numprinted;
00395 uint16_t h,m,s;
00396 uint8_t p1;
00397
00398
00399
00400 static const char httpd_cgi_sensor1_printf[] HTTPD_STRING_ATTR = "%d.%d C";
00401 static const char httpd_cgi_sensor2_printf[] HTTPD_STRING_ATTR = "%d mv";
00402 static const char httpd_cgi_sensr12[] HTTPD_STRING_ATTR = "<em>Temperature:</em> %s <em>Battery:<em> %s<br>";
00403 static const char httpd_cgi_sensor3[] HTTPD_STRING_ATTR = "<em>Elapsed timer :</em> %02d:%02d:%02d<br>";
00404 static const char httpd_cgi_sensor4[] HTTPD_STRING_ATTR = "<em>Sleeping time :</em> %02d:%02d:%02d (%d%%)<br>";
00405
00406 numprinted=0;
00407
00408
00409
00410 BATMON = 16;
00411
00412
00413
00414
00415 #if 1
00416 ADCSRB|=1<<MUX5;
00417 ADMUX =0xc9;
00418 ADCSRA=0x85;
00419
00420
00421 ADCSRA|=1<<ADSC;
00422 while (ADCSRA&(1<<ADSC));
00423 ADCSRA|=1<<ADSC;
00424 while (ADCSRA&(1<<ADSC));
00425 h=ADC;
00426 h=11*h-2728+(h>>2);
00427 ADCSRA=0;
00428 ADMUX=0;
00429 m=h/10;s=h-10*m;
00430 httpd_snprintf(sensor_temperature,sizeof(sensor_temperature),httpd_cgi_sensor1_printf,m,s);
00431 #endif
00432
00433
00434
00435 for ( p1=16; p1<31; p1++) {
00436 BATMON = p1;
00437
00438 if ((BATMON&(1<<BATMON_OK))==0) break;
00439 }
00440 h=2550-75*16-75+75*p1;
00441 httpd_snprintf(sensor_extvoltage,sizeof(sensor_extvoltage),httpd_cgi_sensor2_printf,h);
00442
00443 numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensr12, sensor_temperature,sensor_extvoltage);
00444
00445
00446 #if RADIOSTATS
00447
00448 savedradioontime = radioontime;
00449 #endif
00450 h=seconds/3600;
00451 s=seconds-h*3600;
00452 m=s/60;
00453 s=s-m*60;
00454 numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor3, h,m,s);
00455 if (sleepseconds) {
00456 p1=100UL*sleepseconds/seconds;
00457 h=sleepseconds/3600;
00458 s=sleepseconds-h*3600;
00459 m=s/60;
00460 s=s-m*60;
00461 numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor4, h,m,s,p1);
00462 }
00463 return numprinted;
00464 }
00465 #if RADIOSTATS
00466
00467 static unsigned short
00468 generate_radio_stats(void *arg)
00469 {
00470 uint16_t numprinted;
00471 uint16_t h,m,s;
00472 uint8_t p1,p2;
00473 static const char httpd_cgi_sensor10[] HTTPD_STRING_ATTR = "<em>Radio on time :</em> %02d:%02d:%02d (%d.%02d%%)<br>";
00474 static const char httpd_cgi_sensor11[] HTTPD_STRING_ATTR = "<em>Packets:</em> Tx=%5d Rx=%5d TxL=%5d RxL=%5d RSSI=%2ddBm\n";
00475
00476 s=(10000UL*savedradioontime)/seconds;
00477 p1=s/100;
00478 p2=s-p1*100;
00479 h=savedradioontime/3600;
00480 s=savedradioontime-h*3600;
00481 m=s/60;
00482 s=s-m*60;
00483
00484 numprinted =httpd_snprintf((char *)uip_appdata , uip_mss() , httpd_cgi_sensor10,\
00485 h,m,s,p1,p2);
00486
00487 #if RF230BB
00488 numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00489 RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,-92+rf230_last_rssi);
00490 #else
00491 p1=0;
00492 radio_get_rssi_value(&p1);
00493 p1 = -91*3(p1-1);
00494 numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00495 RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,p1);
00496 #endif
00497
00498 return numprinted;
00499 }
00500 #endif
00501
00502 static
00503 PT_THREAD(sensor_readings(struct httpd_state *s, char *ptr))
00504 {
00505 PSOCK_BEGIN(&s->sout);
00506
00507 PSOCK_GENERATOR_SEND(&s->sout, generate_sensor_readings, s);
00508 #if RADIOSTATS
00509 PSOCK_GENERATOR_SEND(&s->sout, generate_radio_stats, s);
00510 #endif
00511
00512
00513 PSOCK_END(&s->sout);
00514 }
00515
00516 void
00517 httpd_cgi_add(struct httpd_cgi_call *c)
00518 {
00519 struct httpd_cgi_call *l;
00520
00521 c->next = NULL;
00522 if(calls == NULL) {
00523 calls = c;
00524 } else {
00525 for(l = calls; l->next != NULL; l = l->next);
00526 l->next = c;
00527 }
00528 }
00529
00530
00531 #if HTTPD_FS_STATISTICS
00532 HTTPD_CGI_CALL( file, file_name, file_stats);
00533 #endif
00534 HTTPD_CGI_CALL( tcp, tcp_name, tcp_stats );
00535 HTTPD_CGI_CALL( proc, proc_name, processes );
00536 HTTPD_CGI_CALL( adrs, adrs_name, addresses );
00537 HTTPD_CGI_CALL( nbrs, nbrs_name, neighbors );
00538 HTTPD_CGI_CALL( rtes, rtes_name, routes );
00539 HTTPD_CGI_CALL(sensors, sensor_name, sensor_readings);
00540
00541 void
00542 httpd_cgi_init(void)
00543 {
00544 #if HTTPD_FS_STATISTICS
00545 httpd_cgi_add( &file);
00546 #endif
00547 httpd_cgi_add( &tcp);
00548 httpd_cgi_add( &proc);
00549 httpd_cgi_add( &adrs);
00550 httpd_cgi_add( &nbrs);
00551 httpd_cgi_add( &rtes);
00552 httpd_cgi_add(&sensors);
00553 }
00554
00555
00556 uint8_t httpd_cgi_sprint_ip6(uip_ip6addr_t addr, char * result)
00557 {
00558 unsigned char zerocnt = 0;
00559 unsigned char numprinted = 0;
00560 char * starting = result;
00561
00562 unsigned char i = 0;
00563
00564 while (numprinted < 8)
00565 {
00566
00567
00568 if ((addr.u16[i] == 0) && (zerocnt == 0))
00569 {
00570
00571 zerocnt = 0;
00572 while(addr.u16[zerocnt + i] == 0)
00573 zerocnt++;
00574
00575
00576 if (zerocnt == 1)
00577 {
00578 *result++ = '0';
00579 numprinted++;
00580 break;
00581 }
00582
00583
00584 i += zerocnt;
00585 numprinted += zerocnt;
00586 }
00587
00588 else
00589 {
00590 result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i])));
00591 i++;
00592 numprinted++;
00593 }
00594
00595
00596 if (numprinted != 8)
00597 *result++ = ':';
00598 }
00599
00600 return (result - starting);
00601 }
00602