diff --git a/mavlink.c b/mavlink.c index 24d05f3a..5b53ecb4 100644 --- a/mavlink.c +++ b/mavlink.c @@ -204,11 +204,6 @@ int mavlink_heartbeat(unsigned char *frame,int *outlen) return 0; } -extern unsigned long long last_rssi_time; -extern int last_radio_rssi; -extern int last_radio_temperature; -extern int last_radio_rxpackets; - static int parse_heartbeat(struct overlay_interface *interface, const unsigned char *payload) { if (payload[0]==0xFE @@ -218,9 +213,8 @@ static int parse_heartbeat(struct overlay_interface *interface, const unsigned c && payload[5]==MAVLINK_MSG_ID_RADIO){ // we can assume that radio status packets arrive without corruption - last_radio_rssi=(1.0*payload[10]-payload[13])/1.9; - last_radio_temperature=-999; // doesn't get reported - last_radio_rxpackets=-999; // doesn't get reported + interface->radio_rssi=(1.0*payload[10]-payload[13])/1.9; + interface->remote_rssi=(1.0*payload[11] - payload[14])/1.9; int free_space = payload[12]; int free_bytes = (free_space * 1280) / 100 - 30; interface->remaining_space = free_bytes; @@ -228,12 +222,11 @@ static int parse_heartbeat(struct overlay_interface *interface, const unsigned c interface->next_tx_allowed = gettime_ms(); if (free_bytes>720) interface->next_heartbeat=gettime_ms()+1000; - if (config.debug.mavlink||gettime_ms()-last_rssi_time>30000) { + if (config.debug.packetradio) { INFOF("Link budget = %+ddB, remote link budget = %+ddB, buffer space = %d%% (approx %d)", - last_radio_rssi, - (int)((1.0*payload[11] - payload[14])/1.9), + interface->radio_rssi, + interface->remote_rssi, free_space, free_bytes); - last_rssi_time=gettime_ms(); } return 1; } diff --git a/overlay_interface.c b/overlay_interface.c index f711df5d..ef356b52 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -63,6 +63,54 @@ overlay_interface_close(overlay_interface *interface){ interface->state=INTERFACE_STATE_DOWN; } +void interface_state_html(struct strbuf *b, struct overlay_interface *interface) +{ + switch(interface->state){ + case INTERFACE_STATE_UP: + strbuf_sprintf(b, "Interface %s is Up
", interface->name); + break; + default: + strbuf_puts(b, "Interface Down"); + return; + } + switch(interface->type){ + case OVERLAY_INTERFACE_PACKETRADIO: + strbuf_puts(b, "Type: Packet Radio
"); + strbuf_sprintf(b, "RSSI: %ddB
",interface->radio_rssi); + strbuf_sprintf(b, "Remote RSSI: %ddB
",interface->remote_rssi); + break; + case OVERLAY_INTERFACE_ETHERNET: + strbuf_puts(b, "Type: Ethernet
"); + break; + case OVERLAY_INTERFACE_WIFI: + strbuf_puts(b, "Type: Wifi
"); + break; + default: + case OVERLAY_INTERFACE_UNKNOWN: + strbuf_puts(b, "Type: Unknown
"); + } + switch(interface->socket_type){ + case SOCK_STREAM: + strbuf_puts(b, "Socket: Stream
"); + break; + case SOCK_DGRAM: + { + char addrtxt[INET_ADDRSTRLEN]; + strbuf_puts(b, "Socket: DGram
"); + if (inet_ntop(AF_INET, (const void *)&interface->address.sin_addr, addrtxt, INET_ADDRSTRLEN)) + strbuf_sprintf(b, "Address: %s:%d
", addrtxt, ntohs(interface->address.sin_port)); + if (inet_ntop(AF_INET, (const void *)&interface->destination->address.sin_addr, addrtxt, INET_ADDRSTRLEN)) + strbuf_sprintf(b, "Broadcast Address: %s:%d
", addrtxt, ntohs(interface->destination->address.sin_port)); + } + break; + case SOCK_FILE: + strbuf_puts(b, "Socket: File
"); + break; + } + strbuf_sprintf(b, "TX: %d
", interface->tx_count); + strbuf_sprintf(b, "RX: %d
", interface->recv_count); +} + // create a socket with options common to all our UDP sockets static int overlay_bind_socket(const struct sockaddr *addr, size_t addr_size, char *interface_name){ @@ -230,7 +278,6 @@ overlay_interface_read_any(struct sched_ent *alarm){ DEBUGF("Could not find matching interface for packet received from %s", inet_ntoa(src)); return; } - packetOkOverlay(interface, packet, plen, recvttl, &src_addr, addrlen); } if (alarm->poll.revents & (POLLHUP | POLLERR)) { @@ -374,6 +421,8 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr interface->state=INTERFACE_STATE_DOWN; interface->alarm.poll.fd=0; interface->debug = ifconfig->debug; + interface->tx_count=0; + interface->recv_count=0; // How often do we announce ourselves on this interface? int tick_ms=-1; @@ -655,8 +704,6 @@ static void interface_read_stream(struct overlay_interface *interface){ OUT(); return; } - if (config.debug.packetradio) - dump("read bytes", buffer, nread); struct slip_decode_state *state=&interface->slip_decode_state; int i; @@ -681,14 +728,12 @@ static void write_stream_buffer(overlay_interface *interface){ // Queue a hearbeat now mavlink_heartbeat(interface->txbuffer,&interface->tx_bytes_pending); if (config.debug.packetradio) - DEBUGF("Built %d byte heartbeat", interface->tx_bytes_pending); + DEBUGF("Sending heartbeat"); interface->next_heartbeat = now+1000; }else if(interface->tx_packet && interface->remaining_space >= 256 + 8+9){ // prepare a new link layer packet in txbuffer if (mavlink_encode_packet(interface)) break; - if (config.debug.packetradio) - DEBUGF("Built %d byte payload from packet (%d)", interface->tx_bytes_pending, interface->remaining_space); if (interface->remaining_space - interface->tx_bytes_pending < 256 + 8+9) interface->next_heartbeat = now; } @@ -703,8 +748,6 @@ static void write_stream_buffer(overlay_interface *interface){ if (bytes<=0) break; - if (config.debug.packetradio) - DEBUGF("Trying to write %d bytes of %d%s", bytes, interface->tx_bytes_pending, interface->tx_packet?", pending packet":""); int written=write(interface->alarm.poll.fd, interface->txbuffer, bytes); if (written<=0){ DEBUGF("Blocking for POLLOUT"); @@ -720,8 +763,6 @@ static void write_stream_buffer(overlay_interface *interface){ interface->tx_bytes_pending); DEBUGF("Partial write, %d left", interface->tx_bytes_pending); } - if (config.debug.packetradio) - DEBUGF("Wrote %d bytes (%d left pending, %d remains)", written, interface->tx_bytes_pending, interface->remaining_space); } if (total_written>0){ @@ -867,6 +908,8 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o if (interface->debug) DEBUGF("Sending on %s, len %d: %s", interface->name, len, alloca_tohex(bytes, len>64?64:len)); + interface->tx_count++; + switch(interface->socket_type){ case SOCK_STREAM: { diff --git a/overlay_packetformats.c b/overlay_packetformats.c index cd263b77..2dc1f87c 100644 --- a/overlay_packetformats.c +++ b/overlay_packetformats.c @@ -413,6 +413,7 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s RETURN(ret); } f.sender_interface = context.sender_interface; + interface->recv_count++; while(ob_remaining(b)>0){ context.invalid_addresses=0; diff --git a/rhizome_http.c b/rhizome_http.c index 761a946f..997f3556 100644 --- a/rhizome_http.c +++ b/rhizome_http.c @@ -543,58 +543,71 @@ int rhizome_server_parse_http_request(rhizome_http_request *r) if (strcmp(path, "/")==0) { r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER; char temp[8192]; - snprintf(temp,8192, - "" + strbuf b=strbuf_local(temp, sizeof(temp)); + strbuf_sprintf(b, "" "

Hello, I'm %s*


" - "rssi
" - "rhizome status
" - "rhizome files
" - "rhizome bars
" - "", + "Interfaces;
", alloca_tohex(my_subscriber->sid, 8)); - rhizome_server_simple_http_response(r, 200, temp); + int i; + for (i=0;i%d: %s, TX: %d, RX: %d
", + i, i, overlay_interfaces[i].name, overlay_interfaces[i].tx_count, overlay_interfaces[i].recv_count); + } + + strbuf_puts(b, "Neighbours;
"); + link_neighbour_short_status_html(b, "/neighbour"); + + if (is_rhizome_http_enabled()){ + strbuf_puts(b, "Rhizome Status
"); + } + strbuf_puts(b, ""); + if (strbuf_overrun(b)){ + rhizome_server_simple_http_response(r, 500, "

Buffer overflow

\r\n"); + }else{ + rhizome_server_simple_http_response(r, 200, temp); + } + } else if (str_startswith(path, "/neighbour/", (const char **)&id)) { + char buf[8*1024]; + strbuf b=strbuf_local(buf, sizeof buf); + + sid_t neighbour_sid; + if (str_to_sid_t(&neighbour_sid, id) == -1) + rhizome_server_simple_http_response(r, 500, "

Invalid subscriber id

\r\n"); + else{ + struct subscriber *neighbour = find_subscriber(neighbour_sid.binary, sizeof(neighbour_sid.binary), 0); + if (neighbour){ + strbuf_puts(b, ""); + link_neighbour_status_html(b, neighbour); + strbuf_puts(b, ""); + if (strbuf_overrun(b)){ + rhizome_server_simple_http_response(r, 500, "

Buffer overflow

\r\n"); + }else{ + rhizome_server_simple_http_response(r, 200, buf); + } + }else{ + rhizome_server_simple_http_response(r, 404, "

Subscriber not known

\r\n"); + } + } + } else if (str_startswith(path, "/interface/", (const char **)&id)) { + char buf[8*1024]; + strbuf b=strbuf_local(buf, sizeof buf); + int index=atoi(id); + if (index>=0 && index"); + interface_state_html(b, &overlay_interfaces[index]); + strbuf_puts(b, ""); + if (strbuf_overrun(b)){ + rhizome_server_simple_http_response(r, 500, "

Buffer overflow

\r\n"); + }else{ + rhizome_server_simple_http_response(r, 200, buf); + } + }else{ + rhizome_server_simple_http_response(r, 400, "

Invalid interface id

\r\n"); + } } else if (strcmp(path, "/favicon.ico") == 0) { r->request_type = RHIZOME_HTTP_REQUEST_FAVICON; rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len); - } else if (strcmp(path, "/rssi.csv") == 0) { - r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER; - char temp[8192]; - snprintf(temp,8192, - ";%lld;%d;%d;%d;%d;%d;%s;%d;%d;%d;%d;%d\n", - gettime_ms(), - last_radio_rssi,last_radio_temperature,last_radio_rxpackets, - (int)bundles_available, - rhizome_active_fetch_count(), - alloca_tohex(my_subscriber->sid, 8), - rhizome_active_fetch_bytes_received(0), - rhizome_active_fetch_bytes_received(1), - rhizome_active_fetch_bytes_received(2), - rhizome_active_fetch_bytes_received(3), - rhizome_active_fetch_bytes_received(4) - ); - rhizome_server_simple_http_response(r, 200, temp); - } else if (strcmp(path, "/rssi") == 0) { - r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER; - char temp[8192]; - snprintf(temp,8192, - "" - "

Radio link margin = %+ddB (%d packets received)
" - "Radio temperature = %d°C
" - "SID: %s*
" - "%d rhizome bundles in database
" - "%d rhizome transfers in progress
(%d,%d,%d,%d,%d bytes)
" - "

\n", - last_radio_rssi,last_radio_rxpackets,last_radio_temperature, - alloca_tohex(my_subscriber->sid, 8), - (int)bundles_available, - rhizome_active_fetch_count(), - rhizome_active_fetch_bytes_received(0), - rhizome_active_fetch_bytes_received(1), - rhizome_active_fetch_bytes_received(2), - rhizome_active_fetch_bytes_received(3), - rhizome_active_fetch_bytes_received(4) - ); - rhizome_server_simple_http_response(r, 200, temp); } else if (is_rhizome_http_enabled()){ if (strcmp(path, "/rhizome/groups") == 0) { /* Return the list of known groups */ @@ -606,7 +619,11 @@ int rhizome_server_parse_http_request(rhizome_http_request *r) strbuf_puts(&b, ""); rhizome_fetch_status_html(&b); strbuf_puts(&b, ""); - rhizome_server_simple_http_response(r, 200, buf); + if (strbuf_overrun(&b)){ + rhizome_server_simple_http_response(r, 500, "

Buffer overflow

\r\n"); + }else{ + rhizome_server_simple_http_response(r, 200, buf); + } } else if (strcmp(path, "/rhizome/files") == 0) { /* Return the list of known files */ rhizome_server_sql_query_http_response(r, "id", "files", "from files", 32, 1); diff --git a/route_link.c b/route_link.c index d2a0464c..585745b8 100644 --- a/route_link.c +++ b/route_link.c @@ -624,6 +624,75 @@ static void clean_neighbours(time_ms_t now) } } +static void link_status_html(struct strbuf *b, struct subscriber *n, struct link *link) +{ + if (!link) + return; + link_status_html(b, n, link->_left); + int best=0; + if (link->receiver->next_hop==n) + best=1; + else if(link->receiver==n && n->reachable&REACHABLE_DIRECT) + best=1; + strbuf_sprintf(b, "%s* -%s H: %d, C: %d, via %s*
", + alloca_tohex(link->receiver->sid,8), + best?" *best*":"", + link->hop_count, link->path_drop_rate, + link->transmitter?alloca_tohex(link->transmitter->sid,8):"unreachable"); + link_status_html(b, n, link->_right); +} + +void link_neighbour_short_status_html(struct strbuf *b, const char *link_prefix) +{ + struct neighbour *n = neighbours; + if (!n) + strbuf_puts(b, "No peers
"); + while(n){ + strbuf_sprintf(b, "%s*, seq=%d, mask=%08"PRIx64";
", + link_prefix, + alloca_tohex_sid(n->subscriber->sid), + alloca_tohex(n->subscriber->sid,8), + n->mdp_ack_sequence, n->mdp_ack_mask); + n=n->_next; + } +} + +void link_neighbour_status_html(struct strbuf *b, struct subscriber *neighbour) +{ + time_ms_t now = gettime_ms(); + struct neighbour *n = neighbours; + while(n){ + if (n->subscriber == neighbour){ + strbuf_sprintf(b, "Neighbour %s*;
", alloca_tohex(n->subscriber->sid,8)); + strbuf_sprintf(b, "Seq=%d, mask=%08"PRIx64"
", n->mdp_ack_sequence, n->mdp_ack_mask); + struct link_in *link_in = n->links; + while(link_in){ + strbuf_sprintf(b, "In: %s%s, seq=%d, mask=%08"PRIx64"
", + link_in->interface->name, + link_in == n->best_link?" *best":"", + link_in->ack_sequence, + link_in->ack_mask); + link_in = link_in->_next; + } + struct link_out *link_out = n->out_links; + while(link_out){ + if (link_out->timeout >= now){ + strbuf_sprintf(b, "Out: %s %s
", + link_out->destination->interface->name, + link_out->destination->unicast?"unicast":"broadcast"); + } + link_out = link_out->_next; + } + strbuf_puts(b, "Links;
"); + link_status_html(b, n->subscriber, n->root); + return; + } + n = n->_next; + } + strbuf_puts(b, "Not found
"); +} + + static int send_legacy_self_announce_ack(struct neighbour *neighbour, struct link_in *link, time_ms_t now){ struct overlay_frame *frame=emalloc_zero(sizeof(struct overlay_frame)); frame->type = OF_TYPE_SELFANNOUNCE_ACK; diff --git a/serval.h b/serval.h index 38f08a8e..d7cf27b1 100644 --- a/serval.h +++ b/serval.h @@ -472,6 +472,9 @@ typedef struct overlay_interface { int recv_offset; /* file offset */ + int recv_count; + int tx_count; + // stream socket tx state; struct overlay_buffer *tx_packet; unsigned char txbuffer[OVERLAY_INTERFACE_RX_BUFFER_SIZE]; @@ -483,7 +486,8 @@ typedef struct overlay_interface { int32_t remaining_space; time_ms_t next_heartbeat; int mavlink_seq; - + int radio_rssi; + int remote_rssi; struct slip_decode_state slip_decode_state; @@ -723,6 +727,7 @@ overlay_interface * overlay_interface_find(struct in_addr addr, int return_defau overlay_interface * overlay_interface_find_name(const char *name); int overlay_interface_compare(overlay_interface *one, overlay_interface *two); int overlay_broadcast_ensemble(struct network_destination *destination, struct overlay_buffer *buffer); +void interface_state_html(struct strbuf *b, struct overlay_interface *interface); int directory_registration(); int directory_service_init(); @@ -877,9 +882,6 @@ int slip_decode(struct slip_decode_state *state); int upper7_decode(struct slip_decode_state *state,unsigned char byte); uint32_t Crc32_ComputeBuf( uint32_t inCrc32, const void *buf, size_t bufLen ); -extern int last_radio_rssi; -extern int last_radio_temperature; -extern int last_radio_rxpackets; int rhizome_active_fetch_count(); int rhizome_active_fetch_bytes_received(int q); extern int64_t bundles_available; @@ -897,6 +899,8 @@ int link_state_ack_soon(struct subscriber *sender); int link_state_should_forward_broadcast(struct subscriber *transmitter); int link_unicast_ack(struct subscriber *subscriber, struct overlay_interface *interface, struct sockaddr_in addr); int link_add_destinations(struct overlay_frame *frame); +void link_neighbour_short_status_html(struct strbuf *b, const char *link_prefix); +void link_neighbour_status_html(struct strbuf *b, struct subscriber *neighbour); int generate_nonce(unsigned char *nonce,int bytes); diff --git a/strbuf.h b/strbuf.h index 4152119a..5b959953 100644 --- a/strbuf.h +++ b/strbuf.h @@ -41,7 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. strbuf_init(&b, buf, sizeof buf); strbuf_puts(&b, "text"); strbuf_sprintf(&b, "fmt", val...); - if (strbuf_overflow(&b)) + if (strbuf_overrun(&b)) // error... else // use buf