Prechádzať zdrojové kódy

* Mesh: new sendFlood() overload with transport codes.
* BaseChatMesh: sendFloodScoped(), for overriding with some outbound 'scope' / TransportKey
* companion: new 'send_scope' variable.

Scott Powell 9 mesiacov pred
rodič
commit
d9ff3a4d02

+ 24 - 0
examples/companion_radio/MyMesh.cpp

@@ -378,6 +378,29 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe
 #endif
 }
 
+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_scope.isNull()) {
+    sendFlood(pkt, delay_millis);
+  } else {
+    uint16_t codes[2];
+    codes[0] = send_scope.calcTransportCode(pkt);
+    codes[1] = 0;  // REVISIT: set to 'home' Region, for sender/return region?
+    sendFlood(pkt, codes, delay_millis);
+  }
+}
+void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) {
+  // TODO: have per-channel send_scope
+  if (send_scope.isNull()) {
+    sendFlood(pkt, delay_millis);
+  } else {
+    uint16_t codes[2];
+    codes[0] = send_scope.calcTransportCode(pkt);
+    codes[1] = 0;  // REVISIT: set to 'home' Region, for sender/return region?
+    sendFlood(pkt, codes, delay_millis);
+  }
+}
+
 void MyMesh::onMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp,
                            const char *text) {
   markConnectionActive(from); // in case this is from a server, and we have a connection
@@ -663,6 +686,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
   sign_data = NULL;
   dirty_contacts_expiry = 0;
   memset(advert_paths, 0, sizeof(advert_paths));
+  memset(send_scope.key, 0, sizeof(send_scope.key));
 
   // defaults
   memset(&_prefs, 0, sizeof(_prefs));

+ 6 - 0
examples/companion_radio/MyMesh.h

@@ -68,6 +68,7 @@
 #endif
 
 #include <helpers/BaseChatMesh.h>
+#include <helpers/TransportKeyStore.h>
 
 /* -------------------------------------------------------------------------------------- */
 
@@ -107,6 +108,9 @@ protected:
   int calcRxDelay(float score, uint32_t air_time) const override;
   uint8_t getExtraAckTransmitCount() const override;
 
+  void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override;
+  void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override;
+
   void logRxRaw(float snr, float rssi, const uint8_t raw[], int len) override;
   bool isAutoAddEnabled() const override;
   bool onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_t in_path_len, uint8_t* out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
@@ -191,6 +195,8 @@ private:
   uint32_t sign_data_len;
   unsigned long dirty_contacts_expiry;
 
+  TransportKey send_scope;
+
   uint8_t cmd_frame[MAX_FRAME_SIZE + 1];
   uint8_t out_frame[MAX_FRAME_SIZE + 1];
   CayenneLPP telemetry;

+ 25 - 0
src/Mesh.cpp

@@ -610,6 +610,31 @@ void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) {
   sendPacket(packet, pri, delay_millis);
 }
 
+void Mesh::sendFlood(Packet* packet, uint16_t* transport_codes, uint32_t delay_millis) {
+  if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) {
+    MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime());
+    return;
+  }
+
+  packet->header &= ~PH_ROUTE_MASK;
+  packet->header |= ROUTE_TYPE_TRANSPORT_FLOOD;
+  packet->transport_codes[0] = transport_codes[0];
+  packet->transport_codes[1] = transport_codes[1];
+  packet->path_len = 0;
+
+  _tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
+
+  uint8_t pri;
+  if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) {
+    pri = 2;
+  } else if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT) {
+    pri = 3;   // de-prioritie these
+  } else {
+    pri = 1;
+  }
+  sendPacket(packet, pri, delay_millis);
+}
+
 void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uint32_t delay_millis) {
   packet->header &= ~PH_ROUTE_MASK;
   packet->header |= ROUTE_TYPE_DIRECT;

+ 6 - 0
src/Mesh.h

@@ -186,6 +186,12 @@ public:
   */
   void sendFlood(Packet* packet, uint32_t delay_millis=0);
 
+  /**
+   * \brief  send a locally-generated Packet with flood routing
+   * \param transport_codes   array of 2 codes to attach to packet
+  */
+  void sendFlood(Packet* packet, uint16_t* transport_codes, uint32_t delay_millis=0);
+
   /**
    * \brief  send a locally-generated Packet with Direct routing
   */

+ 19 - 12
src/helpers/BaseChatMesh.cpp

@@ -9,6 +9,13 @@
   #define TXT_ACK_DELAY     200
 #endif
 
+void BaseChatMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
+  sendFlood(pkt, delay_millis);
+}
+void BaseChatMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) {
+  sendFlood(pkt, delay_millis);
+}
+
 mesh::Packet* BaseChatMesh::createSelfAdvert(const char* name) {
   uint8_t app_data[MAX_ADVERT_DATA_SIZE];
   uint8_t app_data_len;
@@ -34,7 +41,7 @@ mesh::Packet* BaseChatMesh::createSelfAdvert(const char* name, double lat, doubl
 void BaseChatMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) {
   if (dest.out_path_len < 0) {
     mesh::Packet* ack = createAck(ack_hash);
-    if (ack) sendFlood(ack, TXT_ACK_DELAY);
+    if (ack) sendFloodScoped(dest, ack, TXT_ACK_DELAY);
   } else {
     uint32_t d = TXT_ACK_DELAY;
     if (getExtraAckTransmitCount() > 0) {
@@ -175,7 +182,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
         // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
         mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
                                                 PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
-        if (path) sendFlood(path, TXT_ACK_DELAY);
+        if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
       } else {
         sendAckTo(from, ack_hash);
       }
@@ -186,7 +193,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
       if (packet->isRouteFlood()) {
         // let this sender know path TO here, so they can use sendDirect() (NOTE: no ACK as extra)
         mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len, 0, NULL, 0);
-        if (path) sendFlood(path);
+        if (path) sendFloodScoped(from, path);
       }
     } else if (flags == TXT_TYPE_SIGNED_PLAIN) {
       if (timestamp > from.sync_since) {  // make sure 'sync_since' is up-to-date
@@ -202,7 +209,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
         // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
         mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
                                                 PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
-        if (path) sendFlood(path, TXT_ACK_DELAY);
+        if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
       } else {
         sendAckTo(from, ack_hash);
       }
@@ -218,14 +225,14 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
         // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
         mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
                                               PAYLOAD_TYPE_RESPONSE, temp_buf, reply_len);
-        if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
+        if (path) sendFloodScoped(from, path, SERVER_RESPONSE_DELAY);
       } else {
         mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from.id, secret, temp_buf, reply_len);
         if (reply) {
           if (from.out_path_len >= 0) {  // we have an out_path, so send DIRECT
             sendDirect(reply, from.out_path, from.out_path_len, SERVER_RESPONSE_DELAY);
           } else {
-            sendFlood(reply, SERVER_RESPONSE_DELAY);
+            sendFloodScoped(from, reply, SERVER_RESPONSE_DELAY);
           }
         }
       }
