summaryrefslogtreecommitdiff
path: root/socket/http.c
diff options
context:
space:
mode:
authorPhilip Withnall <philip.withnall@collabora.co.uk>2014-01-20 07:56:47 +0000
committerOlivier Crête <olivier.crete@collabora.com>2014-01-31 01:49:07 -0500
commit515481e6f45da24689d27c8eff60f4b5fa849c49 (patch)
tree90203dd3ce4e5a36dbc5e95d10c9bfa589e57a59 /socket/http.c
parent55e53a9ce7be57740993d8fd9b1ca71d410c6388 (diff)
downloadlibnice-515481e6f45da24689d27c8eff60f4b5fa849c49.tar.gz
socket: Add vectored I/O support for sending on sockets
Replace the send() API with a send_messages() API, which supports sending multiple messages, each with multiple buffers rather than a single monolithic buffer. This doesn’t break API, as the socket API is not exposed outside libnice. It does introduce a new struct: NiceOutputMessage, which is analogous to struct mmsghdr and NiceInputMessage. This includes updates to the test-bsd test to cover the changed API. The existing nice_socket_send() API has been retained as a thin wrapper around nice_socket_send_messages(), for convenience only. It’s hoped that internal usage of this API will decline to the point where it can be removed.
Diffstat (limited to 'socket/http.c')
-rw-r--r--socket/http.c88
1 files changed, 62 insertions, 26 deletions
diff --git a/socket/http.c b/socket/http.c
index f0445ee..c0ec4a8 100644
--- a/socket/http.c
+++ b/socket/http.c
@@ -92,12 +92,12 @@ struct to_be_sent {
static void socket_close (NiceSocket *sock);
static gint socket_recv_messages (NiceSocket *sock,
NiceInputMessage *recv_messages, guint n_recv_messages);
-static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
- guint len, const gchar *buf);
+static gint socket_send_messages (NiceSocket *sock,
+ const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
-static void add_to_be_sent (NiceSocket *sock, const NiceAddress *to,
- const gchar *buf, guint len);
+static void add_to_be_sent (NiceSocket *sock, const NiceOutputMessage *messages,
+ guint n_messages);
static void free_to_be_sent (struct to_be_sent *tbs);
@@ -125,7 +125,7 @@ nice_http_socket_new (NiceSocket *base_socket,
sock->fileno = priv->base_socket->fileno;
sock->addr = priv->base_socket->addr;
- sock->send = socket_send;
+ sock->send_messages = socket_send_messages;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
sock->close = socket_close;
@@ -136,6 +136,9 @@ nice_http_socket_new (NiceSocket *base_socket,
gchar *credential = NULL;
gchar host[INET6_ADDRSTRLEN];
gint port = nice_address_get_port (&priv->addr);
+ GOutputVector local_bufs;
+ NiceOutputMessage local_messages;
+
nice_address_to_string (&priv->addr, host);
if (username) {
@@ -158,7 +161,14 @@ nice_http_socket_new (NiceSocket *base_socket,
credential? credential : "" );
g_free (credential);
- nice_socket_send (priv->base_socket, NULL, strlen (msg), msg);
+ local_bufs.buffer = msg;
+ local_bufs.size = strlen (msg);
+ local_messages.buffers = &local_bufs;
+ local_messages.n_buffers = 1;
+ local_messages.to = NULL;
+ local_messages.length = local_bufs.size;
+
+ nice_socket_send_messages (priv->base_socket, &local_messages, 1);
priv->state = HTTP_STATE_INIT;
g_free (msg);
}
@@ -565,23 +575,25 @@ retry:
return -1;
}
-static gboolean
-socket_send (NiceSocket *sock, const NiceAddress *to,
- guint len, const gchar *buf)
+static gint
+socket_send_messages (NiceSocket *sock, const NiceOutputMessage *messages,
+ guint n_messages)
{
HttpPriv *priv = sock->priv;
if (priv->state == HTTP_STATE_CONNECTED) {
- if (priv->base_socket)
- return nice_socket_send (priv->base_socket, to, len, buf);
- else
- return FALSE;
+ /* Fast path. */
+ if (!priv->base_socket)
+ return -1;
+
+ return nice_socket_send_messages (priv->base_socket, messages, n_messages);
} else if (priv->state == HTTP_STATE_ERROR) {
- return FALSE;
+ return -1;
} else {
- add_to_be_sent (sock, to, buf, len);
+ add_to_be_sent (sock, messages, n_messages);
}
- return TRUE;
+
+ return n_messages;
}
@@ -593,22 +605,46 @@ socket_is_reliable (NiceSocket *sock)
static void
-add_to_be_sent (NiceSocket *sock, const NiceAddress *to,
- const gchar *buf, guint len)
+add_to_be_sent (NiceSocket *sock, const NiceOutputMessage *messages,
+ guint n_messages)
{
HttpPriv *priv = sock->priv;
- struct to_be_sent *tbs = NULL;
+ guint i;
- if (len <= 0)
+ if (n_messages == 0)
return;
- tbs = g_slice_new0 (struct to_be_sent);
- tbs->buf = g_memdup (buf, len);
- tbs->length = len;
- if (to)
- tbs->to = *to;
- g_queue_push_tail (&priv->send_queue, tbs);
+ /* Compact the message’s buffers before queueing. */
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ struct to_be_sent *tbs = NULL;
+ guint j;
+ gsize message_len_remaining = message->length;
+ gsize offset = 0;
+ if (message->length == 0)
+ continue;
+
+ tbs = g_slice_new0 (struct to_be_sent);
+ tbs->buf = g_malloc (message->length);
+ tbs->length = message->length;
+ if (message->to)
+ tbs->to = *message->to;
+ g_queue_push_tail (&priv->send_queue, tbs);
+
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ const GOutputVector *buffer = &message->buffers[j];
+ gsize len;
+
+ len = MIN (buffer->size, message_len_remaining);
+ memcpy (tbs->buf + offset, buffer->buffer, len);
+ message_len_remaining -= len;
+ offset += len;
+ }
+ }
}