static void trickle_recv(struct trickle_conn *c) { if (!is_gateway) { struct gateway_msg *msg; msg = rimebuf_dataptr(); printf("%d.%d: gateway message: %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], msg->gateway.u8[0], msg->gateway.u8[1]); uip_over_mesh_set_gateway(&msg->gateway); } }
/*---------------------------------------------------------------------------*/ static int format_data(struct rudolph2_conn *c, int chunk) { struct rudolph2_hdr *hdr; int len; rimebuf_clear(); hdr = rimebuf_dataptr(); hdr->type = TYPE_DATA; hdr->hops_from_base = c->hops_from_base; hdr->version = c->version; hdr->chunk = chunk; len = read_data(c, TC(hdr) + sizeof(struct rudolph2_hdr), chunk); rimebuf_set_datalen(sizeof(struct rudolph2_hdr) + len); return len; }
/*---------------------------------------------------------------------------*/ void rudolph2_send(struct rudolph2_conn *c, clock_time_t send_interval) { int len; c->hops_from_base = 0; c->version++; c->snd_nxt = 0; len = RUDOLPH2_DATASIZE; rimebuf_clear(); for(c->rcv_nxt = 0; len == RUDOLPH2_DATASIZE; c->rcv_nxt++) { len = read_data(c, rimebuf_dataptr(), c->rcv_nxt); } c->flags = FLAG_LAST_RECEIVED; printf("Highest chunk %d\n", c->rcv_nxt); send_data(c, SEND_INTERVAL); ctimer_set(&c->t, SEND_INTERVAL, timed_send, TC(c)); }
/*---------------------------------------------------------------------------*/ static int read_packet(void) { struct xmac_hdr *hdr; uint8_t len; rimebuf_clear(); len = radio->read(rimebuf_dataptr(), RIMEBUF_SIZE); if(len > 0) { rimebuf_set_datalen(len); hdr = rimebuf_dataptr(); rimebuf_hdrreduce(sizeof(struct xmac_hdr)); if(rimebuf_totlen() == 0) { CPRINTF("."); /* There is no data in the packet so it has to be a strobe. */ someone_is_sending = 2; if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { /* This is a strobe packet for us. */ if(rimeaddr_cmp(&hdr->sender, &rimeaddr_node_addr)) { /* If the sender address is our node address, the strobe is a stray strobe ACK to us, which we ignore unless we are currently sending a packet. */ CPRINTF("&"); someone_is_sending = 0; } else { struct xmac_hdr msg; /* If the sender address is someone else, we should acknowledge the strobe and wait for the packet. By using the same address as both sender and receiver, we flag the message is a strobe ack. */ #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "read send ack"); #endif rimeaddr_copy(&msg.receiver, &hdr->sender); rimeaddr_copy(&msg.sender, &hdr->sender); CPRINTF("!"); /* We turn on the radio in anticipation of the incoming packet. */ someone_is_sending = 1; waiting_for_packet = 1; on(); radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr)); } } else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { /* If the receiver address is null, the strobe is sent to prepare for an incoming broadcast packet. If this is the case, we turn on the radio and wait for the incoming broadcast packet. */ waiting_for_packet = 1; on(); } /* We are done processing the strobe and we therefore return to the caller. */ return RIME_OK; } else { CPRINTF("-"); someone_is_sending = 0; if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) || rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "read got packet"); #endif /* This is a regular packet that is destined to us or to the broadcast address. */ /* We have received the final packet, so we can go back to being asleep. */ off(); waiting_for_packet = 0; /* XXX should set timer to send queued packet later. */ if(queued_packet != NULL) { queuebuf_free(queued_packet); queued_packet = NULL; } return rimebuf_totlen(); } } } return 0; }
/*---------------------------------------------------------------------------*/ static void recv(struct polite_conn *polite) { struct rudolph2_conn * SAFE c = TC(polite); struct rudolph2_hdr *hdr = rimebuf_dataptr(); /* Only accept NACKs from nodes that are farther away from the base than us. */ if(hdr->type == TYPE_NACK && hdr->hops_from_base > c->hops_from_base) { c->nacks++; PRINTF("%d.%d: Got NACK for %d:%d (%d:%d)\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->version, hdr->chunk, c->version, c->rcv_nxt); if(hdr->version == c->version) { if(hdr->chunk < c->rcv_nxt) { c->snd_nxt = hdr->chunk; send_data(c, SEND_INTERVAL); } } else if(LT(hdr->version, c->version)) { c->snd_nxt = 0; send_data(c, SEND_INTERVAL); } } else if(hdr->type == TYPE_DATA) { if(hdr->hops_from_base < c->hops_from_base) { /* Only accept data from nodes that are closer to the base than us. */ c->hops_from_base = hdr->hops_from_base + 1; if(LT(c->version, hdr->version)) { PRINTF("%d.%d: rudolph2 new version %d, chunk %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->version, hdr->chunk); c->version = hdr->version; c->snd_nxt = c->rcv_nxt = 0; c->flags &= ~FLAG_LAST_RECEIVED; c->flags &= ~FLAG_LAST_SENT; if(hdr->chunk != 0) { send_nack(c); } else { rimebuf_hdrreduce(sizeof(struct rudolph2_hdr)); write_data(c, 0, rimebuf_dataptr(), rimebuf_totlen()); } } else if(hdr->version == c->version) { PRINTF("%d.%d: got chunk %d snd_nxt %d rcv_nxt %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->chunk, c->snd_nxt, c->rcv_nxt); if(hdr->chunk == c->rcv_nxt) { int len; rimebuf_hdrreduce(sizeof(struct rudolph2_hdr)); PRINTF("%d.%d: received chunk %d len %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->chunk, rimebuf_totlen()); len = rimebuf_totlen(); write_data(c, hdr->chunk, rimebuf_dataptr(), rimebuf_totlen()); c->rcv_nxt++; if(len < RUDOLPH2_DATASIZE) { c->flags |= FLAG_LAST_RECEIVED; send_data(c, RESEND_INTERVAL); ctimer_set(&c->t, RESEND_INTERVAL, timed_send, TC(c)); } } else if(hdr->chunk > c->rcv_nxt) { PRINTF("%d.%d: received chunk %d > %d, sending NACK\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->chunk, c->rcv_nxt); send_nack(c); } else if(hdr->chunk < c->rcv_nxt) { /* Ignore packets with a lower chunk number */ } } } } }