[Tinyos-beta-commits] CVS: tinyos-1.x/beta/Drip Drip.h, NONE, 1.1 Drip.nc, NONE, 1.1 DripC.nc, NONE, 1.1 DripM.nc, NONE, 1.1 DripState.nc, NONE, 1.1 DripStateC.nc, NONE, 1.1 DripStateM.nc, NONE, 1.1 DripStateMgr.nc, NONE, 1.1 README.txt, NONE, 1.1

Gilman Tolle gtolle at users.sourceforge.net
Tue Jan 18 16:01:22 PST 2005


Update of /cvsroot/tinyos/tinyos-1.x/beta/Drip
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10251

Added Files:
	Drip.h Drip.nc DripC.nc DripM.nc DripState.nc DripStateC.nc 
	DripStateM.nc DripStateMgr.nc README.txt 
Log Message:
Drip is now entirely independent of the Nucleus system. This is the official version of Drip, and the one that will see future improvements and bugfixes. There is a README.

--- NEW FILE: Drip.h ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/*
 *
 * Authors:		Gilman Tolle
 * Date last modified:  3/12/03
 *
 */

/**
 * @author Gilman Tolle
 */


#ifndef __DRIP_H__
#define __DRIP_H__

enum {
  AM_DRIPMSG = 3,
};

typedef struct DripMetadata {
  uint8_t id;
  uint8_t seqno;
} DripMetadata;

typedef struct DripMsg {
  DripMetadata metadata;
  uint8_t      data[0];
} DripMsg;

enum {
  DRIP_INVALID_KEY = 0,
  DRIP_CACHE_ENTRIES = uniqueCount("DripState"),
  DRIP_SEQNO_OLDEST = 0xff,
  DRIP_SEQNO_NEWEST = 0,
  DRIP_TIMER_PERIOD = 1024,
  DRIP_MIN_SEND_INTERVAL = 0,
  DRIP_MAX_SEND_INTERVAL = 15,
  DRIP_PRE_SEND = 0,
  DRIP_POST_SEND = 1,
};

typedef struct DripCacheEntry {
  DripMetadata     metadata;
  uint16_t         trickleAnnounce;
  uint16_t         trickleCountdown;
  uint8_t          trickleStage;
  uint8_t          trickleSuppress:1;
  uint8_t          trickleState:6;
} DripCacheEntry;

#endif



--- NEW FILE: Drip.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/*
 * Authors:	Gilman Tolle
 *
 */

includes Drip;

interface Drip {
  
  /* 
     Call this in StdControl.init(). It sets up local state. 
  */
  command result_t init();

  /*
    If you have saved a copy of the sequence number to persistent
    storage, call this in StdControl.init() after retrieving your
    copy.
  */
  command result_t setSeqno(uint8_t seqno);

  /* 
     This event is signalled when the Trickle algorithm must broadcast
     the value. Fill in the given buffer pointer, then call rebroadcast. 
     Post a task to call rebroadcast.
  */
  event result_t rebroadcastRequest(TOS_MsgPtr msg, void *pData);
  command result_t rebroadcast(TOS_MsgPtr msg, void *pData, uint8_t len);

  /* 
     Call this when you have changed the values locally, and would like
     to disseminate new data with an incremented sequence number.
     Once this is called, you will be receiving a rebroadcastRequest
     event shortly. 
  */
  command result_t change();
}

--- NEW FILE: DripC.nc ---
/*									tab:4
 *
 *
 * "Copyright (c) 2000-2004 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 */

/*
 * @author Gilman Tolle <get at cs.berkeley.edu>
 */

includes Drip;

configuration DripC {
  provides {
    interface StdControl;
    interface Receive[uint8_t id];
    interface Drip[uint8_t id];
  }
  uses {
    interface DripState[uint8_t id];
  }
}

