diff --git a/services/net/src/main.rs b/services/net/src/main.rs index 1504fc3a1..dfc519c45 100644 --- a/services/net/src/main.rs +++ b/services/net/src/main.rs @@ -223,6 +223,9 @@ fn xmain() -> ! { // is being accumulated. let mut tcp_tx_waiting: Vec> = Vec::new(); + // socket handles waiting for writes to flush on close + let mut tcp_tx_closing: Vec<(SocketHandle, xous::MessageSender)> = Vec::new(); + // When a client issues a Connect request, it will get placed here while the connection is // being established. let mut tcp_connect_waiting: Vec< @@ -650,12 +653,24 @@ fn xmain() -> ! { respond_with_error(msg, NetError::Invalid); continue; }; - iface.get_socket::(handle).close(); - iface.remove_socket(handle); - if let Some(response) = msg.body.memory_message_mut() { - response.buf.as_slice_mut::()[0] = 0; - } else if !msg.body.has_memory() && msg.body.is_blocking() { - xous::return_scalar(msg.sender, 0).ok(); + if !std_tcp_can_close(&tcp_tx_waiting, handle) { + log::info!("def"); + tcp_tx_closing.push((handle, msg.sender)); + } else { + let socket = iface.get_socket::(handle); + if socket.may_send() { + log::info!("imm"); + socket.close(); + iface.remove_socket(handle); + if let Some(response) = msg.body.memory_message_mut() { + response.buf.as_slice_mut::()[0] = 0; + } else if !msg.body.has_memory() && msg.body.is_blocking() { + xous::return_scalar(msg.sender, 0).ok(); + } + } else { + log::info!("def2"); + tcp_tx_closing.push((handle, msg.sender)); + } } } @@ -1425,6 +1440,26 @@ fn xmain() -> ! { } } + log::debug!("pump: tcp close"); + if tcp_tx_closing.len() > 0 { + let mut closed = Vec::::new(); + for (index, &(handle, sender)) in tcp_tx_closing.iter().enumerate() { + if std_tcp_can_close(&tcp_tx_waiting, handle) { + let socket = iface.get_socket::(handle); + if socket.may_send() { + socket.close(); + iface.remove_socket(handle); + log::info!("deferred close, socket is not active"); + xous::return_scalar(sender, 0).ok(); + closed.push(index); + } + } + } + for &index in closed.iter().rev() { + tcp_tx_closing.remove(index); + } + } + // this block contains the ICMP Rx handler. Tx is initiated by an incoming message to the Net crate. log::trace!("pump: icmp"); { diff --git a/services/net/src/std_tcpstream.rs b/services/net/src/std_tcpstream.rs index 7f44c552d..1a8969c3a 100644 --- a/services/net/src/std_tcpstream.rs +++ b/services/net/src/std_tcpstream.rs @@ -258,4 +258,15 @@ pub(crate) fn std_tcp_peek( body.offset = xous::MemoryAddress::new(1); body.buf.as_slice_mut::()[0] = 0; } +} + +pub(crate) fn std_tcp_can_close(tx_waiting: &Vec>, handle: SocketHandle) -> bool { + for maybe_socket in tx_waiting.iter() { + if let Some(socket) = maybe_socket { + if socket.handle.0 == handle.0 { + return false + } + } + } + true } \ No newline at end of file diff --git a/services/shellchat/src/cmds/net_cmd.rs b/services/shellchat/src/cmds/net_cmd.rs index 6370fcc7a..b3b2b18c0 100644 --- a/services/shellchat/src/cmds/net_cmd.rs +++ b/services/shellchat/src/cmds/net_cmd.rs @@ -180,6 +180,9 @@ impl<'a> ShellCmdApi<'a> for NetCmd { _ => {} } count += 1; + if count == 10 { + break; + } } }); }