Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 66 additions & 4 deletions include/NetAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,49 @@ struct NetworkAddress
} kind;
};

/**
* Enumeration that defines futex types. Each value corresponds
* to an index in the socket's futex array.
*/
enum SocketEventType : uint8_t
{
/// Triggered when a new TCP connection
/// is accepted on a listening socket.
/// The value of the futex corresponding to
/// SocketAcceptEvent, means the number of
/// pending connections.
SocketAcceptEvent = 0,
/// Triggered when a socket has space available
/// for sending bytes.
/// The value of the futex corresponding to
/// SocketTCPSendEvent, means the number of free
/// bytes available in the txStream buffer of
/// the socket.
/// After multiwaiter_wait() returns, do not wait for this value to reach
/// the full size of the pending send. Call network_socket_send() again
/// whenever any space is available; it may send only part of the requested
/// data.
SocketTCPSendEvent = 1,
/// The connection state of an outgoing TCP socket.
/// Zero means connecting, one means connected. The futex
/// never changes from 1 back to 0. Since the connect futex is a state, not
/// a consumable event. Resetting it to zero would incorrectly mean that
/// this socket it not connected.
SocketTCPConnectEvent = 2,
// Triggered when data is received on a socket
// SocketReceiveEvent = 3,
};

/// Number of distinct socket event futex types.
static constexpr size_t NumFutexTypes =
SocketEventType::SocketTCPConnectEvent + 1;
/// Sentinel value stored in a TCP event futex when the wrapper still exists
/// but the TCP connection has closed.
static constexpr int32_t SocketConnectionClosed = INT32_MIN + 1;
/// Sentinel value stored in a socket event futex after the socket has been
/// torn down.
static constexpr int32_t SocketNotAvailable = INT32_MIN;

/**
* Enumeration defining the connection type.
*/
Expand Down Expand Up @@ -189,19 +232,26 @@ typedef CHERI_SEALED(struct SealedSocket *) Socket;
void __cheri_compartment("TCPIP") network_start(void);

/**
* Create a connected TCP socket.
* Create a TCP socket and connect it to an authorised host.
*
* This function will block until the connection is established or the timeout
* is reached.
* is reached. With a zero timeout, it starts the connection and returns without
* waiting for it to complete.
*
* The `mallocCapability` argument is used to allocate memory for the socket
* and must have sufficient quota remaining for the socket.
*
* The `hostCapability` argument is a capability authorising the connection to
* a specific host.
*
* This returns a valid sealed capability to a socket on success, or an
* untagged value on failure.
* The return value is:
*
* - A valid sealed socket capability if the connection succeeds or a
* zero-timeout call starts the connection.
* - An untagged value if the operation fails or a blocking call reaches its
* timeout.
*
* The caller must close any valid socket returned by this function.
*/
Socket __cheri_compartment("NetAPI")
network_socket_connect_tcp(Timeout *timeout,
Expand Down Expand Up @@ -269,6 +319,18 @@ Socket __cheri_compartment("TCPIP")
AllocatorCapability mallocCapability,
bool isIPv6);

/**
* Return the event source associated with a socket.
*
* The returned capability is read-only and bounded to four bytes.
* For a TCP socket, the futex `SocketTCPSendEvent` initially reports
* the configured maximum txStream capacity before the buffer is allocated.
* This is to prevent the user thread from sleeping on the multi-waiter
* forever before the first `network_socket_send()` is called.
*/
uint32_t *__cheri_compartment("TCPIP")
network_socket_get_event_source(Socket sealedSocket, SocketEventType type);

/**
* Authorise a UDP socket to send packets to a specific host. This opens a
* firewall hole allowing the socket to send and receive packets to the host.
Expand Down
6 changes: 4 additions & 2 deletions lib/netapi/NetAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <atomic>
#include <debug.hh>
#include <endianness.hh>
#include <errno.h>
#include <token.h>

constexpr bool DebugNetAPI =
Expand Down Expand Up @@ -116,8 +117,9 @@ Socket network_socket_connect_tcp(Timeout *timeout,
address.ipv4, kind.localPort, ntohs(host->port));
}

if (network_socket_connect_tcp_internal(
timeout, sealedSocket, address, host->port) != 0)
int connectResult = network_socket_connect_tcp_internal(
timeout, sealedSocket, address, host->port);
if ((connectResult != 0) && (connectResult != -EINPROGRESS))
{
Timeout t{UnlimitedTimeout};
// We pass an unlimited timeout, so this cannot fail in any
Expand Down
2 changes: 2 additions & 0 deletions lib/tcpip/network-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Socket __cheri_compartment("TCPIP")

/**
* Connect a TCP socket to the given address.
*
* Returns `-EINPROGRESS` if a zero timeout starts the connection.
*/
int __cheri_compartment("TCPIP")
network_socket_connect_tcp_internal(Timeout *timeout,
Expand Down
Loading
Loading