소스 검색

* proposed change for re-trying reciprocal path transmit

Scott Powell 11 달 전
부모
커밋
74dea260e5
5개의 변경된 파일35개의 추가작업 그리고 13개의 파일을 삭제
  1. 3 2
      examples/companion_radio/MyMesh.cpp
  2. 2 1
      examples/companion_radio/MyMesh.h
  3. 3 3
      examples/simple_secure_chat/main.cpp
  4. 24 5
      src/helpers/BaseChatMesh.cpp
  5. 3 2
      src/helpers/BaseChatMesh.h

+ 3 - 2
examples/companion_radio/MyMesh.cpp

@@ -294,7 +294,7 @@ void MyMesh::onContactPathUpdated(const ContactInfo &contact) {
   dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
 }
 
-bool MyMesh::processAck(const uint8_t *data) {
+ContactInfo*  MyMesh::processAck(const uint8_t *data) {
   // see if matches any in a table
   for (int i = 0; i < EXPECTED_ACK_TABLE_SIZE; i++) {
     if (memcmp(data, &expected_ack_table[i].ack, 4) == 0) { // got an ACK from recipient
@@ -306,7 +306,7 @@ bool MyMesh::processAck(const uint8_t *data) {
 
       // NOTE: the same ACK can be received multiple times!
       expected_ack_table[i].ack = 0; // clear expected hash, now that we have received ACK
-      return true;
+      return expected_ack_table[i].contact;
     }
   }
   return checkConnectionsAck(data);
@@ -825,6 +825,7 @@ void MyMesh::handleCmdFrame(size_t len) {
         if (expected_ack) {
           expected_ack_table[next_ack_idx].msg_sent = _ms->getMillis(); // add to circular table
           expected_ack_table[next_ack_idx].ack = expected_ack;
+          expected_ack_table[next_ack_idx].contact = recipient;
           next_ack_idx = (next_ack_idx + 1) % EXPECTED_ACK_TABLE_SIZE;
         }
 

+ 2 - 1
examples/companion_radio/MyMesh.h

@@ -112,7 +112,7 @@ protected:
   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;
   void onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) override;
   void onContactPathUpdated(const ContactInfo &contact) override;
-  bool processAck(const uint8_t *data) override;
+  ContactInfo* processAck(const uint8_t *data) override;
   void queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packet *pkt, uint32_t sender_timestamp,
                     const uint8_t *extra, int extra_len, const char *text);
 
@@ -205,6 +205,7 @@ private:
   struct AckTableEntry {
     unsigned long msg_sent;
     uint32_t ack;
+    ContactInfo* contact;
   };
   #define EXPECTED_ACK_TABLE_SIZE 8
   AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table

+ 3 - 3
examples/simple_secure_chat/main.cpp

@@ -217,18 +217,18 @@ protected:
     saveContacts();
   }
 
-  bool processAck(const uint8_t *data) override {
+  ContactInfo* processAck(const uint8_t *data) override {
     if (memcmp(data, &expected_ack_crc, 4) == 0) {     // got an ACK from recipient
       Serial.printf("   Got ACK! (round trip: %d millis)\n", _ms->getMillis() - last_msg_sent);
       // NOTE: the same ACK can be received multiple times!
       expected_ack_crc = 0;  // reset our expected hash, now that we have received ACK
-      return true;
+      return NULL;  // TODO: really should return ContactInfo pointer 
     }
 
     //uint32_t crc;
     //memcpy(&crc, data, 4);
     //MESH_DEBUG_PRINTLN("unknown ACK received: %08X (expected: %08X)", crc, expected_ack_crc);
-    return false;
+    return NULL;
   }
 
   void onMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {

+ 24 - 5
src/helpers/BaseChatMesh.cpp

@@ -223,6 +223,10 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
     }
   } else if (type == PAYLOAD_TYPE_RESPONSE && len > 0) {
     onContactResponse(from, data, len);
+    if (packet->isRouteFlood() && from.out_path_len >= 0) {
+      // we have direct path, but other node is still sending flood response, so maybe they didn't receive reciprocal path properly(?)
+      handleReturnPathRetry(from, packet->path, packet->path_len);
+    }
   }
 }
 
