BaseChatMesh.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #pragma once
  2. #include <Arduino.h> // needed for PlatformIO
  3. #include <Mesh.h>
  4. #include <helpers/AdvertDataHelpers.h>
  5. #include <helpers/TxtDataHelpers.h>
  6. #define MAX_TEXT_LEN (10*CIPHER_BLOCK_SIZE) // must be LESS than (MAX_PACKET_PAYLOAD - 4 - CIPHER_MAC_SIZE - 1)
  7. struct ContactInfo {
  8. mesh::Identity id;
  9. char name[32];
  10. uint8_t type; // on of ADV_TYPE_*
  11. uint8_t flags;
  12. int8_t out_path_len;
  13. uint8_t out_path[MAX_PATH_SIZE];
  14. uint32_t last_advert_timestamp; // by THEIR clock
  15. uint8_t shared_secret[PUB_KEY_SIZE];
  16. uint32_t lastmod; // by OUR clock
  17. int32_t gps_lat, gps_lon; // 6 dec places
  18. uint32_t sync_since;
  19. };
  20. #define MAX_SEARCH_RESULTS 8
  21. #define MSG_SEND_FAILED 0
  22. #define MSG_SEND_SENT_FLOOD 1
  23. #define MSG_SEND_SENT_DIRECT 2
  24. #define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS
  25. #define REQ_TYPE_KEEP_ALIVE 0x02
  26. #define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
  27. class ContactVisitor {
  28. public:
  29. virtual void onContactVisit(const ContactInfo& contact) = 0;
  30. };
  31. class BaseChatMesh;
  32. class ContactsIterator {
  33. int next_idx = 0;
  34. public:
  35. bool hasNext(const BaseChatMesh* mesh, ContactInfo& dest);
  36. };
  37. #ifndef MAX_CONTACTS
  38. #define MAX_CONTACTS 32
  39. #endif
  40. #ifndef MAX_CONNECTIONS
  41. #define MAX_CONNECTIONS 16
  42. #endif
  43. struct ConnectionInfo {
  44. mesh::Identity server_id;
  45. unsigned long next_ping;
  46. uint32_t last_activity;
  47. uint32_t keep_alive_millis;
  48. uint32_t expected_ack;
  49. };
  50. /**
  51. * \brief abstract Mesh class for common 'chat' client
  52. */
  53. class BaseChatMesh : public mesh::Mesh {
  54. friend class ContactsIterator;
  55. ContactInfo contacts[MAX_CONTACTS];
  56. int num_contacts;
  57. int sort_array[MAX_CONTACTS];
  58. int matching_peer_indexes[MAX_SEARCH_RESULTS];
  59. unsigned long txt_send_timeout;
  60. #ifdef MAX_GROUP_CHANNELS
  61. mesh::GroupChannel channels[MAX_GROUP_CHANNELS];
  62. int num_channels;
  63. #endif
  64. mesh::Packet* _pendingLoopback;
  65. uint8_t temp_buf[MAX_TRANS_UNIT];
  66. ConnectionInfo connections[MAX_CONNECTIONS];
  67. mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack);
  68. protected:
  69. BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)
  70. : mesh::Mesh(radio, ms, rng, rtc, mgr, tables)
  71. {
  72. num_contacts = 0;
  73. #ifdef MAX_GROUP_CHANNELS
  74. num_channels = 0;
  75. #endif
  76. txt_send_timeout = 0;
  77. _pendingLoopback = NULL;
  78. memset(connections, 0, sizeof(connections));
  79. }
  80. // 'UI' concepts, for sub-classes to implement
  81. virtual void onDiscoveredContact(ContactInfo& contact, bool is_new) = 0;
  82. virtual bool processAck(const uint8_t *data) = 0;
  83. virtual void onContactPathUpdated(const ContactInfo& contact) = 0;
  84. virtual void onMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0;
  85. virtual void onCommandDataRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0;
  86. virtual void onSignedMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) = 0;
  87. virtual uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const = 0;
  88. virtual uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const = 0;
  89. virtual void onSendTimeout() = 0;
  90. virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) = 0;
  91. virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
  92. // storage concepts, for sub-classes to override/implement
  93. virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented
  94. virtual bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len) { return false; }
  95. // Mesh overrides
  96. void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
  97. int searchPeersByHash(const uint8_t* hash) override;
  98. void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
  99. void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
  100. bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
  101. void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
  102. #ifdef MAX_GROUP_CHANNELS
  103. int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override;
  104. #endif
  105. void onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len) override;
  106. // Connections
  107. bool startConnection(const ContactInfo& contact, uint16_t keep_alive_secs);
  108. void stopConnection(const uint8_t* pub_key);
  109. bool hasConnectionTo(const uint8_t* pub_key);
  110. void markConnectionActive(const ContactInfo& contact);
  111. bool checkConnectionsAck(const uint8_t* data);
  112. void checkConnections();
  113. public:
  114. mesh::Packet* createSelfAdvert(const char* name, double lat=0.0, double lon=0.0);
  115. int sendMessage(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& expected_ack, uint32_t& est_timeout);
  116. int sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout);
  117. bool sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& channel, const char* sender_name, const char* text, int text_len);
  118. int sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout);
  119. int sendStatusRequest(const ContactInfo& recipient, uint32_t& est_timeout);
  120. bool shareContactZeroHop(const ContactInfo& contact);
  121. uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]);
  122. bool importContact(const uint8_t src_buf[], uint8_t len);
  123. void resetPathTo(ContactInfo& recipient);
  124. void scanRecentContacts(int last_n, ContactVisitor* visitor);
  125. ContactInfo* searchContactsByPrefix(const char* name_prefix);
  126. ContactInfo* lookupContactByPubKey(const uint8_t* pub_key, int prefix_len);
  127. bool removeContact(ContactInfo& contact);
  128. bool addContact(const ContactInfo& contact);
  129. int getNumContacts() const { return num_contacts; }
  130. ContactsIterator startContactsIterator();
  131. mesh::GroupChannel* addChannel(const char* psk_base64);
  132. void loop();
  133. };