diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 348916ca5..d9d6d223c 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -504,17 +504,24 @@ bool MyMesh::allowPacketForward(const mesh::Packet* packet) { mesh::Packet* MyMesh::obtainPacketFor(ContactInfo& contact) { auto pkt = obtainNewPacket(); if (pkt) { + uint8_t crypto_mode = contact.direct_mode & 0x0F; if (contact.out_path_len == OUT_PATH_UNKNOWN) { - pkt->header |= ROUTE_TYPE_FLOOD; - // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + if (crypto_mode == CRYPTO_NEW_V1) { + pkt->header |= ROUTE_TYPE_TRANSPORT_FLOOD; + // pkt->transport_codes[0] scope set later + pkt->transport_codes[1] = (contact.curr_session_id & ~(3u << 14)); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); + } else { + pkt->header |= ROUTE_TYPE_FLOOD; + // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + } } else { - uint8_t crypto_mode = contact.direct_mode & 0x0F; - if (crypto_mode == CRYPTO_NEW_DIRECT) { + if (crypto_mode == CRYPTO_NEW_V1) { uint8_t dm_mode = contact.direct_mode >> 4; // upper 4 bits is which DM_MODE_* to use pkt->header |= ROUTE_TYPE_TRANSPORT_DIRECT; pkt->transport_codes[0] = (((uint16_t)dm_mode) << 14) | contact.next_seq_no++; // implicit, cursor = 0 pkt->transport_codes[1] = (contact.curr_session_id & ~(3u << 14)); - pkt->transport_codes[1] |= (CRYPTO_NEW_DIRECT << 14); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); } else { pkt->header |= ROUTE_TYPE_DIRECT; } @@ -537,26 +544,38 @@ void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint3 void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) { // TODO: dynamic send_scope, depending on recipient and current 'home' Region - if (send_unscoped) { - sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1); // app has explicitly requested un-scoped - } else { - TransportKey default_scope; - memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key)); + TransportKey default_scope; + memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key)); + auto scope = send_scope.isNull() ? &default_scope : &send_scope; - auto scope = send_scope.isNull() ? &default_scope : &send_scope; - sendFloodScoped(*scope, pkt, delay_millis); + if (pkt->transport_codes[1] != 0) { // has a new CRYPTO_* encoding + pkt->transport_codes[0] = send_unscoped ? 0 : (scope->isNull() ? 0 : scope->calcTransportCode(pkt)); + pkt->setPathHashSizeAndCount(_prefs.path_hash_mode + 1, 0); + send(pkt, delay_millis); + } else { + if (send_unscoped) { + sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1); // app has explicitly requested un-scoped + } else { + sendFloodScoped(*scope, pkt, delay_millis); + } } } void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) { // TODO: have per-channel send_scope - if (send_unscoped) { - sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1); // app has explicitly requested un-scoped - } else { - TransportKey default_scope; - memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key)); + TransportKey default_scope; + memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key)); + auto scope = send_scope.isNull() ? &default_scope : &send_scope; - auto scope = send_scope.isNull() ? &default_scope : &send_scope; - sendFloodScoped(*scope, pkt, delay_millis); + if (pkt->transport_codes[1] != 0) { // has a new CRYPTO_* encoding + pkt->transport_codes[0] = send_unscoped ? 0 : (scope->isNull() ? 0 : scope->calcTransportCode(pkt)); + pkt->setPathHashSizeAndCount(_prefs.path_hash_mode + 1, 0); + send(pkt, delay_millis); + } else { + if (send_unscoped) { + sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1); // app has explicitly requested un-scoped + } else { + sendFloodScoped(*scope, pkt, delay_millis); + } } } diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 11d23ed22..a95ef6cc6 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -63,17 +63,24 @@ mesh::Packet* MyMesh::obtainPacketFor(ClientInfo& client, const uint8_t* out_path, uint8_t out_path_len) { auto pkt = obtainNewPacket(); if (pkt) { + uint8_t crypto_mode = client.direct_mode & 0x0F; if (out_path_len == OUT_PATH_UNKNOWN) { - pkt->header |= ROUTE_TYPE_FLOOD; - // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + if (crypto_mode == CRYPTO_NEW_V1) { + pkt->header |= ROUTE_TYPE_TRANSPORT_FLOOD; + // pkt->transport_codes[0] scope set later + pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); + } else { + pkt->header |= ROUTE_TYPE_FLOOD; + // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + } } else { - uint8_t crypto_mode = client.direct_mode & 0x0F; - if (crypto_mode == CRYPTO_NEW_DIRECT) { + if (crypto_mode == CRYPTO_NEW_V1) { uint8_t dm_mode = client.direct_mode >> 4; // upper 4 bits is which DM_MODE_* to use pkt->header |= ROUTE_TYPE_TRANSPORT_DIRECT; pkt->transport_codes[0] = (((uint16_t)dm_mode) << 14) | client.next_seq_no++; // implicit, cursor = 0 pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); - pkt->transport_codes[1] |= (CRYPTO_NEW_DIRECT << 14); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); } else { pkt->header |= ROUTE_TYPE_DIRECT; } @@ -168,7 +175,7 @@ uint8_t MyMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secr reply_data[7] = client->permissions; getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness reply_data[12] = FIRMWARE_VER_LEVEL; // New field - reply_data[13] = (1 << CRYPTO_NEW_DIRECT) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported + reply_data[13] = (1 << CRYPTO_NEW_V1) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported return 14; // reply length } @@ -445,18 +452,29 @@ void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, ui bool req_scope_known = recv_pkt_region != NULL && !is_wildcard && region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0; + TransportKey* scope; switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) { case mesh::REPLY_SCOPE_REQUEST: - sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request + scope = &req_scope; break; case mesh::REPLY_SCOPE_DEFAULT: - // requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region. - // un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0 - sendFloodScoped(default_scope, packet, delay_millis, path_hash_size); + scope = &default_scope; break; - case mesh::REPLY_SCOPE_NONE: + default: // mesh::REPLY_SCOPE_NONE: + scope = NULL; // send un-scoped + break; + } + + if (packet->transport_codes[1] != 0) { // has new CRYPTO_* encoding + packet->transport_codes[0] = (scope && !scope->isNull()) ? scope->calcTransportCode(packet) : 0; + packet->setPathHashSizeAndCount(path_hash_size, 0); + send(packet, delay_millis); + } else { + if (scope) { + sendFloodScoped(*scope, packet, delay_millis, path_hash_size); + } else { sendFlood(packet, delay_millis, path_hash_size); // send un-scoped - break; + } } } @@ -644,9 +662,9 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m return; } - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -726,9 +744,9 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, } ClientInfo* client = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -836,9 +854,9 @@ bool MyMesh::onPeerPathRecv(mesh::Packet *packet, int sender_idx, const uint8_t MESH_DEBUG_PRINTLN("PATH to client, path_len=%d", (uint32_t)path_len); auto client = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index ba13dc62b..266b585ca 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -42,17 +42,24 @@ struct ServerStats { mesh::Packet* MyMesh::obtainPacketFor(ClientInfo& client, const uint8_t* out_path, uint8_t out_path_len) { auto pkt = obtainNewPacket(); if (pkt) { + uint8_t crypto_mode = client.direct_mode & 0x0F; if (out_path_len == OUT_PATH_UNKNOWN) { - pkt->header |= ROUTE_TYPE_FLOOD; - // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + if (crypto_mode == CRYPTO_NEW_V1) { + pkt->header |= ROUTE_TYPE_TRANSPORT_FLOOD; + // pkt->transport_codes[0] scope set later + pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); + } else { + pkt->header |= ROUTE_TYPE_FLOOD; + // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + } } else { - uint8_t crypto_mode = client.direct_mode & 0x0F; - if (crypto_mode == CRYPTO_NEW_DIRECT) { + if (crypto_mode == CRYPTO_NEW_V1) { uint8_t dm_mode = client.direct_mode >> 4; // upper 4 bits is which DM_MODE_* to use pkt->header |= ROUTE_TYPE_TRANSPORT_DIRECT; pkt->transport_codes[0] = (((uint16_t)dm_mode) << 14) | client.next_seq_no++; // implicit, cursor = 0 pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); - pkt->transport_codes[1] |= (CRYPTO_NEW_DIRECT << 14); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); } else { pkt->header |= ROUTE_TYPE_DIRECT; } @@ -408,9 +415,9 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m client->out_path_len = OUT_PATH_UNKNOWN; // need to rediscover out_path } - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -424,7 +431,7 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m reply_data[7] = client->permissions; // NEW getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness reply_data[12] = FIRMWARE_VER_LEVEL; // New field - reply_data[13] = (1 << CRYPTO_NEW_DIRECT) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported + reply_data[13] = (1 << CRYPTO_NEW_V1) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported next_push = futureMillis(PUSH_NOTIFY_DELAY_MILLIS); // delay next push, give RESPONSE packet time to arrive first @@ -475,9 +482,9 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, return; } auto client = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -658,9 +665,9 @@ bool MyMesh::onPeerPathRecv(mesh::Packet *packet, int sender_idx, const uint8_t MESH_DEBUG_PRINTLN("PATH to client, path_len=%d", (uint32_t)path_len); auto client = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (client->direct_mode == CRYPTO_LEGACY) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -814,19 +821,30 @@ void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, ui bool req_scope_known = recv_pkt_region != NULL && !is_wildcard && region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0; + TransportKey* scope; switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) { case mesh::REPLY_SCOPE_REQUEST: - sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request + scope = &req_scope; break; case mesh::REPLY_SCOPE_DEFAULT: - // requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region. - // un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0 - sendFloodScoped(default_scope, packet, delay_millis, path_hash_size); + scope = &default_scope; break; - case mesh::REPLY_SCOPE_NONE: - sendFlood(packet, delay_millis, path_hash_size); // send un-scoped + default: // mesh::REPLY_SCOPE_NONE: + scope = NULL; // send un-scoped break; } + + if (packet->transport_codes[1] != 0) { // has new CRYPTO_* encoding + packet->transport_codes[0] = (scope && !scope->isNull()) ? scope->calcTransportCode(packet) : 0; + packet->setPathHashSizeAndCount(path_hash_size, 0); + send(packet, delay_millis); + } else { + if (scope) { + sendFloodScoped(*scope, packet, delay_millis, path_hash_size); + } else { + sendFlood(packet, delay_millis, path_hash_size); // send un-scoped + } + } } void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) { diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index 43d12b343..19ce10aa1 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -104,17 +104,24 @@ static float findTelemValue(const uint8_t* buf, uint8_t size, uint8_t channel, u mesh::Packet* SensorMesh::obtainPacketFor(ClientInfo& client, const uint8_t* out_path, uint8_t out_path_len) { auto pkt = obtainNewPacket(); if (pkt) { + uint8_t crypto_mode = client.direct_mode & 0x0F; if (out_path_len == OUT_PATH_UNKNOWN) { - pkt->header |= ROUTE_TYPE_FLOOD; - // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + if (crypto_mode == CRYPTO_NEW_V1) { + pkt->header |= ROUTE_TYPE_TRANSPORT_FLOOD; + // pkt->transport_codes[0] scope set later + pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); + } else { + pkt->header |= ROUTE_TYPE_FLOOD; + // NOTE: final route type, transport codes, path_len is set later in sendFloodScoped() + } } else { - uint8_t crypto_mode = client.direct_mode & 0x0F; - if (crypto_mode == CRYPTO_NEW_DIRECT) { + if (crypto_mode == CRYPTO_NEW_V1) { uint8_t dm_mode = client.direct_mode >> 4; // upper 4 bits is which DM_MODE_* to use pkt->header |= ROUTE_TYPE_TRANSPORT_DIRECT; pkt->transport_codes[0] = (((uint16_t)dm_mode) << 14) | client.next_seq_no++; // implicit, cursor = 0 pkt->transport_codes[1] = (client.curr_session_id & ~(3u << 14)); - pkt->transport_codes[1] |= (CRYPTO_NEW_DIRECT << 14); + pkt->transport_codes[1] |= (CRYPTO_NEW_V1 << 14); } else { pkt->header |= ROUTE_TYPE_DIRECT; } @@ -433,7 +440,7 @@ uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* reply_data[7] = client->permissions; getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness reply_data[12] = FIRMWARE_VER_LEVEL; - reply_data[13] = (1 << CRYPTO_NEW_DIRECT) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported + reply_data[13] = (1 << CRYPTO_NEW_V1) | (1 << CRYPTO_LEGACY); // New bitfield: which crypto-types supported return 14; // reply length } @@ -588,8 +595,10 @@ void SensorMesh::onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, con MESH_DEBUG_PRINTLN("onAnonDataRecv: client ACL cannot find slot!"); // This shouldn't happen! return; } - if (crypto_type == CRYPTO_NEW_DIRECT) { - client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + if (crypto_type == CRYPTO_NEW_V1) { + if (client->direct_mode == CRYPTO_LEGACY) { + client->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it + } } auto reply = obtainPacketFor(*client, client->out_path, client->out_path_len); @@ -656,9 +665,9 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i } ClientInfo* from = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (from->direct_mode == CRYPTO_LEGACY) { - from->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + from->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -804,9 +813,9 @@ bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint } ClientInfo* from = acl.getClientByIdx(i); - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (from->direct_mode == CRYPTO_LEGACY) { - from->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Client in new scheme, so they must support it + from->direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Client in new scheme, so they must support it } } @@ -983,19 +992,30 @@ void SensorMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis bool req_scope_known = recv_pkt_region != NULL && !is_wildcard && region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0; + TransportKey* scope; switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) { case mesh::REPLY_SCOPE_REQUEST: - sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request + scope = &req_scope; break; case mesh::REPLY_SCOPE_DEFAULT: - // requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region. - // un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0 - sendFloodScoped(default_scope, packet, delay_millis, path_hash_size); + scope = &default_scope; break; - case mesh::REPLY_SCOPE_NONE: - sendFlood(packet, delay_millis, path_hash_size); // send un-scoped + default: // mesh::REPLY_SCOPE_NONE: + scope = NULL; // send un-scoped break; } + + if (packet->transport_codes[1] != 0) { // has new CRYPTO_* encoding + packet->transport_codes[0] = (scope && !scope->isNull()) ? scope->calcTransportCode(packet) : 0; + packet->setPathHashSizeAndCount(path_hash_size, 0); + send(packet, delay_millis); + } else { + if (scope) { + sendFloodScoped(*scope, packet, delay_millis, path_hash_size); + } else { + sendFlood(packet, delay_millis, path_hash_size); // send un-scoped + } + } } void SensorMesh::sendSelfAdvertisement(int delay_millis, bool flood) { diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 01acfc41c..e36f8ab52 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -205,12 +205,17 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { uint8_t data[MAX_PACKET_PAYLOAD]; int len; uint8_t crypto_type; - if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_DIRECT) { + if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { uint8_t iv[3]; memcpy(iv, &pkt->transport_codes[1], 2); // session-id iv[2] = (pkt->transport_codes[0] & 0xFF); // seq-no len = Utils::MACThenDecrypt(secret, iv, 3, data, macAndData, pkt->payload_len - i); - crypto_type = CRYPTO_NEW_DIRECT; + crypto_type = CRYPTO_NEW_V1; + } else if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[2]; + memcpy(iv, &pkt->transport_codes[1], 2); + len = Utils::MACThenDecrypt(secret, iv, 2, data, macAndData, pkt->payload_len - i); + crypto_type = CRYPTO_NEW_V1; } else if (!pkt->hasTransportCodes() || (pkt->transport_codes[1] >> 14) == CRYPTO_LEGACY) { len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); crypto_type = CRYPTO_LEGACY; @@ -276,12 +281,17 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { uint8_t data[MAX_PACKET_PAYLOAD]; uint8_t crypto_type; int len; - if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_DIRECT) { + if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { uint8_t iv[3]; memcpy(iv, &pkt->transport_codes[1], 2); // session-id / crypto-type iv[2] = (pkt->transport_codes[0] & 0xFF); // seq-no len = Utils::MACThenDecrypt(secret, iv, 3, data, macAndData, pkt->payload_len - i); - crypto_type = CRYPTO_NEW_DIRECT; + crypto_type = CRYPTO_NEW_V1; + } else if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[2]; + memcpy(iv, &pkt->transport_codes[1], 2); + len = Utils::MACThenDecrypt(secret, iv, 2, data, macAndData, pkt->payload_len - i); + crypto_type = CRYPTO_NEW_V1; } else if (!pkt->hasTransportCodes() || (pkt->transport_codes[1] >> 14) == CRYPTO_LEGACY) { len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); crypto_type = CRYPTO_LEGACY; @@ -316,9 +326,22 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { for (int j = 0; j < num; j++) { // decrypt, checking MAC is valid uint8_t data[MAX_PACKET_PAYLOAD]; - int len = Utils::MACThenDecrypt(channels[j].secret, data, macAndData, pkt->payload_len - i); + uint8_t crypto_type; + int len; + if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && (pkt->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[2]; + memcpy(iv, &pkt->transport_codes[1], 2); + len = Utils::MACThenDecrypt(channels[j].secret, iv, 2, data, macAndData, pkt->payload_len - i); + crypto_type = CRYPTO_NEW_V1; + } else if (!pkt->hasTransportCodes() || (pkt->transport_codes[1] >> 14) == CRYPTO_LEGACY) { + len = Utils::MACThenDecrypt(channels[j].secret, data, macAndData, pkt->payload_len - i); + crypto_type = CRYPTO_LEGACY; + } else { + MESH_DEBUG_PRINTLN("%s unknown Crypto Type indicator: %u", getLogDateTime(), (uint32_t)(pkt->transport_codes[1] >> 14)); + len = 0; // failed to decode + } if (len > 0) { // success! - onGroupDataRecv(pkt, pkt->getPayloadType(), channels[j], data, len); + onGroupDataRecv(pkt, pkt->getPayloadType(), channels[j], data, len, crypto_type); break; } } @@ -591,12 +614,15 @@ void Mesh::encodeDatagram(Packet* packet, uint8_t type, const Identity& dest, co len += dest.copyHashTo(&packet->payload[len]); // dest hash len += self_id.copyHashTo(&packet->payload[len]); // src hash - if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_DIRECT) { - // new encryption - uint8_t iv[3]; + if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[3]; // new encryption memcpy(iv, &packet->transport_codes[1], 2); // session-id iv[2] = packet->transport_codes[0] & 0xFF; // seq-no len += Utils::encryptThenMAC(secret, iv, 3, &packet->payload[len], data, data_len); + } else if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[2]; // new encryption + memcpy(iv, &packet->transport_codes[1], 2); + len += Utils::encryptThenMAC(secret, iv, 2, &packet->payload[len], data, data_len); } else { // legacy encryption len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len); @@ -648,12 +674,15 @@ void Mesh::encodeAnonDatagram(Packet* packet, uint8_t type, const LocalIdentity& } else { // FUTURE: } - if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_DIRECT) { - // new encryption - uint8_t iv[3]; + if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[3]; // new encryption memcpy(iv, &packet->transport_codes[1], 2); // session-id iv[2] = packet->transport_codes[0] & 0xFF; // seq-no len += Utils::encryptThenMAC(secret, iv, 3, &packet->payload[len], data, data_len); + } else if (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && (packet->transport_codes[1] >> 14) == CRYPTO_NEW_V1) { + uint8_t iv[2]; // new encryption + memcpy(iv, &packet->transport_codes[1], 2); + len += Utils::encryptThenMAC(secret, iv, 2, &packet->payload[len], data, data_len); } else { // legacy encryption len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len); @@ -885,7 +914,7 @@ void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uin void Mesh::send(Packet* packet, uint32_t delay_millis) { // packet header should already be set // transport codes should already be set (optional) - // path/path_len should already be set (if direct) + // path/path_len should already be set uint8_t pri; if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { // TRACE packets are different @@ -898,6 +927,8 @@ void Mesh::send(Packet* packet, uint32_t delay_millis) { } else { if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { pri = 1; // slightly less priority + } else if (packet->isRouteFlood()) { + pri = 1; } else { pri = 0; } diff --git a/src/Mesh.h b/src/Mesh.h index 4999885a1..56de24627 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -162,8 +162,9 @@ protected: * NOTE: the same payload can be received multiple times, via different routes * \param type one of: PAYLOAD_TYPE_GRP_TXT, PAYLOAD_TYPE_GRP_DATA * \param channel the matching GroupChannel + * \param crypto_type the crypto method that was used with this packet, one of CRYPTO_* */ - virtual void onGroupDataRecv(Packet* packet, uint8_t type, const GroupChannel& channel, uint8_t* data, size_t len) { } + virtual void onGroupDataRecv(Packet* packet, uint8_t type, const GroupChannel& channel, uint8_t* data, size_t len, uint8_t crypto_type) { } /** * \brief A simple ACK packet has been received. diff --git a/src/Packet.h b/src/Packet.h index f20fecf60..8a8b0dcd7 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -17,7 +17,7 @@ namespace mesh { #define ROUTE_TYPE_TRANSPORT_DIRECT 0x03 // direct route + transport codes #define CRYPTO_LEGACY 0 -#define CRYPTO_NEW_DIRECT 1 +#define CRYPTO_NEW_V1 1 // REVISIT: need name? #define CRYPTO_RESERVED1 2 #define CRYPTO_RESERVED2 3 diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index fd37c07f1..076910705 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -26,6 +26,8 @@ mesh::Packet* BaseChatMesh::obtainPacketFor(ContactInfo& contact) { // this is } void BaseChatMesh::updateLinkQualityStats(ContactInfo& from, mesh::Packet* packet) { + if (packet->getRouteType() != ROUTE_TYPE_TRANSPORT_DIRECT) return; + uint16_t session_id = packet->transport_codes[1]; uint8_t seq_no = (packet->transport_codes[0] & 0xFF); // lower 8 bits // if (session_id == last_session_id) { @@ -273,9 +275,9 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender } ContactInfo& from = contacts[i]; - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (from.direct_mode == CRYPTO_LEGACY) { - from.direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Contact in new scheme, so they must support it + from.direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Contact in new scheme, so they must support it } updateLinkQualityStats(from, packet); } @@ -406,9 +408,9 @@ bool BaseChatMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const ui } ContactInfo& from = contacts[i]; - if (crypto_type == CRYPTO_NEW_DIRECT) { + if (crypto_type == CRYPTO_NEW_V1) { if (from.direct_mode == CRYPTO_LEGACY) { - from.direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_DIRECT; // have received from Contact in new scheme, so they must support it + from.direct_mode = (DM_MODE_SEQ_NORMAL << 4) | CRYPTO_NEW_V1; // have received from Contact in new scheme, so they must support it } updateLinkQualityStats(from, packet); } @@ -475,7 +477,7 @@ int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel d } #endif -void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len) { +void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len, uint8_t crypto_type) { if (type == PAYLOAD_TYPE_GRP_TXT) { if (len < 5) { MESH_DEBUG_PRINTLN("onGroupDataRecv: dropping short group text payload len=%d", (uint32_t)len); diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index d6846cb2a..a0055a752 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -149,7 +149,7 @@ protected: #ifdef MAX_GROUP_CHANNELS int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override; #endif - void onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len) override; + void onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len, uint8_t crypto_type) override; // Connections bool startConnection(const ContactInfo& contact, uint16_t keep_alive_secs);