Commit e3e02484 authored by Marcus Lundblad's avatar Marcus Lundblad Committed by Youness Alaoui

Track permission per peer, take one (untested so far...)

parent 1c94dece
...@@ -89,10 +89,9 @@ typedef struct { ...@@ -89,10 +89,9 @@ typedef struct {
uint8_t ms_connection_id[20]; uint8_t ms_connection_id[20];
uint32_t ms_sequence_num; uint32_t ms_sequence_num;
bool ms_connection_id_valid; bool ms_connection_id_valid;
gboolean has_permission; GHashTable *permissions;
gboolean sent_permission; GHashTable *sent_permissions;
guint num_sent_permission; GHashTable *send_data_queues;
GQueue *send_data;
guint permission_timeout_source; guint permission_timeout_source;
gboolean has_binding; gboolean has_binding;
gboolean sent_binding; gboolean sent_binding;
...@@ -109,7 +108,7 @@ typedef struct { ...@@ -109,7 +108,7 @@ typedef struct {
typedef struct { typedef struct {
gchar *data; gchar *data;
guint data_len; guint data_len;
NiceAddress *to; TurnPriv *priv;
} SendData; } SendData;
static void socket_close (NiceSocket *sock); static void socket_close (NiceSocket *sock);
...@@ -126,12 +125,45 @@ static void priv_schedule_tick (TurnPriv *priv); ...@@ -126,12 +125,45 @@ static void priv_schedule_tick (TurnPriv *priv);
static void priv_send_turn_message (TurnPriv *priv, TURNMessage *msg); static void priv_send_turn_message (TurnPriv *priv, TURNMessage *msg);
static gboolean priv_send_create_permission (TurnPriv *priv, static gboolean priv_send_create_permission (TurnPriv *priv,
uint8_t *realm, gsize realm_len, uint8_t *nonce, gsize nonce_len, uint8_t *realm, gsize realm_len, uint8_t *nonce, gsize nonce_len,
struct sockaddr *peer); const NiceAddress *peer);
static gboolean priv_send_channel_bind (TurnPriv *priv, StunMessage *resp, static gboolean priv_send_channel_bind (TurnPriv *priv, StunMessage *resp,
uint16_t channel, const NiceAddress *peer); uint16_t channel, const NiceAddress *peer);
static gboolean priv_add_channel_binding (TurnPriv *priv, const NiceAddress *peer); static gboolean priv_add_channel_binding (TurnPriv *priv, const NiceAddress *peer);
static gboolean priv_forget_send_request (gpointer pointer); static gboolean priv_forget_send_request (gpointer pointer);
static guint
priv_nice_address_hash (gconstpointer data)
{
int *buf = (int *) data;
size_t i;
guint hash;
for (i = 0 ; i < sizeof(NiceAddress) / sizeof(int) ; i++) {
hash ^= g_int_hash(&buf[i]);
}
return hash;
}
static void
priv_send_data_queue_destroy (gpointer data)
{
GQueue *send_requests = (GQueue *) data;
GList *i;
for (i = g_queue_peek_head_link (send_requests); i; i = i->next) {
SendRequest *r = i->data;
g_source_destroy (r->source);
g_source_unref (r->source);
r->source = NULL;
stun_agent_forget_transaction (&r->priv->agent, r->id);
g_slice_free (SendRequest, r);
}
g_queue_free (send_requests);
}
NiceSocket * NiceSocket *
nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr, nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr,
...@@ -191,7 +223,15 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr, ...@@ -191,7 +223,15 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr,
priv->server_addr = *server_addr; priv->server_addr = *server_addr;
priv->compatibility = compatibility; priv->compatibility = compatibility;
priv->send_requests = g_queue_new (); priv->send_requests = g_queue_new ();
priv->send_data = g_queue_new(); priv->permissions =
g_hash_table_new_full (priv_nice_address_hash ,
(GEqualFunc) nice_address_equal ,
(GDestroyNotify) nice_address_free, NULL);
priv->send_data_queues =
g_hash_table_new_full (priv_nice_address_hash,
(GEqualFunc) nice_address_equal,
(GDestroyNotify) nice_address_free,
priv_send_data_queue_destroy);
sock->addr = *addr; sock->addr = *addr;
sock->fileno = base_socket->fileno; sock->fileno = base_socket->fileno;
sock->send = socket_send; sock->send = socket_send;
...@@ -203,6 +243,7 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr, ...@@ -203,6 +243,7 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr,
} }
static void static void
socket_close (NiceSocket *sock) socket_close (NiceSocket *sock)
{ {
...@@ -238,13 +279,8 @@ socket_close (NiceSocket *sock) ...@@ -238,13 +279,8 @@ socket_close (NiceSocket *sock)
} }
g_queue_free (priv->send_requests); g_queue_free (priv->send_requests);
for (i = g_queue_peek_head_link (priv->send_data) ; i; i = i->next) { g_hash_table_destroy (priv->permissions);
SendData *d = i->data; g_hash_table_destroy (priv->send_data_queues);
nice_address_free (d->to);
g_slice_free (SendData, d);
}
g_queue_free (priv->send_data);
g_source_remove (priv->permission_timeout_source); g_source_remove (priv->permission_timeout_source);
g_free (priv->current_binding); g_free (priv->current_binding);
...@@ -262,7 +298,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -262,7 +298,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
uint8_t recv_buf[STUN_MAX_MESSAGE_SIZE]; uint8_t recv_buf[STUN_MAX_MESSAGE_SIZE];
gint recv_len; gint recv_len;
NiceAddress recv_from; NiceAddress recv_from;
NiceSocket *dummy;; NiceSocket *dummy;
nice_debug ("received message on TURN socket"); nice_debug ("received message on TURN socket");
...@@ -303,37 +339,53 @@ stun_message_ensure_ms_realm(StunMessage *msg, uint8_t *realm) ...@@ -303,37 +339,53 @@ stun_message_ensure_ms_realm(StunMessage *msg, uint8_t *realm)
} }
} }
static gboolean
priv_has_permission_for_peer (TurnPriv *priv, const NiceAddress *to)
{
return g_hash_table_lookup (priv->permissions, to) != NULL;
}
static gboolean
priv_has_sent_permission_for_peer (TurnPriv *priv, const NiceAddress *to)
{
return g_hash_table_lookup (priv->sent_permissions, to) != NULL;
}
static void static void
socket_enqueue_data(TurnPriv *priv, const NiceAddress *to, socket_enqueue_data(TurnPriv *priv, const NiceAddress *to,
guint len, const gchar *buf) guint len, const gchar *buf)
{ {
SendData *data = g_slice_new0 (SendData); SendData *data = g_slice_new0 (SendData);
GQueue *queue = g_hash_table_lookup (priv->send_data_queues, to);
if (queue == NULL) {
queue = g_queue_new ();
g_hash_table_insert (priv->send_data_queues, nice_address_dup (to),
queue);
}
data->data = g_memdup(buf, len); data->data = g_memdup(buf, len);
data->data_len = len; data->data_len = len;
data->to = nice_address_dup (to); g_queue_push_tail (queue, data);
g_queue_push_tail(priv->send_data, data);
}
static gboolean
socket_has_enqueued_data(TurnPriv *priv)
{
return g_queue_get_length(priv->send_data) > 0;
} }
static void static void
socket_dequeue_data(TurnPriv *priv) socket_dequeue_all_data (TurnPriv *priv, const NiceAddress *to)
{ {
GQueue *send_queue = g_hash_table_lookup (priv->send_data_queues, to);
if (send_queue) {
while (g_queue_get_length (send_queue) > 0) {
SendData *data = SendData *data =
(SendData *) g_queue_pop_head(priv->send_data); (SendData *) g_queue_pop_head(send_queue);
nice_debug("dequeing data enqueued when installing permission or binding"); nice_debug("dequeing data enqueued when installing permission or binding");
nice_socket_send (priv->base_socket, data->to, data->data_len, data->data); nice_socket_send (priv->base_socket, to, data->data_len, data->data);
g_free (data->data); g_free (data->data);
nice_address_free (data->to);
g_slice_free (SendData, data); g_slice_free (SendData, data);
}
}
} }
...@@ -440,10 +492,10 @@ socket_send (NiceSocket *sock, const NiceAddress *to, ...@@ -440,10 +492,10 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
if (msg_len > 0) { if (msg_len > 0) {
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) { if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (!priv->has_permission && !priv->sent_permission) { if (!priv_has_permission_for_peer (priv, to) &&
!priv_has_sent_permission_for_peer (priv, to)) {
nice_debug ("no permission installed for peer"); nice_debug ("no permission installed for peer");
priv_send_create_permission(priv, NULL, 0, NULL, 0, priv_send_create_permission(priv, NULL, 0, NULL, 0, to);
(struct sockaddr *)&sa);
} }
} }
...@@ -453,7 +505,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to, ...@@ -453,7 +505,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
} }
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 && if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
!priv->has_permission) { !priv_has_permission_for_peer (priv, to)) {
/* enque data */ /* enque data */
nice_debug("enqueing data to be sent when aquiring permission or binding"); nice_debug("enqueing data to be sent when aquiring permission or binding");
socket_enqueue_data(priv, to, msg_len, (gchar *)buffer); socket_enqueue_data(priv, to, msg_len, (gchar *)buffer);
...@@ -511,7 +563,9 @@ priv_permission_timeout (gpointer data) ...@@ -511,7 +563,9 @@ priv_permission_timeout (gpointer data)
nice_debug ("Permission is about to timeout, schedule renewal"); nice_debug ("Permission is about to timeout, schedule renewal");
agent_lock (); agent_lock ();
priv->has_permission = FALSE; /* remove all permissions for this agent (the permission for the peer
we are sending to will be renewed) */
g_hash_table_remove_all (priv->permissions);
agent_unlock (); agent_unlock ();
return TRUE; return TRUE;
...@@ -726,11 +780,13 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -726,11 +780,13 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
struct sockaddr peer; struct sockaddr peer;
socklen_t peer_len = sizeof(peer); socklen_t peer_len = sizeof(peer);
int code = -1; int code = -1;
NiceAddress *to = nice_address_new ();;
nice_debug("got response for CreatePermission"); nice_debug("got response for CreatePermission");
stun_message_find_xor_addr (&priv->current_create_permission_msg->message, stun_message_find_xor_addr (&priv->current_create_permission_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &peer, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &peer,
&peer_len); &peer_len);
nice_address_set_from_sockaddr (to, &peer);
g_free (priv->current_create_permission_msg); g_free (priv->current_create_permission_msg);
priv->current_create_permission_msg = NULL; priv->current_create_permission_msg = NULL;
...@@ -754,13 +810,13 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -754,13 +810,13 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
nice_debug("got nonce: %s", recv_nonce); nice_debug("got nonce: %s", recv_nonce);
/* resend CreatePermission */ /* resend CreatePermission */
if (priv->num_sent_permission < 2)
priv_send_create_permission (priv, recv_realm, recv_realm_len, priv_send_create_permission (priv, recv_realm, recv_realm_len,
recv_nonce, recv_nonce_len, &peer); recv_nonce, recv_nonce_len, to);
nice_address_free (to);
} else { } else {
priv->has_permission = TRUE; /* we now have a permission installed for this peer */
priv->sent_permission = FALSE; g_hash_table_insert (priv->permissions, to, to);
priv->num_sent_permission = 0; g_hash_table_remove (priv->sent_permissions, to);
/* install timer to schedule refresh of the permission */ /* install timer to schedule refresh of the permission */
/* (will not schedule refresh if we got an error) */ /* (will not schedule refresh if we got an error) */
...@@ -771,11 +827,9 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -771,11 +827,9 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
priv_permission_timeout, priv); priv_permission_timeout, priv);
} }
/* send enqued data, unless there is also an ongoing channel bind */ /* send enqued data */
nice_debug("about to dequeue data: sent_binding: %d", priv->sent_binding); nice_debug("about to dequeue data");
while (socket_has_enqueued_data (priv)) { socket_dequeue_all_data (priv, to);
socket_dequeue_data (priv);
}
} }
} }
} }
...@@ -927,9 +981,16 @@ priv_retransmissions_create_permission_tick_unlocked (TurnPriv *priv) ...@@ -927,9 +981,16 @@ priv_retransmissions_create_permission_tick_unlocked (TurnPriv *priv)
{ {
/* Time out */ /* Time out */
StunTransactionId id; StunTransactionId id;
NiceAddress *to = nice_address_new ();
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
stun_message_id (&priv->current_create_permission_msg->message, id); stun_message_id (&priv->current_create_permission_msg->message, id);
stun_agent_forget_transaction (&priv->agent, id); stun_agent_forget_transaction (&priv->agent, id);
stun_message_find_xor_addr (&priv->current_create_permission_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &addr,
&addr_len);
nice_address_set_from_sockaddr (to, &addr);
g_free (priv->current_create_permission_msg); g_free (priv->current_create_permission_msg);
priv->current_create_permission_msg = NULL; priv->current_create_permission_msg = NULL;
...@@ -938,13 +999,10 @@ priv_retransmissions_create_permission_tick_unlocked (TurnPriv *priv) ...@@ -938,13 +999,10 @@ priv_retransmissions_create_permission_tick_unlocked (TurnPriv *priv)
message, assume we can just send the data, the server message, assume we can just send the data, the server
might not support RFC TURN, or connectivity check will might not support RFC TURN, or connectivity check will
fail eventually anyway */ fail eventually anyway */
priv->has_permission = TRUE; g_hash_table_insert (priv->permissions, to, to);
priv->sent_permission = FALSE; g_hash_table_remove (priv->sent_permissions, to);
priv->num_sent_permission = 0;
while (socket_has_enqueued_data (priv)) { socket_dequeue_all_data (priv, to);
socket_dequeue_data (priv);
}
break; break;
} }
...@@ -1076,15 +1134,15 @@ priv_send_turn_message (TurnPriv *priv, TURNMessage *msg) ...@@ -1076,15 +1134,15 @@ priv_send_turn_message (TurnPriv *priv, TURNMessage *msg)
static gboolean static gboolean
priv_send_create_permission(TurnPriv *priv, uint8_t *realm, gsize realm_len, priv_send_create_permission(TurnPriv *priv, uint8_t *realm, gsize realm_len,
uint8_t *nonce, gsize nonce_len, uint8_t *nonce, gsize nonce_len,
struct sockaddr *peer) const NiceAddress *peer)
{ {
guint msg_buf_len; guint msg_buf_len;
gboolean res = FALSE; gboolean res = FALSE;
TURNMessage *msg = g_new0 (TURNMessage, 1); TURNMessage *msg = g_new0 (TURNMessage, 1);
nice_debug("creating CreatePermission message"); nice_debug("creating CreatePermission message");
priv->sent_permission = TRUE; g_hash_table_insert (priv->sent_permissions, peer, peer);
priv->num_sent_permission++;
/* send CreatePermission */ /* send CreatePermission */
msg_buf_len = stun_usage_turn_create_permission(&priv->agent, &msg->message, msg_buf_len = stun_usage_turn_create_permission(&priv->agent, &msg->message,
msg->buffer, sizeof(msg->buffer), priv->username, priv->username_len, msg->buffer, sizeof(msg->buffer), priv->username, priv->username_len,
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#endif #endif
# include "stun/stunagent.h" # include "stun/stunagent.h"
# ifdef __cplusplus # ifdef __cplusplus
extern "C" { extern "C" {
# endif # endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment