Contiki 2.6
|
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 /** @} */