Skip to content

Commit

Permalink
reliable broadcast now works
Browse files Browse the repository at this point in the history
  • Loading branch information
geeksville committed May 21, 2020
1 parent e755610 commit 9dd8828
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/mesh/MeshService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ void MeshService::sendToMesh(MeshPacket *p)
}

// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
if (router.send(p) != ERRNO_OK) {
if (router.sendLocal(p) != ERRNO_OK) {
DEBUG_MSG("No radio was able to send packet, discarding...\n");
releaseToPool(p);
}
Expand Down
11 changes: 8 additions & 3 deletions src/mesh/ReliableRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
ErrorCode ReliableRouter::send(MeshPacket *p)
{
if (p->want_ack) {
// If someone asks for acks on broadcast, we need the hop limit to be at least one, so that first node that receives our
// message will rebroadcast
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0)
p->hop_limit = 1;

auto copy = packetPool.allocCopy(*p);
startRetransmission(copy);
}
Expand Down Expand Up @@ -42,7 +47,7 @@ void ReliableRouter::handleReceived(MeshPacket *p)
// If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for
// the original sending process.
if (stopRetransmission(p->from, p->id)) {
DEBUG_MSG("Someone is retransmitting for us, generate implicit ack");
DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n");
sendAckNak(true, p->from, p->id);
}
} else if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (for now)
Expand Down Expand Up @@ -79,10 +84,10 @@ void ReliableRouter::handleReceived(MeshPacket *p)
*/
void ReliableRouter::sendAckNak(bool isAck, NodeNum to, PacketId idFrom)
{
DEBUG_MSG("Sending an ack=%d,to=%d,idFrom=%d\n", isAck, to, idFrom);
auto p = allocForSending();
p->hop_limit = 0; // Assume just immediate neighbors for now
p->to = to;
DEBUG_MSG("Sending an ack=0x%x,to=0x%x,idFrom=%d,id=%d\n", isAck, to, idFrom, p->id);

if (isAck) {
p->decoded.ack.success_id = idFrom;
Expand All @@ -92,7 +97,7 @@ void ReliableRouter::sendAckNak(bool isAck, NodeNum to, PacketId idFrom)
p->decoded.which_ack = SubPacket_fail_id_tag;
}

send(p);
sendLocal(p); // we sometimes send directly to the local node
}

#define NUM_RETRANSMISSIONS 3
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/ReliableRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct PendingPacket {
PendingPacket() {}
PendingPacket(MeshPacket *p);

void setNextTx() { nextTxMsec = millis() + random(30 * 1000, 22 * 1000); }
void setNextTx() { nextTxMsec = millis() + random(20 * 1000, 22 * 1000); }
};

class GlobalPacketIdHashFunction
Expand Down
68 changes: 36 additions & 32 deletions src/mesh/Router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,51 +77,56 @@ MeshPacket *Router::allocForSending()
return p;
}

ErrorCode Router::sendLocal(MeshPacket *p)
{
if (p->to == nodeDB.getNodeNum()) {
DEBUG_MSG("Enqueuing internal message for the receive queue\n");
fromRadioQueue.enqueue(p);
return ERRNO_OK;
} else
return send(p);
}

/**
* Send a packet on a suitable interface. This routine will
* later free() the packet to pool. This routine is not allowed to stall.
* If the txmit queue is full it might return an error.
*/
ErrorCode Router::send(MeshPacket *p)
{
// If this packet was destined only to apps on our node, don't send it out into the network
if (p->to == nodeDB.getNodeNum()) {
DEBUG_MSG("Dropping locally processed message\n");
packetPool.release(p);
return ERRNO_OK;
} else {
// Never set the want_ack flag on broadcast packets sent over the air.
if (p->to == NODENUM_BROADCAST)
p->want_ack = false;
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal

// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)
// Never set the want_ack flag on broadcast packets sent over the air.
if (p->to == NODENUM_BROADCAST)
p->want_ack = false;

assert(p->which_payload == MeshPacket_encrypted_tag ||
p->which_payload == MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now
// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)

// First convert from protobufs to raw bytes
if (p->which_payload == MeshPacket_decoded_tag) {
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
assert(p->which_payload == MeshPacket_encrypted_tag ||
p->which_payload == MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now

size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), SubPacket_fields, &p->decoded);
// First convert from protobufs to raw bytes
if (p->which_payload == MeshPacket_decoded_tag) {
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union

assert(numbytes <= MAX_RHPACKETLEN);
crypto->encrypt(p->from, p->id, numbytes, bytes);
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), SubPacket_fields, &p->decoded);

// Copy back into the packet and set the variant type
memcpy(p->encrypted.bytes, bytes, numbytes);
p->encrypted.size = numbytes;
p->which_payload = MeshPacket_encrypted_tag;
}
assert(numbytes <= MAX_RHPACKETLEN);
crypto->encrypt(p->from, p->id, numbytes, bytes);

if (iface) {
// DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
return iface->send(p);
} else {
DEBUG_MSG("Dropping packet - no interfaces - fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
packetPool.release(p);
return ERRNO_NO_INTERFACES;
}
// Copy back into the packet and set the variant type
memcpy(p->encrypted.bytes, bytes, numbytes);
p->encrypted.size = numbytes;
p->which_payload = MeshPacket_encrypted_tag;
}

if (iface) {
// DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
return iface->send(p);
} else {
DEBUG_MSG("Dropping packet - no interfaces - fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
packetPool.release(p);
return ERRNO_NO_INTERFACES;
}
}

Expand All @@ -132,7 +137,6 @@ ErrorCode Router::send(MeshPacket *p)
void Router::sniffReceived(const MeshPacket *p)
{
DEBUG_MSG("FIXME-update-db Sniffing packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);

}

bool Router::perhapsDecode(MeshPacket *p)
Expand Down
13 changes: 9 additions & 4 deletions src/mesh/Router.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@ class Router
virtual void loop();

/**
* Send a packet on a suitable interface. This routine will
* later free() the packet to pool. This routine is not allowed to stall.
* If the txmit queue is full it might return an error
* Works like send, but if we are sending to the local node, we directly put the message in the receive queue
*/
virtual ErrorCode send(MeshPacket *p);
ErrorCode sendLocal(MeshPacket *p);

/// Allocate and return a meshpacket which defaults as send to broadcast from the current node.
MeshPacket *allocForSending();
Expand All @@ -61,6 +59,13 @@ class Router
NodeNum getNodeNum();

protected:
/**
* Send a packet on a suitable interface. This routine will
* later free() the packet to pool. This routine is not allowed to stall.
* If the txmit queue is full it might return an error
*/
virtual ErrorCode send(MeshPacket *p);

/**
* Called from loop()
* Handle any packet that is received by an interface on this node.
Expand Down

0 comments on commit 9dd8828

Please sign in to comment.