@@ -346,7 +353,7 @@ int  BaseChatMesh::sendMessage(const ContactInfo& recipient, uint32_t timestamp,
 
   int rc;
   if (recipient.out_path_len < 0) {
-    sendFlood(pkt);
+    sendFloodScoped(recipient, pkt);
     txt_send_timeout = futureMillis(est_timeout = calcFloodTimeoutMillisFor(t));
     rc = MSG_SEND_SENT_FLOOD;
   } else {
@@ -372,7 +379,7 @@ int  BaseChatMesh::sendCommandData(const ContactInfo& recipient, uint32_t timest
   uint32_t t = _radio->getEstAirtimeFor(pkt->getRawLength());
   int rc;
   if (recipient.out_path_len < 0) {
-    sendFlood(pkt);
+    sendFloodScoped(recipient, pkt);
     txt_send_timeout = futureMillis(est_timeout = calcFloodTimeoutMillisFor(t));
     rc = MSG_SEND_SENT_FLOOD;
   } else {
@@ -398,7 +405,7 @@ bool BaseChatMesh::sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& chan
 
   auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_TXT, channel, temp, 5 + prefix_len + text_len);
   if (pkt) {
-    sendFlood(pkt);
+    sendFloodScoped(channel, pkt);
     return true;
   }
   return false;
@@ -460,7 +467,7 @@ int BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password,
   if (pkt) {
     uint32_t t = _radio->getEstAirtimeFor(pkt->getRawLength());
     if (recipient.out_path_len < 0) {
-      sendFlood(pkt);
+      sendFloodScoped(recipient, pkt);
       est_timeout = calcFloodTimeoutMillisFor(t);
       return MSG_SEND_SENT_FLOOD;
     } else {
@@ -487,7 +494,7 @@ int  BaseChatMesh::sendRequest(const ContactInfo& recipient, const uint8_t* req_
   if (pkt) {
     uint32_t t = _radio->getEstAirtimeFor(pkt->getRawLength());
     if (recipient.out_path_len < 0) {
-      sendFlood(pkt);
+      sendFloodScoped(recipient, pkt);
       est_timeout = calcFloodTimeoutMillisFor(t);
       return MSG_SEND_SENT_FLOOD;
     } else {
@@ -514,7 +521,7 @@ int  BaseChatMesh::sendRequest(const ContactInfo& recipient, uint8_t req_type, u
   if (pkt) {
     uint32_t t = _radio->getEstAirtimeFor(pkt->getRawLength());
     if (recipient.out_path_len < 0) {
-      sendFlood(pkt);
+      sendFloodScoped(recipient, pkt);
       est_timeout = calcFloodTimeoutMillisFor(t);
       return MSG_SEND_SENT_FLOOD;
     } else {

+ 3 - 0
src/helpers/BaseChatMesh.h

@@ -107,6 +107,9 @@ protected:
   virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
   virtual void handleReturnPathRetry(const ContactInfo& contact, const uint8_t* path, uint8_t path_len);
 
+  virtual void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0);
+  virtual void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0);
+
   // storage concepts, for sub-classes to override/implement
   virtual int  getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; }  // not implemented
   virtual bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len) { return false; }

+ 7 - 0
src/helpers/TransportKeyStore.cpp

@@ -12,6 +12,13 @@ uint16_t TransportKey::calcTransportCode(const mesh::Packet* packet) const {
   return code;
 }
 
+bool TransportKey::isNull() const {
+  for (int i = 0; i < sizeof(key); i++) {
+    if (key[i]) return false;
+  }
+  return true;  // key is all zeroes
+}
+
 void TransportKeyStore::putCache(uint16_t id, const TransportKey& key) {
   if (num_cache < MAX_TKS_ENTRIES) {
     cache_ids[num_cache] = id;

+ 1 - 0
src/helpers/TransportKeyStore.h

@@ -8,6 +8,7 @@ struct TransportKey {
   uint8_t key[16];
 
   uint16_t calcTransportCode(const mesh::Packet* packet) const;
+  bool isNull() const;
 };
 
 #define MAX_TKS_ENTRIES   16