diff options
Diffstat (limited to 'libhw/host_net.c')
-rw-r--r-- | libhw/host_net.c | 130 |
1 files changed, 77 insertions, 53 deletions
diff --git a/libhw/host_net.c b/libhw/host_net.c index eee293e..9d3e97b 100644 --- a/libhw/host_net.c +++ b/libhw/host_net.c @@ -30,8 +30,18 @@ #include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_us_time() */ -LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(io_closer, struct hostnet_tcp_listener, hostnet_tcplist, static) LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static) + +LO_IMPLEMENTATION_C(io_reader, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(io_writer, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(io_readwriter, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(io_closer, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(io_bidi_closer, struct _hostnet_tcp_conn, hostnet_tcp, static) +LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static) + + +LO_IMPLEMENTATION_C(io_closer, struct hostnet_udp_conn, hostnet_udp, static) LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static) /* common *********************************************************************/ @@ -196,27 +206,27 @@ static void hostnet_tcp_set_read_deadline(struct _hostnet_tcp_conn *conn, uint64 conn->read_deadline_ns = ts_ns; } -struct hostnet_pthread_read_args { - pthread_t cr_thread; - cid_t cr_coroutine; +struct hostnet_pthread_readv_args { + pthread_t cr_thread; + cid_t cr_coroutine; - int connfd; - struct timeval timeout; - void *buf; - size_t count; + int connfd; + struct timeval timeout; + const struct iovec *iov; + int iovcnt; - ssize_t *ret; + ssize_t *ret; }; -static void *hostnet_pthread_read(void *_args) { - struct hostnet_pthread_read_args *args = _args; +static void *hostnet_pthread_readv(void *_args) { + struct hostnet_pthread_readv_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); + *(args->ret) = readv(args->connfd, args->iov, args->iovcnt); if (*(args->ret) < 0) goto end; @@ -227,20 +237,19 @@ static void *hostnet_pthread_read(void *_args) { return NULL; } -static ssize_t hostnet_tcp_read(struct _hostnet_tcp_conn *conn, void *buf, size_t count) { +static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { assert(conn); - assert(count == 0 || buf); - if (count == 0) - return 0; + assert(iov); + assert(iovcnt > 0); ssize_t ret; - struct hostnet_pthread_read_args args = { + struct hostnet_pthread_readv_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .connfd = conn->fd, - .buf = buf, - .count = count, + .iov = iov, + .iovcnt = iovcnt, .ret = &ret, }; @@ -253,78 +262,93 @@ static ssize_t hostnet_tcp_read(struct _hostnet_tcp_conn *conn, void *buf, size_ args.timeout = (host_us_time_t){0}; } - if (RUN_PTHREAD(hostnet_pthread_read, &args)) + if (RUN_PTHREAD(hostnet_pthread_readv, &args)) return -NET_ETHREAD; return ret; } /* TCP write() ****************************************************************/ -struct hostnet_pthread_write_args { - pthread_t cr_thread; - cid_t cr_coroutine; +struct hostnet_pthread_writev_args { + pthread_t cr_thread; + cid_t cr_coroutine; - int connfd; - void *buf; - size_t count; + int connfd; + const struct iovec *iov; + int iovcnt; - ssize_t *ret; + ssize_t *ret; }; -static void *hostnet_pthread_write(void *_args) { - struct hostnet_pthread_write_args *args = _args; +static void *hostnet_pthread_writev(void *_args) { + struct hostnet_pthread_writev_args *args = _args; + + size_t count = 0; + struct iovec *iov = alloca(sizeof(struct iovec)*args->iovcnt); + for (int i = 0; i < args->iovcnt; i++) { + iov[i] = args->iov[i]; + count += args->iov[i].iov_len; + } + int iovcnt = args->iovcnt; + size_t done = 0; - while (done < args->count) { - ssize_t r = write(args->connfd, args->buf, args->count); + while (done < count) { + ssize_t r = writev(args->connfd, iov, iovcnt); if (r < 0) { hostnet_map_negerrno(-errno, OP_RECV); break; } done += r; + while (iovcnt && (size_t)r >= iov[0].iov_len) { + r -= iov[0].iov_len; + iov++; + iovcnt--; + } + if (r > 0) { + iov[0].iov_base += r; + iov[0].iov_len -= r; + } } - if (done == args->count) + if (done == count) *(args->ret) = done; WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_tcp_write(struct _hostnet_tcp_conn *conn, void *buf, size_t count) { +static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { assert(conn); - assert(count == 0 || buf); - if (count == 0) - return 0; + assert(iov); + assert(iovcnt > 0); ssize_t ret; - struct hostnet_pthread_write_args args = { + struct hostnet_pthread_writev_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .connfd = conn->fd, - .buf = buf, - .count = count, + .iov = iov, + .iovcnt = iovcnt, .ret = &ret, }; - if (RUN_PTHREAD(hostnet_pthread_write, &args)) + if (RUN_PTHREAD(hostnet_pthread_writev, &args)) return -NET_ETHREAD; return ret; } /* TCP close() ****************************************************************/ -static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn, bool rd, bool wr) { +static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn) { assert(conn); - - int how; - if (rd && wr) - how = SHUT_RDWR; - else if (rd && !wr) - how = SHUT_RD; - else if (!rd && wr) - how = SHUT_WR; - else - assert_notreached("invalid arguments to stream_conn.close()"); - return hostnet_map_negerrno(shutdown(conn->fd, how) ? -errno : 0, OP_NONE); + return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RDWR) ? -errno : 0, OP_NONE); +} +static int hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) { + assert(conn); + return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RD) ? -errno : 0, OP_NONE); +} +static int hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) { + assert(conn); + return hostnet_map_negerrno(shutdown(conn->fd, SHUT_WR) ? -errno : 0, OP_NONE); } /* UDP init() *****************************************************************/ @@ -412,7 +436,7 @@ static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size /* UDP recvfrom() *************************************************************/ -static void hostnet_udp_set_read_deadline(struct hostnet_udp_conn *conn, +static void hostnet_udp_set_recv_deadline(struct hostnet_udp_conn *conn, uint64_t ts_ns) { assert(conn); |