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

Replace sockets with GSocket

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