Commit 041ae5b3 authored by Livio Madaro's avatar Livio Madaro Committed by Youness Alaoui
Browse files

Replace sockets with GSocket

Use GSocket for better Windows compatibility
parent 146ce0f8
......@@ -2292,7 +2292,7 @@ _nice_agent_recv (
gchar tmpbuf[INET6_ADDRSTRLEN];
nice_address_to_string (&from, tmpbuf);
nice_debug ("Agent %p : Packet received on local socket %u from [%s]:%u (%u octets).", agent,
socket->fileno, tmpbuf, nice_address_get_port (&from), len);
g_socket_get_fd(socket->fileno), tmpbuf, nice_address_get_port (&from), len);
}
#endif
......@@ -2549,7 +2549,6 @@ typedef struct _IOCtx IOCtx;
struct _IOCtx
{
GIOChannel *channel;
GSource *source;
NiceAgent *agent;
Stream *stream;
......@@ -2564,7 +2563,6 @@ io_ctx_new (
Stream *stream,
Component *component,
NiceSocket *socket,
GIOChannel *channel,
GSource *source)
{
IOCtx *ctx;
......@@ -2574,7 +2572,6 @@ io_ctx_new (
ctx->stream = stream;
ctx->component = component;
ctx->socket = socket;
ctx->channel = channel;
ctx->source = source;
return ctx;
......@@ -2584,7 +2581,6 @@ io_ctx_new (
static void
io_ctx_free (IOCtx *ctx)
{
g_io_channel_unref (ctx->channel);
g_slice_free (IOCtx, ctx);
}
......@@ -2669,21 +2665,17 @@ agent_attach_stream_component_socket (NiceAgent *agent,
Component *component,
NiceSocket *socket)
{
GIOChannel *io;
GSource *source;
IOCtx *ctx;
if (!component->ctx)
return;
#ifndef G_OS_WIN32
io = g_io_channel_unix_new (socket->fileno);
#else
io = g_io_channel_win32_new_socket (socket->fileno);
#endif
/* note: without G_IO_ERR the glib mainloop goes into
* busyloop if errors are encountered */
source = g_io_create_watch (io, G_IO_IN | G_IO_ERR);
ctx = io_ctx_new (agent, stream, component, socket, io, source);
source = g_socket_create_source(socket->fileno, G_IO_IN | G_IO_ERR, NULL);
ctx = io_ctx_new (agent, stream, component, socket, source);
g_source_set_callback (source, (GSourceFunc) nice_agent_g_source_cb,
ctx, (GDestroyNotify) io_ctx_free);
nice_debug ("Agent %p : Attach source %p (stream %u).", agent, source, stream->id);
......@@ -2908,13 +2900,13 @@ nice_agent_set_selected_remote_candidate (
void
_priv_set_socket_tos (NiceAgent *agent, NiceSocket *sock, gint tos)
{
if (setsockopt (sock->fileno, IPPROTO_IP,
if (setsockopt (g_socket_get_fd(sock->fileno), IPPROTO_IP,
IP_TOS, (const char *) &tos, sizeof (tos)) < 0) {
nice_debug ("Agent %p: Could not set socket ToS", agent,
g_strerror (errno));
}
#ifdef IPV6_TCLASS
if (setsockopt (sock->fileno, IPPROTO_IPV6,
if (setsockopt (g_socket_get_fd(sock->fileno), IPPROTO_IPV6,
IPV6_TCLASS, (const char *) &tos, sizeof (tos)) < 0) {
nice_debug ("Agent %p: Could not set IPV6 socket ToS", agent,
g_strerror (errno));
......
......@@ -582,7 +582,7 @@ static gboolean priv_conn_keepalive_tick_unlocked (NiceAgent *agent)
"socket=%u (c-id:%u), username='%s' (%d), "
"password='%s' (%d), priority=%u.", agent,
tmpbuf, nice_address_get_port (&p->remote->addr),
((NiceSocket *)p->local->sockptr)->fileno, component->id,
g_socket_get_fd(((NiceSocket *)p->local->sockptr)->fileno), component->id,
uname, uname_len, password, password_len, priority);
if (uname_len > 0) {
......@@ -1619,7 +1619,7 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair)
nice_debug ("Agent %p : STUN-CC REQ to '%s:%u', socket=%u, pair=%s (c-id:%u), tie=%llu, username='%s' (%d), password='%s' (%d), priority=%u.", agent,
tmpbuf,
nice_address_get_port (&pair->remote->addr),
((NiceSocket *)pair->local->sockptr)->fileno,
g_socket_get_fd(((NiceSocket *)pair->local->sockptr)->fileno),
pair->foundation, pair->component_id,
(unsigned long long)agent->tie_breaker,
uname, uname_len, password, password_len, priority);
......@@ -1847,7 +1847,7 @@ static void priv_reply_to_conn_check (NiceAgent *agent, Stream *stream, Componen
nice_debug ("Agent %p : STUN-CC RESP to '%s:%u', socket=%u, len=%u, cand=%p (c-id:%u), use-cand=%d.", agent,
tmpbuf,
nice_address_get_port (toaddr),
socket->fileno,
g_socket_get_fd(socket->fileno),
(unsigned)rbuf_len,
rcand, component->id,
(int)use_candidate);
......
......@@ -38,6 +38,7 @@
#define _SOCKET_H
#include "address.h"
#include <gio/gio.h>
#ifdef G_OS_WIN32
#include <winsock2.h>
......@@ -56,7 +57,7 @@ typedef struct _NiceSocket NiceSocket;
struct _NiceSocket
{
NiceAddress addr;
guint fileno;
GSocket *fileno;
gint (*recv) (NiceSocket *sock, NiceAddress *from, guint len,
gchar *buf);
gboolean (*send) (NiceSocket *sock, const NiceAddress *to, guint len,
......
......@@ -57,7 +57,6 @@ typedef struct {
NiceAddress server_addr;
GQueue send_queue;
GMainContext *context;
GIOChannel *io_channel;
GSource *io_source;
gboolean error;
} TcpPriv;
......@@ -87,15 +86,14 @@ static gboolean socket_send_more (GIOChannel *source, GIOCondition condition,
NiceSocket *
nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
{
int sockfd = -1;
int ret;
struct sockaddr_storage name;
socklen_t name_len = sizeof (name);
NiceSocket *sock;
TcpPriv *priv;
#ifdef G_OS_WIN32
unsigned long set_nonblock=1;
#endif
GSocket *gsock = NULL;
GError *gerr = NULL;
boolean gret;
GSocketAddress *gaddr;
if (addr == NULL) {
/* We can't connect a tcp socket with no destination address */
......@@ -106,15 +104,16 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
if (sockfd == -1) {
if (gsock == NULL) {
if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
sockfd = socket (PF_INET, SOCK_STREAM, 0);
gsock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL);
name.ss_family = AF_INET;
#ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in);
#endif
} else if (name.ss_family == AF_INET6) {
sockfd = socket (PF_INET6, SOCK_STREAM, 0);
gsock = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL);
name.ss_family = AF_INET6;
#ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in6);
......@@ -122,56 +121,60 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
}
}
if (sockfd == -1) {
if(gsock == NULL) {
g_slice_free (NiceSocket, sock);
return NULL;
}
}
#ifdef FD_CLOEXEC
fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
#endif
#ifdef O_NONBLOCK
fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
#elif defined G_OS_WIN32
ioctlsocket(sockfd, FIONBIO, &set_nonblock);
#endif
/* GSocket: All socket file descriptors are set to be close-on-exec. */
g_socket_set_blocking(gsock, false);
name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
ret = connect (sockfd, (const struct sockaddr *)&name, name_len);
#ifdef G_OS_WIN32
if (ret < 0 && WSAGetLastError () != WSAEWOULDBLOCK) {
closesocket (sockfd);
#else
if (ret < 0 && errno != EINPROGRESS) {
close (sockfd);
#endif
g_slice_free (NiceSocket, sock);
return NULL;
gaddr = g_socket_address_new_from_native(&name, name_len);
gret = g_socket_connect(gsock, gaddr, NULL, &gerr);
g_object_unref(gaddr);
if(gret == FALSE)
{
if(g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_PENDING) == FALSE)
{
g_socket_close(gsock, NULL);
g_object_unref(gsock);
g_slice_free (NiceSocket, sock);
return NULL;
}
g_error_free(gerr);
}
name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) {
gaddr = g_socket_get_local_address(gsock, NULL);
if(gaddr == NULL)
{
g_slice_free (NiceSocket, sock);
#ifdef G_OS_WIN32
closesocket(sockfd);
#else
close (sockfd);
#endif
g_socket_close(gsock, NULL);
g_object_unref(gsock);
return NULL;
}
nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
g_socket_address_to_native(gaddr, &name, name_len, NULL);
g_object_unref(gaddr);
nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
sock->priv = priv = g_slice_new0 (TcpPriv);
priv->context = g_main_context_ref (ctx);
priv->server_addr = *addr;
priv->error = FALSE;
sock->fileno = sockfd;
sock->fileno = gsock;
sock->send = socket_send;
sock->recv = socket_recv;
sock->is_reliable = socket_is_reliable;
......@@ -186,17 +189,15 @@ socket_close (NiceSocket *sock)
{
TcpPriv *priv = sock->priv;
#ifdef G_OS_WIN32
closesocket(sock->fileno);
#else
close (sock->fileno);
#endif
if(sock->fileno) {
g_socket_close(sock->fileno, NULL);
g_object_unref(sock->fileno);
sock->fileno = NULL;
}
if (priv->io_source) {
g_source_destroy (priv->io_source);
g_source_unref (priv->io_source);
}
if (priv->io_channel)
g_io_channel_unref (priv->io_channel);
g_queue_foreach (&priv->send_queue, (GFunc) free_to_be_sent, NULL);
g_queue_clear (&priv->send_queue);
......@@ -211,12 +212,13 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
{
TcpPriv *priv = sock->priv;
int ret;
GError *gerr = NULL;
/* Don't try to access the socket if it had an error */
if (priv->error)
return -1;
ret = recv (sock->fileno, buf, len, 0);
ret = g_socket_receive(sock->fileno, buf, len, NULL, &gerr);
/* recv returns 0 when the peer performed a shutdown.. we must return -1 here
* so that the agent destroys the g_source */
......@@ -226,14 +228,11 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
}
if (ret < 0) {
#ifdef G_OS_WIN32
if (WSAGetLastError () == WSAEWOULDBLOCK)
#else
if (errno == EAGAIN)
#endif
return 0;
else
return ret;
if(g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
ret = 0;
g_error_free(gerr);
return ret;
}
if (from)
......@@ -250,6 +249,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
{
TcpPriv *priv = sock->priv;
int ret;
GError *gerr = NULL;
/* Don't try to access the socket if it had an error, otherwise we risk a
crash with SIGPIPE (Broken pipe) */
......@@ -259,18 +259,15 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
/* First try to send the data, don't send it later if it can be sent now
this way we avoid allocating memory on every send */
if (g_queue_is_empty (&priv->send_queue)) {
ret = send (sock->fileno, buf, len, 0);
ret = g_socket_send (sock->fileno, buf, len, NULL, &gerr);
if (ret < 0) {
#ifdef G_OS_WIN32
if (WSAGetLastError () == WSAEWOULDBLOCK ||
WSAGetLastError () == WSAENOTCONN) {
#else
if (errno == EAGAIN) {
#endif
if(g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)
|| g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_FAILED)) {
add_to_be_sent (sock, buf, len, FALSE);
g_error_free(gerr);
return TRUE;
} else {
g_error_free(gerr);
return FALSE;
}
} else if ((guint)ret < len) {
......@@ -321,6 +318,7 @@ socket_send_more (
NiceSocket *sock = (NiceSocket *) data;
TcpPriv *priv = sock->priv;
struct to_be_sent *tbs = NULL;
GError *gerr = NULL;
agent_lock ();
......@@ -334,19 +332,22 @@ socket_send_more (
while ((tbs = g_queue_pop_head (&priv->send_queue)) != NULL) {
int ret;
ret = send (sock->fileno, tbs->buf, tbs->length, 0);
if(condition & G_IO_HUP) {
/* connection hangs up */
ret = -1;
}
else
ret = g_socket_send (sock->fileno, tbs->buf, tbs->length, NULL, &gerr);
if (ret < 0) {
#ifdef G_OS_WIN32
if (WSAGetLastError () == WSAEWOULDBLOCK) {
#else
if (errno == EAGAIN) {
#endif
if(gerr!=NULL && g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
add_to_be_sent (sock, tbs->buf, tbs->length, TRUE);
g_free (tbs->buf);
g_slice_free (struct to_be_sent, tbs);
g_error_free(gerr);
break;
}
g_error_free(gerr);
} else if (ret < (int) tbs->length) {
add_to_be_sent (sock, tbs->buf + ret, tbs->length - ret, TRUE);
g_free (tbs->buf);
......@@ -359,8 +360,6 @@ socket_send_more (
}
if (g_queue_is_empty (&priv->send_queue)) {
g_io_channel_unref (priv->io_channel);
priv->io_channel = NULL;
g_source_destroy (priv->io_source);
g_source_unref (priv->io_source);
priv->io_source = NULL;
......@@ -392,13 +391,8 @@ add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head)
else
g_queue_push_tail (&priv->send_queue, tbs);
if (priv->io_channel == NULL) {
#ifndef G_OS_WIN32
priv->io_channel = g_io_channel_unix_new (sock->fileno);
#else
priv->io_channel = g_io_channel_win32_new_socket (sock->fileno);
#endif
priv->io_source = g_io_create_watch (priv->io_channel, G_IO_OUT);
if (priv->io_source == NULL) {
priv->io_source = g_socket_create_source(sock->fileno, G_IO_OUT, NULL);
g_source_set_callback (priv->io_source, (GSourceFunc) socket_send_more,
sock, NULL);
g_source_attach (priv->io_source, priv->context);
......
......@@ -66,13 +66,12 @@ static gboolean socket_is_reliable (NiceSocket *sock);
NiceSocket *
nice_udp_bsd_socket_new (NiceAddress *addr)
{
int sockfd = -1;
struct sockaddr_storage name;
socklen_t name_len = sizeof (name);
NiceSocket *sock = g_slice_new0 (NiceSocket);
#ifdef G_OS_WIN32
unsigned long set_nonblock=1;
#endif
GSocket *gsock = NULL;
gboolean gret;
GSocketAddress *gaddr;
if (addr != NULL) {
nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
......@@ -82,60 +81,53 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
}
if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
gsock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL);
name.ss_family = AF_INET;
#ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in);
#endif
} else if (name.ss_family == AF_INET6) {
sockfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
gsock = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL);
name.ss_family = AF_INET6;
#ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in6);
#endif
}
if (sockfd == -1) {
if(gsock == NULL) {
g_slice_free (NiceSocket, sock);
return NULL;
}
}
/* GSocket: All socket file descriptors are set to be close-on-exec. */
g_socket_set_blocking(gsock, false);
#ifdef FD_CLOEXEC
fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
#endif
#ifdef O_NONBLOCK
fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
#elif defined G_OS_WIN32
ioctlsocket(sockfd, FIONBIO, &set_nonblock);
#endif
name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
if(bind (sockfd, (struct sockaddr *) &name,
name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6)) < 0) {
gret = g_socket_bind(gsock, g_socket_address_new_from_native(&name, name_len), FALSE, NULL);
if(gret == FALSE) {
g_slice_free (NiceSocket, sock);
#ifdef G_OS_WIN32
closesocket(sockfd);
#else
close (sockfd);
#endif
g_socket_close(gsock, NULL);
g_object_unref(gsock);
return NULL;
}
name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) {
gaddr = g_socket_get_local_address(gsock, NULL);
if(gaddr == NULL) {
g_slice_free (NiceSocket, sock);
#ifdef G_OS_WIN32
closesocket(sockfd);
#else
close (sockfd);
#endif
g_socket_close(gsock, NULL);
g_object_unref(gsock);
return NULL;
}
nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
sock->fileno = sockfd;
g_socket_address_to_native(gaddr, &name, name_len, NULL);
g_object_unref(gaddr);
nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
//sock->gsock = gsock;
sock->fileno = gsock;
sock->send = socket_send;
sock->recv = socket_recv;
sock->is_reliable = socket_is_reliable;
......@@ -147,11 +139,11 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
static void
socket_close (NiceSocket *sock)
{
#ifdef G_OS_WIN32
closesocket(sock->fileno);
#else
close (sock->fileno);
#endif
if(sock->fileno) {
g_socket_close(sock->fileno, NULL);
g_object_unref(sock->fileno);
sock->fileno = NULL;
}
}
static gint
......@@ -160,22 +152,26 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
gint recvd;
struct sockaddr_storage sa;
socklen_t from_len = sizeof (sa);
GSocketAddress *gaddr = NULL;
GError *gerr = NULL;
recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
&from_len);
recvd = g_socket_receive_from(sock->fileno, &gaddr, buf, len, NULL, &gerr);
if (recvd < 0) {
#ifdef G_OS_WIN32
if (WSAGetLastError () == WSAEWOULDBLOCK ||
WSAGetLastError () == WSAECONNRESET)
#else
if (errno == EAGAIN || errno == EWOULDBLOCK)
#endif
return 0;
if(g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)
|| g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_FAILED))
recvd = 0;
g_error_free(gerr);
}
if (recvd > 0)
if (recvd > 0) {
if(gaddr != NULL) {
g_socket_address_to_native(gaddr, &sa, from_len, NULL);
g_object_unref(gaddr);
}
nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
}
return recvd;
}
......@@ -186,12 +182,18 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
{
struct sockaddr_storage sa;
ssize_t sent;
socklen_t name_len = sizeof (sa);
GSocketAddress *gaddr;
nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
sa.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6));
name_len = sa.ss_family == AF_INET? sizeof (struct sockaddr_in) :
sizeof(struct sockaddr_in6);
gaddr = g_socket_address_new_from_native(&sa, name_len);
sent = g_socket_send_to(sock->fileno, gaddr, buf, len, NULL, NULL);
g_object_unref(gaddr);
return sent == (ssize_t)len;
}
......
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