Skip to content

Commit c4f10a8

Browse files
sockets::unix: partial implement connect, listen
Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent 780dd03 commit c4f10a8

File tree

8 files changed

+172
-61
lines changed

8 files changed

+172
-61
lines changed

patches/mlibc/mlibc.patch

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
From a649d90c5073ef1f8a9eadb4773fe5f832a3e87c Mon Sep 17 00:00:00 2001
1+
From 989da4c4aa01ce3ad7a52986f0492a6b565add28 Mon Sep 17 00:00:00 2001
22
From: Andy-Python-Programmer <[email protected]>
33
Date: Thu, 10 Feb 2022 19:12:25 +1100
44
Subject: [PATCH] yes
@@ -10,9 +10,9 @@ Signed-off-by: Andy-Python-Programmer <[email protected]>
1010
sysdeps/aero/generic/aero.cpp | 12 +++-
1111
sysdeps/aero/generic/filesystem.cpp | 97 ++++++++++++++++++++++++++---
1212
sysdeps/aero/generic/signals.cpp | 8 ++-
13-
sysdeps/aero/generic/sockets.cpp | 48 ++++++++++++++
13+
sysdeps/aero/generic/sockets.cpp | 59 ++++++++++++++++++
1414
sysdeps/aero/include/aero/syscall.h | 11 ++++
15-
7 files changed, 168 insertions(+), 13 deletions(-)
15+
7 files changed, 179 insertions(+), 13 deletions(-)
1616

1717
diff --git a/.gitignore b/.gitignore
1818
index dbb35e8b..20c8d4c3 100644
@@ -228,10 +228,10 @@ index 3527370c..a6f69fff 100644
228228
} // namespace mlibc
229229
\ No newline at end of file
230230
diff --git a/sysdeps/aero/generic/sockets.cpp b/sysdeps/aero/generic/sockets.cpp
231-
index e69de29b..4e6bd608 100644
231+
index e69de29b..b6b18fe7 100644
232232
--- a/sysdeps/aero/generic/sockets.cpp
233233
+++ b/sysdeps/aero/generic/sockets.cpp
234-
@@ -0,0 +1,48 @@
234+
@@ -0,0 +1,59 @@
235235
+#include <mlibc/all-sysdeps.hpp>
236236
+#include <mlibc/thread-entry.hpp>
237237
+
@@ -279,6 +279,17 @@ index e69de29b..4e6bd608 100644
279279
+
280280
+ return 0;
281281
+}
282+
+
283+
+int sys_accept(int fd, int *newfd) {
284+
+ auto result = syscall(SYS_ACCEPT, fd);
285+
+
286+
+ if (result < 0) {
287+
+ return -result;
288+
+ }
289+
+
290+
+ *newfd = result;
291+
+ return 0;
292+
+}
282293
+} // namespace mlibc
283294
diff --git a/sysdeps/aero/include/aero/syscall.h b/sysdeps/aero/include/aero/syscall.h
284295
index 07b1b51b..6487cd85 100644

src/aero_kernel/src/fs/inode.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ pub trait INodeInterface: Send + Sync + Downcastable {
157157
fn listen(&self, _backlog: usize) -> Result<()> {
158158
Err(FileSystemError::NotSocket)
159159
}
160+
161+
/// Returns the inner UNIX socket inode if bound to one.
162+
fn as_unix_socket(&self) -> Result<Arc<dyn INodeInterface>> {
163+
Err(FileSystemError::NotSocket)
164+
}
160165
}
161166

162167
/// Structure representing the curcial, characteristics of an inode. The metadata

src/aero_kernel/src/fs/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ pub enum FileSystemError {
133133
TooSmall,
134134
InvalidPath,
135135
NotSocket,
136+
ConnectionRefused,
136137
}
137138

138139
impl From<FileSystemError> for AeroSyscallError {
@@ -148,6 +149,7 @@ impl From<FileSystemError> for AeroSyscallError {
148149
FileSystemError::TooSmall => Self::E2BIG,
149150
FileSystemError::InvalidPath => Self::EINVAL,
150151
FileSystemError::NotSocket => Self::ENOTSOCK,
152+
FileSystemError::ConnectionRefused => Self::ECONNREFUSED,
151153
}
152154
}
153155
}

src/aero_kernel/src/fs/ramfs.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,15 @@ impl INodeInterface for LockedRamINode {
382382
))
383383
}
384384

385+
fn as_unix_socket(&self) -> Result<Arc<dyn INodeInterface>> {
386+
let this = self.0.read();
387+
388+
match &this.contents {
389+
FileContents::Socket(socket) => Ok(socket.clone()),
390+
_ => Err(FileSystemError::NotSocket),
391+
}
392+
}
393+
385394
#[inline]
386395
fn weak_filesystem(&self) -> Option<Weak<dyn FileSystem>> {
387396
Some(self.0.read().filesystem.clone())

src/aero_kernel/src/socket/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ impl<'a> SocketAddr<'a> {
3636
_ => None,
3737
}
3838
}
39+
40+
/// Converts the socket address into a unix socket address. Returns [`None`] if
41+
/// the address is not a unix socket address.
42+
pub fn as_unix(&self) -> Option<&'a SocketAddrUnix> {
43+
match self {
44+
SocketAddr::Unix(address) => Some(address),
45+
_ => None,
46+
}
47+
}
3948
}
4049

