Contiki 2.6
|
00001 /** 00002 * \addtogroup rudolph0 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: rudolph0.c,v 1.11 2009/03/12 21:58:21 adamdunkels Exp $ 00037 */ 00038 00039 /** 00040 * \file 00041 * Rudolph0: a simple block data flooding protocol 00042 * \author 00043 * Adam Dunkels <adam@sics.se> 00044 */ 00045 00046 #include <stddef.h> /* for offsetof */ 00047 00048 #include "net/rime.h" 00049 #include "net/rime/rudolph0.h" 00050 00051 #define STEADY_TIME CLOCK_SECOND * 2 00052 00053 #define DEFAULT_SEND_INTERVAL CLOCK_SECOND / 2 00054 enum { 00055 TYPE_DATA, 00056 TYPE_NACK, 00057 }; 00058 00059 enum { 00060 STATE_RECEIVER, 00061 STATE_SENDER, 00062 }; 00063 00064 #define VERSION_LT(a, b) ((signed char)((a) - (b)) < 0) 00065 00066 #define DEBUG 0 00067 #if DEBUG 00068 #include <stdio.h> 00069 #define PRINTF(...) printf(__VA_ARGS__) 00070 #else 00071 #define PRINTF(...) 00072 #endif 00073 00074 /*---------------------------------------------------------------------------*/ 00075 static void 00076 read_new_datapacket(struct rudolph0_conn *c) 00077 { 00078 int len = 0; 00079 00080 if(c->cb->read_chunk) { 00081 len = c->cb->read_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, 00082 c->current.data, RUDOLPH0_DATASIZE); 00083 } 00084 c->current.datalen = len; 00085 00086 PRINTF("read_new_datapacket len %d\n", len); 00087 } 00088 /*---------------------------------------------------------------------------*/ 00089 static void 00090 send_nack(struct rudolph0_conn *c) 00091 { 00092 struct rudolph0_hdr *hdr; 00093 packetbuf_clear(); 00094 packetbuf_hdralloc(sizeof(struct rudolph0_hdr)); 00095 hdr = packetbuf_hdrptr(); 00096 00097 hdr->type = TYPE_NACK; 00098 hdr->version = c->current.h.version; 00099 hdr->chunk = c->current.h.chunk; 00100 00101 PRINTF("Sending nack for %d:%d\n", hdr->version, hdr->chunk); 00102 polite_send(&c->nackc, c->send_interval / 2, sizeof(struct rudolph0_hdr)); 00103 } 00104 /*---------------------------------------------------------------------------*/ 00105 static void 00106 sent(struct stbroadcast_conn *stbroadcast) 00107 { 00108 struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; 00109 00110 if(c->current.datalen == RUDOLPH0_DATASIZE) { 00111 c->current.h.chunk++; 00112 PRINTF("Sending data chunk %d next time\n", c->current.h.chunk); 00113 read_new_datapacket(c); 00114 } else { 00115 stbroadcast_set_timer(&c->c, STEADY_TIME); 00116 PRINTF("Steady: Sending the same data chunk next time datalen %d, %d\n", 00117 c->current.datalen, RUDOLPH0_DATASIZE); 00118 } 00119 } 00120 /*---------------------------------------------------------------------------*/ 00121 static void 00122 recv(struct stbroadcast_conn *stbroadcast) 00123 { 00124 struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; 00125 struct rudolph0_datapacket *p = packetbuf_dataptr(); 00126 00127 if(p->h.type == TYPE_DATA) { 00128 if(c->current.h.version != p->h.version) { 00129 PRINTF("rudolph0 new version %d\n", p->h.version); 00130 c->current.h.version = p->h.version; 00131 c->current.h.chunk = 0; 00132 c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NEWFILE, p->data, 0); 00133 if(p->h.chunk != 0) { 00134 send_nack(c); 00135 } else { 00136 c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NONE, p->data, p->datalen); 00137 c->current.h.chunk++; 00138 } 00139 } else if(p->h.version == c->current.h.version) { 00140 if(p->h.chunk == c->current.h.chunk) { 00141 PRINTF("received chunk %d\n", p->h.chunk); 00142 if(p->datalen < RUDOLPH0_DATASIZE) { 00143 c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, 00144 RUDOLPH0_FLAG_LASTCHUNK, p->data, p->datalen); 00145 } else { 00146 c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, 00147 RUDOLPH0_FLAG_NONE, p->data, p->datalen); 00148 } 00149 c->current.h.chunk++; 00150 00151 } else if(p->h.chunk > c->current.h.chunk) { 00152 PRINTF("received chunk %d > %d, sending NACK\n", p->h.chunk, c->current.h.chunk); 00153 send_nack(c); 00154 } 00155 } else { /* p->h.version < c->current.h.version */ 00156 /* Ignore packets with old version */ 00157 } 00158 } 00159 } 00160 /*---------------------------------------------------------------------------*/ 00161 static void 00162 recv_nack(struct polite_conn *polite) 00163 { 00164 struct rudolph0_conn *c = (struct rudolph0_conn *) 00165 ((char *)polite - offsetof(struct rudolph0_conn, 00166 nackc)); 00167 struct rudolph0_datapacket *p = packetbuf_dataptr(); 00168 00169 if(p->h.type == TYPE_NACK && c->state == STATE_SENDER) { 00170 if(p->h.version == c->current.h.version) { 00171 PRINTF("Reseting chunk to %d\n", p->h.chunk); 00172 c->current.h.chunk = p->h.chunk; 00173 } else { 00174 PRINTF("Wrong version, reseting chunk to 0\n"); 00175 c->current.h.chunk = 0; 00176 } 00177 read_new_datapacket(c); 00178 stbroadcast_set_timer(&c->c, c->send_interval); 00179 } 00180 } 00181 /*---------------------------------------------------------------------------*/ 00182 static const struct polite_callbacks polite = { recv_nack, 0, 0 }; 00183 static const struct stbroadcast_callbacks stbroadcast = { recv, sent }; 00184 /*---------------------------------------------------------------------------*/ 00185 void 00186 rudolph0_open(struct rudolph0_conn *c, uint16_t channel, 00187 const struct rudolph0_callbacks *cb) 00188 { 00189 stbroadcast_open(&c->c, channel, &stbroadcast); 00190 polite_open(&c->nackc, channel + 1, &polite); 00191 c->cb = cb; 00192 c->current.h.version = 0; 00193 c->state = STATE_RECEIVER; 00194 c->send_interval = DEFAULT_SEND_INTERVAL; 00195 } 00196 /*---------------------------------------------------------------------------*/ 00197 void 00198 rudolph0_close(struct rudolph0_conn *c) 00199 { 00200 stbroadcast_close(&c->c); 00201 polite_close(&c->nackc); 00202 } 00203 /*---------------------------------------------------------------------------*/ 00204 void 00205 rudolph0_send(struct rudolph0_conn *c, clock_time_t send_interval) 00206 { 00207 c->state = STATE_SENDER; 00208 c->current.h.version++; 00209 c->current.h.version++; 00210 c->current.h.chunk = 0; 00211 c->current.h.type = TYPE_DATA; 00212 read_new_datapacket(c); 00213 packetbuf_reference(&c->current, sizeof(struct rudolph0_datapacket)); 00214 c->send_interval = send_interval; 00215 stbroadcast_send_stubborn(&c->c, c->send_interval); 00216 } 00217 /*---------------------------------------------------------------------------*/ 00218 void 00219 rudolph0_force_restart(struct rudolph0_conn *c) 00220 { 00221 c->current.h.chunk = 0; 00222 send_nack(c); 00223 } 00224 /*---------------------------------------------------------------------------*/ 00225 void 00226 rudolph0_stop(struct rudolph0_conn *c) 00227 { 00228 stbroadcast_cancel(&c->c); 00229 } 00230 /*---------------------------------------------------------------------------*/ 00231 int 00232 rudolph0_version(struct rudolph0_conn *c) 00233 { 00234 return c->current.h.version; 00235 } 00236 /*---------------------------------------------------------------------------*/ 00237 void 00238 rudolph0_set_version(struct rudolph0_conn *c, int version) 00239 { 00240 c->current.h.version = version; 00241 } 00242 /*---------------------------------------------------------------------------*/ 00243 /** @} */