diff options
Diffstat (limited to 'libhw/host_net.c')
-rw-r--r-- | libhw/host_net.c | 97 |
1 files changed, 58 insertions, 39 deletions
diff --git a/libhw/host_net.c b/libhw/host_net.c index f977739..e89cd66 100644 --- a/libhw/host_net.c +++ b/libhw/host_net.c @@ -33,6 +33,9 @@ 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) @@ -202,27 +205,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; @@ -233,20 +236,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, }; @@ -259,59 +261,76 @@ 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; } |