xmpp: Convert si xfer to gio socket server.

Tue, 12 May 2020 03:01:37 -0400

author
Elliott Sales de Andrade <qulogic@pidgin.im>
date
Tue, 12 May 2020 03:01:37 -0400
changeset 40404
d85e4d3f17be
parent 40403
5529108bd66e
child 40405
dc115c3b7694

xmpp: Convert si xfer to gio socket server.

libpurple/protocols/jabber/si.c file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/jabber/si.c	Tue May 12 01:44:23 2020 -0400
+++ b/libpurple/protocols/jabber/si.c	Tue May 12 03:01:37 2020 -0400
@@ -42,7 +42,7 @@
 	JabberStream *js;
 
 	PurpleProxyConnectData *connect_data;
-	PurpleNetworkListenData *listen_data;
+	GSocketService *service;
 	guint connect_timeout;
 
 	gboolean accepted;
@@ -63,7 +63,7 @@
 	char *rxqueue;
 	size_t rxlen;
 	gsize rxmaxlen;
-	int local_streamhost_fd;
+	GSocketConnection *local_streamhost_conn;
 
 	JabberIBBSession *ibb_session;
 	guint ibb_timeout_handle;
@@ -659,32 +659,30 @@
 }
 
 static void
-jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
+jabber_si_xfer_bytestreams_send_connected_cb(GSocketService *service,
+                                             GSocketConnection *connection,
+                                             GObject *source_object,
+                                             G_GNUC_UNUSED gpointer data)
 {
-	PurpleXfer *xfer = data;
+	PurpleXfer *xfer = PURPLE_XFER(source_object);
 	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	int acceptfd;
+	GSocket *sock;
+	int fd;
 
 	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n");
 
-	acceptfd = accept(source, NULL, 0);
-	if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		return;
-	else if(acceptfd == -1) {
-		purple_debug_warning("jabber", "accept: %s\n", g_strerror(errno));
-		/* Don't cancel the ft - allow it to fall to the next streamhost.*/
-		return;
-	}
+	jsx->local_streamhost_conn = g_object_ref(connection);
+	g_socket_service_stop(jsx->service);
+	g_clear_object(&jsx->service);
 
-	purple_input_remove(purple_xfer_get_watcher(xfer));
-	close(source);
-	jsx->local_streamhost_fd = -1;
+	sock = g_socket_connection_get_socket(connection);
+	fd = g_socket_get_fd(sock);
+	_purple_network_set_common_socket_flags(fd);
 
-	_purple_network_set_common_socket_flags(acceptfd);
-
-	purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ,
-					 jabber_si_xfer_bytestreams_send_read_cb, xfer));
+	purple_xfer_set_watcher(
+	        xfer,
+	        purple_input_add(fd, PURPLE_INPUT_READ,
+	                         jabber_si_xfer_bytestreams_send_read_cb, xfer));
 }
 
 static void
@@ -793,13 +791,10 @@
 	}
 
 	/* Clean up the local streamhost - it isn't going to be used.*/
-	if (purple_xfer_get_watcher(xfer) > 0) {
-		purple_input_remove(purple_xfer_get_watcher(xfer));
-		purple_xfer_set_watcher(xfer, 0);
-	}
-	if (jsx->local_streamhost_fd >= 0) {
-		close(jsx->local_streamhost_fd);
-		jsx->local_streamhost_fd = -1;
+	g_clear_object(&jsx->local_streamhost_conn);
+	if (jsx->service) {
+		g_socket_service_stop(jsx->service);
+		g_clear_object(&jsx->service);
 	}
 
 	jsx->streamhosts = g_list_remove_link(jsx->streamhosts, matched);
@@ -919,31 +914,42 @@
 }
 
 static void
-jabber_si_xfer_bytestreams_listen_cb(int sock, gpointer data)
+jabber_si_xfer_bytestreams_send_init(PurpleXfer *xfer)
 {
-	PurpleXfer *xfer = PURPLE_XFER(data);
 	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
+	PurpleProxyType proxy_type;
 	GList *local_ips = NULL;
 
-	jsx->listen_data = NULL;
-
-	/* I'm not sure under which conditions this can happen
-	 * (it seems like it shouldn't be possible */
-	if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) {
-		g_object_unref(xfer);
-		return;
+	/* TODO: This should probably be done with an account option instead of
+	 *       piggy-backing on the TOR proxy type. */
+	proxy_type = purple_proxy_info_get_proxy_type(
+	        purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc)));
+	if (proxy_type == PURPLE_PROXY_TOR) {
+		purple_debug_info("jabber", "Skipping attempting local streamhost.\n");
+		jsx->service = NULL;
+	} else {
+		guint16 port = 0;
+		GError *error = NULL;
+		jsx->service = g_socket_service_new();
+		port = purple_socket_listener_add_any_inet_port(
+		        G_SOCKET_LISTENER(jsx->service), G_OBJECT(xfer), &error);
+		if (port != 0) {
+			purple_xfer_set_local_port(xfer, port);
+		} else {
+			purple_debug_error("jabber",
+			                   "Unable to create streamhost socket listener: "
+			                   "%s. Trying proxy instead.",
+			                   error->message);
+			g_error_free(error);
+			g_clear_object(&jsx->service);
+		}
 	}
 
-	/* If we successfully started listening locally */
-	if (sock >= 0) {
+	if (jsx->service) {
 		GList *l = NULL;
 		gchar *public_ip;
 		gboolean has_public_ip = FALSE;
 
-		jsx->local_streamhost_fd = sock;
-
-		purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock));
-
 		public_ip = purple_network_get_my_ip_from_gio(
 		        G_SOCKET_CONNECTION(jsx->js->stream));
 
@@ -961,44 +967,12 @@
 			local_ips = g_list_append(local_ips, public_ip);
 		}
 
-		/* The listener for the local proxy */
-		purple_xfer_set_watcher(
-		        xfer,
-		        purple_input_add(sock, PURPLE_INPUT_READ,
-		                         jabber_si_xfer_bytestreams_send_connected_cb,
-		                         xfer));
+		g_signal_connect(
+		        G_OBJECT(jsx->service), "incoming",
+		        G_CALLBACK(jabber_si_xfer_bytestreams_send_connected_cb), NULL);
 	}
 
 	jabber_si_xfer_bytestreams_send_local_info(xfer, local_ips);
-
-	g_object_unref(xfer);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_init(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx;
-	PurpleProxyType proxy_type;
-
-	jsx = JABBER_SI_XFER(xfer);
-
-	/* TODO: This should probably be done with an account option instead of
-	 *       piggy-backing on the TOR proxy type. */
-	proxy_type = purple_proxy_info_get_proxy_type(
-		purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc)));
-	if (proxy_type == PURPLE_PROXY_TOR) {
-		purple_debug_info("jabber", "Skipping attempting local streamhost.\n");
-		jsx->listen_data = NULL;
-	} else
-		jsx->listen_data = purple_network_listen_range(
-		        0, 0, AF_UNSPEC, SOCK_STREAM, TRUE,
-		        jabber_si_xfer_bytestreams_listen_cb, g_object_ref(xfer));
-
-	if (jsx->listen_data == NULL) {
-		/* We couldn't open a local port.  Perhaps we can use a proxy. */
-		jabber_si_xfer_bytestreams_send_local_info(xfer, NULL);
-	}
-
 }
 
 static void
@@ -1749,7 +1723,6 @@
  *****************************************************************************/
 static void
 jabber_si_xfer_init(JabberSIXfer *xfer) {
-	xfer->local_streamhost_fd = -1;
 	xfer->ibb_session = NULL;
 }
 
@@ -1764,18 +1737,16 @@
 		purple_proxy_connect_cancel(jsx->connect_data);
 	}
 
-	if (jsx->listen_data != NULL) {
-		purple_network_listen_cancel(jsx->listen_data);
+	g_clear_object(&jsx->local_streamhost_conn);
+	if (jsx->service) {
+		g_socket_service_stop(jsx->service);
 	}
+	g_clear_object(&jsx->service);
 
 	if (jsx->iq_id != NULL) {
 		jabber_iq_remove_callback_by_id(js, jsx->iq_id);
 	}
 
-	if (jsx->local_streamhost_fd >= 0) {
-		close(jsx->local_streamhost_fd);
-	}
-
 	if (purple_xfer_get_xfer_type(PURPLE_XFER(jsx)) == PURPLE_XFER_TYPE_SEND && purple_xfer_get_fd(PURPLE_XFER(jsx)) >= 0) {
 		purple_debug_info("jabber", "remove port mapping\n");
 		purple_network_remove_port_mapping(purple_xfer_get_fd(PURPLE_XFER(jsx)));

mercurial