/*---------------------------------------------------------------------------*/
static void
recv(struct broadcast_conn *broadcast, const linkaddr_t *from)
{
  struct ipolite_conn *c = (struct ipolite_conn *)broadcast;
  if(c->q != NULL &&
     packetbuf_datalen() == queuebuf_datalen(c->q) &&
     memcmp(packetbuf_dataptr(), queuebuf_dataptr(c->q),
	    MIN(c->hdrsize, packetbuf_datalen())) == 0) {
    /* We received a copy of our own packet, so we increase the
       duplicate counter. If it reaches its maximum, do not send out
       our packet. */
    c->dups++;
    if(c->dups == c->maxdups) {
      queuebuf_free(c->q);
      c->q = NULL;
      ctimer_stop(&c->t);
      if(c->cb->dropped) {
        c->cb->dropped(c);
      }
    }
  }
  if(c->cb->recv) {
    c->cb->recv(c, from);
  }
}
Example #2
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_packetize_process, ev, data)
{
  static struct queuebuf *q = NULL;
  static char *ptr;
  static int size;
  int len;
  PROCESS_BEGIN();

  while(1) {
    struct shell_input *input;
    PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);

    if(q == NULL) {
      packetbuf_clear();
      q = queuebuf_new_from_packetbuf();
      if(q == NULL) {
	shell_output_str(&packetize_command, "packetize: could not allocate packet buffer", "");
	PROCESS_EXIT();
      }
      ptr = queuebuf_dataptr(q);
      size = 0;
    }
    
    input = data;

    len = input->len1 + input->len2;

    if(len + size >= PACKETBUF_SIZE ||
       len  == 0) {
      shell_output(&packetize_command,
		   ptr, size,
		   "", 0);
      queuebuf_free(q);
      q = NULL;
      PROCESS_EXIT();
    }

    memcpy(ptr + size, input->data1, input->len1);
    size += input->len1;
    memcpy(ptr + size, input->data2, input->len2);
    size += input->len2;
    
  }
  
  PROCESS_END();
}
Example #3
0
/*---------------------------------------------------------------------------*/
static void
recv(struct abc_conn *abc)
{
  struct polite_conn *c = (struct polite_conn *)abc;
  if(c->q != NULL &&
     packetbuf_datalen() == queuebuf_datalen(c->q) &&
     memcmp(packetbuf_dataptr(), queuebuf_dataptr(c->q),
	    MIN(c->hdrsize, packetbuf_datalen())) == 0) {
    /* We received a copy of our own packet, so we do not send out
       packet. */
    queuebuf_free(c->q);
    c->q = NULL;
    ctimer_stop(&c->t);
    if(c->cb->dropped) {
      c->cb->dropped(c);
    }
  }
  if(c->cb->recv) {
    c->cb->recv(c);
  }
}
Example #4
0
/*---------------------------------------------------------------------------*/
static char
transmitter(struct rtimer *t, void *ptr)
{
  int r;
  rtimer_clock_t now, rest, period_start, slot_start;

  /* Calculate slot start time */
  now = RTIMER_NOW();
  rest = now % PERIOD_LENGTH;
  period_start = now - rest;
  slot_start = period_start + MY_SLOT*SLOT_LENGTH;

  /* Check if we are inside our slot */
  if(now < slot_start ||
      now > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
    PRINTF("TIMER We are outside our slot: %u != [%u,%u]\n", now, slot_start, slot_start + SLOT_LENGTH);
    while(now > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
      slot_start += PERIOD_LENGTH;
    }

    PRINTF("TIMER Rescheduling until %u\n", slot_start);
    r = rtimer_set(&rtimer, slot_start, 1,
        (void (*)(struct rtimer *, void *))transmitter, NULL);
    if(r) {
      PRINTF("TIMER Error #1: %d\n", r);
    }

    return 1;
  }

  /* Transmit queued packets */
  while(nextsend != freeslot) {
    PRINTF("RADIO Transmitting packet #%i\n", id[nextsend]);
    if(!radio->send(queuebuf_dataptr(data[nextsend]),
		    queuebuf_datalen(data[nextsend]))) {
      sent_counter++;
      PRINTF("RADIO Transmit OK for #%i, total=%i\n", id[nextsend], sent_counter);
      DLEDS_TOGGLE(LEDS_GREEN);
    } else {
      PRINTF("RADIO Transmit failed for #%i, total=%i\n", id[nextsend], sent_counter);
      DLEDS_TOGGLE(LEDS_RED);
    }

    nextsend = (nextsend + 1) % NUM_PACKETS;

    /* Recalculate new slot */
    if(RTIMER_NOW() > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
      PRINTF("TIMER No more time to transmit\n");
      break;
    }
  }

  /* Calculate time of our next slot */
  slot_start += PERIOD_LENGTH;
  PRINTF("TIMER Rescheduling until %u\n", slot_start);
  r = rtimer_set(&rtimer, slot_start, 1,
      (void (*)(struct rtimer *, void *))transmitter, NULL);
  if(r) {
    PRINTF("TIMER Error #2: %d\n", r);
  }

  return 0;
}
Example #5
0
/**
 * Read a packet from the underlying radio driver. If the incoming
 * packet is a probe packet and the sender of the probe matches the
 * destination address of the queued packet (if any), the queued packet
 * is sent.
 */