implementation {
  components 
    DripM, 
    DripStateC,
    SharedMsgBufM,
    GenericComm as Comm, 
    TimerC, 
    RandomLFSR, 
    LedsC as Leds;

  StdControl = DripM;
  Receive = DripM.Receive;
  Drip = DripM;
  DripState = DripM;
  
  DripM.SubControl -> Comm;
  DripM.SubControl -> TimerC;
  DripM.SubControl -> SharedMsgBufM;
  DripM.SubControl -> DripStateC;

  DripM.DripStateMgr -> DripStateC.DripStateMgr;

  DripM.ReceiveMsg -> Comm.ReceiveMsg[AM_DRIPMSG];
  DripM.SendMsg -> Comm.SendMsg[AM_DRIPMSG];

  DripM.SendTimer -> TimerC.Timer[unique("Timer")];

  DripM.Leds -> Leds;
  
  DripM.Random -> RandomLFSR;
}


--- NEW FILE: DripM.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/*
 * Authors:	Gilman Tolle
 *
 */

includes Drip;

module DripM {
  provides {
    interface StdControl;
    interface Receive[uint8_t id];
    interface Drip[uint8_t id];
  }
  uses {
    interface StdControl as SubControl;

    interface DripState[uint8_t id];
    interface DripStateMgr;

    interface ReceiveMsg;
    interface SendMsg;
    interface Timer as SendTimer;
    interface Random;
    interface Leds;
  }
}

implementation {

  TOS_Msg msgBuf;
  bool msgBufBusy;

  command result_t StdControl.init() {
    msgBufBusy = FALSE;
    return call SubControl.init();
  }
  
  command result_t StdControl.start() {
    call SendTimer.start(TIMER_ONE_SHOT, 
			 call Random.rand() % DRIP_TIMER_PERIOD);
    return call SubControl.start();
  }
  
  command result_t StdControl.stop() {
    call SendTimer.stop();
    return SUCCESS;
  }

  command result_t Drip.init[uint8_t id]() {
    call DripState.init[id](id);
    return SUCCESS;
  }

  command result_t Drip.change[uint8_t id]() {
    return call DripState.incrementSeqno[id]();    
  }
  
  command result_t Drip.setSeqno[uint8_t id](uint8_t seqno) {
    return call DripState.setSeqno[id](seqno);
  }

  event result_t SendTimer.fired() {

    TOS_MsgPtr pMsgBuf = &msgBuf;
    DripMsg *dripMsg = (DripMsg*) pMsgBuf->data;
    uint8_t readyKey;

    call DripStateMgr.updateCounters();

    readyKey = call DripStateMgr.findReadyEntry(); 

    if (readyKey != DRIP_INVALID_KEY) {

      if (!msgBufBusy) {

	msgBufBusy = TRUE;
      
	dbg(DBG_USR1, "Sending id: %d\n", readyKey);
	if (!signal Drip.rebroadcastRequest[readyKey](pMsgBuf, dripMsg->data)) {
	  msgBufBusy = FALSE;
	}
      }
    }
    
    call SendTimer.start(TIMER_ONE_SHOT, DRIP_TIMER_PERIOD);
    
    return SUCCESS;
  }

  command result_t Drip.rebroadcast[uint8_t id](TOS_MsgPtr msg,
						void *pData,
						uint8_t len) {
    
    /* msg does not matter right now, because there's only one buf
       they might have been filling. It will matter if we 
       acquire the buf from a lower layer, or if we have a pool. */

    TOS_MsgPtr pMsgBuf = &msgBuf;
    DripMsg *dripMsg = (DripMsg*) pMsgBuf->data;
    result_t result;
    
    if (!msgBufBusy)
      return FAIL;
    
    call DripState.fillMetadata[id](&dripMsg->metadata);
    
    result = call SendMsg.send(TOS_BCAST_ADDR, 
			       offsetof(DripMsg,data) + len,
			       pMsgBuf);

    if (result == SUCCESS) {
      call DripState.entrySent[id]();
    } else {
      msgBufBusy = FALSE;
    }
    
    return result;
  }

  event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, 
				  result_t success) {

    if (pMsg == &msgBuf &&
	msgBufBusy == TRUE) {
      
      msgBufBusy = FALSE;      
    }

    return SUCCESS;
  }

  event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr pMsg) {
    
    TOS_MsgPtr retMsg = pMsg;
    DripMsg *dripMsg = (DripMsg*) pMsg->data;

    dbg(DBG_USR1, "Received msg(id=%d, seqno=%d)\n",
	dripMsg->metadata.id, dripMsg->metadata.seqno);

    if (call DripState.newMsg[dripMsg->metadata.id](dripMsg->metadata)) {

      dripMsg->metadata.seqno = 
	call DripState.getSeqno[dripMsg->metadata.id]();
      
      retMsg = signal Receive.receive[dripMsg->metadata.id]
	(pMsg, dripMsg->data, pMsg->length - offsetof(DripMsg,data));
    }
    
    return retMsg;
  }

  default event TOS_MsgPtr Receive.receive[uint8_t id](TOS_MsgPtr msg, 
						       void* payload, 
						       uint16_t payloadLen) {
    return msg;
  }

  default event result_t Drip.rebroadcastRequest[uint8_t id](TOS_MsgPtr msg, 
							     void *payload) {
    return FAIL;
  }
  
  default command result_t DripState.init[uint8_t localKey](uint8_t globalKey) {
    return FAIL;
  }

  default command uint8_t DripState.getSeqno[uint8_t localKey]() {
    return DRIP_SEQNO_OLDEST;
  }

  default command uint8_t DripState.incrementSeqno[uint8_t localKey]() {
    return FAIL;
  }

  default command result_t DripState.entrySent[uint8_t localKey]() {
    return FAIL;
  }

  default command bool DripState.newMsg[uint8_t localKey](DripMetadata incomingMetadata) {
    return FALSE;
  }

  default command result_t DripState.fillMetadata[uint8_t localKey](DripMetadata *metadata) {
    return FAIL;
  }

}










