mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-26 10:48:52 +00:00
* companion radio: new CMD_EXPORT_CONTACT, CMD_IMPORT_CONTACT
This commit is contained in:
@@ -108,6 +108,8 @@ static uint32_t _atoi(const char* sp) {
|
||||
#define CMD_SET_ADVERT_LATLON 14
|
||||
#define CMD_REMOVE_CONTACT 15
|
||||
#define CMD_SHARE_CONTACT 16
|
||||
#define CMD_EXPORT_CONTACT 17
|
||||
#define CMD_IMPORT_CONTACT 18
|
||||
|
||||
#define RESP_CODE_OK 0
|
||||
#define RESP_CODE_ERR 1
|
||||
@@ -120,6 +122,7 @@ static uint32_t _atoi(const char* sp) {
|
||||
#define RESP_CODE_CHANNEL_MSG_RECV 8 // a reply to CMD_SYNC_NEXT_MESSAGE
|
||||
#define RESP_CODE_CURR_TIME 9 // a reply to CMD_GET_DEVICE_TIME
|
||||
#define RESP_CODE_NO_MORE_MESSAGES 10 // a reply to CMD_SYNC_NEXT_MESSAGE
|
||||
#define RESP_CODE_EXPORT_CONTACT 11
|
||||
|
||||
// these are _pushed_ to client app at any time
|
||||
#define PUSH_CODE_ADVERT 0x80
|
||||
@@ -712,6 +715,35 @@ public:
|
||||
} else {
|
||||
writeErrFrame(); // not found, or unable to send
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_EXPORT_CONTACT) {
|
||||
if (len < 1 + PUB_KEY_SIZE) {
|
||||
// export SELF
|
||||
auto pkt = createSelfAdvert(_prefs.node_name, _prefs.node_lat, _prefs.node_lon);
|
||||
if (pkt) {
|
||||
out_frame[0] = RESP_CODE_EXPORT_CONTACT;
|
||||
uint8_t out_len = pkt->writeTo(&out_frame[1]);
|
||||
releasePacket(pkt); // undo the obtainNewPacket()
|
||||
_serial->writeFrame(out_frame, out_len + 1);
|
||||
} else {
|
||||
writeErrFrame(); // Error
|
||||
}
|
||||
} else {
|
||||
uint8_t* pub_key = &cmd_frame[1];
|
||||
ContactInfo* recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
|
||||
uint8_t out_len;
|
||||
if (recipient && (out_len = exportContact(*recipient, &out_frame[1])) > 0) {
|
||||
out_frame[0] = RESP_CODE_EXPORT_CONTACT;
|
||||
_serial->writeFrame(out_frame, out_len + 1);
|
||||
} else {
|
||||
writeErrFrame(); // not found
|
||||
}
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_IMPORT_CONTACT && len > 2+32+64) {
|
||||
if (importContact(&cmd_frame[1], len - 1)) {
|
||||
writeOKFrame();
|
||||
} else {
|
||||
writeErrFrame();
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SYNC_NEXT_MESSAGE) {
|
||||
int out_len;
|
||||
if ((out_len = getFromOfflineQueue(out_frame)) > 0) {
|
||||
@@ -764,6 +796,7 @@ public:
|
||||
|
||||
void loop() {
|
||||
BaseChatMesh::loop();
|
||||
|
||||
size_t len = _serial->checkRecvFrame(cmd_frame);
|
||||
if (len > 0) {
|
||||
handleCmdFrame(len);
|
||||
|
||||
@@ -200,17 +200,8 @@ class MyMesh : public BaseChatMesh, ContactVisitor {
|
||||
if (len % 2 == 0) {
|
||||
len >>= 1; // halve, for num bytes
|
||||
if (mesh::Utils::fromHex(tmp_buf, len, command)) {
|
||||
auto pkt = obtainNewPacket();
|
||||
if (pkt) {
|
||||
if (pkt->readFrom(tmp_buf, len) && pkt->getPayloadType() == PAYLOAD_TYPE_ADVERT) {
|
||||
pkt->header |= ROUTE_TYPE_FLOOD; // simulate it being received flood-mode
|
||||
onRecvPacket(pkt); // loop-back, as if received over radio
|
||||
releasePacket(pkt); // undo the obtainNewPacket()
|
||||
return;
|
||||
} else {
|
||||
releasePacket(pkt); // undo the obtainNewPacket()
|
||||
}
|
||||
}
|
||||
importContact(tmp_buf, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +262,24 @@ bool BaseChatMesh::shareContactZeroHop(const ContactInfo& contact) {
|
||||
return true; // success
|
||||
}
|
||||
|
||||
uint8_t BaseChatMesh::exportContact(const ContactInfo& contact, uint8_t dest_buf[]) {
|
||||
return getBlobByKey(contact.id.pub_key, PUB_KEY_SIZE, dest_buf); // retrieve last raw advert packet
|
||||
}
|
||||
|
||||
bool BaseChatMesh::importContact(const uint8_t src_buf[], uint8_t len) {
|
||||
auto pkt = obtainNewPacket();
|
||||
if (pkt) {
|
||||
if (pkt->readFrom(src_buf, len) && pkt->getPayloadType() == PAYLOAD_TYPE_ADVERT) {
|
||||
pkt->header |= ROUTE_TYPE_FLOOD; // simulate it being received flood-mode
|
||||
_pendingLoopback = pkt; // loop-back, as if received over radio
|
||||
return true; // success
|
||||
} else {
|
||||
releasePacket(pkt); // undo the obtainNewPacket()
|
||||
}
|
||||
}
|
||||
return false; // error
|
||||
}
|
||||
|
||||
bool BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout) {
|
||||
uint8_t shared_secret[32];
|
||||
self_id.calcSharedSecret(shared_secret, recipient.id); // TODO: cache this
|
||||
@@ -416,4 +434,10 @@ void BaseChatMesh::loop() {
|
||||
onSendTimeout();
|
||||
txt_send_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_pendingLoopback) {
|
||||
onRecvPacket(_pendingLoopback); // loop-back, as if received over radio
|
||||
releasePacket(_pendingLoopback); // undo the obtainNewPacket()
|
||||
_pendingLoopback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ class BaseChatMesh : public mesh::Mesh {
|
||||
mesh::GroupChannel channels[MAX_GROUP_CHANNELS];
|
||||
int num_channels;
|
||||
#endif
|
||||
mesh::Packet* _pendingLoopback;
|
||||
uint8_t temp_buf[MAX_TRANS_UNIT];
|
||||
|
||||
mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack);
|
||||
@@ -73,6 +74,7 @@ protected:
|
||||
num_channels = 0;
|
||||
#endif
|
||||
txt_send_timeout = 0;
|
||||
_pendingLoopback = NULL;
|
||||
}
|
||||
|
||||
// 'UI' concepts, for sub-classes to implement
|
||||
@@ -108,6 +110,8 @@ public:
|
||||
bool sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& channel, const char* sender_name, const char* text, int text_len);
|
||||
bool sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout);
|
||||
bool shareContactZeroHop(const ContactInfo& contact);
|
||||
uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]);
|
||||
bool importContact(const uint8_t src_buf[], uint8_t len);
|
||||
void resetPathTo(ContactInfo& recipient);
|
||||
void scanRecentContacts(int last_n, ContactVisitor* visitor);
|
||||
ContactInfo* searchContactsByPrefix(const char* name_prefix);
|
||||
|
||||
Reference in New Issue
Block a user