Contiki 2.6
|
00001 /** 00002 * \addtogroup rimeexamples 00003 * @{ 00004 */ 00005 00006 /* 00007 * Copyright (c) 2006, Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the Institute nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 * 00034 * This file is part of the Contiki operating system. 00035 * 00036 * $Id: polite-announcement.c,v 1.16 2010/06/16 10:10:10 nifi Exp $ 00037 */ 00038 00039 /** 00040 * \file 00041 * An example announcement back-end, based on the polite primitive 00042 * \author 00043 * Adam Dunkels <adam@sics.se> 00044 */ 00045 00046 #include "contiki.h" 00047 00048 #include "lib/list.h" 00049 #include "net/rime.h" 00050 #include "net/rime/announcement.h" 00051 #include "net/rime/ipolite.h" 00052 00053 #if NETSIM 00054 #include "ether.h" 00055 #endif 00056 00057 #include <string.h> 00058 #include <stdio.h> 00059 #include <stddef.h> 00060 00061 struct announcement_data { 00062 uint16_t id; 00063 uint16_t value; 00064 }; 00065 00066 #ifdef POLITE_ANNOUNCEMENT_CONF_MAX_DUPS 00067 #define NUM_DUPS POLITE_ANNOUNCEMENT_CONF_MAX_DUPS 00068 #else /* POLITE_ANNOUNCEMENT_CONF_MAX_DUPS */ 00069 #define NUM_DUPS 5 00070 #endif /* POLITE_ANNOUNCEMENT_CONF_MAX_DUPS */ 00071 00072 #define ANNOUNCEMENT_MSG_HEADERLEN 2 00073 struct announcement_msg { 00074 uint16_t num; 00075 struct announcement_data data[]; 00076 }; 00077 00078 00079 static struct polite_announcement_state { 00080 struct ipolite_conn c; 00081 struct ctimer t; 00082 clock_time_t interval; 00083 clock_time_t min_interval, max_interval; 00084 } c; 00085 00086 #define DEBUG 0 00087 #if DEBUG 00088 #include <stdio.h> 00089 #define PRINTF(...) printf(__VA_ARGS__) 00090 #else 00091 #define PRINTF(...) 00092 #endif 00093 00094 #define MIN(a, b) ((a)<(b)?(a):(b)) 00095 00096 /*---------------------------------------------------------------------------*/ 00097 static void 00098 send_adv(clock_time_t interval) 00099 { 00100 struct announcement_msg *adata; 00101 struct announcement *a; 00102 00103 packetbuf_clear(); 00104 adata = packetbuf_dataptr(); 00105 adata->num = 0; 00106 for(a = announcement_list(); a != NULL; a = list_item_next(a)) { 00107 adata->data[adata->num].id = a->id; 00108 adata->data[adata->num].value = a->value; 00109 adata->num++; 00110 } 00111 00112 packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN + 00113 sizeof(struct announcement_data) * adata->num); 00114 00115 PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n", 00116 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num); 00117 00118 if(adata->num > 0) { 00119 /* Send the packet only if it contains more than zero announcements. */ 00120 ipolite_send(&c.c, interval, packetbuf_datalen()); 00121 } 00122 } 00123 /*---------------------------------------------------------------------------*/ 00124 static void 00125 adv_packet_received(struct ipolite_conn *ipolite, const rimeaddr_t *from) 00126 { 00127 struct announcement_msg adata; 00128 struct announcement_data data; 00129 uint8_t *ptr; 00130 int i; 00131 00132 ptr = packetbuf_dataptr(); 00133 00134 /* Copy number of announcements */ 00135 memcpy(&adata, ptr, sizeof(struct announcement_msg)); 00136 PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n", 00137 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00138 from->u8[0], from->u8[1], adata.num); 00139 00140 if(ANNOUNCEMENT_MSG_HEADERLEN + adata.num * sizeof(struct announcement_data) > packetbuf_datalen()) { 00141 /* The number of announcements is too large - corrupt packet has 00142 been received. */ 00143 PRINTF("adata.num way out there: %d\n", adata.num); 00144 return; 00145 } 00146 00147 ptr += ANNOUNCEMENT_MSG_HEADERLEN; 00148 for(i = 0; i < adata.num; ++i) { 00149 /* Copy announcements */ 00150 memcpy(&data, ptr, sizeof(struct announcement_data)); 00151 announcement_heard(from, data.id, data.value); 00152 ptr += sizeof(struct announcement_data); 00153 } 00154 } 00155 /*---------------------------------------------------------------------------*/ 00156 static void 00157 send_timer(void *ptr) 00158 { 00159 send_adv(c.interval); 00160 ctimer_set(&c.t, 00161 c.interval, 00162 send_timer, &c); 00163 00164 c.interval = MIN(c.interval * 2, c.max_interval); 00165 } 00166 /*---------------------------------------------------------------------------*/ 00167 static void 00168 new_announcement(uint16_t id, uint8_t has_value, uint16_t newval, 00169 uint16_t oldval, uint8_t bump) 00170 { 00171 if(newval != oldval) { 00172 c.interval = c.min_interval; 00173 send_timer(&c); 00174 } 00175 } 00176 /*---------------------------------------------------------------------------*/ 00177 static const struct ipolite_callbacks ipolite_callbacks = 00178 {adv_packet_received, NULL, NULL}; 00179 /*---------------------------------------------------------------------------*/ 00180 void 00181 polite_announcement_init(uint16_t channel, 00182 clock_time_t min, 00183 clock_time_t max) 00184 { 00185 ipolite_open(&c.c, channel, NUM_DUPS, &ipolite_callbacks); 00186 00187 c.min_interval = min; 00188 c.max_interval = max; 00189 00190 announcement_register_observer_callback(new_announcement); 00191 } 00192 /*---------------------------------------------------------------------------*/ 00193 void 00194 polite_announcement_stop(void) 00195 { 00196 ctimer_stop(&c.t); 00197 ipolite_close(&c.c); 00198 } 00199 /*---------------------------------------------------------------------------*/ 00200 /** @} */