--- NEW FILE: DripState.nc ---
interface DripState {

  command result_t init(uint8_t globalKey);
  command uint8_t getSeqno();
  command result_t setSeqno(uint8_t seqno);
  command result_t incrementSeqno();

  command result_t entrySent();
  command bool newMsg(DripMetadata incomingMetadata);
  command result_t fillMetadata(DripMetadata *metadata);
}

--- NEW FILE: DripStateC.nc ---
configuration DripStateC {
  provides {
    interface StdControl;
    interface DripState[uint8_t local];
    interface DripStateMgr;
  } 
}

implementation {
  components DripStateM, RandomLFSR;

  StdControl = DripStateM;
  DripState = DripStateM;
  DripStateMgr = DripStateM;

  DripStateM.Random -> RandomLFSR;
}

--- NEW FILE: DripStateM.nc ---
includes Drip;

module DripStateM {
  provides {
    interface StdControl;
    interface DripState[uint8_t local];
    interface DripStateMgr;
  }
  uses {
    interface Random;
  }
}

implementation {

  DripCacheEntry dripCache[DRIP_CACHE_ENTRIES];

  void printCacheEntry(DripCacheEntry *entry);
  void printCache();
  void trickleReset(DripCacheEntry *dripEntry);
  void trickleSet(DripCacheEntry *dripEntry);
  void incrementSeqno(DripCacheEntry *dripEntry);

  command result_t StdControl.init() {
    return SUCCESS;
  }

  command result_t StdControl.start() {
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  command result_t DripState.init[uint8_t localKey](uint8_t globalKey) {
    DripCacheEntry *dripEntry = &dripCache[localKey];
    
    dripEntry->metadata.id = globalKey;
    dripEntry->metadata.seqno = 1;

    trickleReset(dripEntry);
    dbg(DBG_USR1, "INIT: ");
    printCacheEntry(dripEntry);

    return SUCCESS;
  }

  command uint8_t DripState.getSeqno[uint8_t localKey]() {
    DripCacheEntry *dripEntry = &dripCache[localKey];
    
    return dripEntry->metadata.seqno;
  }

  command result_t DripState.setSeqno[uint8_t localKey](uint8_t seqno) {
    DripCacheEntry *dripEntry = &dripCache[localKey];

    if (seqno != DRIP_SEQNO_OLDEST && seqno != DRIP_SEQNO_NEWEST) {
      dripEntry->metadata.seqno = seqno;
      return SUCCESS;
    }

    return FAIL;
  }

  command result_t DripState.incrementSeqno[uint8_t localKey]() {
    DripCacheEntry *dripEntry = &dripCache[localKey];

    incrementSeqno(dripEntry);

    trickleReset(dripEntry);

    return SUCCESS;
  }

  void incrementSeqno(DripCacheEntry *dripEntry) {
    dripEntry->metadata.seqno++;
    
    // Seqno 0 means that the seqno is unknown, and should only be seen
    // in a message coming in from the UART.
    while (dripEntry->metadata.seqno == DRIP_SEQNO_OLDEST ||
	   dripEntry->metadata.seqno == DRIP_SEQNO_NEWEST) {
      dripEntry->metadata.seqno++;
    }
  }

  command result_t DripState.entrySent[uint8_t localKey]() {
    DripCacheEntry *dripEntry = &dripCache[localKey];
    dripEntry->trickleState = DRIP_POST_SEND;

    return SUCCESS;
  }

  command bool DripState.newMsg[uint8_t localKey](DripMetadata incomingMetadata) {
    
    DripCacheEntry *dripEntry = &dripCache[localKey];

    /* Avoid the situation in which the sequence numbers both think their
       neighbor is less. */

    /*      
    if ((int8_t)((int8_t)incomingMetadata.seqno - (int8_t)dripEntry->metadata.seqno) == -128 
	&& dripEntry->metadata.seqno > 0) {

      incrementSeqno(dripEntry);
    }
    */

    if (incomingMetadata.seqno != DRIP_SEQNO_OLDEST && 
	((int8_t)(incomingMetadata.seqno - dripEntry->metadata.seqno) > 0 ||
	 incomingMetadata.seqno == DRIP_SEQNO_NEWEST)) {
      
      /* my entry is older. save new data. */
      
      if (incomingMetadata.seqno == DRIP_SEQNO_NEWEST) {
	/* It's coming in from outside, and does not know the seqno. 
	   Give it an incremented seqno. */
	
	incrementSeqno(dripEntry);

      } else {
	
	dripEntry->metadata.seqno = incomingMetadata.seqno;
      }

      trickleReset(dripEntry);

      return TRUE;
      
    } else if ((int8_t)(incomingMetadata.seqno - dripEntry->metadata.seqno) == 0 && 
	       incomingMetadata.seqno != DRIP_SEQNO_OLDEST) {
      
      /* my entry is equal. suppress. */

#ifdef DRIP_NO_SUPPRESS_WAKEUP
      if (dripEntry->metadata.id != DRIP_WAKEUPID)
#endif
	dripEntry->trickleSuppress = TRUE;

    } else {
      
      /* my entry is newer. rebroadcast. */

      trickleReset(dripEntry);
    }

    return FALSE;
  }

  command result_t DripState.fillMetadata[uint8_t localKey](DripMetadata* metadata) {
    DripCacheEntry *dripEntry = &dripCache[localKey];
    
    *metadata = dripEntry->metadata;
    return SUCCESS;
  }

  command result_t DripStateMgr.updateCounters() {

    /*
      For each entry in the cache:
        Decrement the countdown timer.
	If the countdown timer goes below the send time and we haven't
	sent yet:
	  If we have been suppressed, prevent sending.
  	If the countdown timer goes to 0, double the trickle timer.
    */
	
    uint8_t i;

    for(i = 0; i < DRIP_CACHE_ENTRIES; i++) {

      /*      
	      dbg(DBG_USR1, "COUNT:");
	      printCacheEntry(&dripCache[i]);
      */

      if (dripCache[i].trickleCountdown > 0)
	dripCache[i].trickleCountdown--;
      
      if (dripCache[i].trickleCountdown <= dripCache[i].trickleAnnounce &&
	  dripCache[i].trickleState == DRIP_PRE_SEND) {
	
	if (dripCache[i].trickleSuppress) {
	  dripCache[i].trickleState = DRIP_POST_SEND;
	}

      } else if (dripCache[i].trickleCountdown == 0) {
	
	if (dripCache[i].trickleStage < DRIP_MAX_SEND_INTERVAL)
	  dripCache[i].trickleStage++;
	
	trickleSet(&dripCache[i]);
      }
    }

    return SUCCESS;
  }

  command uint8_t DripStateMgr.findReadyEntry() {
    uint8_t i;

    for(i = 0; i < DRIP_CACHE_ENTRIES; i++) {
      if (dripCache[i].trickleCountdown <= dripCache[i].trickleAnnounce &&
	  dripCache[i].trickleState == DRIP_PRE_SEND) {      
	dbg(DBG_USR1, "READY: ");
	printCacheEntry(&dripCache[i]);
	return dripCache[i].metadata.id;
      }
    }
    
    return DRIP_INVALID_KEY;
  }

  void trickleReset(DripCacheEntry *dripEntry) {

    dripEntry->trickleStage = DRIP_MIN_SEND_INTERVAL;
    trickleSet(dripEntry);
  }

  void trickleSet(DripCacheEntry *dripEntry) {

    dripEntry->trickleCountdown = 1 << dripEntry->trickleStage;
    
    if (dripEntry->trickleCountdown < 4) {
      dripEntry->trickleAnnounce = 0;
    } else {
      dripEntry->trickleAnnounce = 
	call Random.rand() % (dripEntry->trickleCountdown / 2);
    }

    dripEntry->trickleSuppress = FALSE;    
    dripEntry->trickleState = DRIP_PRE_SEND;
  }
    
  void printCacheEntry(DripCacheEntry *entry) {
#ifdef PLATFORM_PC
    dbg(DBG_USR1, "@%lld (key=0x%x, seqno=%d), tstage=%d, tcount=%d, tannounce=%d, ts=%d\n", tos_state.tos_time, entry->metadata.id, entry->metadata.seqno, entry->trickleStage, entry->trickleCountdown, entry->trickleAnnounce, entry->trickleState);
#endif
  }

  void printCache() {
    uint8_t i;
    for (i = 0; i < DRIP_CACHE_ENTRIES; i++) {
      printCacheEntry(&dripCache[i]);
    }
  }
}

--- NEW FILE: DripStateMgr.nc ---
interface DripStateMgr {
  command result_t updateCounters();
  command uint8_t findReadyEntry();
}

--- NEW FILE: README.txt ---
Drip is a transport-layer component for epidemically disseminating
messages throughout a network. Each message "channel" uses a sequence
number and retransmissions to ensure that every node eventually gets
the newest message sent on that channel. Neighborhood suppression is
also present, to prevent the dissemination from overwhelming the
network.

Programming With Drip:

Drip provides two interfaces: Receive and Drip. To maintain its
per-channel metadata, it uses a third interface: DripState. Wire to
them like this:

  TestDripM.ReceiveDrip -> DripC.Receive[AM_TESTDRIPMSG];
  TestDripM.Drip -> DripC.Drip[AM_TESTDRIPMSG];
  DripC.DripState[AM_TESTDRIPMSG] ->
    DripStateC.DripState[unique("DripState")];

In StdControl.init(), you must call Drip.init(). This initializes the
sequence number for the channel.

Receive.receive(...) will be signaled when Drip receives a new
message. Your component is then responsible for caching the data
within that message, so that the message can be regenerated when Drip
needs to retransmit it. This is when you should act on the contents of
the message, as well.

To make the dissemination propagate epidemically, Drip will
occasionally signal Drip.rebroadcastRequest(TOS_MsgPtr msg, void*
payload) when it needs to retransmit. Your component should then copy
the cached data into the payload, and call Drip.rebroadcast(TOS_MsgPtr
msg, void *payload, uint8_t len), with the length of the payload.

To inject new messages from the PC side, you can use the Drip.java
component. To inject a new message from the mote, you call
Drip.changed(). Then, the next time you get a
Drip.rebroadcastRequest() event, you give it the new message instead
of the message you had previously cached.

Testing Drip:

There is a test application in the TestDrip directory. This
application listens for one Drip message on channel 254, containing a
2-byte payload.

Injecting Drip Messages:

There is a java tool for injecting Drip messages in
tools/Drip.java. It must be used through a TOSBase node plugged into a
serial connection.

>From the command line, it can be used with TestDrip:

  java Drip <payload>

This injects the appropriate message for the TestDrip
application, with your argument as the payload.

>From another Java app, it can be used to inject arbitrary messages. 

  Drip drip = new Drip(<drip channel ID>);
  MyMsg msg = new MyMsg();
  drip.injectMsg(msg, MyMsg.DEFAULT_MESSAGE_SIZE);	

Known Shortcomings:

The Java tool does not notify the caller of injectMsg when the message
has been injected. This will be corrected soon.

The injectMsg command must be given the size of the message.

Email get at cs.berkeley.edu with any questions.



More information about the Tinyos-beta-commits mailing list