summaryrefslogtreecommitdiff
path: root/libhw/host_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhw/host_net.c')
-rw-r--r--libhw/host_net.c118
1 files changed, 95 insertions, 23 deletions
diff --git a/libhw/host_net.c b/libhw/host_net.c
index fcdac57..1563ced 100644
--- a/libhw/host_net.c
+++ b/libhw/host_net.c
@@ -22,6 +22,7 @@
#include <libcr/coroutine.h>
#include <libmisc/vcall.h>
+#include <libhw/generic/bootclock.h>
#include <libhw/host_net.h>
/* common *********************************************************************/
@@ -86,18 +87,20 @@ static inline ssize_t hostnet_map_errno(ssize_t v) {
/* TCP init() ( AKA socket(3) + listen(3) )************************************/
static implements_net_stream_conn *hostnet_tcp_accept(implements_net_stream_listener *_listener);
+static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *conn, uint64_t ts_ns);
static ssize_t hostnet_tcp_read(implements_net_stream_conn *conn, void *buf, size_t count);
static ssize_t hostnet_tcp_write(implements_net_stream_conn *conn, void *buf, size_t count);
-static int hostnet_tcp_close(implements_net_stream_conn *conn, bool rd, bool wr);
+static int hostnet_tcp_close(implements_net_stream_conn *conn, bool rd, bool wr);
static struct net_stream_listener_vtable hostnet_tcp_listener_vtable = {
.accept = hostnet_tcp_accept,
};
static struct net_stream_conn_vtable hostnet_tcp_conn_vtable = {
- .read = hostnet_tcp_read,
- .write = hostnet_tcp_write,
- .close = hostnet_tcp_close,
+ .set_read_deadline = hostnet_tcp_set_read_deadline,
+ .read = hostnet_tcp_read,
+ .write = hostnet_tcp_write,
+ .close = hostnet_tcp_close,
};
void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) {
@@ -145,7 +148,7 @@ static void *hostnet_pthread_accept(void *_args) {
*(args->ret_connfd) = -errno;
WAKE_COROUTINE(args);
return NULL;
-};
+}
static implements_net_stream_conn *hostnet_tcp_accept(implements_net_stream_listener *_listener) {
struct hostnet_tcp_listener *listener =
@@ -169,11 +172,20 @@ static implements_net_stream_conn *hostnet_tcp_accept(implements_net_stream_list
/* TCP read() *****************************************************************/
+static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *_conn, uint64_t ts_ns) {
+ struct _hostnet_tcp_conn *conn =
+ VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+ assert(conn);
+
+ conn->read_deadline_ns = ts_ns;
+}
+
struct hostnet_pthread_read_args {
pthread_t cr_thread;
cid_t cr_coroutine;
int connfd;
+ struct timeval timeout;
void *buf;
size_t count;
@@ -182,12 +194,22 @@ struct hostnet_pthread_read_args {
static void *hostnet_pthread_read(void *_args) {
struct hostnet_pthread_read_args *args = _args;
+
+ *(args->ret) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
+ &args->timeout, sizeof(args->timeout));
+ if (*(args->ret) < 0)
+ goto end;
+
*(args->ret) = read(args->connfd, args->buf, args->count);
if (*(args->ret) < 0)
+ goto end;
+
+ end:
+ if (*(args->ret) < 0)
*(args->ret) = hostnet_map_errno(-errno);
WAKE_COROUTINE(args);
return NULL;
-};
+}
static ssize_t hostnet_tcp_read(implements_net_stream_conn *_conn, void *buf, size_t count) {
struct _hostnet_tcp_conn *conn =
@@ -205,6 +227,20 @@ static ssize_t hostnet_tcp_read(implements_net_stream_conn *_conn, void *buf, si
.ret = &ret,
};
+ if (conn->read_deadline_ns) {
+ uint64_t now_ns = bootclock_get_ns();
+ if (conn->read_deadline_ns < now_ns)
+ return -NET_ETIMEDOUT;
+ uint64_t timeout_ns = conn->read_deadline_ns-now_ns;
+ args.timeout.tv_sec = timeout_ns
+ /NS_PER_S;
+ args.timeout.tv_usec = (timeout_ns - ((uint64_t)args.timeout.tv_sec)*NS_PER_S)
+ /(NS_PER_S/US_PER_S);
+ } else {
+ args.timeout.tv_sec = 0;
+ args.timeout.tv_usec = 0;
+ }
+
if (RUN_PTHREAD(hostnet_pthread_read, &args))
return -NET_ETHREAD;
return ret;
@@ -238,7 +274,7 @@ static void *hostnet_pthread_write(void *_args) {
*(args->ret) = done;
WAKE_COROUTINE(args);
return NULL;
-};
+}
static ssize_t hostnet_tcp_write(implements_net_stream_conn *_conn, void *buf, size_t count) {
struct _hostnet_tcp_conn *conn =
@@ -282,6 +318,8 @@ static int hostnet_tcp_close(implements_net_stream_conn *_conn, bool rd, bool wr
/* UDP init() *****************************************************************/
+static void hostnet_udp_set_read_deadline(implements_net_packet_conn *self,
+ uint64_t ts_ns);
static ssize_t hostnet_udp_sendto(implements_net_packet_conn *self, void *buf, size_t len,
struct net_ip4_addr addr, uint16_t port);
static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *self, void *buf, size_t len,
@@ -289,9 +327,10 @@ static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *self, void *buf,
static int hostnet_udp_close(implements_net_packet_conn *self);
static struct net_packet_conn_vtable hostnet_udp_conn_vtable = {
- .sendto = hostnet_udp_sendto,
- .recvfrom = hostnet_udp_recvfrom,
- .close = hostnet_udp_close,
+ .set_read_deadline = hostnet_udp_set_read_deadline,
+ .sendto = hostnet_udp_sendto,
+ .recvfrom = hostnet_udp_recvfrom,
+ .close = hostnet_udp_close,
};
void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
@@ -354,7 +393,7 @@ static void *hostnet_pthread_sendto(void *_args) {
}
static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf, size_t count,
- struct net_ip4_addr node, uint16_t port) {
+ struct net_ip4_addr node, uint16_t port) {
struct hostnet_udp_conn *conn =
VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
@@ -379,11 +418,21 @@ static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf,
/* UDP recvfrom() *************************************************************/
+static void hostnet_udp_set_read_deadline(implements_net_packet_conn *_conn,
+ uint64_t ts_ns) {
+ struct hostnet_udp_conn *conn =
+ VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
+ assert(conn);
+
+ conn->read_deadline_ns = ts_ns;
+}
+
struct hostnet_pthread_recvfrom_args {
pthread_t cr_thread;
cid_t cr_coroutine;
int connfd;
+ struct timeval timeout;
void *buf;
size_t count;
@@ -402,26 +451,35 @@ static void *hostnet_pthread_recvfrom(void *_args) {
} addr = { 0 };
socklen_t addr_size;
+ *(args->ret_size) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
+ &args->timeout, sizeof(args->timeout));
+ if (*(args->ret_size) < 0)
+ goto end;
+
*(args->ret_size) = recvfrom(args->connfd, args->buf, args->count, 0, &addr.gen, &addr_size);
if (*(args->ret_size) < 0)
- *(args->ret_size) = hostnet_map_errno(-errno);
- else {
- assert(addr.in.sin_family == AF_INET);
- if (args->ret_node) {
- args->ret_node->octets[0] = (addr.in.sin_addr.s_addr >> 24) & 0xFF;
- args->ret_node->octets[1] = (addr.in.sin_addr.s_addr >> 16) & 0xFF;
- args->ret_node->octets[2] = (addr.in.sin_addr.s_addr >> 8) & 0xFF;
- args->ret_node->octets[3] = (addr.in.sin_addr.s_addr >> 0) & 0xFF;
- }
- if (args->ret_port)
- (*args->ret_port) = ntohs(addr.in.sin_port);
+ goto end;
+
+ assert(addr.in.sin_family == AF_INET);
+ if (args->ret_node) {
+ args->ret_node->octets[0] = (addr.in.sin_addr.s_addr >> 24) & 0xFF;
+ args->ret_node->octets[1] = (addr.in.sin_addr.s_addr >> 16) & 0xFF;
+ args->ret_node->octets[2] = (addr.in.sin_addr.s_addr >> 8) & 0xFF;
+ args->ret_node->octets[3] = (addr.in.sin_addr.s_addr >> 0) & 0xFF;
}
+ if (args->ret_port) {
+ (*args->ret_port) = ntohs(addr.in.sin_port);
+ }
+
+ end:
+ if (*(args->ret_size) < 0)
+ *(args->ret_size) = hostnet_map_errno(-errno);
WAKE_COROUTINE(args);
return NULL;
}
static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf, size_t count,
- struct net_ip4_addr *ret_node, uint16_t *ret_port) {
+ struct net_ip4_addr *ret_node, uint16_t *ret_port) {
struct hostnet_udp_conn *conn =
VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
@@ -439,6 +497,20 @@ static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf
.ret_node = ret_node,
.ret_port = ret_port,
};
+ if (conn->read_deadline_ns) {
+ uint64_t now_ns = bootclock_get_ns();
+ if (conn->read_deadline_ns < now_ns)
+ return -NET_ETIMEDOUT;
+ uint64_t timeout_ns = conn->read_deadline_ns-now_ns;
+ args.timeout.tv_sec = timeout_ns
+ /NS_PER_S;
+ args.timeout.tv_usec = (timeout_ns - ((uint64_t)args.timeout.tv_sec)*NS_PER_S)
+ /(NS_PER_S/US_PER_S);
+ } else {
+ args.timeout.tv_sec = 0;
+ args.timeout.tv_usec = 0;
+ }
+
if (RUN_PTHREAD(hostnet_pthread_recvfrom, &args))
return -NET_ETHREAD;
return ret;