Commit e618baf5 authored by Youness Alaoui's avatar Youness Alaoui

udp turn socket factory now exports functions that would allow libnice to...

udp turn socket factory now exports functions that would allow libnice to override the default socket factory API. This is used because we need to parse a TURN message received on a local candidate
parent 984b21a5
...@@ -57,7 +57,8 @@ ...@@ -57,7 +57,8 @@
typedef struct { typedef struct {
StunAgent agent; StunAgent agent;
int locked; int locked;
NiceUDPSocket udp_socket; NiceUDPSocket *udp_socket;
NiceAddress server_addr;
uint8_t *username; uint8_t *username;
size_t username_len; size_t username_len;
uint8_t *password; uint8_t *password;
...@@ -65,60 +66,82 @@ typedef struct { ...@@ -65,60 +66,82 @@ typedef struct {
} turn_priv; } turn_priv;
static gint gint
socket_recv ( nice_udp_turn_socket_parse_recv (
NiceUDPSocket *sock, NiceUDPSocket *sock,
NiceAddress *from, NiceAddress *from,
guint len, guint len,
gchar *buf) gchar *buf,
NiceAddress *recv_from,
gchar *recv_buf,
guint recv_len)
{ {
turn_priv *priv = (turn_priv *) sock->priv; turn_priv *priv = (turn_priv *) sock->priv;
StunValidationStatus valid; StunValidationStatus valid;
StunMessage msg; StunMessage msg;
uint8_t buffer[STUN_MAX_MESSAGE_SIZE];
size_t stun_len;
struct sockaddr_storage sa; struct sockaddr_storage sa;
guint from_len = sizeof (sa); guint from_len = sizeof (sa);
stun_len = nice_udp_socket_recv (&priv->udp_socket, from, if (nice_address_equal (&priv->server_addr, recv_from)) {
sizeof(buffer), (gchar *)buffer); valid = stun_agent_validate (&priv->agent, &msg,
(uint8_t *) recv_buf, (size_t) recv_len, NULL, NULL);
valid = stun_agent_validate (&priv->agent, &msg, buffer, stun_len, NULL, NULL);
if (valid == STUN_VALIDATION_SUCCESS) {
uint32_t cookie;
if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, &cookie) != 0)
goto recv;
if (cookie != TURN_MAGIC_COOKIE)
goto recv;
if (stun_message_get_class (&msg) == STUN_RESPONSE &&
stun_message_get_method (&msg) == STUN_SEND) {
return 0;
} else if (stun_message_get_class (&msg) == STUN_INDICATION &&
stun_message_get_method (&msg) == STUN_IND_DATA) {
uint16_t data_len;
uint8_t *data;
if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
(struct sockaddr *)&sa, &from_len) != 0)
goto recv;
data = (uint8_t *) stun_message_find (&msg, STUN_ATTRIBUTE_DATA, &data_len); if (valid == STUN_VALIDATION_SUCCESS) {
if (data == NULL) uint32_t cookie;
if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, &cookie) != 0)
goto recv;
if (cookie != TURN_MAGIC_COOKIE)
goto recv; goto recv;
nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); if (stun_message_get_class (&msg) == STUN_RESPONSE &&
stun_message_get_method (&msg) == STUN_SEND) {
memcpy (buf, data, len > data_len ? data_len : len); return 0;
return len > data_len ? data_len : len; } else if (stun_message_get_class (&msg) == STUN_INDICATION &&
} else { stun_message_get_method (&msg) == STUN_IND_DATA) {
goto recv; uint16_t data_len;
uint8_t *data;
if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
(struct sockaddr *)&sa, &from_len) != 0)
goto recv;
data = (uint8_t *) stun_message_find (&msg, STUN_ATTRIBUTE_DATA, &data_len);
if (data == NULL)
goto recv;
nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
memmove (buf, data, len > data_len ? data_len : len);
return len > data_len ? data_len : len;
} else {
goto recv;
}
} }
} }
recv: recv:
memcpy (buf, buffer, len > stun_len ? stun_len : len); *from = *recv_from;
return len > stun_len ? stun_len : len; memmove (buf, recv_buf, len > recv_len ? recv_len : len);
return len > recv_len ? recv_len : len;
}
static gint
socket_recv (
NiceUDPSocket *sock,
NiceAddress *from,
guint len,
gchar *buf)
{
turn_priv *priv = (turn_priv *) sock->priv;
uint8_t recv_buf[STUN_MAX_MESSAGE_SIZE];
gint recv_len;
NiceAddress recv_from;
recv_len = nice_udp_socket_recv (priv->udp_socket, &recv_from,
sizeof(recv_buf), (gchar *) recv_buf);
return nice_udp_turn_socket_parse_recv (sock, from, len, buf, &recv_from,
(gchar *) recv_buf, (guint) recv_len);
} }
static gboolean static gboolean
...@@ -160,11 +183,11 @@ socket_send ( ...@@ -160,11 +183,11 @@ socket_send (
priv->password, priv->password_len); priv->password, priv->password_len);
if (stun_len > 0) { if (stun_len > 0) {
nice_udp_socket_send (&priv->udp_socket, to, stun_len, (gchar *)buffer); nice_udp_socket_send (priv->udp_socket, &priv->server_addr, stun_len, (gchar *)buffer);
return TRUE; return TRUE;
} }
send: send:
nice_udp_socket_send (&priv->udp_socket, to, len, buf); nice_udp_socket_send (priv->udp_socket, to, len, buf);
return TRUE; return TRUE;
} }
...@@ -173,7 +196,6 @@ static void ...@@ -173,7 +196,6 @@ static void
socket_close (NiceUDPSocket *sock) socket_close (NiceUDPSocket *sock)
{ {
turn_priv *priv = (turn_priv *) sock->priv; turn_priv *priv = (turn_priv *) sock->priv;
nice_udp_socket_close (&priv->udp_socket);
g_free (priv); g_free (priv);
} }
...@@ -181,27 +203,40 @@ socket_close (NiceUDPSocket *sock) ...@@ -181,27 +203,40 @@ socket_close (NiceUDPSocket *sock)
static gboolean static gboolean
socket_factory_init_socket ( socket_factory_init_socket (
G_GNUC_UNUSED
NiceUDPSocketFactory *man, NiceUDPSocketFactory *man,
NiceUDPSocket *sock, NiceUDPSocket *sock,
NiceAddress *addr) NiceAddress *addr)
{ {
NiceUDPSocketFactory *udp_socket_factory = man->priv; return FALSE;
turn_priv *priv = g_new0 (turn_priv, 1); }
if (nice_udp_socket_factory_make (udp_socket_factory, &(priv->udp_socket), addr) NICEAPI_EXPORT gboolean
== FALSE) { nice_udp_turn_create_socket_full (
g_free (priv); NiceUDPSocketFactory *man,
return FALSE; NiceUDPSocket *sock,
} NiceAddress *addr,
NiceUDPSocket *udp_socket,
NiceAddress *server_addr,
gchar *username,
gchar *password,
NiceUdpTurnSocketCompatibility compatibility)
{
turn_priv *priv = g_new0 (turn_priv, 1);
stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
STUN_COMPATIBILITY_RFC3489, STUN_COMPATIBILITY_RFC3489,
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
STUN_AGENT_USAGE_IGNORE_CREDENTIALS); STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
sock->addr = priv->udp_socket.addr; priv->locked = FALSE;
sock->fileno = priv->udp_socket.fileno; priv->udp_socket = udp_socket;
priv->username = (uint8_t *)username;
priv->username_len = (size_t) strlen (username);
priv->password = (uint8_t *)password;
priv->password_len = (size_t) strlen (password);
priv->server_addr = *server_addr;
sock->addr = *addr;
sock->fileno = udp_socket->fileno;
sock->send = socket_send; sock->send = socket_send;
sock->recv = socket_recv; sock->recv = socket_recv;
sock->close = socket_close; sock->close = socket_close;
...@@ -214,9 +249,6 @@ socket_factory_close ( ...@@ -214,9 +249,6 @@ socket_factory_close (
G_GNUC_UNUSED G_GNUC_UNUSED
NiceUDPSocketFactory *man) NiceUDPSocketFactory *man)
{ {
NiceUDPSocketFactory *udp_socket_factory = man->priv;
nice_udp_socket_factory_close (udp_socket_factory);
g_free (udp_socket_factory);
} }
NICEAPI_EXPORT void NICEAPI_EXPORT void
...@@ -224,12 +256,9 @@ nice_udp_turn_socket_factory_init ( ...@@ -224,12 +256,9 @@ nice_udp_turn_socket_factory_init (
G_GNUC_UNUSED G_GNUC_UNUSED
NiceUDPSocketFactory *man) NiceUDPSocketFactory *man)
{ {
NiceUDPSocketFactory *udp_socket_factory = g_new0 (NiceUDPSocketFactory, 1);
man->init = socket_factory_init_socket; man->init = socket_factory_init_socket;
man->close = socket_factory_close; man->close = socket_factory_close;
nice_udp_bsd_socket_factory_init (udp_socket_factory);
man->priv = (void *) udp_socket_factory;
} }
...@@ -40,6 +40,34 @@ ...@@ -40,6 +40,34 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef enum {
NICE_UDP_TURN_SOCKET_COMPATIBILITY_TD9,
NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE,
NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN,
} NiceUdpTurnSocketCompatibility;
gint
nice_udp_turn_socket_parse_recv (
NiceUDPSocket *sock,
NiceAddress *from,
guint len,
gchar *buf,
NiceAddress *recv_from,
gchar *recv_buf,
guint recv_len);
gboolean
nice_udp_turn_create_socket_full (
NiceUDPSocketFactory *man,
NiceUDPSocket *sock,
NiceAddress *addr,
NiceUDPSocket *udp_socket,
NiceAddress *server_addr,
gchar *username,
gchar *password,
NiceUdpTurnSocketCompatibility compatibility);
void void
nice_udp_turn_socket_factory_init (NiceUDPSocketFactory *man); nice_udp_turn_socket_factory_init (NiceUDPSocketFactory *man);
......
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