mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-14 16:46:21 +00:00
* companion radio: new CMD_SEND_LOGIN, CMD_SEND_STATUS_REQ
This commit is contained in:
@@ -124,6 +124,8 @@ static uint32_t _atoi(const char* sp) {
|
||||
#define CMD_EXPORT_PRIVATE_KEY 23
|
||||
#define CMD_IMPORT_PRIVATE_KEY 24
|
||||
#define CMD_SEND_RAW_DATA 25
|
||||
#define CMD_SEND_LOGIN 26
|
||||
#define CMD_SEND_STATUS_REQ 27
|
||||
|
||||
#define RESP_CODE_OK 0
|
||||
#define RESP_CODE_ERR 1
|
||||
@@ -148,6 +150,9 @@ static uint32_t _atoi(const char* sp) {
|
||||
#define PUSH_CODE_SEND_CONFIRMED 0x82
|
||||
#define PUSH_CODE_MSG_WAITING 0x83
|
||||
#define PUSH_CODE_RAW_DATA 0x84
|
||||
#define PUSH_CODE_LOGIN_SUCCESS 0x85
|
||||
#define PUSH_CODE_LOGIN_FAIL 0x86
|
||||
#define PUSH_CODE_STATUS_RESPONSE 0x87
|
||||
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
|
||||
@@ -172,6 +177,8 @@ class MyMesh : public BaseChatMesh {
|
||||
IdentityStore* _identity_store;
|
||||
NodePrefs _prefs;
|
||||
uint32_t expected_ack_crc; // TODO: keep table of expected ACKs
|
||||
uint32_t pending_login;
|
||||
uint32_t pending_status;
|
||||
mesh::GroupChannel* _public;
|
||||
BaseSerialInterface* _serial;
|
||||
unsigned long last_msg_sent;
|
||||
@@ -478,8 +485,36 @@ protected:
|
||||
}
|
||||
|
||||
void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) override {
|
||||
// TODO: check for login response
|
||||
// TODO: check for Get Stats response
|
||||
uint32_t sender_timestamp;
|
||||
memcpy(&sender_timestamp, data, 4);
|
||||
|
||||
if (memcmp(&pending_login, contact.id.pub_key, 4) == 0) { // check for login response
|
||||
// yes, is response to pending sendLogin()
|
||||
pending_login = 0;
|
||||
|
||||
int i = 0;
|
||||
if (memcmp(&data[4], "OK", 2) == 0) { // legacy Repeater login OK response
|
||||
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
|
||||
} else if (data[4] == RESP_SERVER_LOGIN_OK) { // new login response
|
||||
// TODO: check the keep_alive_interval in data[]
|
||||
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
|
||||
} else {
|
||||
out_frame[i++] = PUSH_CODE_LOGIN_FAIL;
|
||||
}
|
||||
out_frame[i++] = 0; // reserved
|
||||
memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix
|
||||
_serial->writeFrame(out_frame, i);
|
||||
} else if (len > 4 && memcmp(&pending_status, contact.id.pub_key, 4) == 0) { // check for status response
|
||||
// yes, is response to pending sendStatusRequest()
|
||||
pending_status = 0;
|
||||
|
||||
int i = 0;
|
||||
out_frame[i++] = PUSH_CODE_STATUS_RESPONSE;
|
||||
out_frame[i++] = 0; // reserved
|
||||
memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix
|
||||
memcpy(&out_frame[i], &data[4], len - 4); i += (len - 4);
|
||||
_serial->writeFrame(out_frame, i);
|
||||
}
|
||||
}
|
||||
|
||||
void onRawDataRecv(mesh::Packet* packet) override {
|
||||
@@ -517,6 +552,7 @@ public:
|
||||
offline_queue_len = 0;
|
||||
app_target_ver = 0;
|
||||
_identity_store = NULL;
|
||||
pending_login = pending_status = 0;
|
||||
|
||||
// defaults
|
||||
memset(&_prefs, 0, sizeof(_prefs));
|
||||
@@ -919,6 +955,48 @@ public:
|
||||
} else {
|
||||
writeErrFrame(); // flood, not supported (yet)
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SEND_LOGIN && len >= 1+PUB_KEY_SIZE) {
|
||||
uint8_t* pub_key = &cmd_frame[1];
|
||||
ContactInfo* recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
|
||||
char *password = (char *) &cmd_frame[1+PUB_KEY_SIZE];
|
||||
cmd_frame[len] = 0; // ensure null terminator in password
|
||||
if (recipient) {
|
||||
uint32_t est_timeout;
|
||||
int result = sendLogin(*recipient, password, est_timeout);
|
||||
if (result == MSG_SEND_FAILED) {
|
||||
writeErrFrame();
|
||||
} else {
|
||||
pending_status = 0;
|
||||
memcpy(&pending_login, recipient->id.pub_key, 4); // match this to onContactResponse()
|
||||
out_frame[0] = RESP_CODE_SENT;
|
||||
out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0;
|
||||
memcpy(&out_frame[2], &pending_login, 4);
|
||||
memcpy(&out_frame[6], &est_timeout, 4);
|
||||
_serial->writeFrame(out_frame, 10);
|
||||
}
|
||||
} else {
|
||||
writeErrFrame(); // contact not found
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1+PUB_KEY_SIZE) {
|
||||
uint8_t* pub_key = &cmd_frame[1];
|
||||
ContactInfo* recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
|
||||
if (recipient) {
|
||||
uint32_t est_timeout;
|
||||
int result = sendStatusRequest(*recipient, est_timeout);
|
||||
if (result == MSG_SEND_FAILED) {
|
||||
writeErrFrame();
|
||||
} else {
|
||||
pending_login = 0;
|
||||
memcpy(&pending_status, recipient->id.pub_key, 4); // match this to onContactResponse()
|
||||
out_frame[0] = RESP_CODE_SENT;
|
||||
out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0;
|
||||
memcpy(&out_frame[2], &pending_status, 4);
|
||||
memcpy(&out_frame[6], &est_timeout, 4);
|
||||
_serial->writeFrame(out_frame, 10);
|
||||
}
|
||||
} else {
|
||||
writeErrFrame(); // contact not found
|
||||
}
|
||||
} else {
|
||||
writeErrFrame();
|
||||
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
|
||||
|
||||
@@ -279,10 +279,7 @@ bool BaseChatMesh::importContact(const uint8_t src_buf[], uint8_t len) {
|
||||
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
|
||||
|
||||
int BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout) {
|
||||
int tlen;
|
||||
uint8_t temp[24];
|
||||
uint32_t now = getRTCClock()->getCurrentTimeUnique();
|
||||
@@ -298,20 +295,44 @@ bool BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password,
|
||||
tlen = 4 + len;
|
||||
}
|
||||
|
||||
auto pkt = createAnonDatagram(PAYLOAD_TYPE_ANON_REQ, self_id, recipient.id, shared_secret, temp, tlen);
|
||||
auto pkt = createAnonDatagram(PAYLOAD_TYPE_ANON_REQ, self_id, recipient.id, recipient.shared_secret, temp, tlen);
|
||||
if (pkt) {
|
||||
uint32_t t = _radio->getEstAirtimeFor(pkt->payload_len + pkt->path_len + 2);
|
||||
if (recipient.out_path_len < 0) {
|
||||
sendFlood(pkt);
|
||||
est_timeout = calcFloodTimeoutMillisFor(t);
|
||||
return MSG_SEND_SENT_FLOOD;
|
||||
} else {
|
||||
sendDirect(pkt, recipient.out_path, recipient.out_path_len);
|
||||
est_timeout = calcDirectTimeoutMillisFor(t, recipient.out_path_len);
|
||||
return MSG_SEND_SENT_DIRECT;
|
||||
}
|
||||
} else {
|
||||
return false; // failed
|
||||
}
|
||||
return true; // success
|
||||
return MSG_SEND_FAILED;
|
||||
}
|
||||
|
||||
int BaseChatMesh::sendStatusRequest(const ContactInfo& recipient, uint32_t& est_timeout) {
|
||||
uint8_t temp[13];
|
||||
uint32_t now = getRTCClock()->getCurrentTimeUnique();
|
||||
memcpy(temp, &now, 4); // mostly an extra blob to help make packet_hash unique
|
||||
temp[4] = CMD_GET_STATUS;
|
||||
memset(&temp[5], 0, 4); // reserved (possibly for 'since' param)
|
||||
getRNG()->random(&temp[9], 4); // random blob to help make packet-hash unique
|
||||
|
||||
auto pkt = createDatagram(PAYLOAD_TYPE_REQ, recipient.id, recipient.shared_secret, temp, sizeof(temp));
|
||||
if (pkt) {
|
||||
uint32_t t = _radio->getEstAirtimeFor(pkt->payload_len + pkt->path_len + 2);
|
||||
if (recipient.out_path_len < 0) {
|
||||
sendFlood(pkt);
|
||||
est_timeout = calcFloodTimeoutMillisFor(t);
|
||||
return MSG_SEND_SENT_FLOOD;
|
||||
} else {
|
||||
sendDirect(pkt, recipient.out_path, recipient.out_path_len);
|
||||
est_timeout = calcDirectTimeoutMillisFor(t, recipient.out_path_len);
|
||||
return MSG_SEND_SENT_DIRECT;
|
||||
}
|
||||
}
|
||||
return MSG_SEND_FAILED;
|
||||
}
|
||||
|
||||
void BaseChatMesh::resetPathTo(ContactInfo& recipient) {
|
||||
|
||||
@@ -27,6 +27,10 @@ struct ContactInfo {
|
||||
#define MSG_SEND_SENT_FLOOD 1
|
||||
#define MSG_SEND_SENT_DIRECT 2
|
||||
|
||||
#define CMD_GET_STATUS 0x01 // same as _GET_STATS
|
||||
|
||||
#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
|
||||
|
||||
class ContactVisitor {
|
||||
public:
|
||||
virtual void onContactVisit(const ContactInfo& contact) = 0;
|
||||
@@ -108,7 +112,8 @@ public:
|
||||
mesh::Packet* createSelfAdvert(const char* name, double lat=0.0, double lon=0.0);
|
||||
int sendMessage(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& expected_ack, uint32_t& est_timeout);
|
||||
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);
|
||||
int sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout);
|
||||
int sendStatusRequest(const ContactInfo& recipient, 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);
|
||||
|
||||
Reference in New Issue
Block a user