📄 rudolph0.c
字号:
/** * \addtogroup rudolph0 * @{ *//* * Copyright (c) 2007, 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: rudolph0.c,v 1.10 2008/06/30 08:28:53 adamdunkels Exp $ *//** * \file * Rudolph0: a simple block data flooding protocol * \author * Adam Dunkels <adam@sics.se> */#include <stddef.h> /* for offsetof */#include "net/rime.h"#include "net/rime/rudolph0.h"#define STEADY_TIME CLOCK_SECOND * 2#define DEFAULT_SEND_INTERVAL CLOCK_SECOND / 2enum { TYPE_DATA, TYPE_NACK,};enum { STATE_RECEIVER, STATE_SENDER,};#define VERSION_LT(a, b) ((signed char)((a) - (b)) < 0)#define DEBUG 0#if DEBUG#include <stdio.h>#define PRINTF(...) printf(__VA_ARGS__)#else#define PRINTF(...)#endif/*---------------------------------------------------------------------------*/static voidread_new_datapacket(struct rudolph0_conn *c){ int len = 0; if(c->cb->read_chunk) { len = c->cb->read_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, c->current.data, RUDOLPH0_DATASIZE); } c->current.datalen = len; PRINTF("read_new_datapacket len %d\n", len);}/*---------------------------------------------------------------------------*/static voidsend_nack(struct rudolph0_conn *c){ struct rudolph0_hdr *hdr; rimebuf_clear(); rimebuf_hdralloc(sizeof(struct rudolph0_hdr)); hdr = rimebuf_hdrptr(); hdr->type = TYPE_NACK; hdr->version = c->current.h.version; hdr->chunk = c->current.h.chunk; PRINTF("Sending nack for %d:%d\n", hdr->version, hdr->chunk); polite_send(&c->nackc, c->send_interval / 2, sizeof(struct rudolph0_hdr));}/*---------------------------------------------------------------------------*/static voidsent(struct stbroadcast_conn *stbroadcast){ struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; if(c->current.datalen == RUDOLPH0_DATASIZE) { c->current.h.chunk++; PRINTF("Sending data chunk %d next time\n", c->current.h.chunk); read_new_datapacket(c); } else { stbroadcast_set_timer(&c->c, STEADY_TIME); PRINTF("Steady: Sending the same data chunk next time datalen %d, %d\n", c->current.datalen, RUDOLPH0_DATASIZE); }}/*---------------------------------------------------------------------------*/static voidrecv(struct stbroadcast_conn *stbroadcast){ struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; struct rudolph0_datapacket *p = rimebuf_dataptr(); if(p->h.type == TYPE_DATA) { if(c->current.h.version != p->h.version) { PRINTF("rudolph0 new version %d\n", p->h.version); c->current.h.version = p->h.version; c->current.h.chunk = 0; c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NEWFILE, p->data, 0); if(p->h.chunk != 0) { send_nack(c); } else { c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NONE, p->data, p->datalen); c->current.h.chunk++; } } else if(p->h.version == c->current.h.version) { if(p->h.chunk == c->current.h.chunk) { PRINTF("received chunk %d\n", p->h.chunk); if(p->datalen < RUDOLPH0_DATASIZE) { c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, RUDOLPH0_FLAG_LASTCHUNK, p->data, p->datalen); } else { c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, RUDOLPH0_FLAG_NONE, p->data, p->datalen); } c->current.h.chunk++; } else if(p->h.chunk > c->current.h.chunk) { PRINTF("received chunk %d > %d, sending NACK\n", p->h.chunk, c->current.h.chunk); send_nack(c); } } else { /* p->h.version < c->current.h.version */ /* Ignore packets with old version */ } }}/*---------------------------------------------------------------------------*/static voidrecv_nack(struct polite_conn *polite){ struct rudolph0_conn *c = (struct rudolph0_conn *) ((char *)polite - offsetof(struct rudolph0_conn, nackc)); struct rudolph0_datapacket *p = rimebuf_dataptr(); if(p->h.type == TYPE_NACK && c->state == STATE_SENDER) { if(p->h.version == c->current.h.version) { PRINTF("Reseting chunk to %d\n", p->h.chunk); c->current.h.chunk = p->h.chunk; } else { PRINTF("Wrong version, reseting chunk to 0\n"); c->current.h.chunk = 0; } read_new_datapacket(c); stbroadcast_set_timer(&c->c, c->send_interval); }}/*---------------------------------------------------------------------------*/static const struct polite_callbacks polite = { recv_nack, 0, 0 };static const struct stbroadcast_callbacks stbroadcast = { recv, sent };/*---------------------------------------------------------------------------*/voidrudolph0_open(struct rudolph0_conn *c, uint16_t channel, const struct rudolph0_callbacks *cb){ stbroadcast_open(&c->c, channel, &stbroadcast); polite_open(&c->nackc, channel + 1, &polite); c->cb = cb; c->current.h.version = 0; c->state = STATE_RECEIVER; c->send_interval = DEFAULT_SEND_INTERVAL;}/*---------------------------------------------------------------------------*/voidrudolph0_close(struct rudolph0_conn *c){ stbroadcast_close(&c->c); polite_close(&c->nackc);}/*---------------------------------------------------------------------------*/voidrudolph0_send(struct rudolph0_conn *c, clock_time_t send_interval){ c->state = STATE_SENDER; c->current.h.version++; c->current.h.version++; c->current.h.chunk = 0; c->current.h.type = TYPE_DATA; read_new_datapacket(c); rimebuf_reference(&c->current, sizeof(struct rudolph0_datapacket)); c->send_interval = send_interval; stbroadcast_send_stubborn(&c->c, c->send_interval);}/*---------------------------------------------------------------------------*/voidrudolph0_force_restart(struct rudolph0_conn *c){ c->current.h.chunk = 0; send_nack(c);}/*---------------------------------------------------------------------------*/voidrudolph0_stop(struct rudolph0_conn *c){ stbroadcast_cancel(&c->c);}/*---------------------------------------------------------------------------*/intrudolph0_version(struct rudolph0_conn *c){ return c->current.h.version;}/*---------------------------------------------------------------------------*/voidrudolph0_set_version(struct rudolph0_conn *c, int version){ c->current.h.version = version;}/*---------------------------------------------------------------------------*//** @} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -