bug 677. Don't assert fail for missing interfaces, instead return

nak packet to clients.
pull/678/head
Kevin Hester 2021-02-07 10:26:11 +08:00
rodzic ccb232b6ac
commit 486b03e985
7 zmienionych plików z 68 dodań i 45 usunięć

2
proto

@ -1 +1 @@
Subproject commit 1813b370ab5336fc3ba453fa92206f4941eda96b Subproject commit 106f4bfdebe277ab0b86d2b8c950ab78a35b0654

Wyświetl plik

@ -490,6 +490,8 @@ void setup()
DEBUG_MSG("Warning: Failed to find RF95 radio\n"); DEBUG_MSG("Warning: Failed to find RF95 radio\n");
delete rIf; delete rIf;
rIf = NULL; rIf = NULL;
} else {
DEBUG_MSG("Radio init succeeded, using RF95 radio\n");
} }
} }
#endif #endif
@ -501,6 +503,8 @@ void setup()
DEBUG_MSG("Warning: Failed to find SX1262 radio\n"); DEBUG_MSG("Warning: Failed to find SX1262 radio\n");
delete rIf; delete rIf;
rIf = NULL; rIf = NULL;
} else {
DEBUG_MSG("Radio init succeeded, using SX1262 radio\n");
} }
} }
#endif #endif
@ -512,6 +516,8 @@ void setup()
DEBUG_MSG("Warning: Failed to find simulated radio\n"); DEBUG_MSG("Warning: Failed to find simulated radio\n");
delete rIf; delete rIf;
rIf = NULL; rIf = NULL;
} else {
DEBUG_MSG("Using SIMULATED radio!\n");
} }
} }
#endif #endif

Wyświetl plik

@ -34,7 +34,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
// the original sending process. // the original sending process.
if (stopRetransmission(p->from, p->id)) { if (stopRetransmission(p->from, p->id)) {
DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n"); DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n");
sendAckNak(true, p->from, p->id); sendAckNak(ErrorReason_NONE, p->from, p->id);
} }
} }
@ -60,7 +60,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p)
if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability
// - not DSR routing) // - not DSR routing)
if (p->want_ack) { if (p->want_ack) {
sendAckNak(true, p->from, p->id); sendAckNak(ErrorReason_NONE, p->from, p->id);
} }
// If the payload is valid, look for ack/nak // If the payload is valid, look for ack/nak
@ -84,27 +84,6 @@ void ReliableRouter::sniffReceived(const MeshPacket *p)
FloodingRouter::sniffReceived(p); FloodingRouter::sniffReceived(p);
} }
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void ReliableRouter::sendAckNak(bool isAck, NodeNum to, PacketId 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=0x%x,id=0x%x\n", isAck, to, idFrom, p->id);
if (isAck) {
p->decoded.ack.success_id = idFrom;
p->decoded.which_ack = SubPacket_success_id_tag;
} else {
p->decoded.ack.fail_id = idFrom;
p->decoded.which_ack = SubPacket_fail_id_tag;
}
sendLocal(p); // we sometimes send directly to the local node
}
#define NUM_RETRANSMISSIONS 3 #define NUM_RETRANSMISSIONS 3
PendingPacket::PendingPacket(MeshPacket *p) PendingPacket::PendingPacket(MeshPacket *p)
@ -176,7 +155,7 @@ int32_t ReliableRouter::doRetransmissions()
if (p.numRetransmissions == 0) { if (p.numRetransmissions == 0) {
DEBUG_MSG("Reliable send failed, returning a nak fr=0x%x,to=0x%x,id=%d\n", p.packet->from, p.packet->to, DEBUG_MSG("Reliable send failed, returning a nak fr=0x%x,to=0x%x,id=%d\n", p.packet->from, p.packet->to,
p.packet->id); p.packet->id);
sendAckNak(false, p.packet->from, p.packet->id); sendAckNak(ErrorReason_MAX_RETRANSMIT, p.packet->from, p.packet->id);
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which // Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which
// allows the DSR version to still be able to look at the PendingPacket // allows the DSR version to still be able to look at the PendingPacket
stopRetransmission(it->first); stopRetransmission(it->first);

Wyświetl plik

@ -109,10 +109,6 @@ class ReliableRouter : public FloodingRouter
PendingPacket *startRetransmission(MeshPacket *p); PendingPacket *startRetransmission(MeshPacket *p);
private: private:
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void sendAckNak(bool isAck, NodeNum to, PacketId idFrom);
/** /**
* Stop any retransmissions we are doing of the specified node/packet ID pair * Stop any retransmissions we are doing of the specified node/packet ID pair

Wyświetl plik

@ -99,6 +99,31 @@ MeshPacket *Router::allocForSending()
return p; return p;
} }
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void Router::sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom)
{
auto p = allocForSending();
p->hop_limit = 0; // Assume just immediate neighbors for now
p->to = to;
DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
if (!err) {
p->decoded.ack.success_id = idFrom;
p->decoded.which_ack = SubPacket_success_id_tag;
} else {
p->decoded.ack.fail_id = idFrom;
p->decoded.which_ack = SubPacket_fail_id_tag;
// Also send back the error reason
p->decoded.which_payload = SubPacket_error_reason_tag;
p->decoded.error_reason = err;
}
sendLocal(p); // we sometimes send directly to the local node
}
ErrorCode Router::sendLocal(MeshPacket *p) ErrorCode Router::sendLocal(MeshPacket *p)
{ {
// No need to deliver externally if the destination is the local node // No need to deliver externally if the destination is the local node
@ -106,15 +131,24 @@ ErrorCode Router::sendLocal(MeshPacket *p)
printPacket("Enqueuing local", p); printPacket("Enqueuing local", p);
fromRadioQueue.enqueue(p); fromRadioQueue.enqueue(p);
return ERRNO_OK; return ERRNO_OK;
} } else if (!iface) {
// We must be sending to remote nodes also, fail if no interface found
// If we are sending a broadcast, we also treat it as if we just received it ourself // ERROR! no radio found, report failure back to the client and drop the packet
// this allows local apps (and PCs) to see broadcasts sourced locally DEBUG_MSG("Error: No interface, returning NAK and dropping packet.\n");
if (p->to == NODENUM_BROADCAST) { sendAckNak(ErrorReason_NO_INTERFACE, p->from, p->id);
handleReceived(p); packetPool.release(p);
}
return send(p); return ERRNO_NO_INTERFACES;
} else {
// If we are sending a broadcast, we also treat it as if we just received it ourself
// this allows local apps (and PCs) to see broadcasts sourced locally
if (p->to == NODENUM_BROADCAST) {
handleReceived(p);
}
return send(p);
}
} }
/** /**
@ -154,14 +188,15 @@ ErrorCode Router::send(MeshPacket *p)
p->which_payload = MeshPacket_encrypted_tag; p->which_payload = MeshPacket_encrypted_tag;
} }
if (iface) { assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside)
// DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); // if (iface) {
return iface->send(p); // DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
} else { 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); DEBUG_MSG("Dropping packet - no interfaces - fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
packetPool.release(p); packetPool.release(p);
return ERRNO_NO_INTERFACES; return ERRNO_NO_INTERFACES;
} } */
} }
/** /**

Wyświetl plik

@ -48,7 +48,8 @@ class Router : protected concurrency::OSThread
virtual int32_t runOnce(); virtual int32_t runOnce();
/** /**
* Works like send, but if we are sending to the local node, we directly put the message in the receive queue * Works like send, but if we are sending to the local node, we directly put the message in the receive queue.
* This is the primary method used for sending packets, because it handles both the remote and local cases.
* *
* NOTE: This method will free the provided packet (even if we return an error code) * NOTE: This method will free the provided packet (even if we return an error code)
*/ */
@ -92,6 +93,11 @@ class Router : protected concurrency::OSThread
*/ */
bool perhapsDecode(MeshPacket *p); bool perhapsDecode(MeshPacket *p);
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom);
private: private:
/** /**
* Called from loop() * Called from loop()

Wyświetl plik

@ -16,7 +16,8 @@ typedef enum _ErrorReason {
ErrorReason_NO_ROUTE = 1, ErrorReason_NO_ROUTE = 1,
ErrorReason_GOT_NAK = 2, ErrorReason_GOT_NAK = 2,
ErrorReason_TIMEOUT = 3, ErrorReason_TIMEOUT = 3,
ErrorReason_NO_INTERFACE = 4 ErrorReason_NO_INTERFACE = 4,
ErrorReason_MAX_RETRANSMIT = 5
} ErrorReason; } ErrorReason;
typedef enum _Constants { typedef enum _Constants {
@ -290,8 +291,8 @@ typedef struct _ToRadio {
/* Helper constants for enums */ /* Helper constants for enums */
#define _ErrorReason_MIN ErrorReason_NONE #define _ErrorReason_MIN ErrorReason_NONE
#define _ErrorReason_MAX ErrorReason_NO_INTERFACE #define _ErrorReason_MAX ErrorReason_MAX_RETRANSMIT
#define _ErrorReason_ARRAYSIZE ((ErrorReason)(ErrorReason_NO_INTERFACE+1)) #define _ErrorReason_ARRAYSIZE ((ErrorReason)(ErrorReason_MAX_RETRANSMIT+1))
#define _Constants_MIN Constants_Unused #define _Constants_MIN Constants_Unused
#define _Constants_MAX Constants_DATA_PAYLOAD_LEN #define _Constants_MAX Constants_DATA_PAYLOAD_LEN