Contiki 2.5
neighbor-attr.c
1 /*
2  * Copyright (c) 2010, Vrije Universiteit Brussel
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  *
30  * Author: Joris Borms <joris.borms@vub.ac.be>
31  *
32  */
33 
34 #include "contiki.h"
35 
36 #include "lib/memb.h"
37 #include "lib/list.h"
38 #include <stddef.h>
39 #include <string.h>
40 
41 #include "net/neighbor-attr.h"
42 
43 #define DEBUG 0
44 
45 #if DEBUG
46 #define PRINTF(...) printf(__VA_ARGS__)
47 #else
48 #define PRINTF(...)
49 #endif
50 
51 static uint16_t timeout = 0;
52 
53 MEMB(neighbor_addr_mem, struct neighbor_addr, NEIGHBOR_ATTR_MAX_NEIGHBORS);
54 
55 LIST(neighbor_addrs);
56 LIST(neighbor_attrs);
57 /*---------------------------------------------------------------------------*/
58 static struct neighbor_addr *
59 neighbor_addr_get(const rimeaddr_t *addr)
60 {
61  struct neighbor_addr *item;
62 
63  /* check if addr is derived from table, inside memb */
64  if(memb_inmemb(&neighbor_addr_mem, (char *)addr)) {
65  return (struct neighbor_addr *)
66  (((char *)addr) - offsetof(struct neighbor_addr, addr));
67  }
68 
69  item = list_head(neighbor_addrs);
70  while(item != NULL) {
71  if(rimeaddr_cmp(addr, &item->addr)) {
72  return item;
73  }
74  item = item->next;
75  }
76  return NULL;
77 }
78 /*---------------------------------------------------------------------------*/
79 struct neighbor_addr *
80 neighbor_attr_list_neighbors(void)
81 {
82  return list_head(neighbor_addrs);
83 }
84 /*---------------------------------------------------------------------------*/
85 static void
86 set_attr(struct neighbor_attr *attr, uint16_t index)
87 {
88  if(attr->default_value != NULL) {
89  memcpy((char *)attr->data + index * attr->size,
90  attr->default_value, attr->size);
91  } else {
92  /* fill with zeroes */
93  memset((char *)attr->data + index * attr->size, 0, attr->size);
94  }
95 }
96 /*---------------------------------------------------------------------------*/
97 int
98 neighbor_attr_register(struct neighbor_attr *def)
99 {
100  struct neighbor_addr *addr;
101 
102  list_push(neighbor_attrs, def);
103 
104  /* set default values for already existing neighbors */
105  for(addr = list_head(neighbor_addrs); addr != NULL; addr = addr->next) {
106  set_attr(def, addr->index);
107  }
108  return 1;
109 }
110 /*---------------------------------------------------------------------------*/
111 int
112 neighbor_attr_has_neighbor(const rimeaddr_t *addr)
113 {
114  return neighbor_addr_get(addr) != NULL;
115 }
116 /*---------------------------------------------------------------------------*/
117 int
118 neighbor_attr_add_neighbor(const rimeaddr_t *addr)
119 {
120  struct neighbor_attr *def;
121  struct neighbor_addr *item;
122  struct neighbor_addr *ptr;
123  uint16_t i;
124 
125  if(neighbor_attr_has_neighbor(addr)) {
126  return 0;
127  }
128 
129  item = memb_alloc(&neighbor_addr_mem);
130  if(item == NULL) {
131  return -1;
132  }
133 
134  list_push(neighbor_addrs, item);
135 
136  item->time = 0;
137  rimeaddr_copy(&item->addr, addr);
138 
139  /* look up index and set default values */
140  ptr = neighbor_addr_mem.mem;
141  for(i = 0; i < neighbor_addr_mem.num; ++i) {
142  if(&ptr[i] == item) {
143  break;
144  }
145  }
146 
147  item->index = i;
148 
149  for(def = list_head(neighbor_attrs); def != NULL; def = def->next) {
150  set_attr(def, i);
151  }
152 
153  return 1;
154 }
155 /*---------------------------------------------------------------------------*/
156 int
157 neighbor_attr_remove_neighbor(const rimeaddr_t *addr)
158 {
159  struct neighbor_addr *item = neighbor_addr_get(addr);
160 
161  if(item != NULL) {
162  list_remove(neighbor_addrs, item);
163  memb_free(&neighbor_addr_mem, item);
164  return 0;
165  }
166  return -1;
167 }
168 /*---------------------------------------------------------------------------*/
169 void *
170 neighbor_attr_get_data(struct neighbor_attr *def, const rimeaddr_t *addr)
171 {
172  struct neighbor_addr *attr = neighbor_addr_get(addr);
173 
174  if(attr != NULL) {
175  return (char *)def->data + attr->index * def->size;
176  }
177  return NULL;
178 }
179 /*---------------------------------------------------------------------------*/
180 int
181 neighbor_attr_set_data(struct neighbor_attr *def, const rimeaddr_t *addr,
182  void *data)
183 {
184  struct neighbor_addr *attr = neighbor_addr_get(addr);
185 
186  if(attr == NULL) {
187  if(neighbor_attr_add_neighbor(addr)) {
188  attr = neighbor_addr_get(addr);
189  }
190  }
191  if(attr != NULL) {
192  attr->time = 0;
193  memcpy((char *)def->data + attr->index * def->size, data, def->size);
194  return 1;
195  }
196  return 0;
197 }
198 /*---------------------------------------------------------------------------*/
199 void
200 neighbor_attr_tick(const rimeaddr_t * addr)
201 {
202  struct neighbor_addr *attr = neighbor_addr_get(addr);
203 
204  if(attr != NULL) {
205  attr->time = 0;
206  }
207 }
208 /*---------------------------------------------------------------------------*/
209 uint16_t
210 neighbor_attr_get_timeout(void)
211 {
212  return timeout;
213 }
214 /*---------------------------------------------------------------------------*/
215 static struct ctimer ct;
216 
217 #define TIMEOUT_SECONDS 5
218 static void
219 timeout_check(void *ptr)
220 {
221  if(timeout > 0) {
222  struct neighbor_addr *item = neighbor_attr_list_neighbors();
223 
224  while(item != NULL) {
225  item->time += TIMEOUT_SECONDS;
226  if(item->time >= timeout) {
227  struct neighbor_addr *next_item = item->next;
228 
229  list_remove(neighbor_addrs, item);
230  memb_free(&neighbor_addr_mem, item);
231  item = next_item;
232  } else {
233  item = item->next;
234  }
235  }
236  ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, ptr);
237  }
238 }
239 /*---------------------------------------------------------------------------*/
240 void
241 neighbor_attr_set_timeout(uint16_t time)
242 {
243  if(timeout == 0 && time > 0) {
244  ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, NULL);
245  } else if(timeout > 0 && time == 0) {
246  ctimer_stop(&ct);
247  }
248  timeout = time;
249 }
250 /*---------------------------------------------------------------------------*/