nal: Fix read/write not pushing erroneous socket back to the stack
* Based on quartiq's minimq as of 933687c2e4
* In minimq applications, a socket is expected to be returned when `nal::TcpStack::open()` is called
* `MqttClient::read()`/`write()` takes away the TCP socket handle (wrapped as an `Option`) from its `RefCell`, and then calls `nal::TcpStack::read()`/`write()`; if NAL returns `nb::Error`, then the MQTT client will propagate and return the error, leaving `None` behind
* Afterwards, when `MqttClient::socket_is_connected()` gets called (e.g. while polling the interface), it will detect that the socket handle is `None`, and attempt to call `nal::TcpStack::open()`
* Since `open()` pops a socket from the array (`unused_handles`), when implementing this NAL the socket should have been pushed back to the stack, i.e. by `close()`; this prevents any future calls of `open()` from returning `NetworkError::NoSocket` due to emptiness of the array of socket handles
This commit is contained in:
parent
d9e50bbcb6
commit
99899e6657
22
src/nal.rs
22
src/nal.rs
|
@ -236,6 +236,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, socket: &mut Self::TcpSocket, buffer: &[u8]) -> nb::Result<usize, Self::Error> {
|
fn write(&self, socket: &mut Self::TcpSocket, buffer: &[u8]) -> nb::Result<usize, Self::Error> {
|
||||||
|
let mut write_error = false;
|
||||||
let mut non_queued_bytes = &buffer[..];
|
let mut non_queued_bytes = &buffer[..];
|
||||||
while non_queued_bytes.len() != 0 {
|
while non_queued_bytes.len() != 0 {
|
||||||
let result = {
|
let result = {
|
||||||
|
@ -254,9 +255,18 @@ where
|
||||||
// Process the unwritten bytes again, if any
|
// Process the unwritten bytes again, if any
|
||||||
non_queued_bytes = &non_queued_bytes[num_bytes..]
|
non_queued_bytes = &non_queued_bytes[num_bytes..]
|
||||||
}
|
}
|
||||||
Err(_) => return Err(nb::Error::Other(NetworkError::WriteFailure)),
|
Err(_) => {
|
||||||
|
write_error = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if write_error {
|
||||||
|
// Close the socket to push it back to the array, for
|
||||||
|
// re-opening the socket in the future
|
||||||
|
self.close(*socket)?;
|
||||||
|
return Err(nb::Error::Other(NetworkError::WriteFailure))
|
||||||
|
}
|
||||||
Ok(buffer.len())
|
Ok(buffer.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,14 +278,20 @@ where
|
||||||
// Enqueue received bytes into the TCP socket buffer
|
// Enqueue received bytes into the TCP socket buffer
|
||||||
self.update()?;
|
self.update()?;
|
||||||
self.poll()?;
|
self.poll()?;
|
||||||
|
{
|
||||||
let mut sockets = self.sockets.borrow_mut();
|
let mut sockets = self.sockets.borrow_mut();
|
||||||
let socket: &mut net::socket::TcpSocket = &mut *sockets.get(*socket);
|
let socket: &mut net::socket::TcpSocket = &mut *sockets.get(*socket);
|
||||||
let result = socket.recv_slice(buffer);
|
let result = socket.recv_slice(buffer);
|
||||||
match result {
|
match result {
|
||||||
Ok(num_bytes) => Ok(num_bytes),
|
Ok(num_bytes) => { return Ok(num_bytes) },
|
||||||
Err(_) => Err(nb::Error::Other(NetworkError::ReadFailure)),
|
Err(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Close the socket to push it back to the array, for
|
||||||
|
// re-opening the socket in the future
|
||||||
|
self.close(*socket)?;
|
||||||
|
Err(nb::Error::Other(NetworkError::ReadFailure))
|
||||||
|
}
|
||||||
|
|
||||||
fn close(&self, socket: Self::TcpSocket) -> Result<(), Self::Error> {
|
fn close(&self, socket: Self::TcpSocket) -> Result<(), Self::Error> {
|
||||||
let mut sockets = self.sockets.borrow_mut();
|
let mut sockets = self.sockets.borrow_mut();
|
||||||
|
|
Loading…
Reference in New Issue