Contiki 2.5
polite-announcement.c
Go to the documentation of this file.
1 /**
2  * \addtogroup rimeexamples
3  * @{
4  */
5 
6 /*
7  * Copyright (c) 2006, Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the Institute nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * This file is part of the Contiki operating system.
35  *
36  * $Id: polite-announcement.c,v 1.16 2010/06/16 10:10:10 nifi Exp $
37  */
38 
39 /**
40  * \file
41  * An example announcement back-end, based on the polite primitive
42  * \author
43  * Adam Dunkels <adam@sics.se>
44  */
45 
46 #include "contiki.h"
47 
48 #include "lib/list.h"
49 #include "net/rime.h"
50 #include "net/rime/announcement.h"
51 #include "net/rime/ipolite.h"
52 
53 #if NETSIM
54 #include "ether.h"
55 #endif
56 
57 #include <string.h>
58 #include <stdio.h>
59 #include <stddef.h>
60 
61 struct announcement_data {
62  uint16_t id;
63  uint16_t value;
64 };
65 
66 #ifdef POLITE_ANNOUNCEMENT_CONF_MAX_DUPS
67 #define NUM_DUPS POLITE_ANNOUNCEMENT_CONF_MAX_DUPS
68 #else /* POLITE_ANNOUNCEMENT_CONF_MAX_DUPS */
69 #define NUM_DUPS 5
70 #endif /* POLITE_ANNOUNCEMENT_CONF_MAX_DUPS */
71 
72 #define ANNOUNCEMENT_MSG_HEADERLEN 2
73 struct announcement_msg {
74  uint16_t num;
75  struct announcement_data data[];
76 };
77 
78 
79 static struct polite_announcement_state {
80  struct ipolite_conn c;
81  struct ctimer t;
82  clock_time_t interval;
83  clock_time_t min_interval, max_interval;
84 } c;
85 
86 #define DEBUG 0
87 #if DEBUG
88 #include <stdio.h>
89 #define PRINTF(...) printf(__VA_ARGS__)
90 #else
91 #define PRINTF(...)
92 #endif
93 
94 #define MIN(a, b) ((a)<(b)?(a):(b))
95 
96 /*---------------------------------------------------------------------------*/
97 static void
98 send_adv(clock_time_t interval)
99 {
100  struct announcement_msg *adata;
101  struct announcement *a;
102 
103  packetbuf_clear();
104  adata = packetbuf_dataptr();
105  adata->num = 0;
106  for(a = announcement_list(); a != NULL; a = list_item_next(a)) {
107  adata->data[adata->num].id = a->id;
108  adata->data[adata->num].value = a->value;
109  adata->num++;
110  }
111 
112  packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
113  sizeof(struct announcement_data) * adata->num);
114 
115  PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
116  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num);
117 
118  if(adata->num > 0) {
119  /* Send the packet only if it contains more than zero announcements. */
120  ipolite_send(&c.c, interval, packetbuf_datalen());
121  }
122 }
123 /*---------------------------------------------------------------------------*/
124 static void
125 adv_packet_received(struct ipolite_conn *ipolite, const rimeaddr_t *from)
126 {
127  struct announcement_msg adata;
128  int i;
129 
130  /* Copy number of announcements */
131  memcpy(&adata, packetbuf_dataptr(), sizeof(struct announcement_msg));
132  PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
134  from->u8[0], from->u8[1], adata.num);
135 
136  for(i = 0; i < adata.num; ++i) {
137  struct announcement_data data;
138 
139  /* Copy announcements */
140  memcpy(&data.id, &((struct announcement_msg *)packetbuf_dataptr())->data[i].id,
141  sizeof(uint16_t));
142  memcpy(&data.value, &((struct announcement_msg *)packetbuf_dataptr())->data[i].value,
143  sizeof(uint16_t));
144  announcement_heard(from,
145  data.id,
146  data.value);
147  }
148 }
149 /*---------------------------------------------------------------------------*/
150 static void
151 send_timer(void *ptr)
152 {
153  send_adv(c.interval);
154  ctimer_set(&c.t,
155  c.interval,
156  send_timer, &c);
157 
158  c.interval = MIN(c.interval * 2, c.max_interval);
159 }
160 /*---------------------------------------------------------------------------*/
161 static void
162 new_announcement(uint16_t id, uint8_t has_value, uint16_t newval,
163  uint16_t oldval, uint8_t bump)
164 {
165  if(newval != oldval) {
166  c.interval = c.min_interval;
167  send_timer(&c);
168  }
169 }
170 /*---------------------------------------------------------------------------*/
171 static const struct ipolite_callbacks ipolite_callbacks =
172  {adv_packet_received, NULL, NULL};
173 /*---------------------------------------------------------------------------*/
174 void
175 polite_announcement_init(uint16_t channel,
176  clock_time_t min,
177  clock_time_t max)
178 {
179  ipolite_open(&c.c, channel, NUM_DUPS, &ipolite_callbacks);
180 
181  c.min_interval = min;
182  c.max_interval = max;
183 
184  announcement_register_observer_callback(new_announcement);
185 }
186 /*---------------------------------------------------------------------------*/
187 void
188 polite_announcement_stop(void)
189 {
190  ctimer_stop(&c.t);
191  ipolite_close(&c.c);
192 }
193 /*---------------------------------------------------------------------------*/
194 /** @} */