Browse Source
Fix companion disconnect on inbound packet; use server.accept()
EthernetServer::available() returns any socket with data, including the
already-connected client's socket. The companion path then called stop()
on what it thought was a duplicate client, closing the shared socket and
disconnecting the companion after the first packet.
Switch both SerialEthernetInterface and EthernetCLI to server.accept(),
which only returns newly-accepted sockets. Removes the IP/port duplicate
detection in the companion path (no longer reachable) and the same-socket
early-return in the CLI path.
Reported by mcode6726 on PR #1983 .
pull/1983/head
Ryan Gregg
2 months ago
Failed to extract signature
2 changed files with
11 additions and
23 deletions
src/helpers/nrf52/EthernetCLI.h
src/helpers/nrf52/SerialEthernetInterface.cpp
@ -98,12 +98,13 @@ static bool ethernet_handle_command(const char* command, char* reply) {
return false ;
}
// Check for new TCP client connections, replacing any existing connection
// Check for new TCP client connections, replacing any existing connection.
// Use accept() (not available()) so we only see newly-accepted sockets;
// available() also returns existing connected sockets that have data, which
// would force us to disambiguate every inbound packet from a real new client.
static void ethernet_check_client ( ) {
auto newClient = ethernet_server . available ( ) ;
auto newClient = ethernet_server . accept ( ) ;
if ( newClient ) {
// Only replace if this is actually a different client
if ( newClient = = ethernet_client & & ethernet_client . connected ( ) ) return ;
if ( ethernet_client ) ethernet_client . stop ( ) ;
ethernet_client = newClient ;
IPAddress ip = ethernet_client . remoteIP ( ) ;
@ -120,34 +120,21 @@ bool SerialEthernetInterface::isWriteBusy() const {
}
size_t SerialEthernetInterface : : checkRecvFrame ( uint8_t dest [ ] ) {
// check if new client connected; new connections replace existing ones
auto newClient = server . available ( ) ;
// Use accept() (not available()) so we only see newly-accepted sockets.
// available() also returns existing connected sockets that have data,
// which would cause us to treat each inbound packet as a "new client"
// and stop() the underlying socket — disconnecting the companion.
auto newClient = server . accept ( ) ;
if ( newClient ) {
IPAddress new_ip = newClient . remoteIP ( ) ;
uint16_t new_port = newClient . remotePort ( ) ;
ETHERNET_DEBUG_PRINTLN (
" New client available %u.%u.%u.%u:%u " ,
" New client accepted %u.%u.%u.%u:%u " ,
new_ip [ 0 ] ,
new_ip [ 1 ] ,
new_ip [ 2 ] ,
new_ip [ 3 ] ,
new_port ) ;
if ( client & & client . connected ( ) ) {
IPAddress cur_ip = client . remoteIP ( ) ;
uint16_t cur_port = client . remotePort ( ) ;
ETHERNET_DEBUG_PRINTLN (
" Current client %u.%u.%u.%u:%u " ,
cur_ip [ 0 ] ,
cur_ip [ 1 ] ,
cur_ip [ 2 ] ,
cur_ip [ 3 ] ,
cur_port ) ;
if ( cur_ip = = new_ip & & cur_port = = new_port ) {
ETHERNET_DEBUG_PRINTLN ( " Ignoring duplicate client " ) ;
newClient . stop ( ) ;
return 0 ;
}
}
deviceConnected = false ;
if ( client ) {