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 <stdio.h>
00060 #include <stddef.h>
00061 
00062 struct announcement_data {
00063   uint16_t id;
00064   uint16_t value;
00065 };
00066 
00067 #ifdef BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
00068 #define NUM_DUPS BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
00069 #else /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
00070 #define NUM_DUPS 5
00071 #endif /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
00072 
00073 #define ANNOUNCEMENT_MSG_HEADERLEN 2
00074 struct announcement_msg {
00075   uint16_t num;
00076   struct announcement_data data[];
00077 };
00078 
00079 
00080 static struct broadcast_announcement_state {
00081   struct broadcast_conn c;
00082   struct ctimer send_timer, interval_timer;
00083   clock_time_t initial_interval, min_interval, max_interval;
00084   clock_time_t current_interval;
00085   uint16_t val;
00086 } c;
00087 
00088 
00089 #define DEBUG 0
00090 #if DEBUG
00091 #include <stdio.h>
00092 #define PRINTF(...) printf(__VA_ARGS__)
00093 #else
00094 #define PRINTF(...)
00095 #endif
00096 
00097 #define MIN(a, b) ((a)<(b)?(a):(b))
00098 
00099 /*---------------------------------------------------------------------------*/
00100 static void
00101 send_adv(void *ptr)
00102 {
00103   struct announcement_msg *adata;
00104   struct announcement *a;
00105 
00106   packetbuf_clear();
00107   adata = packetbuf_dataptr();
00108   adata->num = 0;
00109   for(a = announcement_list(); a != NULL && a->has_value; a = list_item_next(a)) {
00110     adata->data[adata->num].id = a->id;
00111     adata->data[adata->num].value = a->value;
00112     adata->num++;
00113   }
00114 
00115   packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
00116                       sizeof(struct announcement_data) * adata->num);
00117 
00118   PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
00119          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num);
00120 
00121   if(adata->num > 0) {
00122     /* Send the packet only if it contains more than zero announcements. */
00123     broadcast_send(&c.c);
00124   }
00125   PRINTF("%d.%d: sending neighbor advertisement with val %d\n",
00126          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00127          c.val);
00128 }
00129 /*---------------------------------------------------------------------------*/
00130 static void
00131 adv_packet_received(struct broadcast_conn *ibc, const rimeaddr_t *from)
00132 {
00133   struct announcement_msg adata;
00134   int i;
00135 
00136   /* Copy number of announcements */
00137   memcpy(&adata, packetbuf_dataptr(), sizeof(struct announcement_msg));
00138   PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
00139          rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00140          from->u8[0], from->u8[1], adata.num);
00141 
00142   if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
00143     /* The number of announcements is too large - corrupt packet has
00144        been received. */
00145     printf("adata.num way out there: %d\n", adata.num);
00146     return;
00147   }
00148   
00149   for(i = 0; i < adata.num; ++i) {
00150     struct announcement_data data;
00151 
00152     /* Copy announcements */
00153     memcpy(&data.id, &((struct announcement_msg *)packetbuf_dataptr())->data[i].id,
00154           sizeof(uint16_t));
00155     memcpy(&data.value, &((struct announcement_msg *)packetbuf_dataptr())->data[i].value,
00156           sizeof(uint16_t));
00157     announcement_heard(from,
00158                        data.id,
00159                        data.value);
00160   }
00161 }
00162 /*---------------------------------------------------------------------------*/
00163 static void
00164 adv_packet_sent(struct broadcast_conn *bc, int status, int num_tx)
00165 {
00166 }
00167 /*---------------------------------------------------------------------------*/
00168 static void send_timer(void *ptr);
00169 
00170 static void
00171 set_timers(void)
00172 {
00173   ctimer_set(&c.interval_timer, c.current_interval, send_timer, NULL);
00174   ctimer_set(&c.send_timer, random_rand() % c.current_interval,
00175              send_adv, NULL);
00176 }
00177 /*---------------------------------------------------------------------------*/
00178 static void
00179 send_timer(void *ptr)
00180 {
00181   clock_time_t interval;
00182 
00183   interval = c.current_interval * 2;
00184 
00185   if(interval > c.max_interval) {
00186     interval = c.max_interval;
00187   }
00188 
00189   c.current_interval = interval;
00190 
00191   /*  printf("current_interval %lu\n", (long unsigned int) interval);*/
00192 
00193   set_timers();
00194 }
00195 /*---------------------------------------------------------------------------*/
00196 static void
00197 new_announcement(uint16_t id, uint8_t has_value,
00198                  uint16_t newval, uint16_t oldval, uint8_t bump)
00199 {
00200   if(bump == ANNOUNCEMENT_BUMP) {
00201     c.current_interval = c.initial_interval;
00202     set_timers();
00203     /*  } else if(newval != oldval) {
00204     c.current_interval = c.min_interval;
00205     set_timers();*/
00206   }
00207 }
00208 /*---------------------------------------------------------------------------*/
00209 static CC_CONST_FUNCTION struct broadcast_callbacks broadcast_callbacks =
00210   {adv_packet_received, adv_packet_sent };
00211 /*---------------------------------------------------------------------------*/
00212 void
00213 broadcast_announcement_init(uint16_t channel,
00214                             clock_time_t initial,
00215                             clock_time_t min,
00216                             clock_time_t max)
00217 {
00218   broadcast_open(&c.c, channel, &broadcast_callbacks);
00219   c.initial_interval = initial;
00220   c.min_interval = min;
00221   c.max_interval = max;
00222 
00223   announcement_register_observer_callback(new_announcement);
00224 }
00225 /*---------------------------------------------------------------------------*/
00226 void
00227 broadcast_announcement_stop(void)
00228 {
00229   ctimer_stop(&c.interval_timer);
00230   ctimer_stop(&c.send_timer);
00231   broadcast_close(&c.c);
00232 }
00233 /*---------------------------------------------------------------------------*/
00234 clock_time_t
00235 broadcast_announcement_beacon_interval(void)
00236 {
00237   return c.current_interval;
00238 }
00239 /*---------------------------------------------------------------------------*/
00240 /** @} */

Generated on Mon Apr 11 14:23:30 2011 for Contiki 2.5 by  doxygen 1.6.1