4150
pub mod unix;

src/aero_kernel/src/socket/unix.rs

Lines changed: 102 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,84 +17,138 @@
1717
* along with Aero. If not, see <https://www.gnu.org/licenses/>.
1818
*/
1919

20-
use alloc::{
21-
string::String,
22-
sync::{Arc, Weak},
23-
};
20+
use aero_syscall::SocketAddrUnix;
21+
22+
use alloc::string::String;
23+
use alloc::sync::{Arc, Weak};
24+
use alloc::vec::Vec;
25+
use spin::RwLock;
2426

2527
use crate::fs;
26-
use crate::fs::{
27-
inode::{DirEntry, FileType, INodeInterface, Metadata},
28-
FileSystemError, Path, Result,
29-
};
28+
use crate::fs::inode::{DirEntry, FileType, INodeInterface, Metadata};
29+
use crate::fs::{FileSystemError, Path, Result};
30+
use crate::utils::downcast;
3031

3132
use super::SocketAddr;
3233

34+
fn path_from_unix_sock<'sock>(address: &'sock SocketAddrUnix) -> Result<&'sock Path> {
35+
// The abstract namespace socket allows the creation of a socket
36+
// connection which does not require a path to be created.
37+
let abstrat_namespaced = address.path[0] == 0;
38+
assert!(!abstrat_namespaced);
39+
40+
let path_len = address
41+
.path
42+
.iter()
43+
.position(|&c| c == 0)
44+
.unwrap_or(address.path.len());
45+
46+
let path_str = core::str::from_utf8(&address.path[..path_len])
47+
.ok()
48+
.ok_or(FileSystemError::InvalidPath)?;
49+
50+
Ok(Path::new(path_str))
51+
}
52+
53+
#[derive(Default)]
54+
struct UnixSocketBacklog {
55+
backlog: Option<Vec<Arc<UnixSocket>>>,
56+
}
57+
58+
impl UnixSocketBacklog {
59+
pub fn push(&mut self, socket: Arc<UnixSocket>) {
60+
if let Some(ref mut backlog) = self.backlog {
61+
assert!(backlog.len() != backlog.capacity());
62+
backlog.push(socket);
63+
}
64+
}
65+
66+
pub fn update_capacity(&mut self, capacity: usize) {
67+
assert!(
68+
self.backlog.is_none(),
69+
"UnixSocket::listen() has already been called"
70+
);
71+
72+
self.backlog = Some(Vec::with_capacity(capacity));
73+
}
74+
}
75+
76+
#[derive(Default)]
77+
struct UnixSocketInner {
78+
backlog: UnixSocketBacklog,
79+
listening: bool,
80+
}
81+
3382
pub struct UnixSocket {
83+
inner: RwLock<UnixSocketInner>,
3484
weak: Weak<UnixSocket>,
3585
}
3686

3787
impl UnixSocket {
3888
pub fn new() -> Arc<UnixSocket> {
39-
Arc::new_cyclic(|weak| UnixSocket { weak: weak.clone() })
89+
Arc::new_cyclic(|weak| UnixSocket {
90+
inner: RwLock::new(UnixSocketInner::default()),
91+
weak: weak.clone(),
92+
})
93+
}
94+
95+
pub fn sref(&self) -> Arc<UnixSocket> {
96+
self.weak.upgrade().unwrap()
4097
}
4198
}
4299

