diff --git a/core/net/rime/Makefile.rime b/core/net/rime/Makefile.rime index aa0afce8f..1ca784600 100644 --- a/core/net/rime/Makefile.rime +++ b/core/net/rime/Makefile.rime @@ -1,6 +1,6 @@ RIME_CHAMELEON = chameleon.c channel.c chameleon-raw.c chameleon-bitopt.c RIME_BASE = rimebuf.c queuebuf.c rimeaddr.c ctimer.c rime.c timesynch.c \ - rimestats.c #announcement.c polite-announcement.c + rimestats.c announcement.c polite-announcement.c RIME_SINGLEHOP = broadcast.c stbroadcast.c unicast.c stunicast.c \ runicast.c abc.c \ rucb.c polite.c ipolite.c diff --git a/core/net/rime/announcement.c b/core/net/rime/announcement.c new file mode 100644 index 000000000..0bc17a7e6 --- /dev/null +++ b/core/net/rime/announcement.c @@ -0,0 +1,139 @@ +/** + * \addtogroup rimeannouncement + * @{ + */ + +/* + * Copyright (c) 2008, 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: announcement.c,v 1.1 2009/02/05 19:32:01 adamdunkels Exp $ + */ + +/** + * \file + * Implementation of the announcement primitive + * \author + * Adam Dunkels + */ + +#include "net/rime/announcement.h" +#include "lib/list.h" +#include "sys/cc.h" + +LIST(announcements); + +static void (* listen_callback)(int time); +static void (* observer_callback)(uint16_t id, uint16_t val); + +/*---------------------------------------------------------------------------*/ +void +announcement_init(void) +{ + list_init(announcements); +} +/*---------------------------------------------------------------------------*/ +void +announcement_register(struct announcement *a, uint16_t id, uint16_t value, + announcement_callback_t callback) +{ + a->id = id; + a->value = value; + a->callback = callback; + list_add(announcements, a); + if(observer_callback) { + observer_callback(a->id, a->value); + } +} +/*---------------------------------------------------------------------------*/ +void +announcement_remove(struct announcement *a) +{ + list_remove(announcements, a); +} +/*---------------------------------------------------------------------------*/ +void +announcement_set_value(struct announcement *a, uint16_t value) +{ + a->value = value; + if(observer_callback) { + observer_callback(a->id, a->value); + } +} +/*---------------------------------------------------------------------------*/ +void +announcement_set_id(struct announcement *a, uint16_t id) +{ + a->id = id; + if(observer_callback) { + observer_callback(a->id, a->value); + } +} +/*---------------------------------------------------------------------------*/ +void +announcement_listen(int time) +{ + if(listen_callback) { + listen_callback(time); + } +} +/*---------------------------------------------------------------------------*/ +void +announcement_register_listen_callback(void (*callback)(int time)) +{ + listen_callback = callback; +} +/*---------------------------------------------------------------------------*/ +void +announcement_register_observer_callback(void (*callback)(uint16_t id, uint16_t value)) +{ + observer_callback = callback; +} +/*---------------------------------------------------------------------------*/ +struct announcement * +announcement_list(void) +{ + return list_head(announcements); +} +/*---------------------------------------------------------------------------*/ +void +announcement_heard(rimeaddr_t *from, uint16_t id, uint16_t value) +{ + struct announcement *a; + for(a = list_head(announcements); a != NULL; a = a->next) { + if(a->id == id) { + if(a->callback != NULL) { + a->callback(a, from, id, value); + } + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/rime/announcement.h b/core/net/rime/announcement.h new file mode 100644 index 000000000..633501cc0 --- /dev/null +++ b/core/net/rime/announcement.h @@ -0,0 +1,246 @@ +/** + * \addtogroup rime + * @{ + */ + +/** + * \defgroup rimeannouncement Announcements + * @{ + * + * The Announcement primitive does local area announcements. An + * announcement is an (ID, value) tuple that is disseminated to local + * area neighbors. An application or protocol can explicitly listen to + * announcements from neighbors. When an announcement is heard, a + * callback is invoked. + * + * Announcements can be used for a variety of network mechanisms such + * as neighbor discovery, node-level service discovery, or routing + * metric dissemination. + * + * Application programs and protocols register announcements with the + * announcement module. An announcement back-end, implemented by the + * system, takes care of sending out announcements over the radio, as + * well as collecting announcements heard from neighbors. + * + */ + +/* + * Copyright (c) 2008, 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: announcement.h,v 1.1 2009/02/05 19:32:01 adamdunkels Exp $ + */ + +/** + * \file + * Header file for the announcement primitive + * \author + * Adam Dunkels + */ + +#ifndef __ANNOUNCEMENT_H__ +#define __ANNOUNCEMENT_H__ + +#include "net/rime/rimeaddr.h" + +struct announcement; + +typedef void (*announcement_callback_t)(struct announcement *a, + rimeaddr_t *from, + uint16_t id, uint16_t val); + +struct announcement { + struct announcement *next; + uint16_t id; + uint16_t value; + announcement_callback_t callback; +}; + +/** + * \name Application API + * *{ + */ +/** + * \brief Register an announcement + * \param a A pointer to a struct announcement + * \param id The identifying number of the announcement + * \param value The initial value of the announcement + * \param callback A pointer to a callback function that is called + * when an announcement is heard + * + * This function registers an announcement with the + * announcement module. The state of the announcement is + * held in a struct announcement variable, which is passed + * as an argument to this function. This variable must be + * allocated by the caller. An announcement is identified + * with a 16-bit number, which is passed as a parameter to + * the function. The announcement also has an initial + * value, that can later be changed with + * announcement_set_value(). + * + */ +void announcement_register(struct announcement *a, + uint16_t id, uint16_t value, + announcement_callback_t callback); + +/** + * \brief Remove a previously registered announcement + * \param a A pointer to a struct announcement that has + * previously been registered + * + * This function removes an announcement that has + * previously been registered with + * announcement_register(). + * + */ +void announcement_remove(struct announcement *a); + + +/** + * \brief Set the value of an announcement + * \param a A pointer to a struct announcement that has + * previously been registered + * + * This function sets the value of an announcement that + * has previously been registered with + * announcement_register(). + * + */ +void announcement_set_value(struct announcement *a, uint16_t value); + + +/** + * \brief Set the identifier of an announcement + * \param a A pointer to a struct announcement that has + * previously been registered + * + * This function sets the identifier of an announcement + * that has previously been registered with + * announcement_register(). + * + */ +void announcement_set_id(struct announcement *a, uint16_t id); + +/** + * \brief Listen for announcements for a spefic amount of + * announcement periods + * \param periods The number of periods to listen for announcement + * + * This function starts to listen for announcements for + * the specified amount of announcement periods. This + * function is called to ensure that the announcement + * module hears announcements from neighbors. The + * announcement module may hear announcements even if + * listening is not explicitly enabled, but with listening + * enabled, more announcements will be heard. + * + */ +void announcement_listen(int periods); +/** + * @} + */ + +/** + * \name System API + * *{ + */ + +/** + * \brief Initialize the announcement module + * + * This function initializes the announcement module, and + * is called by the system at boot up. + */ +void announcement_init(void); + +/** + * \brief Get the list of registered announcements + * \return The list of registered announcements + * + * This function returns the list of registered + * announcements. This function is used by the back-end to + * compile announcement packets from the registered + * announcements. + * + * The announcement list is an ordinary Contiki list, as + * defined by the \ref list "list module". + * + */ +struct announcement *announcement_list(void); + +/** + * \brief Inform the announcement module of an incoming announcement + * \param from The address of the sender of the announcement + * \param id The identifier of the announcement + * \param value The value of the announcement + * + * This function is called by the back-end to inform the + * announcement module that an announcement from a + * neighbor has been heard. + * + */ +void announcement_heard(rimeaddr_t *from, uint16_t id, uint16_t value); + +/** + * \brief Register a listen callback with the announcement module + * \param callback A pointer to a callback function + * + * This function is called by the back-end to register a + * listen callback with the announcement module. The + * listen callback function is called by the announcement + * module as part of the announcement_listen() function. + * + */ +void announcement_register_listen_callback(void (*callback)(int time)); + +/** + * \brief Register an observer callback with the announcement module + * \param observer A pointer to an observer function + * + * This function is callback by the back-end to register + * an observer callback with the announcement module. The + * observer callback is called by the announcement module + * when an announcement is registered, removed, or have + * its identifier or value updated. + * + * The back-end may chose to send out a new announcement + * message with the updated values. + * + */ +void announcement_register_observer_callback(void (*observer)(uint16_t id, + uint16_t value)); + +/** + * @} + */ + +#endif /* __ANNOUNCE_H__ */ + +/** @} */ +/** @} */ diff --git a/core/net/rime/polite-announcement.c b/core/net/rime/polite-announcement.c new file mode 100644 index 000000000..aeb652024 --- /dev/null +++ b/core/net/rime/polite-announcement.c @@ -0,0 +1,172 @@ +/** + * \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.1 2009/02/05 19:32:01 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; + + rimebuf_clear(); + adata = rimebuf_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++; + } + + rimebuf_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); + + ipolite_send(&c.c, interval, rimebuf_datalen()); +} +/*---------------------------------------------------------------------------*/ +static void +adv_packet_received(struct ipolite_conn *ipolite, rimeaddr_t *from) +{ + struct announcement_msg *adata = rimebuf_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}; +/*---------------------------------------------------------------------------*/ +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); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/rime/polite-announcement.h b/core/net/rime/polite-announcement.h new file mode 100644 index 000000000..dba18a54f --- /dev/null +++ b/core/net/rime/polite-announcement.h @@ -0,0 +1,72 @@ +/** + * \addtogroup rime + * @{ + */ + +/** + * \defgroup rimepoliteannouncement + * @{ + * + * The polite announcement module implements a periodic explicit + * announcement. THe module announces the announcements that have been + * registered with the \ref rimeannouncement "announcement module". + * + * \section channels Channels + * + * The polite announcement module uses 1 channel. + * + */ + +/* + * 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.h,v 1.1 2009/02/05 19:32:01 adamdunkels Exp $ + */ + +/** + * \file + * Neighbor discovery header file + * \author + * Adam Dunkels + */ + +#ifndef __POLITE_ANNOUNCEMENT_H__ +#define __POLITE_ANNOUNCEMENT_H__ + +#include "net/rime/announcement.h" +#include "net/rime/ipolite.h" + +void polite_announcement_init(uint16_t channel, + clock_time_t min, + clock_time_t max); + +#endif /* __POLITE_ANNOUNCEMENT_H__ */ +/** @} */ +/** @} */