Contiki 3.x
polite-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  * \file
35  * An example announcement back-end, based on the polite primitive
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 /**
41  * \addtogroup rimepoliteannouncement
42  * @{
43  */
44 
45 #include "contiki.h"
46 #include "sys/cc.h"
47 #include "lib/list.h"
48 #include "net/rime/rime.h"
49 #include "net/rime/announcement.h"
50 #include "net/rime/ipolite.h"
51 
52 #if NETSIM
53 #include "ether.h"
54 #endif
55 
56 #include <string.h>
57 #include <stdio.h>
58 #include <stddef.h>
59 
60 struct announcement_data {
61  uint16_t id;
62  uint16_t value;
63 };
64 
65 #ifdef POLITE_ANNOUNCEMENT_CONF_MAX_DUPS
66 #define NUM_DUPS POLITE_ANNOUNCEMENT_CONF_MAX_DUPS
67 #else /* POLITE_ANNOUNCEMENT_CONF_MAX_DUPS */
68 #define NUM_DUPS 5
69 #endif /* POLITE_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 polite_announcement_state {
79  struct ipolite_conn c;
80  struct ctimer t;
81  clock_time_t interval;
82  clock_time_t min_interval, max_interval;
83 } c;
84 
85 #define DEBUG 0
86 #if DEBUG
87 #include <stdio.h>
88 #define PRINTF(...) printf(__VA_ARGS__)
89 #else
90 #define PRINTF(...)
91 #endif
92 
93 /*---------------------------------------------------------------------------*/
94 static void
95 send_adv(clock_time_t interval)
96 {
97  struct announcement_msg *adata;
98  struct announcement *a;
99 
100  packetbuf_clear();
101  adata = packetbuf_dataptr();
102  adata->num = 0;
103  for(a = announcement_list(); a != NULL; a = list_item_next(a)) {
104  adata->data[adata->num].id = a->id;
105  adata->data[adata->num].value = a->value;
106  adata->num++;
107  }
108 
109  packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
110  sizeof(struct announcement_data) * adata->num);
111 
112  PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
113  linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], adata->num);
114 
115  if(adata->num > 0) {
116  /* Send the packet only if it contains more than zero announcements. */
117  ipolite_send(&c.c, interval, packetbuf_datalen());
118  }
119 }
120 /*---------------------------------------------------------------------------*/
121 static void
122 adv_packet_received(struct ipolite_conn *ipolite, const linkaddr_t *from)
123 {
124  struct announcement_msg adata;
125  struct announcement_data data;
126  uint8_t *ptr;
127  int i;
128 
129  ptr = packetbuf_dataptr();
130 
131  /* Copy number of announcements */
132  memcpy(&adata, ptr, sizeof(struct announcement_msg));
133  PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
135  from->u8[0], from->u8[1], adata.num);
136 
137  if(ANNOUNCEMENT_MSG_HEADERLEN + adata.num * sizeof(struct announcement_data) > packetbuf_datalen()) {
138  /* The number of announcements is too large - corrupt packet has
139  been received. */
140  PRINTF("adata.num way out there: %d\n", adata.num);
141  return;
142  }
143 
144  ptr += ANNOUNCEMENT_MSG_HEADERLEN;
145  for(i = 0; i < adata.num; ++i) {
146  /* Copy announcements */
147  memcpy(&data, ptr, sizeof(struct announcement_data));
148  announcement_heard(from, data.id, data.value);
149  ptr += sizeof(struct announcement_data);
150  }
151 }
152 /*---------------------------------------------------------------------------*/
153 static void
154 send_timer(void *ptr)
155 {
156  send_adv(c.interval);
157  ctimer_set(&c.t,
158  c.interval,
159  send_timer, &c);
160 
161  c.interval = MIN(c.interval * 2, c.max_interval);
162 }
163 /*---------------------------------------------------------------------------*/
164 static void
165 new_announcement(uint16_t id, uint8_t has_value, uint16_t newval,
166  uint16_t oldval, uint8_t bump)
167 {
168  if(newval != oldval) {
169  c.interval = c.min_interval;
170  send_timer(&c);
171  }
172 }
173 /*---------------------------------------------------------------------------*/
174 static const struct ipolite_callbacks ipolite_callbacks =
175  {adv_packet_received, NULL, NULL};
176 /*---------------------------------------------------------------------------*/
177 void
178 polite_announcement_init(uint16_t channel,
179  clock_time_t min,
180  clock_time_t max)
181 {
182  ipolite_open(&c.c, channel, NUM_DUPS, &ipolite_callbacks);
183 
184  c.min_interval = min;
185  c.max_interval = max;
186 
187  announcement_register_observer_callback(new_announcement);
188 }
189 /*---------------------------------------------------------------------------*/
190 void
191 polite_announcement_stop(void)
192 {
193  ctimer_stop(&c.t);
194  ipolite_close(&c.c);
195 }
196 /*---------------------------------------------------------------------------*/
197 /** @} */
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:158
void announcement_register_observer_callback(announcement_observer callback)
Register an observer callback with the announcement module.
Definition: announcement.c:128
Representation of an announcement.
Definition: announcement.h:83
Header file for the announcement primitive
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:76
Default definitions of C compiler quirk work-arounds.
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
void ipolite_close(struct ipolite_conn *c)
Close an ipolite connection.
Definition: ipolite.c:126
A structure with callback functions for an ipolite connection.
Definition: ipolite.h:113
Header file for the Rime stack
#define NULL
The null pointer.
struct announcement * announcement_list(void)
Get the list of registered announcements.
Definition: announcement.c:134
Linked list manipulation routines.
An opaque structure with no user-visible elements that holds the state of an ipolite connection...
Definition: ipolite.h:135
Header file for Ipolite best effort local Broadcast (ipolite)
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:151
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:170
void ipolite_open(struct ipolite_conn *c, uint16_t channel, uint8_t dups, const struct ipolite_callbacks *cb)
Open an ipolite connection.
Definition: ipolite.c:116
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48
int ipolite_send(struct ipolite_conn *c, clock_time_t interval, uint8_t hdrsize)
Send a packet on an ipolite connection.
Definition: ipolite.c:137