Mesh.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #include "Mesh.h"
  2. //#include <Arduino.h>
  3. namespace mesh {
  4. void Mesh::begin() {
  5. Dispatcher::begin();
  6. }
  7. void Mesh::loop() {
  8. Dispatcher::loop();
  9. }
  10. bool Mesh::allowPacketForward(const mesh::Packet* packet) {
  11. return false; // by default, Transport NOT enabled
  12. }
  13. uint32_t Mesh::getRetransmitDelay(const mesh::Packet* packet) {
  14. uint32_t t = (_radio->getEstAirtimeFor(packet->getRawLength()) * 52 / 50) / 2;
  15. return _rng->nextInt(0, 5)*t;
  16. }
  17. uint32_t Mesh::getDirectRetransmitDelay(const Packet* packet) {
  18. return 0; // by default, no delay
  19. }
  20. uint32_t Mesh::getCADFailRetryDelay() const {
  21. return _rng->nextInt(1, 4)*120;
  22. }
  23. int Mesh::searchPeersByHash(const uint8_t* hash) {
  24. return 0; // not found
  25. }
  26. int Mesh::searchChannelsByHash(const uint8_t* hash, GroupChannel channels[], int max_matches) {
  27. return 0; // not found
  28. }
  29. DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
  30. if (pkt->getPayloadVer() > PAYLOAD_VER_1) { // not supported in this firmware version
  31. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): unsupported packet version", getLogDateTime());
  32. return ACTION_RELEASE;
  33. }
  34. if (pkt->isRouteDirect() && pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
  35. if (pkt->path_len < MAX_PATH_SIZE) {
  36. uint8_t i = 0;
  37. uint32_t trace_tag;
  38. memcpy(&trace_tag, &pkt->payload[i], 4); i += 4;
  39. uint32_t auth_code;
  40. memcpy(&auth_code, &pkt->payload[i], 4); i += 4;
  41. uint8_t flags = pkt->payload[i++];
  42. uint8_t len = pkt->payload_len - i;
  43. if (pkt->path_len >= len) { // TRACE has reached end of given path
  44. onTraceRecv(pkt, trace_tag, auth_code, flags, pkt->path, &pkt->payload[i], len);
  45. } else if (self_id.isHashMatch(&pkt->payload[i + pkt->path_len]) && allowPacketForward(pkt) && !_tables->hasSeen(pkt)) {
  46. // append SNR (Not hash!)
  47. pkt->path[pkt->path_len] = (int8_t) (pkt->getSNR()*4);
  48. pkt->path_len += PATH_HASH_SIZE;
  49. uint32_t d = getDirectRetransmitDelay(pkt);
  50. return ACTION_RETRANSMIT_DELAYED(5, d); // schedule with priority 5 (for now), maybe make configurable?
  51. }
  52. }
  53. return ACTION_RELEASE;
  54. }
  55. if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) {
  56. if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) {
  57. if (_tables->hasSeen(pkt)) return ACTION_RELEASE; // don't retransmit!
  58. // remove our hash from 'path', then re-broadcast
  59. pkt->path_len -= PATH_HASH_SIZE;
  60. #if 0
  61. memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len);
  62. #elif PATH_HASH_SIZE == 1
  63. for (int k = 0; k < pkt->path_len; k++) { // shuffle bytes by 1
  64. pkt->path[k] = pkt->path[k + 1];
  65. }
  66. #else
  67. #error "need path remove impl"
  68. #endif
  69. uint32_t d = getDirectRetransmitDelay(pkt);
  70. return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
  71. }
  72. return ACTION_RELEASE; // this node is NOT the next hop (OR this packet has already been forwarded), so discard.
  73. }
  74. DispatcherAction action = ACTION_RELEASE;
  75. switch (pkt->getPayloadType()) {
  76. case PAYLOAD_TYPE_ACK: {
  77. int i = 0;
  78. uint32_t ack_crc;
  79. memcpy(&ack_crc, &pkt->payload[i], 4); i += 4;
  80. if (i > pkt->payload_len) {
  81. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete ACK packet", getLogDateTime());
  82. } else if (!_tables->hasSeen(pkt)) {
  83. onAckRecv(pkt, ack_crc);
  84. action = routeRecvPacket(pkt);
  85. }
  86. break;
  87. }
  88. case PAYLOAD_TYPE_PATH:
  89. case PAYLOAD_TYPE_REQ:
  90. case PAYLOAD_TYPE_RESPONSE:
  91. case PAYLOAD_TYPE_TXT_MSG: {
  92. int i = 0;
  93. uint8_t dest_hash = pkt->payload[i++];
  94. uint8_t src_hash = pkt->payload[i++];
  95. uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
  96. if (i + CIPHER_MAC_SIZE >= pkt->payload_len) {
  97. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime());
  98. } else if (!_tables->hasSeen(pkt)) {
  99. // NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins.
  100. // For flood mode, the path may not be the 'best' in terms of hops.
  101. // FUTURE: could send back multiple paths, using createPathReturn(), and let sender choose which to use(?)
  102. if (self_id.isHashMatch(&dest_hash)) {
  103. // scan contacts DB, for all matching hashes of 'src_hash' (max 4 matches supported ATM)
  104. int num = searchPeersByHash(&src_hash);
  105. // for each matching contact, try to decrypt data
  106. bool found = false;
  107. for (int j = 0; j < num; j++) {
  108. uint8_t secret[PUB_KEY_SIZE];
  109. getPeerSharedSecret(secret, j);
  110. // decrypt, checking MAC is valid
  111. uint8_t data[MAX_PACKET_PAYLOAD];
  112. int len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i);
  113. if (len > 0) { // success!
  114. if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) {
  115. int k = 0;
  116. uint8_t path_len = data[k++];
  117. uint8_t* path = &data[k]; k += path_len;
  118. uint8_t extra_type = data[k++] & 0x0F; // upper 4 bits reserved for future use
  119. uint8_t* extra = &data[k];
  120. uint8_t extra_len = len - k; // remainder of packet (may be padded with zeroes!)
  121. if (onPeerPathRecv(pkt, j, secret, path, path_len, extra_type, extra, extra_len)) {
  122. if (pkt->isRouteFlood()) {
  123. // send a reciprocal return path to sender, but send DIRECTLY!
  124. mesh::Packet* rpath = createPathReturn(&src_hash, secret, pkt->path, pkt->path_len, 0, NULL, 0);
  125. if (rpath) sendDirect(rpath, path, path_len, 500);
  126. }
  127. }
  128. } else {
  129. onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len);
  130. }
  131. found = true;
  132. break;
  133. }
  134. }
  135. if (found) {
  136. pkt->markDoNotRetransmit(); // packet was for this node, so don't retransmit
  137. } else {
  138. MESH_DEBUG_PRINTLN("%s recv matches no peers, src_hash=%02X", getLogDateTime(), (uint32_t)src_hash);
  139. }
  140. }
  141. action = routeRecvPacket(pkt);
  142. }
  143. break;
  144. }
  145. case PAYLOAD_TYPE_ANON_REQ: {
  146. int i = 0;
  147. uint8_t dest_hash = pkt->payload[i++];
  148. uint8_t* sender_pub_key = &pkt->payload[i]; i += PUB_KEY_SIZE;
  149. uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
  150. if (i + 2 >= pkt->payload_len) {
  151. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime());
  152. } else if (!_tables->hasSeen(pkt)) {
  153. if (self_id.isHashMatch(&dest_hash)) {
  154. Identity sender(sender_pub_key);
  155. uint8_t secret[PUB_KEY_SIZE];
  156. self_id.calcSharedSecret(secret, sender);
  157. // decrypt, checking MAC is valid
  158. uint8_t data[MAX_PACKET_PAYLOAD];
  159. int len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i);
  160. if (len > 0) { // success!
  161. onAnonDataRecv(pkt, pkt->getPayloadType(), sender, data, len);
  162. pkt->markDoNotRetransmit();
  163. }
  164. }
  165. action = routeRecvPacket(pkt);
  166. }
  167. break;
  168. }
  169. case PAYLOAD_TYPE_GRP_DATA:
  170. case PAYLOAD_TYPE_GRP_TXT: {
  171. int i = 0;
  172. uint8_t channel_hash = pkt->payload[i++];
  173. uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
  174. if (i + 2 >= pkt->payload_len) {
  175. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime());
  176. } else if (!_tables->hasSeen(pkt)) {
  177. // scan channels DB, for all matching hashes of 'channel_hash' (max 2 matches supported ATM)
  178. GroupChannel channels[2];
  179. int num = searchChannelsByHash(&channel_hash, channels, 2);
  180. // for each matching channel, try to decrypt data
  181. for (int j = 0; j < num; j++) {
  182. // decrypt, checking MAC is valid
  183. uint8_t data[MAX_PACKET_PAYLOAD];
  184. int len = Utils::MACThenDecrypt(channels[j].secret, data, macAndData, pkt->payload_len - i);
  185. if (len > 0) { // success!
  186. onGroupDataRecv(pkt, pkt->getPayloadType(), channels[j], data, len);
  187. break;
  188. }
  189. }
  190. action = routeRecvPacket(pkt);
  191. }
  192. break;
  193. }
  194. case PAYLOAD_TYPE_ADVERT: {
  195. int i = 0;
  196. Identity id;
  197. memcpy(id.pub_key, &pkt->payload[i], PUB_KEY_SIZE); i += PUB_KEY_SIZE;
  198. uint32_t timestamp;
  199. memcpy(&timestamp, &pkt->payload[i], 4); i += 4;
  200. const uint8_t* signature = &pkt->payload[i]; i += SIGNATURE_SIZE;
  201. if (i > pkt->payload_len) {
  202. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete advertisement packet", getLogDateTime());
  203. } else if (self_id.matches(id.pub_key)) {
  204. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): receiving SELF advert packet", getLogDateTime());
  205. } else if (!_tables->hasSeen(pkt)) {
  206. uint8_t* app_data = &pkt->payload[i];
  207. int app_data_len = pkt->payload_len - i;
  208. if (app_data_len > MAX_ADVERT_DATA_SIZE) { app_data_len = MAX_ADVERT_DATA_SIZE; }
  209. // check that signature is valid
  210. bool is_ok;
  211. {
  212. uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE];
  213. int msg_len = 0;
  214. memcpy(&message[msg_len], id.pub_key, PUB_KEY_SIZE); msg_len += PUB_KEY_SIZE;
  215. memcpy(&message[msg_len], &timestamp, 4); msg_len += 4;
  216. memcpy(&message[msg_len], app_data, app_data_len); msg_len += app_data_len;
  217. is_ok = id.verify(signature, message, msg_len);
  218. }
  219. if (is_ok) {
  220. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): valid advertisement received!", getLogDateTime());
  221. onAdvertRecv(pkt, id, timestamp, app_data, app_data_len);
  222. action = routeRecvPacket(pkt);
  223. } else {
  224. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): received advertisement with forged signature! (app_data_len=%d)", getLogDateTime(), app_data_len);
  225. }
  226. }
  227. break;
  228. }
  229. case PAYLOAD_TYPE_RAW_CUSTOM: {
  230. if (pkt->isRouteDirect() && !_tables->hasSeen(pkt)) {
  231. onRawDataRecv(pkt);
  232. //action = routeRecvPacket(pkt); don't flood route these (yet)
  233. }
  234. break;
  235. }
  236. default:
  237. MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): unknown payload type, header: %d", getLogDateTime(), (int) pkt->header);
  238. // Don't flood route unknown packet types! action = routeRecvPacket(pkt);
  239. break;
  240. }
  241. return action;
  242. }
  243. DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
  244. if (packet->isRouteFlood() && !packet->isMarkedDoNotRetransmit()
  245. && packet->path_len + PATH_HASH_SIZE <= MAX_PATH_SIZE && allowPacketForward(packet)) {
  246. // append this node's hash to 'path'
  247. packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]);
  248. uint32_t d = getRetransmitDelay(packet);
  249. // as this propagates outwards, give it lower and lower priority
  250. return ACTION_RETRANSMIT_DELAYED(packet->path_len, d); // give priority to closer sources, than ones further away
  251. }
  252. return ACTION_RELEASE;
  253. }
  254. Packet* Mesh::createAdvert(const LocalIdentity& id, const uint8_t* app_data, size_t app_data_len) {
  255. if (app_data_len > MAX_ADVERT_DATA_SIZE) return NULL;
  256. Packet* packet = obtainNewPacket();
  257. if (packet == NULL) {
  258. MESH_DEBUG_PRINTLN("%s Mesh::createAdvert(): error, packet pool empty", getLogDateTime());
  259. return NULL;
  260. }
  261. packet->header = (PAYLOAD_TYPE_ADVERT << PH_TYPE_SHIFT); // ROUTE_TYPE_* is set later
  262. int len = 0;
  263. memcpy(&packet->payload[len], id.pub_key, PUB_KEY_SIZE); len += PUB_KEY_SIZE;
  264. uint32_t emitted_timestamp = _rtc->getCurrentTime();
  265. memcpy(&packet->payload[len], &emitted_timestamp, 4); len += 4;
  266. uint8_t* signature = &packet->payload[len]; len += SIGNATURE_SIZE; // will fill this in later
  267. memcpy(&packet->payload[len], app_data, app_data_len); len += app_data_len;
  268. packet->payload_len = len;
  269. {
  270. uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE];
  271. int msg_len = 0;
  272. memcpy(&message[msg_len], id.pub_key, PUB_KEY_SIZE); msg_len += PUB_KEY_SIZE;
  273. memcpy(&message[msg_len], &emitted_timestamp, 4); msg_len += 4;
  274. memcpy(&message[msg_len], app_data, app_data_len); msg_len += app_data_len;
  275. id.sign(signature, message, msg_len);
  276. }
  277. return packet;
  278. }
  279. #define MAX_COMBINED_PATH (MAX_PACKET_PAYLOAD - 2 - CIPHER_BLOCK_SIZE)
  280. Packet* Mesh::createPathReturn(const Identity& dest, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len) {
  281. uint8_t dest_hash[PATH_HASH_SIZE];
  282. dest.copyHashTo(dest_hash);
  283. return createPathReturn(dest_hash, secret, path, path_len, extra_type, extra, extra_len);
  284. }
  285. Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len) {
  286. if (path_len + extra_len + 5 > MAX_COMBINED_PATH) return NULL; // too long!!
  287. Packet* packet = obtainNewPacket();
  288. if (packet == NULL) {
  289. MESH_DEBUG_PRINTLN("%s Mesh::createPathReturn(): error, packet pool empty", getLogDateTime());
  290. return NULL;
  291. }
  292. packet->header = (PAYLOAD_TYPE_PATH << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  293. int len = 0;
  294. memcpy(&packet->payload[len], dest_hash, PATH_HASH_SIZE); len += PATH_HASH_SIZE; // dest hash
  295. len += self_id.copyHashTo(&packet->payload[len]); // src hash
  296. {
  297. int data_len = 0;
  298. uint8_t data[MAX_PACKET_PAYLOAD];
  299. data[data_len++] = path_len;
  300. memcpy(&data[data_len], path, path_len); data_len += path_len;
  301. if (extra_len > 0) {
  302. data[data_len++] = extra_type;
  303. memcpy(&data[data_len], extra, extra_len); data_len += extra_len;
  304. } else {
  305. // append a timestamp, or random blob (to make packet_hash unique)
  306. data[data_len++] = 0xFF; // dummy payload type
  307. getRNG()->random(&data[data_len], 4); data_len += 4;
  308. }
  309. len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
  310. }
  311. packet->payload_len = len;
  312. return packet;
  313. }
  314. Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) {
  315. if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE) {
  316. if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL;
  317. } else {
  318. return NULL; // invalid type
  319. }
  320. Packet* packet = obtainNewPacket();
  321. if (packet == NULL) {
  322. MESH_DEBUG_PRINTLN("%s Mesh::createDatagram(): error, packet pool empty", getLogDateTime());
  323. return NULL;
  324. }
  325. packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  326. int len = 0;
  327. len += dest.copyHashTo(&packet->payload[len]); // dest hash
  328. len += self_id.copyHashTo(&packet->payload[len]); // src hash
  329. len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
  330. packet->payload_len = len;
  331. return packet;
  332. }
  333. Packet* Mesh::createAnonDatagram(uint8_t type, const LocalIdentity& sender, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) {
  334. if (type == PAYLOAD_TYPE_ANON_REQ) {
  335. if (data_len + 1 + PUB_KEY_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL;
  336. } else {
  337. return NULL; // invalid type
  338. }
  339. Packet* packet = obtainNewPacket();
  340. if (packet == NULL) {
  341. MESH_DEBUG_PRINTLN("%s Mesh::createAnonDatagram(): error, packet pool empty", getLogDateTime());
  342. return NULL;
  343. }
  344. packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  345. int len = 0;
  346. if (type == PAYLOAD_TYPE_ANON_REQ) {
  347. len += dest.copyHashTo(&packet->payload[len]); // dest hash
  348. memcpy(&packet->payload[len], sender.pub_key, PUB_KEY_SIZE); len += PUB_KEY_SIZE; // sender pub_key
  349. } else {
  350. // FUTURE:
  351. }
  352. len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
  353. packet->payload_len = len;
  354. return packet;
  355. }
  356. Packet* Mesh::createGroupDatagram(uint8_t type, const GroupChannel& channel, const uint8_t* data, size_t data_len) {
  357. if (!(type == PAYLOAD_TYPE_GRP_TXT || type == PAYLOAD_TYPE_GRP_DATA)) return NULL; // invalid type
  358. if (data_len + 1 + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; // too long
  359. Packet* packet = obtainNewPacket();
  360. if (packet == NULL) {
  361. MESH_DEBUG_PRINTLN("%s Mesh::createGroupDatagram(): error, packet pool empty", getLogDateTime());
  362. return NULL;
  363. }
  364. packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  365. int len = 0;
  366. memcpy(&packet->payload[len], channel.hash, PATH_HASH_SIZE); len += PATH_HASH_SIZE;
  367. len += Utils::encryptThenMAC(channel.secret, &packet->payload[len], data, data_len);
  368. packet->payload_len = len;
  369. return packet;
  370. }
  371. Packet* Mesh::createAck(uint32_t ack_crc) {
  372. Packet* packet = obtainNewPacket();
  373. if (packet == NULL) {
  374. MESH_DEBUG_PRINTLN("%s Mesh::createAck(): error, packet pool empty", getLogDateTime());
  375. return NULL;
  376. }
  377. packet->header = (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  378. memcpy(packet->payload, &ack_crc, 4);
  379. packet->payload_len = 4;
  380. return packet;
  381. }
  382. Packet* Mesh::createRawData(const uint8_t* data, size_t len) {
  383. if (len > sizeof(Packet::payload)) return NULL; // invalid arg
  384. Packet* packet = obtainNewPacket();
  385. if (packet == NULL) {
  386. MESH_DEBUG_PRINTLN("%s Mesh::createRawData(): error, packet pool empty", getLogDateTime());
  387. return NULL;
  388. }
  389. packet->header = (PAYLOAD_TYPE_RAW_CUSTOM << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  390. memcpy(packet->payload, data, len);
  391. packet->payload_len = len;
  392. return packet;
  393. }
  394. Packet* Mesh::createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags) {
  395. Packet* packet = obtainNewPacket();
  396. if (packet == NULL) {
  397. MESH_DEBUG_PRINTLN("%s Mesh::createTrace(): error, packet pool empty", getLogDateTime());
  398. return NULL;
  399. }
  400. packet->header = (PAYLOAD_TYPE_TRACE << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
  401. memcpy(packet->payload, &tag, 4);
  402. memcpy(&packet->payload[4], &auth_code, 4);
  403. packet->payload[8] = flags;
  404. packet->payload_len = 9; // NOTE: path will be appended to payload[] later
  405. return packet;
  406. }
  407. void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) {
  408. if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) {
  409. MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime());
  410. return;
  411. }
  412. packet->header &= ~PH_ROUTE_MASK;
  413. packet->header |= ROUTE_TYPE_FLOOD;
  414. packet->path_len = 0;
  415. _tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
  416. uint8_t pri;
  417. if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) {
  418. pri = 2;
  419. } else if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT) {
  420. pri = 3; // de-prioritie these
  421. } else {
  422. pri = 1;
  423. }
  424. sendPacket(packet, pri, delay_millis);
  425. }
  426. void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uint32_t delay_millis) {
  427. packet->header &= ~PH_ROUTE_MASK;
  428. packet->header |= ROUTE_TYPE_DIRECT;
  429. uint8_t pri;
  430. if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { // TRACE packets are different
  431. // for TRACE packets, path is appended to end of PAYLOAD. (path is used for SNR's)
  432. memcpy(&packet->payload[packet->payload_len], path, path_len);
  433. packet->payload_len += path_len;
  434. packet->path_len = 0;
  435. pri = 5; // maybe make this configurable
  436. } else {
  437. memcpy(packet->path, path, packet->path_len = path_len);
  438. if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) {
  439. pri = 1; // slightly less priority
  440. } else {
  441. pri = 0;
  442. }
  443. }
  444. _tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
  445. sendPacket(packet, pri, delay_millis);
  446. }
  447. void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) {
  448. packet->header &= ~PH_ROUTE_MASK;
  449. packet->header |= ROUTE_TYPE_DIRECT;
  450. packet->path_len = 0; // path_len of zero means Zero Hop
  451. _tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
  452. sendPacket(packet, 0, delay_millis);
  453. }
  454. }