⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rudolph2.c

📁 Contiki是一个开源
💻 C
字号:
/* XXX todo: add timeout so that hops_from_sink is reset to MAX   after a while. *//* XXX todo: use a ctimer to drive peridodic transmission: the current   way does not work if a queuebuf cannot be allocated. *//** * \addtogroup rudolph2 * @{ *//* * 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: rudolph2.c,v 1.6 2008/11/09 12:16:33 adamdunkels Exp $ *//** * \file *         Rudolph2: a simple block data flooding protocol * \author *         Adam Dunkels <adam@sics.se> */#include <stdio.h>#include <stddef.h> /* for offsetof */#include "net/rime.h"#include "net/rime/polite.h"#include "net/rime/rudolph2.h"#include "cfs/cfs.h"#define SEND_INTERVAL CLOCK_SECOND / 2#define STEADY_INTERVAL CLOCK_SECOND * 16#define RESEND_INTERVAL SEND_INTERVAL * 4#define NACK_TIMEOUT CLOCK_SECOND / 4struct rudolph2_hdr {  uint8_t type;  uint8_t hops_from_base;  uint16_t version;  uint16_t chunk;};#define POLITE_HEADER 1#define HOPS_MAX 64enum {  TYPE_DATA,  TYPE_NACK,};#define FLAG_LAST_SENT     0x01#define FLAG_LAST_RECEIVED 0x02#define FLAG_IS_STOPPED    0x04#define DEBUG 0#if DEBUG#include <stdio.h>#define PRINTF(...) printf(__VA_ARGS__)#else#define PRINTF(...)#endif#define LT(a, b) ((signed short)((a) - (b)) < 0)/*---------------------------------------------------------------------------*/static intread_data(struct rudolph2_conn *c, uint8_t *dataptr, int chunk){  int len = 0;  if(c->cb->read_chunk) {    len = c->cb->read_chunk(c, chunk * RUDOLPH2_DATASIZE,			    dataptr, RUDOLPH2_DATASIZE);  }  return len;}/*---------------------------------------------------------------------------*/static intformat_data(struct rudolph2_conn *c, int chunk){  struct rudolph2_hdr *hdr;  int len;    rimebuf_clear();  hdr = rimebuf_dataptr();  hdr->type = TYPE_DATA;  hdr->hops_from_base = c->hops_from_base;  hdr->version = c->version;  hdr->chunk = chunk;  len = read_data(c, (uint8_t *)hdr + sizeof(struct rudolph2_hdr), chunk);  rimebuf_set_datalen(sizeof(struct rudolph2_hdr) + len);  return len;}/*---------------------------------------------------------------------------*/static voidwrite_data(struct rudolph2_conn *c, int chunk, uint8_t *data, int datalen){  /* xxx Don't write any data if the application has been stopped. */  if(c->flags & FLAG_IS_STOPPED) {    return;  }    if(chunk == 0) {    c->cb->write_chunk(c, 0, RUDOLPH2_FLAG_NEWFILE, data, 0);  }    PRINTF("%d.%d: get %d bytes\n",	 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	 datalen);    if(datalen < RUDOLPH2_DATASIZE) {    PRINTF("%d.%d: get %d bytes, file complete\n",	   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	   datalen);    c->cb->write_chunk(c, chunk * RUDOLPH2_DATASIZE,		       RUDOLPH2_FLAG_LASTCHUNK, data, datalen);  } else {    c->cb->write_chunk(c, chunk * RUDOLPH2_DATASIZE,		       RUDOLPH2_FLAG_NONE, data, datalen);  }}/*---------------------------------------------------------------------------*/static intsend_data(struct rudolph2_conn *c, clock_time_t interval){  int len;  len = format_data(c, c->snd_nxt);  polite_send(&c->c, interval, POLITE_HEADER);  PRINTF("%d.%d: send_data chunk %d, rcv_nxt %d\n",	 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	 c->snd_nxt, c->rcv_nxt);  return len;}/*---------------------------------------------------------------------------*/static voidsend_nack(struct rudolph2_conn *c){  struct rudolph2_hdr *hdr;  rimebuf_clear();  rimebuf_hdralloc(sizeof(struct rudolph2_hdr));  hdr = rimebuf_hdrptr();  hdr->hops_from_base = c->hops_from_base;  hdr->type = TYPE_NACK;  hdr->version = c->version;  hdr->chunk = c->rcv_nxt;  PRINTF("%d.%d: Sending nack for %d\n",	 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	 hdr->chunk);  polite_send(&c->c, NACK_TIMEOUT, POLITE_HEADER);}/*---------------------------------------------------------------------------*/#if 0 /* Function below not currently used in the code */static voidsend_next(struct rudolph2_conn *c){  int len;  clock_time_t interval;  if(c->flags & FLAG_LAST_SENT) {    interval = STEADY_INTERVAL;  } else {    interval = SEND_INTERVAL;  }    len = send_data(c, interval);  if(len < RUDOLPH2_DATASIZE) {    c->flags |= FLAG_LAST_SENT;  } else {    c->flags &= ~FLAG_LAST_SENT;  }    if(c->nacks == 0 &&     len == RUDOLPH2_DATASIZE &&     c->snd_nxt + 1 < c->rcv_nxt) {    c->snd_nxt++;  }  c->nacks = 0;}#endif /* 0 *//*---------------------------------------------------------------------------*/static voidsent(struct polite_conn *polite){  /*  struct rudolph2_conn *c = (struct rudolph2_conn *)polite;  if((c->flags & FLAG_IS_STOPPED) == 0 &&     (c->flags & FLAG_LAST_RECEIVED)) {    if(c->snd_nxt < c->rcv_nxt) {      send_next(c);    } else {      send_data(c, STEADY_INTERVAL);    }    }*/  }/*---------------------------------------------------------------------------*/static voiddropped(struct polite_conn *polite){  /*  struct rudolph2_conn *c = (struct rudolph2_conn *)polite;  if((c->flags & FLAG_IS_STOPPED) == 0 &&     (c->flags & FLAG_LAST_RECEIVED)) {    if(c->snd_nxt + 1 < c->rcv_nxt) {      send_data(c, SEND_INTERVAL);    } else {      send_data(c, STEADY_INTERVAL);    }    }*/}/*---------------------------------------------------------------------------*/static voidtimed_send(void *ptr){  struct rudolph2_conn *c = (struct rudolph2_conn *)ptr;  clock_time_t interval;  int len;    if((c->flags & FLAG_IS_STOPPED) == 0 &&     (c->flags & FLAG_LAST_RECEIVED)) {    /*    if(c->snd_nxt + 1 < c->rcv_nxt) {      interval = SEND_INTERVAL;    } else {      interval = STEADY_INTERVAL;      }*/    /*    send_data(c, interval);*/    if(c->flags & FLAG_LAST_SENT) {      interval = STEADY_INTERVAL;    } else {      interval = SEND_INTERVAL;    }      len = send_data(c, interval);        if(len < RUDOLPH2_DATASIZE) {      c->flags |= FLAG_LAST_SENT;    } else {      c->flags &= ~FLAG_LAST_SENT;    }        if(c->nacks == 0 &&       len == RUDOLPH2_DATASIZE &&     c->snd_nxt + 1 < c->rcv_nxt) {      c->snd_nxt++;    }    c->nacks = 0;    ctimer_set(&c->t, interval, timed_send, c);  }}/*---------------------------------------------------------------------------*/static voidrecv(struct polite_conn *polite){  struct rudolph2_conn *c = (struct rudolph2_conn *)polite;  struct rudolph2_hdr *hdr = rimebuf_dataptr();  /* Only accept NACKs from nodes that are farther away from the base     than us. */  if(hdr->type == TYPE_NACK && hdr->hops_from_base > c->hops_from_base) {    c->nacks++;    PRINTF("%d.%d: Got NACK for %d:%d (%d:%d)\n",	   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	   hdr->version, hdr->chunk,	   c->version, c->rcv_nxt);    if(hdr->version == c->version) {      if(hdr->chunk < c->rcv_nxt) {	c->snd_nxt = hdr->chunk;	send_data(c, SEND_INTERVAL);      }    } else if(LT(hdr->version, c->version)) {      c->snd_nxt = 0;      send_data(c, SEND_INTERVAL);    }  } else if(hdr->type == TYPE_DATA) {    if(hdr->hops_from_base < c->hops_from_base) {      /* Only accept data from nodes that are closer to the base than	 us. */      c->hops_from_base = hdr->hops_from_base + 1;      if(LT(c->version, hdr->version)) {	PRINTF("%d.%d: rudolph2 new version %d, chunk %d\n",	       rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	       hdr->version, hdr->chunk);	c->version = hdr->version;	c->snd_nxt = c->rcv_nxt = 0;	c->flags &= ~FLAG_LAST_RECEIVED;	c->flags &= ~FLAG_LAST_SENT;	if(hdr->chunk != 0) {	  send_nack(c);	} else {	  rimebuf_hdrreduce(sizeof(struct rudolph2_hdr));	  write_data(c, 0, rimebuf_dataptr(), rimebuf_totlen());	}      } else if(hdr->version == c->version) {	PRINTF("%d.%d: got chunk %d snd_nxt %d rcv_nxt %d\n",	       rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],	       hdr->chunk, c->snd_nxt, c->rcv_nxt);		if(hdr->chunk == c->rcv_nxt) {	  int len;	  rimebuf_hdrreduce(sizeof(struct rudolph2_hdr));	  PRINTF("%d.%d: received chunk %d len %d\n",		 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],		 hdr->chunk, rimebuf_totlen());	  len = rimebuf_totlen();	  write_data(c, hdr->chunk, rimebuf_dataptr(), rimebuf_totlen());	  c->rcv_nxt++;	  if(len < RUDOLPH2_DATASIZE) {	    c->flags |= FLAG_LAST_RECEIVED;	    send_data(c, RESEND_INTERVAL);	    ctimer_set(&c->t, RESEND_INTERVAL, timed_send, c);	  }	} else if(hdr->chunk > c->rcv_nxt) {	  PRINTF("%d.%d: received chunk %d > %d, sending NACK\n",		 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],		 hdr->chunk, c->rcv_nxt);	  send_nack(c);	} else if(hdr->chunk < c->rcv_nxt) {	  /* Ignore packets with a lower chunk number */	}      }    }  }}/*---------------------------------------------------------------------------*/static const struct polite_callbacks polite = { recv, sent, dropped };/*---------------------------------------------------------------------------*/voidrudolph2_open(struct rudolph2_conn *c, uint16_t channel,	      const struct rudolph2_callbacks *cb){  polite_open(&c->c, channel, &polite);  c->cb = cb;  c->version = 0;  c->hops_from_base = HOPS_MAX;}/*---------------------------------------------------------------------------*/voidrudolph2_close(struct rudolph2_conn *c){  polite_close(&c->c);}/*---------------------------------------------------------------------------*/voidrudolph2_send(struct rudolph2_conn *c, clock_time_t send_interval){  int len;  c->hops_from_base = 0;  c->version++;  c->snd_nxt = 0;  len = RUDOLPH2_DATASIZE;  rimebuf_clear();  for(c->rcv_nxt = 0; len == RUDOLPH2_DATASIZE; c->rcv_nxt++) {    len = read_data(c, rimebuf_dataptr(), c->rcv_nxt);  }  c->flags = FLAG_LAST_RECEIVED;  /*  printf("Highest chunk %d\n", c->rcv_nxt);*/  send_data(c, SEND_INTERVAL);  ctimer_set(&c->t, SEND_INTERVAL, timed_send, c);}/*---------------------------------------------------------------------------*/voidrudolph2_stop(struct rudolph2_conn *c){  polite_cancel(&c->c);  c->flags |= FLAG_IS_STOPPED;}/*---------------------------------------------------------------------------*//** @} */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -