static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
NiceSocket *
nice_http_socket_new (NiceSocket *base_socket,
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
/* Send HTTP CONNECT */
return nice_socket_is_reliable (priv->base_socket);
}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ HttpPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ HttpPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
NiceSocket *
nice_pseudossl_socket_new (NiceSocket *base_socket,
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
/* We send 'to' NULL because it will always be to an already connected
return nice_socket_is_reliable (priv->base_socket);
}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
return sock->is_reliable (sock);
}
+gboolean
+nice_socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ if (sock->can_send)
+ return sock->can_send (sock, addr);
+ return TRUE;
+}
+
+void
+nice_socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ if (sock->set_writable_callback)
+ sock->set_writable_callback (sock, callback, user_data);
+}
+
void
nice_socket_free (NiceSocket *sock)
{
NICE_SOCKET_TYPE_TCP_SO
} NiceSocketType;
+typedef void (*NiceSocketWritableCb) (NiceSocket *sock, gpointer user_data);
+
struct _NiceSocket
{
NiceAddress addr;
gint (*send_messages_reliable) (NiceSocket *sock, const NiceAddress *to,
const NiceOutputMessage *messages, guint n_messages);
gboolean (*is_reliable) (NiceSocket *sock);
+ gboolean (*can_send) (NiceSocket *sock, NiceAddress *addr);
+ void (*set_writable_callback) (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
void (*close) (NiceSocket *sock);
void *priv;
};
+
G_GNUC_WARN_UNUSED_RESULT
gint
nice_socket_recv_messages (NiceSocket *sock,
gboolean
nice_socket_is_reliable (NiceSocket *sock);
+gboolean
+nice_socket_can_send (NiceSocket *sock, NiceAddress *addr);
+
+void
+nice_socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
void
nice_socket_free (NiceSocket *sock);
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
NiceSocket *
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
/* Send SOCKS5 handshake */
return nice_socket_is_reliable (priv->base_socket);
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ Socks5Priv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ Socks5Priv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
NiceSocket *
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
return sock;
return TRUE;
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ return FALSE;
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+}
+
NiceSocket *
nice_tcp_active_socket_connect (NiceSocket *sock, NiceAddress *addr)
{
GSource *io_source;
gboolean error;
gboolean reliable;
+ NiceSocketWritableCb writable_cb;
+ gpointer writable_data;
} TcpPriv;
#define MAX_QUEUE_LENGTH 20
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
static gboolean socket_send_more (GSocket *gsocket, GIOCondition condition,
gpointer data);
priv->remote_addr = *remote_addr;
priv->error = FALSE;
priv->reliable = reliable;
+ priv->writable_cb = NULL;
+ priv->writable_data = NULL;
sock->type = NICE_SOCKET_TYPE_TCP_BSD;
sock->fileno = g_object_ref (gsock);
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
return sock;
return priv->reliable;
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TcpPriv *priv = sock->priv;
-/*
- * Returns:
- * -1 = error
- * 0 = have more to send
- * 1 = sent everything
- */
+ return g_queue_is_empty (&priv->send_queue);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TcpPriv *priv = sock->priv;
+
+ priv->writable_cb = callback;
+ priv->writable_data = user_data;
+}
static gboolean
socket_send_more (
priv->io_source = NULL;
agent_unlock ();
+
+ if (priv->writable_cb)
+ priv->writable_cb (sock, priv->writable_data);
+
return FALSE;
}
G_BEGIN_DECLS
-
NiceSocket *
nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *remote_addr,
NiceAddress *local_addr, gboolean reliable);
typedef struct {
GMainContext *context;
GHashTable *connections;
+ NiceSocketWritableCb writable_cb;
+ gpointer writable_data;
} TcpPassivePriv;
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
static guint nice_address_hash (const NiceAddress * key);
+static void _set_child_callbacks (NiceAddress *addr, NiceSocket *child,
+ NiceSocket *sock);
NiceSocket *
nice_tcp_passive_socket_new (GMainContext *ctx, NiceAddress *addr)
priv->connections = g_hash_table_new_full ((GHashFunc) nice_address_hash,
(GEqualFunc) nice_address_equal, (
GDestroyNotify) nice_address_free, NULL);
+ priv->writable_cb = NULL;
+ priv->writable_data = NULL;
sock->type = NICE_SOCKET_TYPE_TCP_PASSIVE;
sock->fileno = gsock;
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
return sock;
return TRUE;
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TcpPassivePriv *priv = sock->priv;
+ NiceSocket *peer_socket = NULL;
+
+ /* FIXME: Danger if child socket was closed */
+ if (addr)
+ peer_socket = g_hash_table_lookup (priv->connections, addr);
+ if (peer_socket)
+ return nice_socket_can_send (peer_socket, addr);
+ return FALSE;
+}
+
+static void
+_set_child_callbacks (NiceAddress *addr, NiceSocket *child, NiceSocket *sock)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ /* FIXME: Danger if child socket was closed */
+ nice_socket_set_writable_callback (child, priv->writable_cb,
+ priv->writable_data);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ priv->writable_cb = callback;
+ priv->writable_data = user_data;
+
+ g_hash_table_foreach (priv->connections, (GHFunc) _set_child_callbacks, sock);
+}
+
NiceSocket *
nice_tcp_passive_socket_accept (NiceSocket *sock)
{
if (new_socket) {
NiceAddress *key = nice_address_dup (&remote_addr);
+ _set_child_callbacks (key, new_socket, sock);
g_hash_table_insert (priv->connections, key, new_socket);
}
return new_socket;
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
struct UdpBsdSocketPrivate
{
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
return sock;
return FALSE;
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ return TRUE;
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+}
+
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
NiceSocket *
nice_udp_turn_over_tcp_socket_new (NiceSocket *base_socket,
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
return sock;
return nice_socket_is_reliable (priv->base_socket);
}
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
static gint socket_send_messages_reliable (NiceSocket *sock,
const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
static void priv_process_pending_bindings (UdpTurnPriv *priv);
static gboolean priv_retransmissions_tick_unlocked (UdpTurnPriv *priv);
sock->send_messages_reliable = socket_send_messages_reliable;
sock->recv_messages = socket_recv_messages;
sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
sock->close = socket_close;
sock->priv = (void *) priv;
}
static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ UdpTurnPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ UdpTurnPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
priv_forget_send_request (gpointer pointer)
{
SendRequest *req = pointer;