Contiki 2.6

polite-announcement.c

Go to the documentation of this file.
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 /** @} */