Fix TCP listening endpoint, fpath formatting, port release while listening:
Now TCPListenEndpoint is stored in the SchemeFile because the TcpSocket::endpoint() only store endpoints for connected sockets, not listening ones
This commit is contained in:
+143
-72
@@ -1,24 +1,27 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, SubAssign};
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
|
||||
use syscall;
|
||||
use syscall::{Error as SyscallError, EventFlags as SyscallEventFlags, Packet as SyscallPacket, Result as SyscallResult, SchemeBlockMut};
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::flag::{EVENT_READ, EVENT_WRITE};
|
||||
use syscall::{
|
||||
Error as SyscallError, EventFlags as SyscallEventFlags, Packet as SyscallPacket,
|
||||
Result as SyscallResult, SchemeBlockMut,
|
||||
};
|
||||
|
||||
use super::Interface;
|
||||
use crate::scheme::smoltcp::iface::SocketHandle;
|
||||
use redox_netstack::error::{Error, Result};
|
||||
use smoltcp::socket::AnySocket;
|
||||
use crate::scheme::smoltcp::iface::SocketHandle;
|
||||
use super::Interface;
|
||||
|
||||
use super::{post_fevent, SocketSet};
|
||||
|
||||
@@ -73,7 +76,8 @@ enum Setting<SettingT: Copy> {
|
||||
Ttl,
|
||||
ReadTimeout,
|
||||
WriteTimeout,
|
||||
#[allow(dead_code)] Other(SettingT),
|
||||
#[allow(dead_code)]
|
||||
Other(SettingT),
|
||||
}
|
||||
|
||||
pub struct SettingFile<SettingT: Copy> {
|
||||
@@ -101,7 +105,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn events(&mut self, socket_set: &mut SocketSet) -> usize where SocketT: AnySocket<'static> {
|
||||
pub fn events(&mut self, socket_set: &mut SocketSet) -> usize
|
||||
where
|
||||
SocketT: AnySocket<'static>,
|
||||
{
|
||||
let mut revents = 0;
|
||||
if let &mut SchemeFile::Socket(SocketFile {
|
||||
socket_handle,
|
||||
@@ -113,7 +120,9 @@ where
|
||||
{
|
||||
let socket = socket_set.get::<SocketT>(socket_handle);
|
||||
|
||||
if events & syscall::EVENT_READ.bits() == syscall::EVENT_READ.bits() && (socket.can_recv() || !socket.may_recv()) {
|
||||
if events & syscall::EVENT_READ.bits() == syscall::EVENT_READ.bits()
|
||||
&& (socket.can_recv() || !socket.may_recv())
|
||||
{
|
||||
if !*read_notified {
|
||||
*read_notified = true;
|
||||
revents |= EVENT_READ.bits();
|
||||
@@ -122,7 +131,9 @@ where
|
||||
*read_notified = false;
|
||||
}
|
||||
|
||||
if events & syscall::EVENT_WRITE.bits() == syscall::EVENT_WRITE.bits() && socket.can_send() {
|
||||
if events & syscall::EVENT_WRITE.bits() == syscall::EVENT_WRITE.bits()
|
||||
&& socket.can_send()
|
||||
{
|
||||
if !*write_notified {
|
||||
*write_notified = true;
|
||||
revents |= EVENT_WRITE.bits();
|
||||
@@ -165,22 +176,42 @@ where
|
||||
fn hop_limit(&self) -> u8;
|
||||
fn set_hop_limit(&mut self, hop_limit: u8);
|
||||
|
||||
fn get_setting(file: &SocketFile<Self::DataT>, setting: Self::SettingT, buf: &mut [u8]) -> SyscallResult<usize>;
|
||||
fn set_setting(file: &mut SocketFile<Self::DataT>, setting: Self::SettingT, buf: &[u8]) -> SyscallResult<usize>;
|
||||
fn get_setting(
|
||||
file: &SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<usize>;
|
||||
fn set_setting(
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<usize>;
|
||||
|
||||
fn new_socket(
|
||||
sockets: &mut SocketSet,
|
||||
path: &str,
|
||||
uid: u32,
|
||||
data: &mut Self::SchemeDataT,
|
||||
iface: &Interface
|
||||
iface: &Interface,
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)>;
|
||||
|
||||
fn close_file(&self, file: &SchemeFile<Self>, data: &mut Self::SchemeDataT) -> SyscallResult<()>;
|
||||
fn close_file(
|
||||
&self,
|
||||
file: &SchemeFile<Self>,
|
||||
data: &mut Self::SchemeDataT,
|
||||
) -> SyscallResult<()>;
|
||||
|
||||
fn write_buf(&mut self, file: &mut SocketFile<Self::DataT>, buf: &[u8]) -> SyscallResult<Option<usize>>;
|
||||
fn write_buf(
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>>;
|
||||
|
||||
fn read_buf(&mut self, file: &mut SocketFile<Self::DataT>, buf: &mut [u8]) -> SyscallResult<Option<usize>>;
|
||||
fn read_buf(
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>>;
|
||||
|
||||
fn fpath(&self, file: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize>;
|
||||
|
||||
@@ -212,7 +243,11 @@ impl<SocketT> SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
pub fn new(iface: Interface, socket_set: Rc<RefCell<SocketSet>>, scheme_file: File) -> SocketScheme<SocketT> {
|
||||
pub fn new(
|
||||
iface: Interface,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
scheme_file: File,
|
||||
) -> SocketScheme<SocketT> {
|
||||
SocketScheme {
|
||||
next_fd: 1,
|
||||
nulls: BTreeMap::new(),
|
||||
@@ -234,12 +269,14 @@ where
|
||||
Ok(0) => {
|
||||
//TODO: Cleanup must occur
|
||||
break Some(());
|
||||
},
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(err) => if err.kind() == ErrorKind::WouldBlock {
|
||||
break None;
|
||||
} else {
|
||||
return Err(Error::from(err));
|
||||
Err(err) => {
|
||||
if err.kind() == ErrorKind::WouldBlock {
|
||||
break None;
|
||||
} else {
|
||||
return Err(Error::from(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(a) = self.handle(&mut packet) {
|
||||
@@ -252,7 +289,7 @@ where
|
||||
until: timeout,
|
||||
packet,
|
||||
});
|
||||
},
|
||||
}
|
||||
Err(err) => {
|
||||
packet.a = (-err.errno) as usize;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
@@ -301,7 +338,7 @@ where
|
||||
self.wait_queue.remove(i);
|
||||
packet.a = (-syscall::ETIMEDOUT) as usize;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
i += 1;
|
||||
}
|
||||
@@ -315,15 +352,13 @@ where
|
||||
fn handle_block(&mut self, packet: &mut SyscallPacket) -> SyscallResult<Option<TimeSpec>> {
|
||||
let fd = packet.b;
|
||||
let (read_timeout, write_timeout) = {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
if let SchemeFile::Socket(ref scheme_file) = *file {
|
||||
Ok((
|
||||
scheme_file.read_timeout,
|
||||
scheme_file.write_timeout,
|
||||
))
|
||||
Ok((scheme_file.read_timeout, scheme_file.write_timeout))
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
@@ -350,7 +385,8 @@ where
|
||||
setting: Setting<SocketT::SettingT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
let file = match *file {
|
||||
@@ -362,14 +398,16 @@ where
|
||||
|
||||
match setting {
|
||||
Setting::Other(setting) => SocketT::get_setting(file, setting, buf),
|
||||
Setting::Ttl => if let Some(hop_limit) = buf.get_mut(0) {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get::<SocketT>(file.socket_handle);
|
||||
*hop_limit = socket.hop_limit();
|
||||
Ok(1)
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EIO))
|
||||
},
|
||||
Setting::Ttl => {
|
||||
if let Some(hop_limit) = buf.get_mut(0) {
|
||||
let socket_set = self.socket_set.borrow();
|
||||
let socket = socket_set.get::<SocketT>(file.socket_handle);
|
||||
*hop_limit = socket.hop_limit();
|
||||
Ok(1)
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EIO))
|
||||
}
|
||||
}
|
||||
Setting::ReadTimeout | Setting::WriteTimeout => {
|
||||
let timespec = match (setting, file.read_timeout, file.write_timeout) {
|
||||
(Setting::ReadTimeout, Some(read_timeout), _) => read_timeout,
|
||||
@@ -397,7 +435,8 @@ where
|
||||
setting: Setting<SocketT::SettingT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
let file = match *file {
|
||||
@@ -430,14 +469,16 @@ where
|
||||
};
|
||||
Ok(count)
|
||||
}
|
||||
Setting::Ttl => if let Some(hop_limit) = buf.get(0) {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
|
||||
socket.set_hop_limit(*hop_limit);
|
||||
Ok(1)
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EIO))
|
||||
},
|
||||
Setting::Ttl => {
|
||||
if let Some(hop_limit) = buf.get(0) {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
|
||||
socket.set_hop_limit(*hop_limit);
|
||||
Ok(1)
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EIO))
|
||||
}
|
||||
}
|
||||
Setting::Other(setting) => SocketT::set_setting(file, setting, buf),
|
||||
}
|
||||
}
|
||||
@@ -447,7 +488,13 @@ impl<SocketT> syscall::SchemeBlockMut for SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
fn open(&mut self, path: &str, flags: usize, uid: u32, _gid: u32) -> SyscallResult<Option<usize>> {
|
||||
fn open(
|
||||
&mut self,
|
||||
path: &str,
|
||||
flags: usize,
|
||||
uid: u32,
|
||||
_gid: u32,
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
if path.is_empty() {
|
||||
let null = NullFile {
|
||||
flags,
|
||||
@@ -467,7 +514,7 @@ where
|
||||
path,
|
||||
uid,
|
||||
&mut self.scheme_data,
|
||||
&self.iface
|
||||
&self.iface,
|
||||
)?;
|
||||
|
||||
let file = SchemeFile::Socket(SocketFile {
|
||||
@@ -497,7 +544,8 @@ where
|
||||
}
|
||||
|
||||
let socket_handle = {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
file.socket_handle()
|
||||
@@ -520,20 +568,22 @@ where
|
||||
Entry::Vacant(_) => {
|
||||
warn!("Closing a socket_handle with no ref");
|
||||
true
|
||||
},
|
||||
Entry::Occupied(mut e) => if *e.get() == 0 {
|
||||
warn!("Closing a socket_handle with no ref");
|
||||
e.remove();
|
||||
true
|
||||
} else {
|
||||
*e.get_mut() -= 1;
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
if *e.get() == 0 {
|
||||
warn!("Closing a socket_handle with no ref");
|
||||
e.remove();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
*e.get_mut() -= 1;
|
||||
if *e.get() == 0 {
|
||||
e.remove();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if remove {
|
||||
@@ -544,7 +594,8 @@ where
|
||||
|
||||
fn write(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<Option<usize>> {
|
||||
let (fd, setting) = {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
@@ -564,7 +615,8 @@ where
|
||||
|
||||
fn read(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<Option<usize>> {
|
||||
let (fd, setting) = {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
match *file {
|
||||
@@ -584,7 +636,8 @@ where
|
||||
fn dup(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<Option<usize>> {
|
||||
let path = str::from_utf8(buf).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
|
||||
|
||||
if let Some((flags, uid, gid)) = self.nulls
|
||||
if let Some((flags, uid, gid)) = self
|
||||
.nulls
|
||||
.get(&fd)
|
||||
.map(|null| (null.flags, null.uid, null.gid))
|
||||
{
|
||||
@@ -592,7 +645,8 @@ where
|
||||
}
|
||||
|
||||
let new_file = {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
@@ -636,14 +690,23 @@ where
|
||||
|
||||
if let Some((socket_handle, data)) = update_with {
|
||||
if let SchemeFile::Socket(ref mut file) = *file {
|
||||
// We replace the socket_handle pointed by file so update the ref_counts
|
||||
// accordingly
|
||||
self.ref_counts
|
||||
.entry(file.socket_handle)
|
||||
.and_modify(|e| *e = e.saturating_sub(1))
|
||||
.or_insert(0);
|
||||
|
||||
*self.ref_counts.entry(socket_handle).or_insert(0) += 1;
|
||||
|
||||
file.socket_handle = socket_handle;
|
||||
file.data = data;
|
||||
} else {
|
||||
*self.ref_counts.entry(file.socket_handle()).or_insert(0) += 1;
|
||||
}
|
||||
} else {
|
||||
*self.ref_counts.entry(file.socket_handle()).or_insert(0) += 1;
|
||||
}
|
||||
*self
|
||||
.ref_counts
|
||||
.entry(new_handle.socket_handle())
|
||||
.or_insert(0) += 1;
|
||||
new_handle
|
||||
};
|
||||
|
||||
@@ -654,8 +717,13 @@ where
|
||||
Ok(Some(id))
|
||||
}
|
||||
|
||||
fn fevent(&mut self, fd: usize, events: SyscallEventFlags) -> SyscallResult<Option<SyscallEventFlags>> {
|
||||
let file = self.files
|
||||
fn fevent(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
events: SyscallEventFlags,
|
||||
) -> SyscallResult<Option<SyscallEventFlags>> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
match *file {
|
||||
@@ -673,7 +741,8 @@ where
|
||||
|
||||
fn fsync(&mut self, fd: usize) -> SyscallResult<Option<usize>> {
|
||||
{
|
||||
let _file = self.files
|
||||
let _file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
}
|
||||
@@ -683,11 +752,12 @@ where
|
||||
}
|
||||
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<Option<usize>> {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket_set = self.socket_set.borrow();
|
||||
let socket = socket_set.get::<SocketT>(file.socket_handle());
|
||||
|
||||
socket.fpath(file, buf).map(Some)
|
||||
@@ -704,7 +774,8 @@ where
|
||||
_ => Err(SyscallError::new(syscall::EINVAL)),
|
||||
}
|
||||
} else {
|
||||
let file = self.files
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
|
||||
+61
-20
@@ -1,19 +1,20 @@
|
||||
use smoltcp::iface::SocketHandle;
|
||||
use smoltcp::socket::tcp::{Socket as TcpSocket, SocketBuffer as TcpSocketBuffer};
|
||||
use smoltcp::wire::IpEndpoint;
|
||||
use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
|
||||
use std::fmt::Write;
|
||||
use std::str;
|
||||
use syscall;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
|
||||
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{parse_endpoint, SocketSet, Interface};
|
||||
use super::{parse_endpoint, Interface, SocketSet};
|
||||
use crate::port_set::PortSet;
|
||||
|
||||
pub type TcpScheme = SocketScheme<TcpSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
type SchemeDataT = PortSet;
|
||||
type DataT = ();
|
||||
type DataT = Option<IpListenEndpoint>;
|
||||
type SettingT = ();
|
||||
|
||||
fn new_scheme_data() -> Self::SchemeDataT {
|
||||
@@ -61,7 +62,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
path: &str,
|
||||
uid: u32,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
iface: &Interface
|
||||
iface: &Interface,
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)> {
|
||||
trace!("TCP open {}", path);
|
||||
let mut parts = path.split('/');
|
||||
@@ -90,19 +91,25 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
|
||||
let tcp_socket = socket_set.get_mut::<TcpSocket>(socket_handle);
|
||||
|
||||
if remote_endpoint.is_specified() {
|
||||
let listen_enpoint = if remote_endpoint.is_specified() {
|
||||
trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint);
|
||||
tcp_socket
|
||||
.connect(iface.borrow_mut().context(), IpEndpoint::new(remote_endpoint.addr.unwrap(), remote_endpoint.port), local_endpoint)
|
||||
.connect(
|
||||
iface.borrow_mut().context(),
|
||||
IpEndpoint::new(remote_endpoint.addr.unwrap(), remote_endpoint.port),
|
||||
local_endpoint,
|
||||
)
|
||||
.expect("Can't connect tcp socket ");
|
||||
None
|
||||
} else {
|
||||
trace!("Listening tcp {}", local_endpoint);
|
||||
tcp_socket
|
||||
.listen(local_endpoint)
|
||||
.expect("Can't listen on local endpoint");
|
||||
}
|
||||
Some(local_endpoint)
|
||||
};
|
||||
|
||||
Ok((socket_handle, ()))
|
||||
Ok((socket_handle, listen_enpoint))
|
||||
}
|
||||
|
||||
fn close_file(
|
||||
@@ -110,8 +117,12 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
file: &SchemeFile<Self>,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> SyscallResult<()> {
|
||||
if let SchemeFile::Socket(_) = *file {
|
||||
if let SchemeFile::Socket(SocketFile { data, .. }) = *file {
|
||||
if let Some(endpoint) = self.local_endpoint() {
|
||||
// Socket was connected on some port
|
||||
port_set.release_port(endpoint.port);
|
||||
} else if let Some(endpoint) = data {
|
||||
// Socket was listening on some port
|
||||
port_set.release_port(endpoint.port);
|
||||
}
|
||||
}
|
||||
@@ -170,7 +181,13 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
let file = match path {
|
||||
"listen" => {
|
||||
if let SchemeFile::Socket(ref tcp_handle) = *file {
|
||||
let Some(listen_enpoint) = tcp_handle.data else {
|
||||
// This socket is not listening so we can't accept a connection
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
};
|
||||
|
||||
if !is_active {
|
||||
// Socket listening but no connection received
|
||||
if tcp_handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
return Err(SyscallError::new(syscall::EAGAIN));
|
||||
} else {
|
||||
@@ -178,8 +195,11 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
}
|
||||
}
|
||||
trace!("TCP creating new listening socket");
|
||||
let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(()));
|
||||
// We pass None as data because this new handle is to the active connection so
|
||||
// not a listening socket
|
||||
let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(None));
|
||||
|
||||
// Creating a socket to continue listening
|
||||
let rx_packets = vec![0; 0xffff];
|
||||
let tx_packets = vec![0; 0xffff];
|
||||
let rx_buffer = TcpSocketBuffer::new(rx_packets);
|
||||
@@ -195,12 +215,16 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
)
|
||||
.expect("Can't listen on local endpoint");
|
||||
}
|
||||
// We got a new connection to the socket so acquire the port
|
||||
port_set.acquire_port(
|
||||
local_endpoint
|
||||
.expect("Socket was active so local endpoint must be set")
|
||||
.port,
|
||||
);
|
||||
return Ok(Some((new_handle, Some((new_socket_handle, ())))));
|
||||
return Ok(Some((
|
||||
new_handle,
|
||||
Some((new_socket_handle, Some(listen_enpoint))),
|
||||
)));
|
||||
} else {
|
||||
return Err(SyscallError::new(syscall::EBADF));
|
||||
}
|
||||
@@ -208,9 +232,9 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
_ => {
|
||||
trace!("TCP dup unknown {}", path);
|
||||
if let SchemeFile::Socket(ref tcp_handle) = *file {
|
||||
SchemeFile::Socket(tcp_handle.clone_with_data(()))
|
||||
SchemeFile::Socket(tcp_handle.clone_with_data(tcp_handle.data))
|
||||
} else {
|
||||
SchemeFile::Socket(SocketFile::new_with_data(socket_handle, ()))
|
||||
SchemeFile::Socket(SocketFile::new_with_data(socket_handle, None))
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -224,13 +248,30 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
Ok(Some((file, None)))
|
||||
}
|
||||
|
||||
fn fpath(&self, _: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let path = match (self.remote_endpoint(), self.local_endpoint()) {
|
||||
(Some(remote_endpoint), Some(local_endpoint)) => format!("tcp:{}/{}", remote_endpoint, local_endpoint),
|
||||
(Some(remote_endpoint), None) => format!("tcp:{}/none", remote_endpoint),
|
||||
(None, Some(local_endpoint)) => format!("tcp:none/{}", local_endpoint),
|
||||
(None, None) => "tcp:none/none".into(),
|
||||
};
|
||||
fn fpath(&self, file: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let unspecified = "0.0.0.0:0";
|
||||
let mut path = String::from("tcp:");
|
||||
match self.remote_endpoint() {
|
||||
Some(endpoint) => write!(&mut path, "{}", endpoint).unwrap(),
|
||||
None => path.push_str(unspecified),
|
||||
}
|
||||
path.push('/');
|
||||
match (self.local_endpoint(), file) {
|
||||
(Some(endpoint), _) => write!(&mut path, "{}", endpoint).unwrap(),
|
||||
(
|
||||
None,
|
||||
SchemeFile::Socket(SocketFile {
|
||||
data: Some(endpoint),
|
||||
..
|
||||
}),
|
||||
) => if endpoint.is_specified() {
|
||||
write!(&mut path, "{}", endpoint).unwrap()
|
||||
} else {
|
||||
write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap()
|
||||
},
|
||||
_ => path.push_str(unspecified),
|
||||
}
|
||||
trace!("fpath: {}", path);
|
||||
let path = path.as_bytes();
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
Reference in New Issue
Block a user