Commit 9f5d0b5b authored by Youness Alaoui's avatar Youness Alaoui

Port tcp-turn to the new NiceSocket API

parent 439f5c72
...@@ -25,7 +25,9 @@ libsocket_la_SOURCES = \ ...@@ -25,7 +25,9 @@ libsocket_la_SOURCES = \
udp-bsd.h \ udp-bsd.h \
udp-bsd.c \ udp-bsd.c \
udp-turn.h \ udp-turn.h \
udp-turn.c udp-turn.c \
tcp-turn.h \
tcp-turn.c
check_PROGRAMS = test-bsd check_PROGRAMS = test-bsd
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
*/ */
/* /*
* Implementation of UDP socket interface using TCP Berkeley sockets. (See * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
* http://en.wikipedia.org/wiki/Berkeley_sockets.) * http://en.wikipedia.org/wiki/Berkeley_sockets.)
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
...@@ -59,8 +59,6 @@ ...@@ -59,8 +59,6 @@
typedef struct { typedef struct {
NiceUdpTurnSocketCompatibility compatibility; NiceUdpTurnSocketCompatibility compatibility;
GQueue send_queue; GQueue send_queue;
WriteBlockedCb cb;
gpointer user_data;
gchar recv_buf[65536]; gchar recv_buf[65536];
guint recv_buf_len; guint recv_buf_len;
guint expecting_len; guint expecting_len;
...@@ -71,21 +69,21 @@ struct to_be_sent { ...@@ -71,21 +69,21 @@ struct to_be_sent {
gchar *buf; gchar *buf;
}; };
/*** NiceUDPSocket ***/ /*** NiceSocket ***/
static gint static gint
socket_recv ( socket_recv (
NiceUDPSocket *sock, NiceSocket *sock,
NiceAddress *from, NiceAddress *from,
guint len, guint len,
gchar *buf) gchar *buf)
{ {
TurnTcpPriv *priv = sock->priv; TurnTcpPriv *priv = sock->priv;
int ret; int ret;
int padlen; guint padlen;
if (priv->expecting_len == 0) { if (priv->expecting_len == 0) {
int headerlen = 0; guint headerlen = 0;
if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9)
headerlen = 4; headerlen = 4;
...@@ -105,19 +103,18 @@ socket_recv ( ...@@ -105,19 +103,18 @@ socket_recv (
priv->recv_buf_len += ret; priv->recv_buf_len += ret;
if (ret < headerlen) if (priv->recv_buf_len < headerlen)
return 0; return 0;
if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) {
guint16 magic = ntohs (*(guint16*)priv->recv_buf); guint16 magic = ntohs (*(guint16*)priv->recv_buf);
guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2)); guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2));
if (magic < 0x4000) {
/* Its STUN */ /* Its STUN */
if (magic < 4000) {
priv->expecting_len = 20 + packetlen; priv->expecting_len = 20 + packetlen;
} else {
/* Channel data */ /* Channel data */
}
else {
priv->expecting_len = 4 + packetlen; priv->expecting_len = 4 + packetlen;
} }
} }
...@@ -128,7 +125,10 @@ socket_recv ( ...@@ -128,7 +125,10 @@ socket_recv (
} }
} }
padlen = (priv->expecting_len % 4) ? 4 - priv->expecting_len % 4 : 0; if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9)
padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0;
else
padlen = 0;
ret = read (sock->fileno, priv->recv_buf + priv->recv_buf_len, ret = read (sock->fileno, priv->recv_buf + priv->recv_buf_len,
priv->expecting_len + padlen - priv->recv_buf_len); priv->expecting_len + padlen - priv->recv_buf_len);
...@@ -151,19 +151,10 @@ socket_recv ( ...@@ -151,19 +151,10 @@ socket_recv (
return 0; return 0;
} }
static void static void
add_to_be_sent (NiceUDPSocket *sock, const gchar *buf, guint len) add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head);
{
TurnTcpPriv *priv = sock->priv;
struct to_be_sent *tbs = g_slice_new (struct to_be_sent);
tbs->buf = g_memdup (buf, len);
tbs->length = len;
g_queue_push_tail (&priv->send_queue, tbs);
priv->cb (sock, priv->user_data);
}
/* /*
* Returns: * Returns:
...@@ -172,8 +163,8 @@ add_to_be_sent (NiceUDPSocket *sock, const gchar *buf, guint len) ...@@ -172,8 +163,8 @@ add_to_be_sent (NiceUDPSocket *sock, const gchar *buf, guint len)
* 1 = sent everything * 1 = sent everything
*/ */
gint static gint
socket_send_more (NiceUDPSocket *sock) socket_send_more (NiceSocket *sock)
{ {
TurnTcpPriv *priv = sock->priv; TurnTcpPriv *priv = sock->priv;
struct to_be_sent *tbs = NULL; struct to_be_sent *tbs = NULL;
...@@ -183,22 +174,43 @@ socket_send_more (NiceUDPSocket *sock) ...@@ -183,22 +174,43 @@ socket_send_more (NiceUDPSocket *sock)
ret = write (sock->fileno, tbs->buf, tbs->length); ret = write (sock->fileno, tbs->buf, tbs->length);
if (ret <= 0) { if (ret < 0) {
if (errno == EAGAIN) if (errno == EAGAIN) {
return 0; add_to_be_sent (sock, tbs->buf, tbs->length, TRUE);
else }
return -1; } else if (ret < (int) tbs->length) {
add_to_be_sent (sock, tbs->buf + ret, tbs->length - ret, TRUE);
} }
g_free (tbs->buf);
g_slice_free (struct to_be_sent, tbs); g_slice_free (struct to_be_sent, tbs);
} }
return 1; return 1;
} }
static void
add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head)
{
TurnTcpPriv *priv = sock->priv;
struct to_be_sent *tbs = g_slice_new (struct to_be_sent);
tbs->buf = g_memdup (buf, len);
tbs->length = len;
if (head)
g_queue_push_head (&priv->send_queue, tbs);
else
g_queue_push_tail (&priv->send_queue, tbs);
/* TODO add io watch */
socket_send_more (NULL);
}
static gboolean static gboolean
socket_send ( socket_send (
NiceUDPSocket *sock, NiceSocket *sock,
const NiceAddress *to, const NiceAddress *to,
guint len, guint len,
const gchar *buf) const gchar *buf)
...@@ -208,36 +220,38 @@ socket_send ( ...@@ -208,36 +220,38 @@ socket_send (
if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
guint16 tmpbuf = htons (len); guint16 tmpbuf = htons (len);
ret = write (sock->fileno, &tmpbuf, 2); ret = write (sock->fileno, &tmpbuf, sizeof(guint16));
if (ret <= 0) { if (ret < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
add_to_be_sent (sock, (gchar*) &tmpbuf, 2); add_to_be_sent (sock, (gchar*) &tmpbuf, sizeof(guint16), FALSE);
add_to_be_sent (sock, buf, len); add_to_be_sent (sock, buf, len, FALSE);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
} }
} else if ((guint)ret < sizeof(guint16)) {
add_to_be_sent (sock, ((gchar*) &tmpbuf) + ret,
sizeof(guint16) - ret, FALSE);
add_to_be_sent (sock, buf, len, FALSE);
return TRUE;
} }
if ((guint)ret != len)
return FALSE;
} }
ret = write (sock->fileno, buf, len); ret = write (sock->fileno, buf, len);
if (ret <= 0) { if (ret < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
add_to_be_sent (sock, buf, len); add_to_be_sent (sock, buf, len, FALSE);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
} }
} else if ((guint)ret < len) {
add_to_be_sent (sock, buf + ret, len - ret, FALSE);
return TRUE;
} }
if ((guint)ret != len)
return FALSE;
if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9 && if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9 &&
len % 4) { len % 4) {
gchar padbuf[3] = {0, 0, 0}; gchar padbuf[3] = {0, 0, 0};
...@@ -245,13 +259,16 @@ socket_send ( ...@@ -245,13 +259,16 @@ socket_send (
ret = write (sock->fileno, padbuf, padlen); ret = write (sock->fileno, padbuf, padlen);
if (ret <= 0) { if (ret < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
add_to_be_sent (sock, padbuf, padlen); add_to_be_sent (sock, padbuf, padlen, FALSE);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
} }
} else if (ret < padlen) {
add_to_be_sent (sock, padbuf, padlen - ret, FALSE);
return TRUE;
} }
} }
...@@ -266,7 +283,7 @@ free_to_be_sent (struct to_be_sent *tbs) ...@@ -266,7 +283,7 @@ free_to_be_sent (struct to_be_sent *tbs)
} }
static void static void
socket_close (NiceUDPSocket *sock) socket_close (NiceSocket *sock)
{ {
TurnTcpPriv *priv = sock->priv; TurnTcpPriv *priv = sock->priv;
close (sock->fileno); close (sock->fileno);
...@@ -275,39 +292,36 @@ socket_close (NiceUDPSocket *sock) ...@@ -275,39 +292,36 @@ socket_close (NiceUDPSocket *sock)
g_slice_free(TurnTcpPriv, sock->priv); g_slice_free(TurnTcpPriv, sock->priv);
} }
static gboolean
socket_is_reliable (NiceSocket *sock)
{
return TRUE;
}
gboolean NiceSocket *
nice_tcp_turn_create_socket_full ( nice_tcp_turn_socket_new (
G_GNUC_UNUSED NiceAgent *agent,
NiceUDPSocketFactory *man, NiceAddress *addr,
NiceUDPSocket *sock, NiceUdpTurnSocketCompatibility compatibility)
NiceAddress *local_addr,
NiceAddress *remote_addr,
NiceUdpTurnSocketCompatibility compatibility,
WriteBlockedCb cb,
gpointer user_data)
{ {
int sockfd = -1; int sockfd = -1;
int ret;
struct sockaddr_storage name; struct sockaddr_storage name;
guint name_len = sizeof (name); guint name_len = sizeof (name);
struct sockaddr_storage remote_name; NiceSocket *sock = g_slice_new0 (NiceSocket);
guint remote_name_len = sizeof (remote_name);
int ret;
TurnTcpPriv *priv; TurnTcpPriv *priv;
if (local_addr != NULL) if (addr != NULL) {
{ nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
nice_address_copy_to_sockaddr(local_addr, (struct sockaddr *)&name); } else {
}
else
{
memset (&name, 0, sizeof (name)); memset (&name, 0, sizeof (name));
name.ss_family = AF_UNSPEC; name.ss_family = AF_UNSPEC;
} }
if ((sockfd == -1) if ((sockfd == -1) &&
&& ((name.ss_family == AF_UNSPEC) || (name.ss_family == AF_INET))) ((name.ss_family == AF_UNSPEC) ||
{ (name.ss_family == AF_INET))) {
sockfd = socket (PF_INET, SOCK_STREAM, 0); sockfd = socket (PF_INET, SOCK_STREAM, 0);
name.ss_family = AF_INET; name.ss_family = AF_INET;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
...@@ -315,8 +329,10 @@ nice_tcp_turn_create_socket_full ( ...@@ -315,8 +329,10 @@ nice_tcp_turn_create_socket_full (
#endif #endif
} }
if (sockfd == -1) if (sockfd == -1) {
return FALSE; g_slice_free (NiceSocket, sock);
return NULL;
}
#ifdef FD_CLOEXEC #ifdef FD_CLOEXEC
fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC); fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
...@@ -325,70 +341,24 @@ nice_tcp_turn_create_socket_full ( ...@@ -325,70 +341,24 @@ nice_tcp_turn_create_socket_full (
fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK); fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
#endif #endif
if(bind (sockfd, (struct sockaddr *) &name, sizeof (name)) != 0)
{
close (sockfd);
return FALSE;
}
if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) != 0) ret = connect (sockfd, (const struct sockaddr *)&name, name_len);
{
close (sockfd);
return FALSE;
}
nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
nice_address_copy_to_sockaddr (remote_addr, (struct sockaddr *)&remote_name);
ret = connect (sockfd, (const struct sockaddr *)&remote_name,
remote_name_len);
if (ret < 0 && errno != EINPROGRESS) { if (ret < 0 && errno != EINPROGRESS) {
close (sockfd); close (sockfd);
return FALSE; g_slice_free (NiceSocket, sock);
return NULL;
} }
sock->priv = priv = g_slice_new0 (TurnTcpPriv); sock->priv = priv = g_slice_new0 (TurnTcpPriv);
priv->cb = cb;
priv->user_data = user_data;
priv->compatibility = compatibility; priv->compatibility = compatibility;
sock->fileno = sockfd; sock->fileno = sockfd;
sock->send = socket_send; sock->send = socket_send;
sock->recv = socket_recv; sock->recv = socket_recv;
sock->is_reliable = socket_is_reliable;
sock->close = socket_close; sock->close = socket_close;
return TRUE;
}
/*** NiceUDPSocketFactory ***/
static void
socket_factory_close (
G_GNUC_UNUSED
NiceUDPSocketFactory *man)
{
(void)man;
}
static gboolean
socket_factory_init_socket (
NiceUDPSocketFactory *man,
NiceUDPSocket *sock,
NiceAddress *addr)
{
return FALSE;
}
NICEAPI_EXPORT void return sock;
nice_tcp_turn_socket_factory_init (
G_GNUC_UNUSED
NiceUDPSocketFactory *man)
{
man->init = socket_factory_init_socket;
man->close = socket_factory_close;
} }
...@@ -38,28 +38,16 @@ ...@@ -38,28 +38,16 @@
#ifndef _TCP_TURN_H #ifndef _TCP_TURN_H
#define _TCP_TURN_H #define _TCP_TURN_H
#include "udp.h" #include "socket.h"
#include "udp-turn.h"
G_BEGIN_DECLS G_BEGIN_DECLS
void
nice_tcp_turn_socket_factory_init (NiceUDPSocketFactory *man);
typedef void (*WriteBlockedCb) (NiceUDPSocket *sock, gpointer user_data); NiceSocket *
nice_tcp_turn_socket_new (
gboolean NiceAgent *agent,
nice_tcp_turn_create_socket_full ( NiceAddress *addr,
G_GNUC_UNUSED NiceUdpTurnSocketCompatibility compatibility);
NiceUDPSocketFactory *man,
NiceUDPSocket *sock,
NiceAddress *local_addr,
NiceAddress *remote_addr,
NiceUdpTurnSocketCompatibility compatibility,
WriteBlockedCb cb,
gpointer user_data);
gint socket_send_more (NiceUDPSocket *sock);
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