--- a/libpurple/protocols/irc/dcc_send.c Fri Apr 24 01:58:16 2020 +0000
+++ b/libpurple/protocols/irc/dcc_send.c Mon Apr 27 00:31:21 2020 +0000
@@ -32,9 +32,9 @@
- PurpleNetworkListenData *listen_data;
+ GSocketService *service; + GSocketConnection *conn;
@@ -218,124 +218,93 @@
-static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) {
- PurpleXfer *xfer = PURPLE_XFER(data);
+irc_dccsend_send_connected(GSocketService *service, + GSocketConnection *connection, + GObject *source_object, G_GNUC_UNUSED gpointer data) + PurpleXfer *xfer = PURPLE_XFER(source_object); IrcXfer *xd = IRC_XFER(xfer);
- conn = accept(xd->fd, NULL, 0);
- /* Accepting the connection failed. This could just be related
- * to the nonblocking nature of the listening socket, so we'll
- * just try again next time */
- /* Let's print an error message anyway */
- purple_debug_warning("irc", "accept: %s\n", g_strerror(errno));
- purple_input_remove(purple_xfer_get_watcher(xfer));
- purple_xfer_set_watcher(xfer, 0);
- _purple_network_set_common_socket_flags(conn);
- xd->inpa = purple_input_add(conn, PURPLE_INPUT_READ, irc_dccsend_send_read, xfer);
- /* Start the transfer */
- purple_xfer_start(xfer, conn, NULL, 0);
-irc_dccsend_network_listen_cb(int sock, gpointer data)
- PurpleXfer *xfer = PURPLE_XFER(data);
- IrcXfer *xd = IRC_XFER(xfer);
- unsigned short int port;
- /* not sure what the deal is here, but it needs to be here.. gk 20190626 */
- xd->listen_data = NULL;
- if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL
- || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_REMOTE) {
- gc = purple_account_get_connection(purple_xfer_get_account(xfer));
- irc = purple_connection_get_protocol_data(gc);
- purple_notify_error(gc, NULL, _("File Transfer Failed"),
- _("Unable to open a listening port."),
- purple_request_cpar_from_connection(gc));
- purple_xfer_cancel_local(xfer);
+ xd->conn = g_object_ref(connection); + g_socket_service_stop(xd->service); + g_clear_object(&xd->service); - port = purple_network_get_port_from_fd(sock);
- purple_debug_misc("irc", "port is %hu\n", port);
- /* Monitor the listening socket */
- purple_xfer_set_watcher(
- purple_input_add(sock, PURPLE_INPUT_READ, irc_dccsend_send_connected, xfer)
- /* Send the intended recipient the DCC request */
- arg[0] = purple_xfer_get_remote_user(xfer);
+ sock = g_socket_connection_get_socket(connection); + fd = g_socket_get_fd(sock); + _purple_network_set_common_socket_flags(fd); - /* Fetching this fd here assumes it won't be modified */
- gsock = g_socket_connection_get_socket(irc->conn);
- fd = g_socket_get_fd(gsock);
- inet_aton(purple_network_get_my_ip(fd), &addr);
- arg[1] = tmp = g_strdup_printf(
- "\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001",
- purple_xfer_get_filename(xfer),
- purple_xfer_get_size(xfer)
- irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg);
+ xd->inpa = purple_input_add(fd, PURPLE_INPUT_READ, irc_dccsend_send_read, + /* Start the transfer */ + purple_xfer_start(xfer, fd, NULL, 0); * This function is called after the user has selected a file to send.
-static void irc_dccsend_send_init(PurpleXfer *xfer) {
+irc_dccsend_send_init(PurpleXfer *xfer) IrcXfer *xd = IRC_XFER(xfer);
- PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer));
+ purple_account_get_connection(purple_xfer_get_account(xfer)); - purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
+ purple_xfer_set_filename( + xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer))); /* Create a listening socket */
- xd->listen_data = purple_network_listen_range(
- irc_dccsend_network_listen_cb,
- if (xd->listen_data == NULL) {
+ xd->service = g_socket_service_new(); + if (xd->service == NULL) { + purple_notify_error(gc, NULL, _("File Transfer Failed"), + _("Unable to open a listening port."), + purple_request_cpar_from_connection(gc)); + purple_xfer_cancel_local(xfer); + /* Monitor the listening socket */ + g_signal_connect(xd->service, "incoming", + G_CALLBACK(irc_dccsend_send_connected), NULL); + port = purple_socket_listener_add_any_inet_port( + G_SOCKET_LISTENER(xd->service), G_OBJECT(xfer), &error); + purple_xfer_set_local_port(xfer, port); purple_notify_error(gc, NULL, _("File Transfer Failed"),
_("Unable to open a listening port."),
purple_request_cpar_from_connection(gc));
+ g_clear_object(&xd->service); purple_xfer_cancel_local(xfer);
+ irc = purple_connection_get_protocol_data(gc); + purple_debug_misc("irc", "port is %hu\n", port); + /* Send the intended recipient the DCC request */ + arg[0] = purple_xfer_get_remote_user(xfer); + tmp = purple_network_get_my_ip_from_gio(irc->conn); + arg[1] = tmp = g_strdup_printf( + "\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001", + purple_xfer_get_filename(xfer), ntohl(addr.s_addr), port, + purple_xfer_get_size(xfer)); + irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg); PurpleXfer *irc_dccsend_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who) {
@@ -381,8 +350,8 @@
*****************************************************************************/
-irc_xfer_init(IrcXfer *xfer) {
+irc_xfer_init(IrcXfer *xfer) @@ -394,13 +363,14 @@
/* clean up the sending properties */
- g_clear_pointer(&xfer->listen_data, purple_network_listen_cancel);
+ g_socket_service_stop(xfer->service); + g_clear_object(&xfer->service); purple_input_remove(xfer->inpa);
+ g_clear_object(&xfer->conn); G_OBJECT_CLASS(irc_xfer_parent_class)->finalize(obj);
--- a/libpurple/purple-gio.c Fri Apr 24 01:58:16 2020 +0000
+++ b/libpurple/purple-gio.c Mon Apr 27 00:31:21 2020 +0000
@@ -129,3 +129,29 @@
+purple_socket_listener_add_any_inet_port(GSocketListener *listener, + GObject *source_object, GError **error) + GError *internal_error = NULL; + guint16 port, start, end; + if (!purple_prefs_get_bool("/purple/network/ports_range_use")) { + return g_socket_listener_add_any_inet_port(listener, source_object, + start = purple_prefs_get_int("/purple/network/ports_range_start"); + end = purple_prefs_get_int("/purple/network/ports_range_end"); + for (port = start; port <= end; port++) { + if (g_socket_listener_add_inet_port(listener, port, source_object, + } else if (port != end) { + g_error_free(internal_error); + g_propagate_error(error, internal_error); --- a/libpurple/purple-gio.h Fri Apr 24 01:58:16 2020 +0000
+++ b/libpurple/purple-gio.h Mon Apr 27 00:31:21 2020 +0000
@@ -71,6 +71,23 @@
purple_gio_socket_client_new(PurpleAccount *account, GError **error);
+ * purple_socket_listener_add_any_inet_port: + * @listener: A #GSocketListener. + * @source_object: (nullable): Optional GObject identifying this source. + * @error: A #GError location to store the error occurring, or %NULL to ignore. + * Listens for TCP connections on any available port number for both IPv6 and + * IPv4 (if each is available). This is a simple wrapper around + * g_socket_listener_add_any_inet_port(), except if the user specified a port + * range in the settings, than a port will be chosen from that range. + * Returns: The port number, or 0 in case of failure. +guint16 purple_socket_listener_add_any_inet_port(GSocketListener *listener, + GObject *source_object, #endif /* PURPLE_GIO_H */