Commit 501f9a82 authored by Olivier Crête's avatar Olivier Crête

turn: Cache the nonce & realm to remove useless round trips

Instead of re-discovering the nonce and realm for every request, cache them
in th socket.
parent 82ea4d71
...@@ -2838,6 +2838,9 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -2838,6 +2838,9 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
} }
if (relay_cand) { if (relay_cand) {
if (d->stun_resp_msg.buffer)
nice_udp_turn_socket_cache_realm_nonce (relay_cand->sockptr,
&d->stun_resp_msg);
if (agent->compatibility == NICE_COMPATIBILITY_OC2007 || if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
/* These data are needed on TURN socket when sending requests, /* These data are needed on TURN socket when sending requests,
......
...@@ -98,6 +98,11 @@ typedef struct { ...@@ -98,6 +98,11 @@ typedef struct {
GHashTable *send_data_queues; /* stores a send data queue for per peer */ GHashTable *send_data_queues; /* stores a send data queue for per peer */
GSource *permission_timeout_source; /* timer used to invalidate GSource *permission_timeout_source; /* timer used to invalidate
permissions */ permissions */
guint8 *cached_realm;
uint16_t cached_realm_len;
guint8 *cached_nonce;
uint16_t cached_nonce_len;
} UdpTurnPriv; } UdpTurnPriv;
...@@ -132,9 +137,9 @@ static gboolean priv_retransmissions_tick_unlocked (UdpTurnPriv *priv); ...@@ -132,9 +137,9 @@ static gboolean priv_retransmissions_tick_unlocked (UdpTurnPriv *priv);
static gboolean priv_retransmissions_tick (gpointer pointer); static gboolean priv_retransmissions_tick (gpointer pointer);
static void priv_schedule_tick (UdpTurnPriv *priv); static void priv_schedule_tick (UdpTurnPriv *priv);
static void priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg); static void priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg);
static gboolean priv_send_create_permission (UdpTurnPriv *priv, StunMessage *resp, static gboolean priv_send_create_permission (UdpTurnPriv *priv,
const NiceAddress *peer); const NiceAddress *peer);
static gboolean priv_send_channel_bind (UdpTurnPriv *priv, StunMessage *resp, static gboolean priv_send_channel_bind (UdpTurnPriv *priv,
uint16_t channel, uint16_t channel,
const NiceAddress *peer); const NiceAddress *peer);
static gboolean priv_add_channel_binding (UdpTurnPriv *priv, static gboolean priv_add_channel_binding (UdpTurnPriv *priv,
...@@ -319,6 +324,8 @@ socket_close (NiceSocket *sock) ...@@ -319,6 +324,8 @@ socket_close (NiceSocket *sock)
g_list_free(priv->pending_permissions); g_list_free(priv->pending_permissions);
g_free (priv->username); g_free (priv->username);
g_free (priv->password); g_free (priv->password);
g_free (priv->cached_realm);
g_free (priv->cached_nonce);
g_free (priv); g_free (priv);
sock->priv = NULL; sock->priv = NULL;
...@@ -834,7 +841,7 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to, ...@@ -834,7 +841,7 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to,
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 && if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
!priv_has_permission_for_peer (priv, to)) { !priv_has_permission_for_peer (priv, to)) {
if (!priv_has_sent_permission_for_peer (priv, to)) { if (!priv_has_sent_permission_for_peer (priv, to)) {
priv_send_create_permission (priv, NULL, to); priv_send_create_permission (priv, to);
} }
/* enque data */ /* enque data */
...@@ -1097,7 +1104,7 @@ priv_binding_timeout (gpointer data) ...@@ -1097,7 +1104,7 @@ priv_binding_timeout (gpointer data)
/* Send renewal */ /* Send renewal */
if (!priv->current_binding_msg) if (!priv->current_binding_msg)
priv_send_channel_bind (priv, NULL, b->channel, &b->peer); priv_send_channel_bind (priv, b->channel, &b->peer);
break; break;
} }
} }
...@@ -1107,6 +1114,31 @@ priv_binding_timeout (gpointer data) ...@@ -1107,6 +1114,31 @@ priv_binding_timeout (gpointer data)
return FALSE; return FALSE;
} }
void
nice_udp_turn_socket_cache_realm_nonce (NiceSocket *sock, StunMessage *msg)
{
UdpTurnPriv *priv = sock->priv;
gconstpointer tmp;
g_assert (sock->type == NICE_SOCKET_TYPE_UDP_TURN);
g_free (priv->cached_realm);
priv->cached_realm = NULL;
priv->cached_realm_len = 0;
g_free (priv->cached_nonce);
priv->cached_nonce = NULL;
priv->cached_nonce_len = 0;
tmp = stun_message_find (msg, STUN_ATTRIBUTE_REALM, &priv->cached_realm_len);
if (tmp && priv->cached_realm_len < 764)
priv->cached_realm = g_memdup (tmp, priv->cached_realm_len);
tmp = stun_message_find (msg, STUN_ATTRIBUTE_NONCE, &priv->cached_nonce_len);
if (tmp && priv->cached_nonce_len < 764)
priv->cached_nonce = g_memdup (tmp, priv->cached_nonce_len);
}
guint guint
nice_udp_turn_socket_parse_recv_message (NiceSocket *sock, NiceSocket **from_sock, nice_udp_turn_socket_parse_recv_message (NiceSocket *sock, NiceSocket **from_sock,
NiceInputMessage *message) NiceInputMessage *message)
...@@ -1310,8 +1342,9 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -1310,8 +1342,9 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
g_free (priv->current_binding_msg); g_free (priv->current_binding_msg);
priv->current_binding_msg = NULL; priv->current_binding_msg = NULL;
nice_udp_turn_socket_cache_realm_nonce (sock, &msg);
if (binding) if (binding)
priv_send_channel_bind (priv, &msg, binding->channel, priv_send_channel_bind (priv, binding->channel,
&binding->peer); &binding->peer);
} else { } else {
g_free (priv->current_binding); g_free (priv->current_binding);
...@@ -1412,8 +1445,10 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -1412,8 +1445,10 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
priv->pending_permissions, i); priv->pending_permissions, i);
g_free (current_create_permission_msg); g_free (current_create_permission_msg);
current_create_permission_msg = NULL; current_create_permission_msg = NULL;
nice_udp_turn_socket_cache_realm_nonce (sock, &msg);
/* resend CreatePermission */ /* resend CreatePermission */
priv_send_create_permission (priv, &msg, &to); priv_send_create_permission (priv, &to);
return 0; return 0;
} }
} }
...@@ -1480,7 +1515,7 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, ...@@ -1480,7 +1515,7 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 && if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
!priv_has_permission_for_peer (priv, from)) { !priv_has_permission_for_peer (priv, from)) {
if (!priv_has_sent_permission_for_peer (priv, from)) { if (!priv_has_sent_permission_for_peer (priv, from)) {
priv_send_create_permission (priv, NULL, from); priv_send_create_permission (priv, from);
} }
} }
...@@ -1566,7 +1601,7 @@ priv_process_pending_bindings (UdpTurnPriv *priv) ...@@ -1566,7 +1601,7 @@ priv_process_pending_bindings (UdpTurnPriv *priv)
for (i = priv->channels ; i; i = i->next) { for (i = priv->channels ; i; i = i->next) {
ChannelBinding *b = i->data; ChannelBinding *b = i->data;
if (b->renew) { if (b->renew) {
priv_send_channel_bind (priv, NULL, b->channel, &b->peer); priv_send_channel_bind (priv, b->channel, &b->peer);
break; break;
} }
} }
...@@ -1821,7 +1856,7 @@ priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg) ...@@ -1821,7 +1856,7 @@ priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg)
} }
static gboolean static gboolean
priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp, priv_send_create_permission(UdpTurnPriv *priv,
const NiceAddress *peer) const NiceAddress *peer)
{ {
guint msg_buf_len; guint msg_buf_len;
...@@ -1831,17 +1866,6 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp, ...@@ -1831,17 +1866,6 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp,
struct sockaddr_storage storage; struct sockaddr_storage storage;
struct sockaddr addr; struct sockaddr addr;
} addr; } addr;
uint8_t *realm = NULL;
uint16_t realm_len = 0;
uint8_t *nonce = NULL;
uint16_t nonce_len = 0;
if (resp) {
realm = (uint8_t *) stun_message_find (resp,
STUN_ATTRIBUTE_REALM, &realm_len);
nonce = (uint8_t *) stun_message_find (resp,
STUN_ATTRIBUTE_NONCE, &nonce_len);
}
/* register this peer as being pening a permission (if not already pending) */ /* register this peer as being pening a permission (if not already pending) */
if (!priv_has_sent_permission_for_peer (priv, peer)) { if (!priv_has_sent_permission_for_peer (priv, peer)) {
...@@ -1858,8 +1882,8 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp, ...@@ -1858,8 +1882,8 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp,
priv->username_len, priv->username_len,
priv->password, priv->password,
priv->password_len, priv->password_len,
realm, realm_len, priv->cached_realm, priv->cached_realm_len,
nonce, nonce_len, priv->cached_nonce, priv->cached_nonce_len,
&addr.storage, &addr.storage,
STUN_USAGE_TURN_COMPATIBILITY_RFC5766); STUN_USAGE_TURN_COMPATIBILITY_RFC5766);
...@@ -1893,8 +1917,8 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp, ...@@ -1893,8 +1917,8 @@ priv_send_create_permission(UdpTurnPriv *priv, StunMessage *resp,
} }
static gboolean static gboolean
priv_send_channel_bind (UdpTurnPriv *priv, StunMessage *resp, priv_send_channel_bind (UdpTurnPriv *priv, uint16_t channel,
uint16_t channel, const NiceAddress *peer) const NiceAddress *peer)
{ {
uint32_t channel_attr = channel << 16; uint32_t channel_attr = channel << 16;
size_t stun_len; size_t stun_len;
...@@ -1927,37 +1951,29 @@ priv_send_channel_bind (UdpTurnPriv *priv, StunMessage *resp, ...@@ -1927,37 +1951,29 @@ priv_send_channel_bind (UdpTurnPriv *priv, StunMessage *resp,
return FALSE; return FALSE;
} }
if (priv->username != NULL && priv->username_len > 0) { if (priv->username != NULL && priv->username_len > 0 &&
priv->cached_realm != NULL && priv->cached_realm_len > 0 &&
priv->cached_nonce != NULL && priv->cached_nonce_len > 0) {
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME, if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME,
priv->username, priv->username_len) priv->username, priv->username_len)
!= STUN_MESSAGE_RETURN_SUCCESS) { != STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg); g_free (msg);
return FALSE; return FALSE;
} }
}
if (resp) {
uint8_t *realm;
uint8_t *nonce;
uint16_t len;
realm = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_REALM, &len); if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM,
if (realm != NULL) { priv->cached_realm, priv->cached_realm_len)
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM, != STUN_MESSAGE_RETURN_SUCCESS) {
realm, len) g_free (msg);
!= STUN_MESSAGE_RETURN_SUCCESS) { return 0;
g_free (msg);
return 0;
}
} }
nonce = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_NONCE, &len);
if (nonce != NULL) { if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE,
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE, priv->cached_nonce, priv->cached_nonce_len)
nonce, len) != STUN_MESSAGE_RETURN_SUCCESS) {
!= STUN_MESSAGE_RETURN_SUCCESS) { g_free (msg);
g_free (msg); return 0;
return 0;
}
} }
} }
...@@ -2005,7 +2021,7 @@ priv_add_channel_binding (UdpTurnPriv *priv, const NiceAddress *peer) ...@@ -2005,7 +2021,7 @@ priv_add_channel_binding (UdpTurnPriv *priv, const NiceAddress *peer)
} }
if (channel >= 0x4000 && channel < 0xffff) { if (channel >= 0x4000 && channel < 0xffff) {
gboolean ret = priv_send_channel_bind (priv, NULL, channel, peer); gboolean ret = priv_send_channel_bind (priv, channel, peer);
if (ret) { if (ret) {
priv->current_binding = g_new0 (ChannelBinding, 1); priv->current_binding = g_new0 (ChannelBinding, 1);
priv->current_binding->channel = channel; priv->current_binding->channel = channel;
......
...@@ -75,6 +75,9 @@ nice_udp_turn_socket_set_ms_realm(NiceSocket *sock, StunMessage *msg); ...@@ -75,6 +75,9 @@ nice_udp_turn_socket_set_ms_realm(NiceSocket *sock, StunMessage *msg);
void void
nice_udp_turn_socket_set_ms_connection_id (NiceSocket *sock, StunMessage *msg); nice_udp_turn_socket_set_ms_connection_id (NiceSocket *sock, StunMessage *msg);
void
nice_udp_turn_socket_cache_realm_nonce (NiceSocket *sock, StunMessage *msg);
G_END_DECLS G_END_DECLS
......
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