Contiki 2.6

broadcast-announcement.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup rimeexamples
00003  * @{
00004  */
00005 
00006 /*
00007  * Copyright (c) 2006, Swedish Institute of Computer Science.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of the Institute nor the names of its contributors
00019  *    may be used to endorse or promote products derived from this software
00020  *    without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * This file is part of the Contiki operating system.
00035  *
00036  * $Id: broadcast-announcement.c,v 1.7 2010/10/11 23:43:01 adamdunkels Exp $
00037  */
00038 
00039 /**
00040  * \file
00041  *         An example announcement back-end, based on the broadcast primitive
00042  * \author
00043  *         Adam Dunkels <adam@sics.se>
00044  */
00045 
00046 #include "contiki.h"
00047 
00048 #include "net/rime.h"
00049 #include "net/rime/announcement.h"
00050 #include "net/rime/broadcast.h"
00051 #include "lib/random.h"
00052 #include "lib/list.h"
00053 
00054 #if NETSIM
00055 #include "ether.h"
00056 #endif
00057 
00058 #include <string.h>
00059 #include <stddef.h>
00060 
00061 struct announcement_data {
00062   uint16_t id;
00063   uint16_t value;
00064 };
00065 
00066 #ifdef BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
00067 #define NUM_DUPS BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
00068 #else /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
00069 #define NUM_DUPS 5
00070 #endif /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
00071 
00072 #define ANNOUNCEMENT_MSG_HEADERLEN 2
00073 struct announcement_msg {
00074   uint16_t num;
00075   struct announcement_data data[];
00076 };
00077 
00078 
00079 static struct broadcast_announcement_state {
00080   struct broadcast_conn c;
00081   struct ctimer send_timer, interval_timer;
00082   clock_time_t initial_interval, min_interval, max_interval;
00083   clock_time_t current_interval;
00084   uint16_t val;
00085 } c;
00086 
00087 
00088 #define DEBUG 0
00089 #if DEBUG
00090 #include <stdio.h>
00091 #define PRINTF(...) printf(__VA_ARGS__)
00092 #else
00093 #define PRINTF(...)
00094 #endif
00095 
00096 #define MIN(a, b) ((a)<(b)?(a):(b))
00097 
00098 /*---------------------------------------------------------------------------*/
00099 static void
00100 send_adv(void *ptr)
00101 {
00102   struct announcement_msg *adata;
00103   struct announcement *a;
00104 
00105   packetbuf_clear();
00106   adata = packetbuf_dataptr();
00107   adata->num = 0;
00108   for(a = announcement_list(); a != NULL && a->has_value; a = list_item_next(a)) {
00109     adata->data[adata->num].id = a->id;
00110     adata->data[adata->num].value = a->value;
00111     adata->num++;
00112   }
00113 
00114   packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
00115                       sizeof(struct announcement_data) * adata->num);
00116 
00117   PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
00118          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num);
00119 
00120   if(adata->num > 0) {
00121     /* Send the packet only if it contains more than zero announcements. */
00122     broadcast_send(&c.c);
00123   }
00124   PRINTF("%d.%d: sending neighbor advertisement with val %d\n",
00125          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00126          c.val);
00127 }
00128 /*---------------------------------------------------------------------------*/
00129 static void
00130 adv_packet_received(struct broadcast_conn *ibc, const rimeaddr_t *from)
00131 {
00132   struct announcement_msg adata;
00133   struct announcement_data data;
00134   uint8_t *ptr;
00135   int i;
00136 
00137   ptr = packetbuf_dataptr();
00138 
00139   /* Copy number of announcements */
00140   memcpy(&adata, ptr, sizeof(struct announcement_msg));
00141   PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
00142          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00143          from->u8[0], from->u8[1], adata.num);
00144 
00145   if(ANNOUNCEMENT_MSG_HEADERLEN + adata.num * sizeof(struct announcement_data) > packetbuf_datalen()) {
00146     /* The number of announcements is too large - corrupt packet has
00147        been received. */
00148     PRINTF("adata.num way out there: %d\n", adata.num);
00149     return;
00150   }
00151 
00152   ptr += ANNOUNCEMENT_MSG_HEADERLEN;
00153   for(i = 0; i < adata.num; ++i) {
00154     /* Copy announcements */
00155     memcpy(&data, ptr, sizeof(struct announcement_data));
00156     announcement_heard(from, data.id, data.value);
00157     ptr += sizeof(struct announcement_data);
00158   }
00159 }
00160 /*---------------------------------------------------------------------------*/
00161 static void
00162 adv_packet_sent(struct broadcast_conn *bc, int status, int num_tx)
00163 {
00164 }
00165 /*---------------------------------------------------------------------------*/
00166 static void send_timer(void *ptr);
00167 
00168 static void
00169 set_timers(void)
00170 {
00171   ctimer_set(&c.interval_timer, c.current_interval, send_timer, NULL);
00172   ctimer_set(&c.send_timer, random_rand() % c.current_interval,
00173              send_adv, NULL);
00174 }
00175 /*---------------------------------------------------------------------------*/
00176 static void
00177 send_timer(void *ptr)
00178 {
00179   clock_time_t interval;
00180 
00181   interval = c.current_interval * 2;
00182 
00183   if(interval > c.max_interval) {
00184     interval = c.max_interval;
00185   }
00186 
00187   c.current_interval = interval;
00188 
00189   /*  printf("current_interval %lu\n", (long unsigned int) interval);*/
00190 
00191   set_timers();
00192 }
00193 /*---------------------------------------------------------------------------*/
00194 static void
00195 new_announcement(uint16_t id, uint8_t has_value,
00196                  uint16_t newval, uint16_t oldval, uint8_t bump)
00197 {
00198   if(bump == ANNOUNCEMENT_BUMP) {
00199     c.current_interval = c.initial_interval;
00200     set_timers();
00201     /*  } else if(newval != oldval) {
00202     c.current_interval = c.min_interval;
00203     set_timers();*/
00204   }
00205 }
00206 /*---------------------------------------------------------------------------*/
00207 static CC_CONST_FUNCTION struct broadcast_callbacks broadcast_callbacks =
00208   {adv_packet_received, adv_packet_sent };
00209 /*---------------------------------------------------------------------------*/
00210 void
00211 broadcast_announcement_init(uint16_t channel,
00212                             clock_time_t initial,
00213                             clock_time_t min,
00214                             clock_time_t max)
00215 {
00216   broadcast_open(&c.c, channel, &broadcast_callbacks);
00217   c.initial_interval = initial;
00218   c.min_interval = min;
00219   c.max_interval = max;
00220 
00221   announcement_register_observer_callback(new_announcement);
00222 }
00223 /*---------------------------------------------------------------------------*/
00224 void
00225 broadcast_announcement_stop(void)
00226 {
00227   ctimer_stop(&c.interval_timer);
00228   ctimer_stop(&c.send_timer);
00229   broadcast_close(&c.c);
00230 }
00231 /*---------------------------------------------------------------------------*/
00232 clock_time_t
00233 broadcast_announcement_beacon_interval(void)
00234 {
00235   return c.current_interval;
00236 }
00237 /*---------------------------------------------------------------------------*/
00238 /** @} */