diff --git a/examples/rime/example-runicast.c b/examples/rime/example-runicast.c index 8c5a040ba..82f237a01 100644 --- a/examples/rime/example-runicast.c +++ b/examples/rime/example-runicast.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: example-runicast.c,v 1.2 2008/11/11 13:50:21 fros4943 Exp $ + * $Id: example-runicast.c,v 1.3 2009/03/03 12:28:39 fros4943 Exp $ */ /** @@ -38,39 +38,77 @@ * Adam Dunkels */ +#include + #include "contiki.h" #include "net/rime.h" -#include "dev/button-sensor.h" +#include "lib/list.h" +#include "lib/memb.h" +#include "dev/button-sensor.h" #include "dev/leds.h" -#include - #define MAX_RETRANSMISSIONS 4 +#define NUM_HISTORY_ENTRIES 4 /*---------------------------------------------------------------------------*/ PROCESS(test_runicast_process, "runicast test"); AUTOSTART_PROCESSES(&test_runicast_process); /*---------------------------------------------------------------------------*/ -static uint8_t in_tx; +/* OPTIONAL: Sender history. + * Detects duplicate callbacks at receiving nodes. + * Duplicates appear when ack messages are lost. */ +struct history_entry { + struct history_entry *next; + rimeaddr_t addr; + uint8_t seq; +}; +LIST(history_table); +MEMB(history_mem, struct history_entry, NUM_HISTORY_ENTRIES); +/*---------------------------------------------------------------------------*/ static void recv_runicast(struct runicast_conn *c, rimeaddr_t *from, uint8_t seqno) { + /* OPTIONAL: Sender history */ + struct history_entry *e = NULL; + for(e = list_head(history_table); e != NULL; e = e->next) { + if (rimeaddr_cmp(&e->addr, from)) { + break; + } + } + if (e == NULL) { + /* Create new history entry */ + e = memb_alloc(&history_mem); + if(e == NULL) { + e = list_chop(history_table); /* Remove oldest at full history */ + } + rimeaddr_copy(&e->addr, from); + e->seq = seqno; + list_push(history_table, e); + } else { + /* Detect duplicate callback */ + if (e->seq == seqno) { + printf("runicast message received from %d.%d, seqno %d (DUPLICATE)\n", + from->u8[0], from->u8[1], seqno); + return; + } + /* Update existing history entry */ + e->seq = seqno; + } + printf("runicast message received from %d.%d, seqno %d\n", from->u8[0], from->u8[1], seqno); } static void sent_runicast(struct runicast_conn *c, rimeaddr_t *to, uint8_t retransmissions) { - in_tx = 0; printf("runicast message sent to %d.%d, retransmissions %d\n", to->u8[0], to->u8[1], retransmissions); } static void timedout_runicast(struct runicast_conn *c, rimeaddr_t *to, uint8_t retransmissions) { - in_tx = 0; printf("runicast message timed out when sending to %d.%d, retransmissions %d\n", to->u8[0], to->u8[1], retransmissions); } @@ -86,31 +124,36 @@ PROCESS_THREAD(test_runicast_process, ev, data) PROCESS_BEGIN(); runicast_open(&runicast, 128, &runicast_callbacks); - in_tx = 0; + + /* OPTIONAL: Sender history */ + list_init(history_table); + memb_init(&history_mem); + + /* Receiver node: do nothing */ + if(rimeaddr_node_addr.u8[0] == 1 && + rimeaddr_node_addr.u8[1] == 0) { + PROCESS_WAIT_EVENT_UNTIL(0); + } while(1) { static struct etimer et; etimer_set(&et, 10*CLOCK_SECOND); - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - if(!in_tx && - !(rimeaddr_node_addr.u8[0] == 1 && - rimeaddr_node_addr.u8[1] == 0)) { + if(!runicast_is_transmitting(&runicast)) { rimeaddr_t recv; rimebuf_copyfrom("Hello", 5); recv.u8[0] = 1; recv.u8[1] = 0; - /*printf("%u.%u: sending runicast to address %u.%u\n", + printf("%u.%u: sending runicast to address %u.%u\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], recv.u8[0], - recv.u8[1]);*/ + recv.u8[1]); - in_tx = 1; runicast_send(&runicast, &recv, MAX_RETRANSMISSIONS); } }