Skip to content

Commit

Permalink
WIP: TLS sockets
Browse files Browse the repository at this point in the history
Removal of std.net.socket.Type

The Type enum is removed in favour of dedicated factory methods, e.g.
Socket.stream instead of Socket.new(Type.STREAM). This removes the need
for importing two types (Socket and Type) when manually creating
sockets.

SocketAddress changes

This commit changes std.net.socket.SocketAddress such that it no
longer stores IP address as a String, instead storing them as a proper
IpAddress instance. In addition, SocketAddress.new is removed in favour
of creating an instance of the class directly, as all fields are (and
will remain) public such that a dedicated "new" method is redundant.

This fixes #329.

Changelog: added
  • Loading branch information
yorickpeterse committed Jul 18, 2024
1 parent 915b00c commit 4f74c68
Show file tree
Hide file tree
Showing 33 changed files with 2,661 additions and 703 deletions.
422 changes: 328 additions & 94 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion compiler/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,13 @@ pub(crate) fn link(
cmd.arg("-lm");
cmd.arg("-lpthread");
}
_ => {}
OperatingSystem::Mac => {
// This is needed for TLS support.
for name in ["Security", "CoreFoundation"] {
cmd.arg("-framework");
cmd.arg(name);
}
}
}

let mut static_linking = state.config.static_linking;
Expand Down
13 changes: 13 additions & 0 deletions rt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ unicode-segmentation = "^1.10"
backtrace = "^0.3"
rustix = { version = "^0.38", features = ["fs", "mm", "param", "process", "net", "std", "time", "event"], default-features = false }

# The dependencies needed for TLS support.
#
# We use ring instead of the default aws-lc-sys because:
#
# 1. aws-lc-sys requires cmake to be installed when building on FreeBSD (and
# potentially other platforms), as aws-lc-sys only provides generated
# bindings for a limited set of platforms
# 2. aws-lc-sys increases compile times quite a bit
# 3. We don't care about FIPS compliance at the time of writing
rustls = { version = "^0.23", features = ["ring", "tls12", "std"], default-features = false }
rustls-platform-verifier = "^0.3"
rustls-pemfile = "^2.1"

[dependencies.socket2]
version = "^0.5"
features = ["all"]
11 changes: 11 additions & 0 deletions rt/src/network_poller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ pub(crate) type NetworkPoller = sys::Poller;
pub(crate) enum Interest {
Read,
Write,
ReadWrite,
}

impl Interest {
pub(crate) fn new(read: bool, write: bool) -> Interest {
match (read, write) {
(true, true) => Interest::ReadWrite,
(false, true) => Interest::Write,
_ => Interest::Read,
}
}
}

/// A thread that polls a poller and reschedules processes.
Expand Down
1 change: 1 addition & 0 deletions rt/src/network_poller/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn flags_for(interest: Interest) -> EventFlags {
let flags = match interest {
Interest::Read => EventFlags::IN,
Interest::Write => EventFlags::OUT,
Interest::ReadWrite => EventFlags::IN | EventFlags::OUT,
};

flags | EventFlags::ET | EventFlags::ONESHOT
Expand Down
24 changes: 15 additions & 9 deletions rt/src/network_poller/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,24 @@ impl Poller {
source: impl AsFd,
interest: Interest,
) {
let fd = source.as_fd().as_raw_fd();
let (add, del) = match interest {
Interest::Read => (EventFilter::Read(fd), EventFilter::Write(fd)),
Interest::Write => (EventFilter::Write(fd), EventFilter::Read(fd)),
};
let id = process.identifier() as isize;
let fd = source.as_fd().as_raw_fd();
let flags =
EventFlags::CLEAR | EventFlags::ONESHOT | EventFlags::RECEIPT;
let events = [
Event::new(add, EventFlags::ADD | flags, id),
Event::new(del, EventFlags::DELETE, 0),
];
let events = match interest {
Interest::Read => [
Event::new(EventFilter::Read(fd), EventFlags::ADD | flags, id),
Event::new(EventFilter::Write(fd), EventFlags::DELETE, 0),
],
Interest::Write => [
Event::new(EventFilter::Write(fd), EventFlags::ADD | flags, id),
Event::new(EventFilter::Read(fd), EventFlags::DELETE, 0),
],
Interest::ReadWrite => [
Event::new(EventFilter::Write(fd), EventFlags::ADD | flags, id),
Event::new(EventFilter::Read(fd), EventFlags::ADD | flags, id),
],
};

self.apply(&events);
}
Expand Down
8 changes: 6 additions & 2 deletions rt/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ pub(crate) fn error_to_int(error: io::Error) -> i64 {
// raw_os_error() above returns a None.
Errno::TIMEDOUT.raw_os_error()
} else {
-1
match error.kind() {
io::ErrorKind::InvalidData => -2,
io::ErrorKind::UnexpectedEof => -3,
_ => -1,
}
};

code as i64
Expand Down Expand Up @@ -60,7 +64,7 @@ impl Result {
}

pub(crate) fn io_error(error: io::Error) -> Result {
Self::error({ error_to_int(error) } as _)
Self::error(error_to_int(error) as _)
}
}

Expand Down
6 changes: 6 additions & 0 deletions rt/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ pub unsafe extern "system" fn inko_runtime_new(
// does for us when compiling an executable.
signal_sched::block_all();

// Configure the TLS provider. This must be done once before we start the
// program.
rustls::crypto::ring::default_provider()
.install_default()
.expect("failed to set up the default TLS cryptography provider");

Box::into_raw(Box::new(Runtime::new(&*counts, args)))
}

Expand Down
20 changes: 0 additions & 20 deletions rt/src/runtime/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,6 @@ pub unsafe extern "system" fn inko_env_size(state: *const State) -> i64 {
(*state).environment.len() as _
}

#[no_mangle]
pub unsafe extern "system" fn inko_env_home_directory(
state: *const State,
) -> InkoResult {
let state = &*state;

// Rather than performing all sorts of magical incantations to get the home
// directory, we're just going to require that HOME is set.
//
// If the home is explicitly set to an empty string we still ignore it,
// because there's no scenario in which Some("") is useful.
state
.environment
.get("HOME")
.filter(|&path| !path.is_empty())
.cloned()
.map(|v| InkoResult::ok(InkoString::alloc(state.string_class, v) as _))
.unwrap_or_else(InkoResult::none)
}

#[no_mangle]
pub unsafe extern "system" fn inko_env_temp_directory(
state: *const State,
Expand Down
Loading

0 comments on commit 4f74c68

Please sign in to comment.