@@ -248,7 +252,7 @@ bool BaseChatMesh::onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_
 
   if (extra_type == PAYLOAD_TYPE_ACK && extra_len >= 4) {
     // also got an encoded ACK!
-    if (processAck(extra)) {
+    if (processAck(extra) != NULL) {
       txt_send_timeout = 0;   // matched one we're waiting for, cancel timeout timer
     }
   } else if (extra_type == PAYLOAD_TYPE_RESPONSE && extra_len > 0) {
@@ -258,12 +262,25 @@ bool BaseChatMesh::onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_
 }
 
 void BaseChatMesh::onAckRecv(mesh::Packet* packet, uint32_t ack_crc) {
-  if (processAck((uint8_t *)&ack_crc)) {
+  ContactInfo* from;
+  if ((from = processAck((uint8_t *)&ack_crc)) != NULL) {
     txt_send_timeout = 0;   // matched one we're waiting for, cancel timeout timer
     packet->markDoNotRetransmit();   // ACK was for this node, so don't retransmit
+
+    if (packet->isRouteFlood() && from->out_path_len >= 0) {
+      // we have direct path, but other node is still sending flood, so maybe they didn't receive reciprocal path properly(?)
+      handleReturnPathRetry(*from, packet->path, packet->path_len);
+    }
   }
 }
 
+void BaseChatMesh::handleReturnPathRetry(const ContactInfo& contact, const uint8_t* path, uint8_t path_len) {
+  // NOTE: simplest impl is just to re-send a reciprocal return path to sender (DIRECTLY)
+  //        override this method in various firmwares, if there's a better strategy
+  mesh::Packet* rpath = createPathReturn(contact.id, contact.shared_secret, path, path_len, 0, NULL, 0);
+  if (rpath) sendDirect(rpath, contact.out_path, contact.out_path_len, 3000);   // 3 second delay
+}
+
 #ifdef MAX_GROUP_CHANNELS
 int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel dest[], int max_matches) {
   int n = 0;
@@ -550,7 +567,7 @@ void BaseChatMesh::markConnectionActive(const ContactInfo& contact) {
   }
 }
 
-bool BaseChatMesh::checkConnectionsAck(const uint8_t* data) {
+ContactInfo* BaseChatMesh::checkConnectionsAck(const uint8_t* data) {
   for (int i = 0; i < MAX_CONNECTIONS; i++) {
     if (connections[i].keep_alive_millis > 0 && memcmp(&connections[i].expected_ack, data, 4) == 0) {
       // yes, got an ack for our keep_alive request!
@@ -559,10 +576,12 @@ bool BaseChatMesh::checkConnectionsAck(const uint8_t* data) {
 
       // re-schedule next KEEP_ALIVE, now that we have heard from server
       connections[i].next_ping = futureMillis(connections[i].keep_alive_millis);
-      return true;  // yes, a match
+
+      auto id = &connections[i].server_id;
+      return lookupContactByPubKey(id->pub_key, PUB_KEY_SIZE);  // yes, a match
     }
   }
-  return false;  /// no match
+  return NULL;  /// no match
 }
 
 void BaseChatMesh::checkConnections() {

+ 3 - 2
src/helpers/BaseChatMesh.h

@@ -93,7 +93,7 @@ protected:
   // 'UI' concepts, for sub-classes to implement
   virtual bool isAutoAddEnabled() const { return true; }
   virtual void onDiscoveredContact(ContactInfo& contact, bool is_new, uint8_t path_len, const uint8_t* path) = 0;
-  virtual bool processAck(const uint8_t *data) = 0;
+  virtual ContactInfo* processAck(const uint8_t *data) = 0;
   virtual void onContactPathUpdated(const ContactInfo& contact) = 0;
   virtual 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);
   virtual void onMessageRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) = 0;
@@ -105,6 +105,7 @@ protected:
   virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
   virtual uint8_t onContactRequest(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t* data, uint8_t len, uint8_t* reply) = 0;
   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);
 
   // 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
@@ -127,7 +128,7 @@ protected:
   void stopConnection(const uint8_t* pub_key);
   bool hasConnectionTo(const uint8_t* pub_key);
   void markConnectionActive(const ContactInfo& contact);
-  bool checkConnectionsAck(const uint8_t* data);
+  ContactInfo* checkConnectionsAck(const uint8_t* data);
   void checkConnections();
 
 public: