V148
Fork of RadioHead-148 by
RHRouter.cpp@0:ab4e012489ef, 2015-10-15 (annotated)
- Committer:
- davidr99
- Date:
- Thu Oct 15 01:27:00 2015 +0000
- Revision:
- 0:ab4e012489ef
Messy start, but a port for RadioHead.; Currently the SPI modulus are the only ones that work.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
davidr99 | 0:ab4e012489ef | 1 | // RHRouter.cpp |
davidr99 | 0:ab4e012489ef | 2 | // |
davidr99 | 0:ab4e012489ef | 3 | // Define addressed datagram |
davidr99 | 0:ab4e012489ef | 4 | // |
davidr99 | 0:ab4e012489ef | 5 | // Part of the Arduino RH library for operating with HopeRF RH compatible transceivers |
davidr99 | 0:ab4e012489ef | 6 | // (see http://www.hoperf.com) |
davidr99 | 0:ab4e012489ef | 7 | // RHDatagram will be received only by the addressed node or all nodes within range if the |
davidr99 | 0:ab4e012489ef | 8 | // to address is RH_BROADCAST_ADDRESS |
davidr99 | 0:ab4e012489ef | 9 | // |
davidr99 | 0:ab4e012489ef | 10 | // Author: Mike McCauley (mikem@airspayce.com) |
davidr99 | 0:ab4e012489ef | 11 | // Copyright (C) 2011 Mike McCauley |
davidr99 | 0:ab4e012489ef | 12 | // $Id: RHRouter.cpp,v 1.7 2015/08/13 02:45:47 mikem Exp $ |
davidr99 | 0:ab4e012489ef | 13 | |
davidr99 | 0:ab4e012489ef | 14 | #include <RHRouter.h> |
davidr99 | 0:ab4e012489ef | 15 | |
davidr99 | 0:ab4e012489ef | 16 | RHRouter::RoutedMessage RHRouter::_tmpMessage; |
davidr99 | 0:ab4e012489ef | 17 | |
davidr99 | 0:ab4e012489ef | 18 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 19 | // Constructors |
davidr99 | 0:ab4e012489ef | 20 | RHRouter::RHRouter(RHGenericDriver& driver, uint8_t thisAddress) |
davidr99 | 0:ab4e012489ef | 21 | : RHReliableDatagram(driver, thisAddress) |
davidr99 | 0:ab4e012489ef | 22 | { |
davidr99 | 0:ab4e012489ef | 23 | _max_hops = RH_DEFAULT_MAX_HOPS; |
davidr99 | 0:ab4e012489ef | 24 | clearRoutingTable(); |
davidr99 | 0:ab4e012489ef | 25 | } |
davidr99 | 0:ab4e012489ef | 26 | |
davidr99 | 0:ab4e012489ef | 27 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 28 | // Public methods |
davidr99 | 0:ab4e012489ef | 29 | bool RHRouter::init() |
davidr99 | 0:ab4e012489ef | 30 | { |
davidr99 | 0:ab4e012489ef | 31 | bool ret = RHReliableDatagram::init(); |
davidr99 | 0:ab4e012489ef | 32 | if (ret) |
davidr99 | 0:ab4e012489ef | 33 | _max_hops = RH_DEFAULT_MAX_HOPS; |
davidr99 | 0:ab4e012489ef | 34 | return ret; |
davidr99 | 0:ab4e012489ef | 35 | } |
davidr99 | 0:ab4e012489ef | 36 | |
davidr99 | 0:ab4e012489ef | 37 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 38 | void RHRouter::setMaxHops(uint8_t max_hops) |
davidr99 | 0:ab4e012489ef | 39 | { |
davidr99 | 0:ab4e012489ef | 40 | _max_hops = max_hops; |
davidr99 | 0:ab4e012489ef | 41 | } |
davidr99 | 0:ab4e012489ef | 42 | |
davidr99 | 0:ab4e012489ef | 43 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 44 | void RHRouter::addRouteTo(uint8_t dest, uint8_t next_hop, uint8_t state) |
davidr99 | 0:ab4e012489ef | 45 | { |
davidr99 | 0:ab4e012489ef | 46 | uint8_t i; |
davidr99 | 0:ab4e012489ef | 47 | |
davidr99 | 0:ab4e012489ef | 48 | // First look for an existing entry we can update |
davidr99 | 0:ab4e012489ef | 49 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 50 | { |
davidr99 | 0:ab4e012489ef | 51 | if (_routes[i].dest == dest) |
davidr99 | 0:ab4e012489ef | 52 | { |
davidr99 | 0:ab4e012489ef | 53 | _routes[i].dest = dest; |
davidr99 | 0:ab4e012489ef | 54 | _routes[i].next_hop = next_hop; |
davidr99 | 0:ab4e012489ef | 55 | _routes[i].state = state; |
davidr99 | 0:ab4e012489ef | 56 | return; |
davidr99 | 0:ab4e012489ef | 57 | } |
davidr99 | 0:ab4e012489ef | 58 | } |
davidr99 | 0:ab4e012489ef | 59 | |
davidr99 | 0:ab4e012489ef | 60 | // Look for an invalid entry we can use |
davidr99 | 0:ab4e012489ef | 61 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 62 | { |
davidr99 | 0:ab4e012489ef | 63 | if (_routes[i].state == Invalid) |
davidr99 | 0:ab4e012489ef | 64 | { |
davidr99 | 0:ab4e012489ef | 65 | _routes[i].dest = dest; |
davidr99 | 0:ab4e012489ef | 66 | _routes[i].next_hop = next_hop; |
davidr99 | 0:ab4e012489ef | 67 | _routes[i].state = state; |
davidr99 | 0:ab4e012489ef | 68 | return; |
davidr99 | 0:ab4e012489ef | 69 | } |
davidr99 | 0:ab4e012489ef | 70 | } |
davidr99 | 0:ab4e012489ef | 71 | |
davidr99 | 0:ab4e012489ef | 72 | // Need to make room for a new one |
davidr99 | 0:ab4e012489ef | 73 | retireOldestRoute(); |
davidr99 | 0:ab4e012489ef | 74 | // Should be an invalid slot now |
davidr99 | 0:ab4e012489ef | 75 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 76 | { |
davidr99 | 0:ab4e012489ef | 77 | if (_routes[i].state == Invalid) |
davidr99 | 0:ab4e012489ef | 78 | { |
davidr99 | 0:ab4e012489ef | 79 | _routes[i].dest = dest; |
davidr99 | 0:ab4e012489ef | 80 | _routes[i].next_hop = next_hop; |
davidr99 | 0:ab4e012489ef | 81 | _routes[i].state = state; |
davidr99 | 0:ab4e012489ef | 82 | } |
davidr99 | 0:ab4e012489ef | 83 | } |
davidr99 | 0:ab4e012489ef | 84 | } |
davidr99 | 0:ab4e012489ef | 85 | |
davidr99 | 0:ab4e012489ef | 86 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 87 | RHRouter::RoutingTableEntry* RHRouter::getRouteTo(uint8_t dest) |
davidr99 | 0:ab4e012489ef | 88 | { |
davidr99 | 0:ab4e012489ef | 89 | uint8_t i; |
davidr99 | 0:ab4e012489ef | 90 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 91 | if (_routes[i].dest == dest && _routes[i].state != Invalid) |
davidr99 | 0:ab4e012489ef | 92 | return &_routes[i]; |
davidr99 | 0:ab4e012489ef | 93 | return NULL; |
davidr99 | 0:ab4e012489ef | 94 | } |
davidr99 | 0:ab4e012489ef | 95 | |
davidr99 | 0:ab4e012489ef | 96 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 97 | void RHRouter::deleteRoute(uint8_t index) |
davidr99 | 0:ab4e012489ef | 98 | { |
davidr99 | 0:ab4e012489ef | 99 | // Delete a route by copying following routes on top of it |
davidr99 | 0:ab4e012489ef | 100 | memcpy(&_routes[index], &_routes[index+1], |
davidr99 | 0:ab4e012489ef | 101 | sizeof(RoutingTableEntry) * (RH_ROUTING_TABLE_SIZE - index - 1)); |
davidr99 | 0:ab4e012489ef | 102 | _routes[RH_ROUTING_TABLE_SIZE - 1].state = Invalid; |
davidr99 | 0:ab4e012489ef | 103 | } |
davidr99 | 0:ab4e012489ef | 104 | |
davidr99 | 0:ab4e012489ef | 105 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 106 | void RHRouter::printRoutingTable() |
davidr99 | 0:ab4e012489ef | 107 | { |
davidr99 | 0:ab4e012489ef | 108 | #ifdef RH_HAVE_SERIAL |
davidr99 | 0:ab4e012489ef | 109 | uint8_t i; |
davidr99 | 0:ab4e012489ef | 110 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 111 | { |
davidr99 | 0:ab4e012489ef | 112 | Serial.print(i, DEC); |
davidr99 | 0:ab4e012489ef | 113 | Serial.print(" Dest: "); |
davidr99 | 0:ab4e012489ef | 114 | Serial.print(_routes[i].dest, DEC); |
davidr99 | 0:ab4e012489ef | 115 | Serial.print(" Next Hop: "); |
davidr99 | 0:ab4e012489ef | 116 | Serial.print(_routes[i].next_hop, DEC); |
davidr99 | 0:ab4e012489ef | 117 | Serial.print(" State: "); |
davidr99 | 0:ab4e012489ef | 118 | Serial.println(_routes[i].state, DEC); |
davidr99 | 0:ab4e012489ef | 119 | } |
davidr99 | 0:ab4e012489ef | 120 | #endif |
davidr99 | 0:ab4e012489ef | 121 | } |
davidr99 | 0:ab4e012489ef | 122 | |
davidr99 | 0:ab4e012489ef | 123 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 124 | bool RHRouter::deleteRouteTo(uint8_t dest) |
davidr99 | 0:ab4e012489ef | 125 | { |
davidr99 | 0:ab4e012489ef | 126 | uint8_t i; |
davidr99 | 0:ab4e012489ef | 127 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 128 | { |
davidr99 | 0:ab4e012489ef | 129 | if (_routes[i].dest == dest) |
davidr99 | 0:ab4e012489ef | 130 | { |
davidr99 | 0:ab4e012489ef | 131 | deleteRoute(i); |
davidr99 | 0:ab4e012489ef | 132 | return true; |
davidr99 | 0:ab4e012489ef | 133 | } |
davidr99 | 0:ab4e012489ef | 134 | } |
davidr99 | 0:ab4e012489ef | 135 | return false; |
davidr99 | 0:ab4e012489ef | 136 | } |
davidr99 | 0:ab4e012489ef | 137 | |
davidr99 | 0:ab4e012489ef | 138 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 139 | void RHRouter::retireOldestRoute() |
davidr99 | 0:ab4e012489ef | 140 | { |
davidr99 | 0:ab4e012489ef | 141 | // We just obliterate the first in the table and clear the last |
davidr99 | 0:ab4e012489ef | 142 | deleteRoute(0); |
davidr99 | 0:ab4e012489ef | 143 | } |
davidr99 | 0:ab4e012489ef | 144 | |
davidr99 | 0:ab4e012489ef | 145 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 146 | void RHRouter::clearRoutingTable() |
davidr99 | 0:ab4e012489ef | 147 | { |
davidr99 | 0:ab4e012489ef | 148 | uint8_t i; |
davidr99 | 0:ab4e012489ef | 149 | for (i = 0; i < RH_ROUTING_TABLE_SIZE; i++) |
davidr99 | 0:ab4e012489ef | 150 | _routes[i].state = Invalid; |
davidr99 | 0:ab4e012489ef | 151 | } |
davidr99 | 0:ab4e012489ef | 152 | |
davidr99 | 0:ab4e012489ef | 153 | |
davidr99 | 0:ab4e012489ef | 154 | uint8_t RHRouter::sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest, uint8_t flags) |
davidr99 | 0:ab4e012489ef | 155 | { |
davidr99 | 0:ab4e012489ef | 156 | return sendtoFromSourceWait(buf, len, dest, _thisAddress, flags); |
davidr99 | 0:ab4e012489ef | 157 | } |
davidr99 | 0:ab4e012489ef | 158 | |
davidr99 | 0:ab4e012489ef | 159 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 160 | // Waits for delivery to the next hop (but not for delivery to the final destination) |
davidr99 | 0:ab4e012489ef | 161 | uint8_t RHRouter::sendtoFromSourceWait(uint8_t* buf, uint8_t len, uint8_t dest, uint8_t source, uint8_t flags) |
davidr99 | 0:ab4e012489ef | 162 | { |
davidr99 | 0:ab4e012489ef | 163 | if (((uint16_t)len + sizeof(RoutedMessageHeader)) > _driver.maxMessageLength()) |
davidr99 | 0:ab4e012489ef | 164 | return RH_ROUTER_ERROR_INVALID_LENGTH; |
davidr99 | 0:ab4e012489ef | 165 | |
davidr99 | 0:ab4e012489ef | 166 | // Construct a RH RouterMessage message |
davidr99 | 0:ab4e012489ef | 167 | _tmpMessage.header.source = source; |
davidr99 | 0:ab4e012489ef | 168 | _tmpMessage.header.dest = dest; |
davidr99 | 0:ab4e012489ef | 169 | _tmpMessage.header.hops = 0; |
davidr99 | 0:ab4e012489ef | 170 | _tmpMessage.header.id = _lastE2ESequenceNumber++; |
davidr99 | 0:ab4e012489ef | 171 | _tmpMessage.header.flags = flags; |
davidr99 | 0:ab4e012489ef | 172 | memcpy(_tmpMessage.data, buf, len); |
davidr99 | 0:ab4e012489ef | 173 | |
davidr99 | 0:ab4e012489ef | 174 | return route(&_tmpMessage, sizeof(RoutedMessageHeader)+len); |
davidr99 | 0:ab4e012489ef | 175 | } |
davidr99 | 0:ab4e012489ef | 176 | |
davidr99 | 0:ab4e012489ef | 177 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 178 | uint8_t RHRouter::route(RoutedMessage* message, uint8_t messageLen) |
davidr99 | 0:ab4e012489ef | 179 | { |
davidr99 | 0:ab4e012489ef | 180 | // Reliably deliver it if possible. See if we have a route: |
davidr99 | 0:ab4e012489ef | 181 | uint8_t next_hop = RH_BROADCAST_ADDRESS; |
davidr99 | 0:ab4e012489ef | 182 | if (message->header.dest != RH_BROADCAST_ADDRESS) |
davidr99 | 0:ab4e012489ef | 183 | { |
davidr99 | 0:ab4e012489ef | 184 | RoutingTableEntry* route = getRouteTo(message->header.dest); |
davidr99 | 0:ab4e012489ef | 185 | if (!route) |
davidr99 | 0:ab4e012489ef | 186 | return RH_ROUTER_ERROR_NO_ROUTE; |
davidr99 | 0:ab4e012489ef | 187 | next_hop = route->next_hop; |
davidr99 | 0:ab4e012489ef | 188 | } |
davidr99 | 0:ab4e012489ef | 189 | |
davidr99 | 0:ab4e012489ef | 190 | if (!RHReliableDatagram::sendtoWait((uint8_t*)message, messageLen, next_hop)) |
davidr99 | 0:ab4e012489ef | 191 | return RH_ROUTER_ERROR_UNABLE_TO_DELIVER; |
davidr99 | 0:ab4e012489ef | 192 | |
davidr99 | 0:ab4e012489ef | 193 | return RH_ROUTER_ERROR_NONE; |
davidr99 | 0:ab4e012489ef | 194 | } |
davidr99 | 0:ab4e012489ef | 195 | |
davidr99 | 0:ab4e012489ef | 196 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 197 | // Subclasses may want to override this to peek at messages going past |
davidr99 | 0:ab4e012489ef | 198 | void RHRouter::peekAtMessage(RoutedMessage* message, uint8_t messageLen) |
davidr99 | 0:ab4e012489ef | 199 | { |
davidr99 | 0:ab4e012489ef | 200 | // Default does nothing |
davidr99 | 0:ab4e012489ef | 201 | } |
davidr99 | 0:ab4e012489ef | 202 | |
davidr99 | 0:ab4e012489ef | 203 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 204 | bool RHRouter::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags) |
davidr99 | 0:ab4e012489ef | 205 | { |
davidr99 | 0:ab4e012489ef | 206 | uint8_t tmpMessageLen = sizeof(_tmpMessage); |
davidr99 | 0:ab4e012489ef | 207 | uint8_t _from; |
davidr99 | 0:ab4e012489ef | 208 | uint8_t _to; |
davidr99 | 0:ab4e012489ef | 209 | uint8_t _id; |
davidr99 | 0:ab4e012489ef | 210 | uint8_t _flags; |
davidr99 | 0:ab4e012489ef | 211 | if (RHReliableDatagram::recvfromAck((uint8_t*)&_tmpMessage, &tmpMessageLen, &_from, &_to, &_id, &_flags)) |
davidr99 | 0:ab4e012489ef | 212 | { |
davidr99 | 0:ab4e012489ef | 213 | // Here we simulate networks with limited visibility between nodes |
davidr99 | 0:ab4e012489ef | 214 | // so we can test routing |
davidr99 | 0:ab4e012489ef | 215 | #ifdef RH_TEST_NETWORK |
davidr99 | 0:ab4e012489ef | 216 | if ( |
davidr99 | 0:ab4e012489ef | 217 | #if RH_TEST_NETWORK==1 |
davidr99 | 0:ab4e012489ef | 218 | // This network looks like 1-2-3-4 |
davidr99 | 0:ab4e012489ef | 219 | (_thisAddress == 1 && _from == 2) |
davidr99 | 0:ab4e012489ef | 220 | || (_thisAddress == 2 && (_from == 1 || _from == 3)) |
davidr99 | 0:ab4e012489ef | 221 | || (_thisAddress == 3 && (_from == 2 || _from == 4)) |
davidr99 | 0:ab4e012489ef | 222 | || (_thisAddress == 4 && _from == 3) |
davidr99 | 0:ab4e012489ef | 223 | |
davidr99 | 0:ab4e012489ef | 224 | #elif RH_TEST_NETWORK==2 |
davidr99 | 0:ab4e012489ef | 225 | // This network looks like 1-2-4 |
davidr99 | 0:ab4e012489ef | 226 | // | | | |
davidr99 | 0:ab4e012489ef | 227 | // --3-- |
davidr99 | 0:ab4e012489ef | 228 | (_thisAddress == 1 && (_from == 2 || _from == 3)) |
davidr99 | 0:ab4e012489ef | 229 | || _thisAddress == 2 |
davidr99 | 0:ab4e012489ef | 230 | || _thisAddress == 3 |
davidr99 | 0:ab4e012489ef | 231 | || (_thisAddress == 4 && (_from == 2 || _from == 3)) |
davidr99 | 0:ab4e012489ef | 232 | |
davidr99 | 0:ab4e012489ef | 233 | #elif RH_TEST_NETWORK==3 |
davidr99 | 0:ab4e012489ef | 234 | // This network looks like 1-2-4 |
davidr99 | 0:ab4e012489ef | 235 | // | | |
davidr99 | 0:ab4e012489ef | 236 | // --3-- |
davidr99 | 0:ab4e012489ef | 237 | (_thisAddress == 1 && (_from == 2 || _from == 3)) |
davidr99 | 0:ab4e012489ef | 238 | || (_thisAddress == 2 && (_from == 1 || _from == 4)) |
davidr99 | 0:ab4e012489ef | 239 | || (_thisAddress == 3 && (_from == 1 || _from == 4)) |
davidr99 | 0:ab4e012489ef | 240 | || (_thisAddress == 4 && (_from == 2 || _from == 3)) |
davidr99 | 0:ab4e012489ef | 241 | |
davidr99 | 0:ab4e012489ef | 242 | #elif RH_TEST_NETWORK==4 |
davidr99 | 0:ab4e012489ef | 243 | // This network looks like 1-2-3 |
davidr99 | 0:ab4e012489ef | 244 | // | |
davidr99 | 0:ab4e012489ef | 245 | // 4 |
davidr99 | 0:ab4e012489ef | 246 | (_thisAddress == 1 && _from == 2) |
davidr99 | 0:ab4e012489ef | 247 | || _thisAddress == 2 |
davidr99 | 0:ab4e012489ef | 248 | || (_thisAddress == 3 && _from == 2) |
davidr99 | 0:ab4e012489ef | 249 | || (_thisAddress == 4 && _from == 2) |
davidr99 | 0:ab4e012489ef | 250 | |
davidr99 | 0:ab4e012489ef | 251 | #endif |
davidr99 | 0:ab4e012489ef | 252 | ) |
davidr99 | 0:ab4e012489ef | 253 | { |
davidr99 | 0:ab4e012489ef | 254 | // OK |
davidr99 | 0:ab4e012489ef | 255 | } |
davidr99 | 0:ab4e012489ef | 256 | else |
davidr99 | 0:ab4e012489ef | 257 | { |
davidr99 | 0:ab4e012489ef | 258 | return false; // Pretend we got nothing |
davidr99 | 0:ab4e012489ef | 259 | } |
davidr99 | 0:ab4e012489ef | 260 | #endif |
davidr99 | 0:ab4e012489ef | 261 | |
davidr99 | 0:ab4e012489ef | 262 | peekAtMessage(&_tmpMessage, tmpMessageLen); |
davidr99 | 0:ab4e012489ef | 263 | // See if its for us or has to be routed |
davidr99 | 0:ab4e012489ef | 264 | if (_tmpMessage.header.dest == _thisAddress || _tmpMessage.header.dest == RH_BROADCAST_ADDRESS) |
davidr99 | 0:ab4e012489ef | 265 | { |
davidr99 | 0:ab4e012489ef | 266 | // Deliver it here |
davidr99 | 0:ab4e012489ef | 267 | if (source) *source = _tmpMessage.header.source; |
davidr99 | 0:ab4e012489ef | 268 | if (dest) *dest = _tmpMessage.header.dest; |
davidr99 | 0:ab4e012489ef | 269 | if (id) *id = _tmpMessage.header.id; |
davidr99 | 0:ab4e012489ef | 270 | if (flags) *flags = _tmpMessage.header.flags; |
davidr99 | 0:ab4e012489ef | 271 | uint8_t msgLen = tmpMessageLen - sizeof(RoutedMessageHeader); |
davidr99 | 0:ab4e012489ef | 272 | if (*len > msgLen) |
davidr99 | 0:ab4e012489ef | 273 | *len = msgLen; |
davidr99 | 0:ab4e012489ef | 274 | memcpy(buf, _tmpMessage.data, *len); |
davidr99 | 0:ab4e012489ef | 275 | return true; // Its for you! |
davidr99 | 0:ab4e012489ef | 276 | } |
davidr99 | 0:ab4e012489ef | 277 | else if ( _tmpMessage.header.dest != RH_BROADCAST_ADDRESS |
davidr99 | 0:ab4e012489ef | 278 | && _tmpMessage.header.hops++ < _max_hops) |
davidr99 | 0:ab4e012489ef | 279 | { |
davidr99 | 0:ab4e012489ef | 280 | // Maybe it has to be routed to the next hop |
davidr99 | 0:ab4e012489ef | 281 | // REVISIT: if it fails due to no route or unable to deliver to the next hop, |
davidr99 | 0:ab4e012489ef | 282 | // tell the originator. BUT HOW? |
davidr99 | 0:ab4e012489ef | 283 | route(&_tmpMessage, tmpMessageLen); |
davidr99 | 0:ab4e012489ef | 284 | } |
davidr99 | 0:ab4e012489ef | 285 | // Discard it and maybe wait for another |
davidr99 | 0:ab4e012489ef | 286 | } |
davidr99 | 0:ab4e012489ef | 287 | return false; |
davidr99 | 0:ab4e012489ef | 288 | } |
davidr99 | 0:ab4e012489ef | 289 | |
davidr99 | 0:ab4e012489ef | 290 | //////////////////////////////////////////////////////////////////// |
davidr99 | 0:ab4e012489ef | 291 | bool RHRouter::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags) |
davidr99 | 0:ab4e012489ef | 292 | { |
davidr99 | 0:ab4e012489ef | 293 | unsigned long starttime = millis(); |
davidr99 | 0:ab4e012489ef | 294 | int32_t timeLeft; |
davidr99 | 0:ab4e012489ef | 295 | while ((timeLeft = timeout - (millis() - starttime)) > 0) |
davidr99 | 0:ab4e012489ef | 296 | { |
davidr99 | 0:ab4e012489ef | 297 | if (waitAvailableTimeout(timeLeft)) |
davidr99 | 0:ab4e012489ef | 298 | { |
davidr99 | 0:ab4e012489ef | 299 | if (recvfromAck(buf, len, source, dest, id, flags)) |
davidr99 | 0:ab4e012489ef | 300 | return true; |
davidr99 | 0:ab4e012489ef | 301 | } |
davidr99 | 0:ab4e012489ef | 302 | YIELD; |
davidr99 | 0:ab4e012489ef | 303 | } |
davidr99 | 0:ab4e012489ef | 304 | return false; |
davidr99 | 0:ab4e012489ef | 305 | } |
davidr99 | 0:ab4e012489ef | 306 |