Contiki 2.6
|
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 /*---------------------------------------------------------------------------*/