static void
input_packet(void)
{
  struct lpp_hdr hdr;
  clock_time_t reception_time;

  reception_time = clock_time();

  if(!NETSTACK_FRAMER.parse()) {
    printf("lpp input_packet framer error\n");
  }

  memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));;
  packetbuf_hdrreduce(sizeof(struct lpp_hdr));
  /*    PRINTF("got packet type %d\n", hdr->type);*/

  if(hdr.type == TYPE_PROBE) {
    struct announcement_msg adata;
    
    /* Register the encounter with the sending node. We now know the
       neighbor's phase. */
    register_encounter(&hdr.sender, reception_time);

    /* Parse incoming announcements */
    memcpy(&adata, packetbuf_dataptr(),
           MIN(packetbuf_datalen(), sizeof(adata)));
#if 0
    PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
    
    if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
      /* Sanity check. The number of announcements is too large -
         corrupt packet has been received. */
      return 0;
    }

    for(i = 0; i < adata.num; ++i) {
      /*	  PRINTF("%d.%d: announcement %d: %d\n",
		  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		  adata->data[i].id,
		  adata->data[i].value);*/

      announcement_heard(&hdr.sender,
                         adata.data[i].id,
                         adata.data[i].value);
    }
#endif  /* 0 */

    /* Go through the list of packets to be sent to see if any of
       them match the sender of the probe, or if they are a
       broadcast packet that should be sent. */
    if(list_length(queued_packets_list) > 0) {
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        const rimeaddr_t *receiver;
        uint8_t sent;

        sent = 0;
 
        receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
        if(rimeaddr_cmp(receiver, &hdr.sender) ||
           rimeaddr_cmp(receiver, &rimeaddr_null)) {
          queuebuf_to_packetbuf(i->packet);

#if WITH_PENDING_BROADCAST
          if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
             i->broadcast_flag == BROADCAST_FLAG_SEND) {
            i->num_transmissions = 1;
            NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                                queuebuf_datalen(i->packet));
            sent = 1;
            PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1],
                   receiver->u8[0], receiver->u8[1]);
	      
          } else {
            PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
                   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1]);
          }
#else /* WITH_PENDING_BROADCAST */
          i->num_transmissions = 1;
          NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                               queuebuf_datalen(i->packet));
          PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
                 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                 hdr.sender.u8[0], hdr.sender.u8[1],
                 receiver->u8[0], receiver->u8[1]);
#endif /* WITH_PENDING_BROADCAST */

          /*          off();*/

          /* Attribute the energy spent on listening for the probe
             to this packet transmission. */
          compower_accumulate(&i->compower);
	    
          /* If the packet was not a broadcast packet, we dequeue it
             now. Broadcast packets should be transmitted to all
             neighbors, and are dequeued by the dutycycling function
             instead, after the appropriate time. */
          if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
            if(detect_ack()) {
              remove_queued_packet(i, 1);
            } else {
              remove_queued_packet(i, 0);
            }

#if WITH_PROBE_AFTER_TRANSMISSION
            /* Send a probe packet to catch any reply from the other node. */
            restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
#endif /* WITH_PROBE_AFTER_TRANSMISSION */

#if WITH_STREAMING
            if(is_streaming) {
              ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
                         send_stream_probe, NULL);
            }
#endif /* WITH_STREAMING */
          }

          if(sent) {
            turn_radio_off();
          }

#if WITH_ACK_OPTIMIZATION
          if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
             packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
            /* We're sending a packet that needs an ACK, so we keep
               the radio on in anticipation of the ACK. */
            turn_radio_on();
          }
#endif /* WITH_ACK_OPTIMIZATION */

        }
      }
    }

  } else if(hdr.type == TYPE_DATA) {
    turn_radio_off();
    if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
        /* Not broadcast or for us */
        PRINTF("%d.%d: data not for us from %d.%d\n",
               rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
               hdr.sender.u8[0], hdr.sender.u8[1]);
        return;
      }
      packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
    }
    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);

    PRINTF("%d.%d: got data from %d.%d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1]);

    /* Accumulate the power consumption for the packet reception. */
    compower_accumulate(&current_packet);
    /* Convert the accumulated power consumption for the received
       packet to packet attributes so that the higher levels can
       keep track of the amount of energy spent on receiving the
       packet. */
    compower_attrconv(&current_packet);
      
    /* Clear the accumulated power consumption so that it is ready
       for the next packet. */
    compower_clear(&current_packet);

#if WITH_PENDING_BROADCAST
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      /* This is a broadcast packet. Check the list of pending
         packets to see if we are currently sending a broadcast. If
         so, we refrain from sending our broadcast until one sleep
         cycle period, so that the other broadcaster will have
         finished sending. */
	
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        /* If the packet is a broadcast packet that is not yet
           ready to be sent, we do not send it. */
        if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
          PRINTF("Someone else is sending, pending -> waiting\n");
          set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
        }
      }
    }
#endif /* WITH_PENDING_BROADCAST */


#if WITH_PROBE_AFTER_RECEPTION
    /* XXX send probe after receiving a packet to facilitate data
       streaming. We must first copy the contents of the packetbuf into
       a queuebuf to avoid overwriting the data with the probe packet. */
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
      struct queuebuf *q;
      q = queuebuf_new_from_packetbuf();
      if(q != NULL) {
        send_probe();
        queuebuf_to_packetbuf(q);
        queuebuf_free(q);
      }
    }
#endif /* WITH_PROBE_AFTER_RECEPTION */

#if WITH_ADAPTIVE_OFF_TIME
    off_time = LOWEST_OFF_TIME;
    restart_dutycycle(off_time);
#endif /* WITH_ADAPTIVE_OFF_TIME */

    NETSTACK_MAC.input();
  }
}