summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYouness Alaoui <youness.alaoui@collabora.co.uk>2009-06-11 14:07:54 -0400
committerYouness Alaoui <youness.alaoui@collabora.co.uk>2009-06-11 14:07:54 -0400
commit9497d78fb13d1d2648dea0211b06c8fd79435e03 (patch)
tree1eda7b0cfcc6a9e9796967c488bd08337e11295d
parentfa38c1ad3533b3e6f1096bdf7e833ba2e9160531 (diff)
Add support for droping packets when using TCP and the bandwidth is too slow for the data output. The queue now has a limit of 20 packets and the tcp-turn now has to call send in a single shot to avoid dropping parts of the packet (dropping the length but send the data, or dropping only the padding at the end, etc..)
-rw-r--r--TODO1
-rw-r--r--socket/tcp-bsd.c25
-rw-r--r--socket/tcp-turn.c25
3 files changed, 34 insertions, 17 deletions
diff --git a/TODO b/TODO
index c3c30ed..eaab911 100644
--- a/TODO
+++ b/TODO
@@ -2,7 +2,6 @@ check for the cookie and act accordingly for incoming messages.
channel bind have a 10 minutes expiration :@
nice_socket_recv returns -1 means we must close the nice_socket and stop all connchecks/candidates and reelect if was eleected...
Add HTTP Digest support
-tcp turn must drop packets if the queue fills too fast
make sure the timers don't race condition with frees, and have some kind of refcounting (like in turn send requests) for timers
Add support for TURN-13
diff --git a/socket/tcp-bsd.c b/socket/tcp-bsd.c
index 2c41d75..2b829ba 100644
--- a/socket/tcp-bsd.c
+++ b/socket/tcp-bsd.c
@@ -70,8 +70,10 @@ typedef struct {
struct to_be_sent {
guint length;
gchar *buf;
+ gboolean can_drop;
};
+#define MAX_QUEUE_LENGTH 20
static void socket_close (NiceSocket *sock);
static gint socket_recv (NiceSocket *sock, NiceAddress *from,
@@ -222,7 +224,9 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
return ret;
}
-
+/* Data sent to this function must be a single entity because buffers can be
+ * dropped if the bandwidth isn't fast enough. So do not send a message in
+ * multiple chunks. */
static gboolean
socket_send (NiceSocket *sock, const NiceAddress *to,
guint len, const gchar *buf)
@@ -247,10 +251,24 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
return FALSE;
}
} else if ((guint)ret < len) {
- add_to_be_sent (sock, buf + ret, len - ret, FALSE);
+ add_to_be_sent (sock, buf + ret, len - ret, TRUE);
return TRUE;
}
} else {
+ if (g_queue_get_length(&priv->send_queue) >= MAX_QUEUE_LENGTH) {
+ int peek_idx = 0;
+ struct to_be_sent *tbs = NULL;
+ while ((tbs = g_queue_peek_nth (&priv->send_queue, peek_idx)) != NULL) {
+ if (tbs->can_drop) {
+ tbs = g_queue_pop_nth (&priv->send_queue, peek_idx);
+ g_free (tbs->buf);
+ g_slice_free (struct to_be_sent, tbs);
+ break;
+ } else {
+ peek_idx++;
+ }
+ }
+ }
add_to_be_sent (sock, buf, len, FALSE);
}
@@ -283,7 +301,7 @@ socket_send_more (
g_static_rec_mutex_lock (&priv->agent->mutex);
- while ((tbs = g_queue_pop_head (&priv->send_queue))) {
+ while ((tbs = g_queue_pop_head (&priv->send_queue)) != NULL) {
int ret;
ret = send (sock->fileno, tbs->buf, tbs->length, 0);
@@ -338,6 +356,7 @@ add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head)
tbs = g_slice_new0 (struct to_be_sent);
tbs->buf = g_memdup (buf, len);
tbs->length = len;
+ tbs->can_drop = !head;
if (head)
g_queue_push_head (&priv->send_queue, tbs);
else
diff --git a/socket/tcp-turn.c b/socket/tcp-turn.c
index b0306da..0d0dc53 100644
--- a/socket/tcp-turn.c
+++ b/socket/tcp-turn.c
@@ -65,6 +65,7 @@ typedef struct {
NiceSocket *base_socket;
} TurnTcpPriv;
+#define MAX_UDP_MESSAGE_SIZE 65535
static void socket_close (NiceSocket *sock);
static gint socket_recv (NiceSocket *sock, NiceAddress *from,
@@ -183,32 +184,30 @@ static gboolean
socket_send (NiceSocket *sock, const NiceAddress *to,
guint len, const gchar *buf)
{
- gboolean ret = TRUE;
TurnTcpPriv *priv = sock->priv;
gchar padbuf[3] = {0, 0, 0};
int padlen = (len%4) ? 4 - (len%4) : 0;
+ gchar buffer[MAX_UDP_MESSAGE_SIZE + sizeof(guint16) + sizeof(padbuf)];
+ guint buffer_len = 0;
if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
padlen = 0;
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
guint16 tmpbuf = htons (len);
- ret = nice_socket_send (priv->base_socket, to,
- sizeof(guint16), (gchar *)&tmpbuf);
-
- if (!ret)
- return ret;
+ memcpy (buffer + buffer_len, (gchar *)&tmpbuf, sizeof(guint16));
+ buffer_len += sizeof(guint16);
}
- ret = nice_socket_send (priv->base_socket, to, len, buf);
-
- if (!ret)
- return ret;
+ memcpy (buffer + buffer_len, buf, len);
+ buffer_len += len;
- if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
- ret = nice_socket_send (priv->base_socket, to, padlen, padbuf);
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) {
+ memcpy (buffer + buffer_len, padbuf, padlen);
+ buffer_len += padlen;
+ }
+ return nice_socket_send (priv->base_socket, to, buffer_len, buffer);
- return ret;
}