Contiki 2.6

neighbor-attr.c

00001 /*
00002  * Copyright (c) 2010, Vrije Universiteit Brussel
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  *
00030  * Author: Joris Borms <joris.borms@vub.ac.be>
00031  *
00032  */
00033 
00034 #include "contiki.h"
00035 
00036 #include "lib/memb.h"
00037 #include "lib/list.h"
00038 #include <stddef.h>
00039 #include <string.h>
00040 
00041 #include "net/neighbor-attr.h"
00042 
00043 #define DEBUG 0
00044 
00045 #if DEBUG
00046 #define PRINTF(...) printf(__VA_ARGS__)
00047 #else
00048 #define PRINTF(...)
00049 #endif
00050 
00051 static uint16_t timeout = 0;
00052 
00053 MEMB(neighbor_addr_mem, struct neighbor_addr, NEIGHBOR_ATTR_MAX_NEIGHBORS);
00054 
00055 LIST(neighbor_addrs);
00056 LIST(neighbor_attrs);
00057 /*---------------------------------------------------------------------------*/
00058 static struct neighbor_addr *
00059 neighbor_addr_get(const rimeaddr_t *addr)
00060 {
00061   struct neighbor_addr *item;
00062 
00063   /* check if addr is derived from table, inside memb */
00064   if(memb_inmemb(&neighbor_addr_mem, (char *)addr)) {
00065     return (struct neighbor_addr *)
00066         (((char *)addr) - offsetof(struct neighbor_addr, addr));
00067   }
00068 
00069   item = list_head(neighbor_addrs);
00070   while(item != NULL) {
00071     if(rimeaddr_cmp(addr, &item->addr)) {
00072       return item;
00073     }
00074     item = item->next;
00075   }
00076   return NULL;
00077 }
00078 /*---------------------------------------------------------------------------*/
00079 struct neighbor_addr *
00080 neighbor_attr_list_neighbors(void)
00081 {
00082   return list_head(neighbor_addrs);
00083 }
00084 /*---------------------------------------------------------------------------*/
00085 static void
00086 set_attr(struct neighbor_attr *attr, uint16_t index)
00087 {
00088   if(attr->default_value != NULL) {
00089     memcpy((char *)attr->data + index * attr->size,
00090            attr->default_value, attr->size);
00091   } else {
00092     /* fill with zeroes */
00093     memset((char *)attr->data + index * attr->size, 0, attr->size);
00094   }
00095 }
00096 /*---------------------------------------------------------------------------*/
00097 int
00098 neighbor_attr_register(struct neighbor_attr *def)
00099 {
00100   struct neighbor_addr *addr;
00101 
00102   list_push(neighbor_attrs, def);
00103 
00104   /* set default values for already existing neighbors */
00105   for(addr = list_head(neighbor_addrs); addr != NULL; addr = addr->next) {
00106     set_attr(def, addr->index);
00107   }
00108   return 1;
00109 }
00110 /*---------------------------------------------------------------------------*/
00111 int
00112 neighbor_attr_has_neighbor(const rimeaddr_t *addr)
00113 {
00114   return neighbor_addr_get(addr) != NULL;
00115 }
00116 /*---------------------------------------------------------------------------*/
00117 int
00118 neighbor_attr_add_neighbor(const rimeaddr_t *addr)
00119 {
00120   struct neighbor_attr *def;
00121   struct neighbor_addr *item;
00122   struct neighbor_addr *ptr;
00123   uint16_t i;
00124 
00125   if(neighbor_attr_has_neighbor(addr)) {
00126     return 0;
00127   }
00128 
00129   item = memb_alloc(&neighbor_addr_mem);
00130   if(item == NULL) {
00131     return -1;
00132   }
00133 
00134   list_push(neighbor_addrs, item);
00135 
00136   item->time = 0;
00137   rimeaddr_copy(&item->addr, addr);
00138 
00139   /* look up index and set default values */
00140   ptr = neighbor_addr_mem.mem;
00141   for(i = 0; i < neighbor_addr_mem.num; ++i) {
00142     if(&ptr[i] == item) {
00143       break;
00144     }
00145   }
00146 
00147   item->index = i;
00148 
00149   for(def = list_head(neighbor_attrs); def != NULL; def = def->next) {
00150     set_attr(def, i);
00151   }
00152 
00153   return 1;
00154 }
00155 /*---------------------------------------------------------------------------*/
00156 int
00157 neighbor_attr_remove_neighbor(const rimeaddr_t *addr)
00158 {
00159   struct neighbor_addr *item = neighbor_addr_get(addr);
00160 
00161   if(item != NULL) {
00162     list_remove(neighbor_addrs, item);
00163     memb_free(&neighbor_addr_mem, item);
00164     return 0;
00165   }
00166   return -1;
00167 }
00168 /*---------------------------------------------------------------------------*/
00169 void *
00170 neighbor_attr_get_data(struct neighbor_attr *def, const rimeaddr_t *addr)
00171 {
00172   struct neighbor_addr *attr = neighbor_addr_get(addr);
00173 
00174   if(attr != NULL) {
00175     return (char *)def->data + attr->index * def->size;
00176   }
00177   return NULL;
00178 }
00179 /*---------------------------------------------------------------------------*/
00180 int
00181 neighbor_attr_set_data(struct neighbor_attr *def, const rimeaddr_t *addr,
00182                        void *data)
00183 {
00184   struct neighbor_addr *attr = neighbor_addr_get(addr);
00185 
00186   if(attr == NULL) {
00187     if(neighbor_attr_add_neighbor(addr)) {
00188       attr = neighbor_addr_get(addr);
00189     }
00190   }
00191   if(attr != NULL) {
00192     attr->time = 0;
00193     memcpy((char *)def->data + attr->index * def->size, data, def->size);
00194     return 1;
00195   }
00196   return 0;
00197 }
00198 /*---------------------------------------------------------------------------*/
00199 void
00200 neighbor_attr_tick(const rimeaddr_t * addr)
00201 {
00202   struct neighbor_addr *attr = neighbor_addr_get(addr);
00203 
00204   if(attr != NULL) {
00205     attr->time = 0;
00206   }
00207 }
00208 /*---------------------------------------------------------------------------*/
00209 uint16_t
00210 neighbor_attr_get_timeout(void)
00211 {
00212   return timeout;
00213 }
00214 /*---------------------------------------------------------------------------*/
00215 static struct ctimer ct;
00216 
00217 #define TIMEOUT_SECONDS 5
00218 static void
00219 timeout_check(void *ptr)
00220 {
00221   if(timeout > 0) {
00222     struct neighbor_addr *item = neighbor_attr_list_neighbors();
00223 
00224     while(item != NULL) {
00225       item->time += TIMEOUT_SECONDS;
00226       if(item->time >= timeout) {
00227         struct neighbor_addr *next_item = item->next;
00228 
00229         list_remove(neighbor_addrs, item);
00230         memb_free(&neighbor_addr_mem, item);
00231         item = next_item;
00232       } else {
00233         item = item->next;
00234       }
00235     }
00236     ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, ptr);
00237   }
00238 }
00239 /*---------------------------------------------------------------------------*/
00240 void
00241 neighbor_attr_set_timeout(uint16_t time)
00242 {
00243   if(timeout == 0 && time > 0) {
00244     ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, NULL);
00245   } else if(timeout > 0 && time == 0) {
00246     ctimer_stop(&ct);
00247   }
00248   timeout = time;
00249 }
00250 /*---------------------------------------------------------------------------*/