43100
impl INodeInterface for UnixSocket {
44101
fn metadata(&self) -> Result<Metadata> {
45102
Ok(Metadata {
46-
id: 0, // FIXME: What should this be?
103+
id: 0,
47104
file_type: FileType::Socket,
48105
size: 0,
49106
children_len: 0,
50107
})
51108
}
52109

53110
fn bind(&self, address: SocketAddr, _length: usize) -> Result<()> {
54-
if let SocketAddr::Unix(address) = address {
55-
// The abstract namespace socket allows the creation of a socket
56-
// connection which does not require a path to be created.
57-
let abstrat_namespaced = address.path[0] == 0;
58-
assert!(!abstrat_namespaced);
59-
60-
let path_len = address
61-
.path
62-
.iter()
63-
.position(|&c| c == 0)
64-
.unwrap_or(address.path.len());
65-
66-
let path_str = core::str::from_utf8(&address.path[..path_len])
67-
.ok()
68-
.ok_or(FileSystemError::InvalidPath)?;
69-
70-
let path = Path::new(path_str);
71-
72-
// Ensure that the path is not already in use.
73-
if fs::lookup_path(path).is_ok() {
74-
return Err(FileSystemError::EntryExists);
75-
}
76-
77-
let (parent, name) = path.parent_and_basename();
78-
79-
DirEntry::from_socket_inode(
80-
fs::lookup_path(parent)?,
81-
String::from(name),
82-
self.weak.upgrade().unwrap(),
83-
)?;
84-
85-
Ok(())
86-
} else {
87-
Err(FileSystemError::NotSupported)
111+
let address = address.as_unix().ok_or(FileSystemError::NotSupported)?;
112+
let path = path_from_unix_sock(address)?;
113+
114+
// ensure that the provided path is not already in use.
115+
if fs::lookup_path(path).is_ok() {
116+
return Err(FileSystemError::EntryExists);
88117
}
118+
119+
let (parent, name) = path.parent_and_basename();
120+
121+
// create the socket inode.
122+
DirEntry::from_socket_inode(fs::lookup_path(parent)?, String::from(name), self.sref())?;
123+
124+
Ok(())
89125
}
90126

91-
fn connect(&self, _address: SocketAddr, _length: usize) -> Result<()> {
92-
log::error!("UnixSocket::connect() is not implemented");
127+
fn connect(&self, address: SocketAddr, _length: usize) -> Result<()> {
128+
let address = address.as_unix().ok_or(FileSystemError::NotSupported)?;
129+
let path = path_from_unix_sock(address)?;
130+
let socket = fs::lookup_path(path)?;
131+
132+
let target = downcast::<dyn INodeInterface, UnixSocket>(&socket.inode().as_unix_socket()?)
133+
.ok_or(FileSystemError::NotSocket)?; // NOTE: the provided socket was not a unix socket.
134+
135+
let mut target = target.inner.write();
136+
137+
// ensure that the target socket is listening for new connections.
138+
if !target.listening {
139+
return Err(FileSystemError::ConnectionRefused);
140+
}
141+
142+
target.backlog.push(self.sref());
93143
Ok(())
94144
}
95145

96-
fn listen(&self, _backlog: usize) -> Result<()> {
97-
log::error!("UnixSocket::listen() not implemented");
146+
fn listen(&self, backlog: usize) -> Result<()> {
147+
let mut this = self.inner.write();
148+
149+
this.backlog.update_capacity(backlog);
150+
this.listening = true;
151+
98152
Ok(())
99153
}
100154
}

src/aero_kernel/src/syscall/net.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ pub fn socket(
5353
socket_type: usize,
5454
protocol: usize,
5555
) -> Result<usize, AeroSyscallError> {
56-
let socket = match (domain as u32, socket_type, protocol) {
57-
(AF_UNIX, SOCK_STREAM, 0) => UnixSocket::new(),
58-
(_, _, _) => {
56+
let socket = match domain as u32 {
57+
AF_UNIX => UnixSocket::new(),
58+
_ => {
5959
log::warn!(
6060
"unsupported socket type: domain={domain}, socket_type={socket_type}, protocol={protocol}"
6161
);
@@ -64,11 +64,11 @@ pub fn socket(
6464
}
6565
};
6666

67+
let sockfd_flags = SocketFlags::from_bits_truncate(socket_type).into();
68+
6769
let entry = DirEntry::from_inode(socket);
6870
let current_task = scheduler::get_scheduler().current_task();
69-
let fd = current_task
70-
.file_table
71-
.open_file(entry, OpenFlags::empty())?;
71+
let fd = current_task.file_table.open_file(entry, sockfd_flags)?;
7272

7373
Ok(fd)
7474
}

src/aero_syscall/src/lib.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,8 +680,29 @@ pub const SOCK_DGRAM: usize = 1;
680680
pub const SOCK_RAW: usize = 2;
681681
pub const SOCK_SEQPACKET: usize = 3;
682682
pub const SOCK_STREAM: usize = 4;
683-
pub const SOCK_NONBLOCK: usize = 0x10000;
684-
pub const SOCK_CLOEXEC: usize = 0x20000;
683+
684+
bitflags::bitflags! {
685+
pub struct SocketFlags: usize {
686+
const NONBLOCK = 0x10000;
687+
const CLOEXEC = 0x20000;
688+
}
689+
}
690+
691+
impl From<SocketFlags> for OpenFlags {
692+
fn from(flags: SocketFlags) -> Self {
693+
let mut result = OpenFlags::empty();
694+
695+
if flags.contains(SocketFlags::NONBLOCK) {
696+
result.insert(OpenFlags::O_NONBLOCK);
697+
}
698+
699+
if flags.contains(SocketFlags::CLOEXEC) {
700+
result.insert(OpenFlags::O_CLOEXEC);
701+
}
702+
703+
result
704+
}
705+
}
685706

686707
pub const PF_INET: u32 = 1;
687708
pub const PF_INET6: u32 = 2;

0 commit comments

Comments
 (0)