📄 forwardingenginem.nc
字号:
/* * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin@gmail.com> * Published under the terms of the GNU General Public License (GPLv2). */#include "routing.h"/** * ForwardingEngineM - Handles received packets of a certain protocol * in a multihop context. The component uses a route selector to * determine if the packet should be forwarded or passed to the upper * layer. If the packet is forwarded, the next hop is given by the * route selector. * * @author Romain Thouvenin *///TODO probably need a lot of cleaning, and to be moved elsewheregeneric module ForwardingEngineM () { provides { //For the upper layer interface AMSend[uint8_t id]; interface Receive[uint8_t id]; interface Intercept[uint8_t id]; interface LinkMonitor; } uses { interface RouteSelect; interface AMSend as SubSend; interface AMPacket; interface Packet as PPacket; interface Packet as SubPacket; interface PacketAcknowledgements as Acks; interface Receive as SubReceive; interface Timer<TMilli>; } provides interface MHControl;}implementation { message_t buf; //first available, do NOT use it message_t * avail = &buf; message_t * waiting; uint8_t typebuf; uint8_t lenWaiting; uint8_t amWaiting; am_addr_t bufAddr; am_addr_t * addrWaiting; bool lockAvail, lockWaiting; uint32_t wait_time; bool acks; enum { WAIT_BEFORE_RETRY = 100, MAX_WAIT = 10 * WAIT_BEFORE_RETRY }; command error_t AMSend.send[uint8_t am](am_addr_t addr, message_t * msg, uint8_t len){ switch(call RouteSelect.selectRoute(msg, &addr, &am)){ case FW_SEND: call PPacket.setPayloadLength(msg, len); acks = DYMO_LINK_FEEDBACK && (call Acks.requestAck(msg) == SUCCESS); return call SubSend.send(call AMPacket.destination(msg), msg, call SubPacket.payloadLength(msg)); case FW_WAIT: atomic { if(lockWaiting) return EBUSY; lockWaiting = TRUE; } waiting = msg; amWaiting = am; call PPacket.setPayloadLength(msg, len); lenWaiting = call SubPacket.payloadLength(msg); bufAddr = addr; addrWaiting = &bufAddr; wait_time = 0; call Timer.startOneShot(WAIT_BEFORE_RETRY); dbg("fwe", "FE: I'll retry later.\n"); return SUCCESS; default: //We don't allow sending to oneself return FAIL; } } event message_t * SubReceive.receive(message_t * msg, void * payload, uint8_t len){ dbg("fwe", "FE: Received a message from %u\n", call AMPacket.source(msg)); signal MHControl.msgReceived(msg); switch(call RouteSelect.selectRoute(msg, NULL, &typebuf)){ case FW_SEND: atomic { if(lockAvail) return msg; lockAvail = TRUE; } if ( signal Intercept.forward[typebuf](msg, call PPacket.getPayload(msg, call PPacket.payloadLength(msg)), call PPacket.payloadLength(msg)) ) { call SubSend.send(call AMPacket.destination(msg), msg, len); } return avail; case FW_RECEIVE: payload = call PPacket.getPayload(msg, call PPacket.payloadLength(msg)); return signal Receive.receive[typebuf](msg, payload, call PPacket.payloadLength(msg)); case FW_WAIT: atomic { if(lockAvail || lockWaiting) return msg; lockAvail = lockWaiting = TRUE; } waiting = msg; lenWaiting = len; addrWaiting = NULL; wait_time = 0; call Timer.startOneShot(WAIT_BEFORE_RETRY); return avail; default: return msg; } } event void SubSend.sendDone(message_t * msg, error_t e){ dbg("fwe", "FE: Sending done.\n"); if( (e == SUCCESS) && acks ){ if( !(call Acks.wasAcked(msg)) ){ e = FAIL; dbg("fwe", "FE: The message was not acked => FAIL.\n"); signal MHControl.sendFailed(msg, 2); signal LinkMonitor.brokenLink(call AMPacket.destination(msg)); } } else if (e != SUCCESS) { dbg("fwe", "FE: But failed!\n"); signal MHControl.sendFailed(msg, 1); } if(lockAvail){ avail = msg; atomic { lockAvail = FALSE; } } else { signal AMSend.sendDone[amWaiting](msg, e); atomic { lockWaiting = FALSE; } } } event void Timer.fired(){ switch(call RouteSelect.selectRoute(waiting, addrWaiting, &amWaiting)){ case FW_SEND: dbg("fwe", "FE: I'm retrying to send my message.\n"); if (addrWaiting) { call SubSend.send(call AMPacket.destination(waiting), waiting, lenWaiting); } else if ( signal Intercept.forward[amWaiting](waiting, call PPacket.getPayload(waiting, call PPacket.payloadLength(waiting)), call PPacket.payloadLength(waiting)) ) { call SubSend.send(call AMPacket.destination(waiting), waiting, lenWaiting); } call Timer.stop(); break; case FW_WAIT: dbg("fwe", "FE: I'll retry later again.\n"); wait_time += call Timer.getdt(); if(wait_time < MAX_WAIT){ call Timer.startOneShot(wait_time); break; } //else: Continue to default default: if(addrWaiting) signal AMSend.sendDone[amWaiting](waiting, FAIL); if(lockAvail){ avail = waiting; atomic { lockAvail = FALSE; } } atomic { lockWaiting = FALSE; } } } command error_t AMSend.cancel[uint8_t am](message_t *msg){ if(lockWaiting){ call Timer.stop(); atomic { lockWaiting = FALSE; } return SUCCESS; } else { return call SubSend.cancel(msg); } } command void * AMSend.getPayload[uint8_t am](message_t *msg, uint8_t len){ return call PPacket.getPayload(msg, len); } command uint8_t AMSend.maxPayloadLength[uint8_t am](){ return call PPacket.maxPayloadLength(); } /*** defaults ***/ default event message_t * Receive.receive[uint8_t am](message_t * msg, void * payload, uint8_t len){ return msg; } default event void AMSend.sendDone[uint8_t am](message_t * msg, error_t e){} default event bool Intercept.forward[uint8_t am](message_t * msg, void * payload, uint8_t len){ return TRUE; } default event void MHControl.msgReceived(message_t * msg){ } default event void MHControl.sendFailed(message_t * msg, uint8_t why){ } default event void LinkMonitor.brokenLink(addr_t neighbor){ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -