Contiki 2.6

ipolite.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup rimeipolite
00003  * @{
00004  */
00005 
00006 /*
00007  * Copyright (c) 2007, 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: ipolite.c,v 1.17 2010/02/23 18:38:05 adamdunkels Exp $
00037  */
00038 
00039 /**
00040  * \file
00041  *         Ipolite Anonymous best effort local area BroadCast (ipolite)
00042  * \author
00043  *         Adam Dunkels <adam@sics.se>
00044  */
00045 
00046 #include "net/rime.h"
00047 #include "net/rime/ipolite.h"
00048 #include "lib/random.h"
00049 
00050 #include <string.h>
00051 
00052 #ifndef MAX
00053 #define MAX(a, b) ((a) > (b)? (a) : (b))
00054 #endif /* MAX */
00055 
00056 #ifndef MIN
00057 #define MIN(a, b) ((a) < (b)? (a) : (b))
00058 #endif /* MIN */
00059 
00060 #define DEBUG 0
00061 #if DEBUG
00062 #include <stdio.h>
00063 #define PRINTF(...) printf(__VA_ARGS__)
00064 #else
00065 #define PRINTF(...)
00066 #endif
00067 
00068 /*---------------------------------------------------------------------------*/
00069 static void
00070 recv(struct broadcast_conn *broadcast, const rimeaddr_t *from)
00071 {
00072   struct ipolite_conn *c = (struct ipolite_conn *)broadcast;
00073   if(c->q != NULL &&
00074      packetbuf_datalen() == queuebuf_datalen(c->q) &&
00075      memcmp(packetbuf_dataptr(), queuebuf_dataptr(c->q),
00076             MIN(c->hdrsize, packetbuf_datalen())) == 0) {
00077     /* We received a copy of our own packet, so we increase the
00078        duplicate counter. If it reaches its maximum, do not send out
00079        our packet. */
00080     c->dups++;
00081     if(c->dups == c->maxdups) {
00082       queuebuf_free(c->q);
00083       c->q = NULL;
00084       ctimer_stop(&c->t);
00085       if(c->cb->dropped) {
00086         c->cb->dropped(c);
00087       }
00088     }
00089   }
00090   if(c->cb->recv) {
00091     c->cb->recv(c, from);
00092   }
00093 }
00094 /*---------------------------------------------------------------------------*/
00095 static void
00096 sent(struct broadcast_conn *bc, int status, int num_tx)
00097 {
00098 
00099 }
00100 /*---------------------------------------------------------------------------*/
00101 static void
00102 send(void *ptr)
00103 {
00104   struct ipolite_conn *c = ptr;
00105   
00106   PRINTF("%d.%d: ipolite: send queuebuf %p\n",
00107          rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00108          c->q);
00109   
00110   if(c->q != NULL) {
00111     queuebuf_to_packetbuf(c->q);
00112     queuebuf_free(c->q);
00113     c->q = NULL;
00114     broadcast_send(&c->c);
00115     if(c->cb->sent) {
00116       c->cb->sent(c);
00117     }
00118   }
00119 }
00120 /*---------------------------------------------------------------------------*/
00121 static const struct broadcast_callbacks broadcast = { recv, sent };
00122 /*---------------------------------------------------------------------------*/
00123 void
00124 ipolite_open(struct ipolite_conn *c, uint16_t channel, uint8_t dups,
00125           const struct ipolite_callbacks *cb)
00126 {
00127   broadcast_open(&c->c, channel, &broadcast);
00128   c->cb = cb;
00129   c->maxdups = dups;
00130   PRINTF("ipolite open channel %d\n", channel);
00131 }
00132 /*---------------------------------------------------------------------------*/
00133 void
00134 ipolite_close(struct ipolite_conn *c)
00135 {
00136   broadcast_close(&c->c);
00137   ctimer_stop(&c->t);
00138   if(c->q != NULL) {
00139     queuebuf_free(c->q);
00140     c->q = NULL;
00141   }
00142 }
00143 /*---------------------------------------------------------------------------*/
00144 int
00145 ipolite_send(struct ipolite_conn *c, clock_time_t interval, uint8_t hdrsize)
00146 {
00147   if(c->q != NULL) {
00148     /* If we are already about to send a packet, we cancel the old one. */
00149     PRINTF("%d.%d: ipolite_send: cancel old send\n",
00150            rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
00151     queuebuf_free(c->q);
00152   }
00153   c->dups = 0;
00154   c->hdrsize = hdrsize;
00155   if(interval == 0) {
00156     PRINTF("%d.%d: ipolite_send: interval 0\n",
00157            rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
00158     if(broadcast_send(&c->c)) {
00159       if(c->cb->sent) {
00160         c->cb->sent(c);
00161       }
00162       return 1;
00163     }
00164 
00165   } else {
00166     c->q = queuebuf_new_from_packetbuf();
00167     if(c->q != NULL) {
00168       ctimer_set(&c->t,
00169                  interval / 2 + (random_rand() % (interval / 2)),
00170                  send, c);
00171       return 1;
00172     }
00173     PRINTF("%d.%d: ipolite_send: could not allocate queue buffer\n",
00174            rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
00175   }
00176   return 0;
00177 }
00178 /*---------------------------------------------------------------------------*/
00179 void
00180 ipolite_cancel(struct ipolite_conn *c)
00181 {
00182   ctimer_stop(&c->t);
00183   if(c->q != NULL) {
00184     queuebuf_free(c->q);
00185     c->q = NULL;
00186   }
00187 }
00188 /*---------------------------------------------------------------------------*/
00189 /** @} */