summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYouness Alaoui <youness.alaoui@collabora.co.uk>2009-03-30 14:00:26 -0400
committerYouness Alaoui <youness.alaoui@collabora.co.uk>2009-03-30 14:00:26 -0400
commit763cd8ed36a6591742e6e8db8949a14c8e6f53f9 (patch)
tree4c6396d2059440ce25d1cad8f7a6099035c50f48
parentfe6330f5d0e6c192f0a05a9992beda00e981f54b (diff)
downloadlibnice-763cd8ed36a6591742e6e8db8949a14c8e6f53f9.tar.gz
Correctly forget turn send request transactions if they time out
-rw-r--r--socket/turn.c85
1 files changed, 77 insertions, 8 deletions
diff --git a/socket/turn.c b/socket/turn.c
index 728f8ad..a0c02a9 100644
--- a/socket/turn.c
+++ b/socket/turn.c
@@ -53,13 +53,15 @@
#include "stun/usages/timer.h"
#include "agent-priv.h"
+#define STUN_END_TIMEOUT 8000
+
+
typedef struct {
StunMessage message;
uint8_t buffer[STUN_MAX_MESSAGE_SIZE];
StunTimer timer;
} TURNMessage;
-
typedef struct {
NiceAddress peer;
uint16_t channel;
@@ -80,9 +82,15 @@ typedef struct {
uint8_t *password;
size_t password_len;
NiceTurnSocketCompatibility compatibility;
+ GList *send_requests;
} TurnPriv;
+typedef struct {
+ StunTransactionId id;
+ GSource *source;
+ TurnPriv *priv;
+} SendRequest;
static void socket_close (NiceSocket *sock);
static gint socket_recv (NiceSocket *sock, NiceAddress *from,
@@ -99,7 +107,7 @@ static void priv_send_turn_message (TurnPriv *priv, TURNMessage *msg);
static gboolean priv_send_channel_bind (TurnPriv *priv, StunMessage *resp,
uint16_t channel, NiceAddress *peer);
static gboolean priv_add_channel_binding (TurnPriv *priv, NiceAddress *peer);
-
+static gboolean priv_forget_send_request (gpointer pointer);
NiceSocket *
@@ -185,6 +193,15 @@ socket_close (NiceSocket *sock)
priv->tick_source = NULL;
}
+ for (i = priv->send_requests; i; i = i->next) {
+ SendRequest *r = i->data;
+ g_source_destroy (r->source);
+ g_source_unref (r->source);
+ g_slice_free (SendRequest, r);
+ }
+ g_list_free (priv->send_requests);
+
+
g_free (priv->current_binding);
g_free (priv->current_binding_msg);
g_free (priv->username);
@@ -288,6 +305,15 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
msg_len = stun_agent_finish_message (&priv->agent, &msg,
priv->password, priv->password_len);
+ if (msg_len > 0 && stun_message_get_class (&msg) == STUN_REQUEST) {
+ SendRequest *req = g_slice_new0 (SendRequest);
+
+ req->priv = priv;
+ stun_message_id (&msg, req->id);
+ req->source = agent_timeout_add_with_context (priv->nice, STUN_END_TIMEOUT,
+ priv_forget_send_request, req);
+ priv->send_requests = g_list_append (priv->send_requests, req);
+ }
}
if (msg_len > 0) {
@@ -305,6 +331,25 @@ socket_is_reliable (NiceSocket *sock)
return nice_socket_is_reliable (priv->base_socket);
}
+static gboolean
+priv_forget_send_request (gpointer pointer)
+{
+ SendRequest *req = pointer;
+
+ g_static_rec_mutex_lock (&req->priv->nice->mutex);
+
+ stun_agent_forget_transaction (&req->priv->agent, req->id);
+
+ g_source_destroy (req->source);
+ g_source_unref (req->source);
+
+ req->priv->send_requests = g_list_remove (req->priv->send_requests, req);
+
+ g_static_rec_mutex_unlock (&req->priv->nice->mutex);
+
+ g_slice_free (SendRequest, req);
+ return FALSE;
+}
gint
@@ -336,12 +381,36 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
}
if (stun_message_get_method (&msg) == STUN_SEND) {
- if (stun_message_get_class (&msg) == STUN_RESPONSE &&
- priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
- uint32_t opts = 0;
- if (stun_message_find32 (&msg, STUN_ATTRIBUTE_OPTIONS, &opts) ==
- STUN_MESSAGE_RETURN_SUCCESS && opts & 0x1)
- goto msn_google_lock;
+ if (stun_message_get_class (&msg) == STUN_RESPONSE) {
+ SendRequest *req = NULL;
+ GList *i = priv->send_requests;
+ StunTransactionId msg_id;
+
+ stun_message_id (&msg, msg_id);
+
+ for (; i; i = i->next) {
+ SendRequest *r = i->data;
+ if (memcmp (&r->id, msg_id, sizeof(StunTransactionId)) == 0) {
+ req = r;
+ break;
+ }
+ }
+
+ if (req) {
+ g_source_destroy (req->source);
+ g_source_unref (req->source);
+
+ priv->send_requests = g_list_remove (priv->send_requests, req);
+
+ g_slice_free (SendRequest, req);
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ uint32_t opts = 0;
+ if (stun_message_find32 (&msg, STUN_ATTRIBUTE_OPTIONS, &opts) ==
+ STUN_MESSAGE_RETURN_SUCCESS && opts & 0x1)
+ goto msn_google_lock;
+ }
}
return 0;
} else if (stun_message_get_method (&msg) == STUN_OLD_SET_ACTIVE_DST) {