Contiki 3.x
broadcast-announcement.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \addtogroup rimebroadcastannouncement
35  * @{
36  */
37 
38 /**
39  * \file
40  * An example announcement back-end, based on the broadcast primitive
41  * \author
42  * Adam Dunkels <adam@sics.se>
43  */
44 
45 #include "contiki.h"
46 
47 #include "net/rime/rime.h"
48 #include "net/rime/announcement.h"
49 #include "net/rime/broadcast.h"
50 #include "lib/random.h"
51 #include "lib/list.h"
52 
53 #if NETSIM
54 #include "ether.h"
55 #endif
56 
57 #include <string.h>
58 #include <stddef.h>
59 
60 struct announcement_data {
61  uint16_t id;
62  uint16_t value;
63 };
64 
65 #ifdef BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
66 #define NUM_DUPS BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
67 #else /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
68 #define NUM_DUPS 5
69 #endif /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
70 
71 #define ANNOUNCEMENT_MSG_HEADERLEN 2
72 struct announcement_msg {
73  uint16_t num;
74  struct announcement_data data[];
75 };
76 
77 
78 static struct broadcast_announcement_state {
79  struct broadcast_conn c;
80  struct ctimer send_timer, interval_timer;
81  clock_time_t initial_interval, min_interval, max_interval;
82  clock_time_t current_interval;
83  uint16_t val;
84 } c;
85 
86 
87 #define DEBUG 0
88 #if DEBUG
89 #include <stdio.h>
90 #define PRINTF(...) printf(__VA_ARGS__)
91 #else
92 #define PRINTF(...)
93 #endif
94 
95 #define MIN(a, b) ((a)<(b)?(a):(b))
96 
97 /*---------------------------------------------------------------------------*/
98 static void
99 send_adv(void *ptr)
100 {
101  struct announcement_msg *adata;
102  struct announcement *a;
103 
104  packetbuf_clear();
105  adata = packetbuf_dataptr();
106  adata->num = 0;
107  for(a = announcement_list(); a != NULL && a->has_value; a = list_item_next(a)) {
108  adata->data[adata->num].id = a->id;
109  adata->data[adata->num].value = a->value;
110  adata->num++;
111  }
112 
113  packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
114  sizeof(struct announcement_data) * adata->num);
115 
116  PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
117  linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], adata->num);
118 
119  if(adata->num > 0) {
120  /* Send the packet only if it contains more than zero announcements. */
121  broadcast_send(&c.c);
122  }
123  PRINTF("%d.%d: sending neighbor advertisement with val %d\n",
125  c.val);
126 }
127 /*---------------------------------------------------------------------------*/
128 static void
129 adv_packet_received(struct broadcast_conn *ibc, const linkaddr_t *from)
130 {
131  struct announcement_msg adata;
132  struct announcement_data data;
133  uint8_t *ptr;
134  int i;
135 
136  ptr = packetbuf_dataptr();
137 
138  /* Copy number of announcements */
139  memcpy(&adata, ptr, sizeof(struct announcement_msg));
140  PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
142  from->u8[0], from->u8[1], adata.num);
143 
144  if(ANNOUNCEMENT_MSG_HEADERLEN + adata.num * sizeof(struct announcement_data) > packetbuf_datalen()) {
145  /* The number of announcements is too large - corrupt packet has
146  been received. */
147  PRINTF("adata.num way out there: %d\n", adata.num);
148  return;
149  }
150 
151  ptr += ANNOUNCEMENT_MSG_HEADERLEN;
152  for(i = 0; i < adata.num; ++i) {
153  /* Copy announcements */
154  memcpy(&data, ptr, sizeof(struct announcement_data));
155  announcement_heard(from, data.id, data.value);
156  ptr += sizeof(struct announcement_data);
157  }
158 }
159 /*---------------------------------------------------------------------------*/
160 static void
161 adv_packet_sent(struct broadcast_conn *bc, int status, int num_tx)
162 {
163 }
164 /*---------------------------------------------------------------------------*/
165 static void send_timer(void *ptr);
166 
167 static void
168 set_timers(void)
169 {
170  ctimer_set(&c.interval_timer, c.current_interval, send_timer, NULL);
171  ctimer_set(&c.send_timer, random_rand() % c.current_interval,
172  send_adv, NULL);
173 }
174 /*---------------------------------------------------------------------------*/
175 static void
176 send_timer(void *ptr)
177 {
178  clock_time_t interval;
179 
180  interval = c.current_interval * 2;
181 
182  if(interval > c.max_interval) {
183  interval = c.max_interval;
184  }
185 
186  c.current_interval = interval;
187 
188  /* printf("current_interval %lu\n", (long unsigned int) interval);*/
189 
190  set_timers();
191 }
192 /*---------------------------------------------------------------------------*/
193 static void
194 new_announcement(uint16_t id, uint8_t has_value,
195  uint16_t newval, uint16_t oldval, uint8_t bump)
196 {
197  if(bump == ANNOUNCEMENT_BUMP) {
198  c.current_interval = c.initial_interval;
199  set_timers();
200  /* } else if(newval != oldval) {
201  c.current_interval = c.min_interval;
202  set_timers();*/
203  }
204 }
205 /*---------------------------------------------------------------------------*/
207  {adv_packet_received, adv_packet_sent };
208 /*---------------------------------------------------------------------------*/
209 void
210 broadcast_announcement_init(uint16_t channel,
211  clock_time_t initial,
212  clock_time_t min,
213  clock_time_t max)
214 {
215  broadcast_open(&c.c, channel, &broadcast_callbacks);
216  c.initial_interval = initial;
217  c.min_interval = min;
218  c.max_interval = max;
219 
220  announcement_register_observer_callback(new_announcement);
221 }
222 /*---------------------------------------------------------------------------*/
223 void
224 broadcast_announcement_stop(void)
225 {
226  ctimer_stop(&c.interval_timer);
227  ctimer_stop(&c.send_timer);
228  broadcast_close(&c.c);
229 }
230 /*---------------------------------------------------------------------------*/
231 clock_time_t
232 broadcast_announcement_beacon_interval(void)
233 {
234  return c.current_interval;
235 }
236 /*---------------------------------------------------------------------------*/
237 /** @} */
Linked list manipulation routines.
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48
#define CC_CONST_FUNCTION
Configure if the C compiler have problems with const function pointers.
Definition: cc.h:86
void broadcast_close(struct broadcast_conn *c)
Close a broadcast connection.
Definition: broadcast.c:105
void announcement_register_observer_callback(announcement_observer callback)
Register an observer callback with the announcement module.
Definition: announcement.c:128
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:325
void announcement_heard(const linkaddr_t *from, uint16_t id, uint16_t value)
Inform the announcement module of an incoming announcement.
Definition: announcement.c:140
#define NULL
The null pointer.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
Header file for the Rime stack
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:239
struct announcement * announcement_list(void)
Get the list of registered announcements.
Definition: announcement.c:134
Header file for the announcement primitive
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
Callback structure for broadcast.
Definition: broadcast.h:80
int broadcast_send(struct broadcast_conn *c)
Send an identified best-effort broadcast packet.
Definition: broadcast.c:111
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
Representation of an announcement.
Definition: announcement.h:83
Header file for identified best-effort local area broadcast
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u)
Set up an identified best-effort broadcast connection.
Definition: broadcast.c:96
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:142
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
Definition: random.c:47