/** * \addtogroup rimeexamples * @{ */ /* * Copyright (c) 2006, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the Contiki operating system. * * $Id: polite-announcement.c,v 1.5 2009/05/08 08:52:55 adamdunkels Exp $ */ /** * \file * An example announcement back-end, based on the polite primitive * \author * Adam Dunkels */ #include "contiki.h" #include "net/rime.h" #include "net/rime/announcement.h" #include "net/rime/ipolite.h" #if NETSIM #include "ether.h" #endif #include #include #include struct announcement_data { uint16_t id; uint16_t value; }; #define ANNOUNCEMENT_MSG_HEADERLEN 2 struct announcement_msg { uint16_t num; struct announcement_data data[]; }; struct polite_announcement_state { struct ipolite_conn c; struct ctimer t; clock_time_t interval; clock_time_t min_interval, max_interval; } c; #define DEBUG 0 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) #endif #define MIN(a, b) ((a)<(b)?(a):(b)) /*---------------------------------------------------------------------------*/ static void send_adv(clock_time_t interval) { struct announcement_msg *adata; struct announcement *a; packetbuf_clear(); adata = packetbuf_dataptr(); adata->num = 0; for(a = announcement_list(); a != NULL; a = a->next) { adata->data[adata->num].id = a->id; adata->data[adata->num].value = a->value; adata->num++; } packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN + sizeof(struct announcement_data) * adata->num); PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num); if(adata->num > 0) { /* Send the packet only if it contains more than zero announcements. */ ipolite_send(&c.c, interval, packetbuf_datalen()); } } /*---------------------------------------------------------------------------*/ static void adv_packet_received(struct ipolite_conn *ipolite, rimeaddr_t *from) { struct announcement_msg *adata = packetbuf_dataptr(); int i; PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], from->u8[0], from->u8[1], adata->num); for(i = 0; i < adata->num; ++i) { announcement_heard(from, adata->data[i].id, adata->data[i].value); } } /*---------------------------------------------------------------------------*/ static void send_timer(void *ptr) { send_adv(c.interval); ctimer_set(&c.t, c.interval, send_timer, &c); c.interval = MIN(c.interval * 2, c.max_interval); } /*---------------------------------------------------------------------------*/ static void new_announcement(uint16_t id, uint16_t val) { c.interval = c.min_interval; send_timer(&c); } /*---------------------------------------------------------------------------*/ static const struct ipolite_callbacks ipolite_callbacks = {adv_packet_received, NULL, NULL}; /*---------------------------------------------------------------------------*/ void polite_announcement_init(uint16_t channel, clock_time_t min, clock_time_t max) { ipolite_open(&c.c, channel, &ipolite_callbacks); c.min_interval = min; c.max_interval = max; announcement_register_observer_callback(new_announcement); } /*---------------------------------------------------------------------------*/ void polite_announcement_stop(void) { ctimer_stop(&c.t); ipolite_close(&c.c); } /*---------------------------------------------------------------------------*/ /** @} */