diff --git a/src/core/ioqueue.c b/src/core/ioqueue.c index 9e2c69a..30a7232 100644 --- a/src/core/ioqueue.c +++ b/src/core/ioqueue.c @@ -160,10 +160,46 @@ static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) int ioq_send_send(struct ioq_send* q, struct net_connection* con) { - int ret; - struct adc_message* msg = list_get_first(q->queue); - if (!msg) return 0; - uhub_assert(msg->cache && *msg->cache); + int ret; + struct adc_message* msg = list_get_first(q->queue); + if (!msg) return 0; + uhub_assert(msg->cache && *msg->cache); + +#ifdef HAVE_FUNC_WRITEV +#define MAX_IOVEC 32 + struct iovec vec[MAX_IOVEC]; + size_t n = 0; + vec[0].iov_base = msg->cache + q->offset; + vec[0].iov_len = msg->length - q->offset; + + for (struct adc_message* tmp = (struct adc_message*) list_get_next(q->queue), n = 1; tmp && n < MAX_IOVEC; tmp = (struct adc_message*) list_get_next(q->queue), n++) + { + vec[n].iov_base = msg->cache; + vec[n].iov_len = msg->length; + } + + ret = net_con_writev(con, &iovec, n); + + if (ret > 0) + { + while (ret > 0) + { + if (ret >= (msg->length - q->offset)) + { + ret -= (msg->length - q->offset); + q->offset = 0; + ioq_send_remove(q, msg); + } + else + { + q->offset += ret; + return 0; + } + } + return 1; + } + return ret; +#else ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset); if (ret > 0) @@ -176,8 +212,10 @@ int ioq_send_send(struct ioq_send* q, struct net_connection* con) return 1; } return ret; +#endif } + int ioq_send_is_empty(struct ioq_send* q) { return (q->size - q->offset) == 0; diff --git a/src/network/connection.c b/src/network/connection.c index a96da10..718d585 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -57,6 +57,48 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) return ret; } +#ifdef HAVE_FUNC_WRITEV +ssize_t net_con_writev(struct net_connection* con, const struct iovec* iov, size_t iocnt) +{ + int ret; +#ifdef SSL_SUPPORT + if (!con->ssl) + { +#endif + ret = writev(con->sd, iovec, (int) iocnt); + if (ret == -1) + { + if (is_blocked_or_interrupted()) + return 0; + return -1; + } +#ifdef SSL_SUPPORT + } + else + { + ssize_t total = 0; + ret = 0; + while (iocnt--) + { + ret = net_ssl_send(con, buf, len); + if (ret >= 0) + total += ret; + else + { + break; + } + } + + if (total == 0 && !is_blocked_or_interrupted()) + return -1; + + return total; + } +#endif /* SSL_SUPPORT */ + return ret; +} +#endif + ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) { int ret; diff --git a/src/network/connection.h b/src/network/connection.h index 490e636..aac4bb9 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -92,6 +92,11 @@ extern void net_con_close(struct net_connection* con); */ extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len); + +#ifdef HAVE_FUNC_WRITEV +extern ssize_t net_con_writev(struct net_connection* con, const struct iovec* iov, size_t iocnt); +#endif + /** * Receive data *