--- a/libpurple/upnp.c Fri Dec 11 04:12:45 2020 -0600
+++ b/libpurple/upnp.c Mon Dec 14 16:31:55 2020 -0600
@@ -29,6 +29,7 @@
@@ -113,14 +114,14 @@
guint inpa; /* purple_input_add handle */
guint tima; /* g_timeout_add handle */
- struct sockaddr_in server;
+ GSocketAddress *server; @@ -386,7 +387,7 @@
control_info.status = control_url ? PURPLE_UPNP_STATUS_DISCOVERED
: PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER;
- control_info.lookup_time = time(NULL);
+ control_info.lookup_time = g_get_monotonic_time(); control_info.control_url = control_url;
g_strlcpy(control_info.service_type, dd->service_type,
sizeof(control_info.service_type));
@@ -399,11 +400,17 @@
- purple_input_remove(dd->inpa);
+ g_source_remove(dd->inpa); g_source_remove(dd->tima);
+ g_clear_object(&dd->socket); + g_clear_object(&dd->server); @@ -486,29 +493,30 @@
UPnPDiscoveryData* dd = data;
- purple_input_remove(dd->inpa);
+ g_source_remove(dd->inpa); g_source_remove(dd->tima);
if (dd->retry_count < NUM_UDP_ATTEMPTS) {
/* TODO: We probably shouldn't be incrementing retry_count in two places */
purple_upnp_discover_send_broadcast(dd);
control_info.status = PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER;
- control_info.lookup_time = time(NULL);
+ control_info.lookup_time = g_get_monotonic_time(); control_info.service_type[0] = '\0';
g_free(control_info.control_url);
control_info.control_url = NULL;
fire_discovery_callbacks(FALSE);
+ g_clear_object(&dd->socket); + g_clear_object(&dd->server); @@ -516,31 +524,24 @@
-purple_upnp_discover_udp_read(gpointer data, gint sock, PurpleInputCondition cond)
+purple_upnp_discover_udp_read(GSocket *socket, GIOCondition condition,
UPnPDiscoveryData *dd = data;
- len = recv(dd->fd, buf,
- } else if(errno != EINTR) {
- /* We'll either get called again, or time out */
- } while (errno == EINTR);
+ len = g_socket_receive(dd->socket, buf, sizeof(buf) - 1, NULL, NULL); + /* We'll either get called again, or time out */ - purple_input_remove(dd->inpa);
+ g_source_remove(dd->inpa);
/* parse the response, and see if it was a success */
purple_upnp_parse_discover_response(buf, len, dd);
@@ -553,6 +554,7 @@
gchar *sendMessage = NULL;
/* because we are sending over UDP, if there is a failure
we should retry the send NUM_UDP_ATTEMPTS times. Also,
@@ -571,23 +573,29 @@
totalSize = strlen(sendMessage);
- gssize sent = sendto(dd->fd, sendMessage, totalSize, 0,
- (struct sockaddr*) &(dd->server),
- sizeof(struct sockaddr_in));
+ sent = g_socket_send_to(dd->socket, dd->server, sendMessage, + totalSize, NULL, &error); if (sent >= 0 && (gsize)sent == totalSize) {
- } while (errno == EINTR || errno == EAGAIN);
+ } while (error != NULL && error->code == G_IO_ERROR_WOULD_BLOCK); + source = g_socket_create_source(dd->socket, G_IO_IN, NULL); + g_source_set_callback(source, + G_SOURCE_FUNC(purple_upnp_discover_udp_read), + dd->inpa = g_source_attach(source, NULL); + g_object_unref(source); dd->tima = g_timeout_add_seconds(DISCOVERY_TIMEOUT,
purple_upnp_discover_timeout, dd);
- dd->inpa = purple_input_add(dd->fd, PURPLE_INPUT_READ,
- purple_upnp_discover_udp_read, dd);
@@ -601,8 +609,8 @@
purple_upnp_discover(PurpleUPnPCallback cb, gpointer cb_data)
/* Socket Setup Variables */
/* UDP RECEIVE VARIABLES */
@@ -625,30 +633,22 @@
- dd->fd = sock = socket(AF_INET, SOCK_DGRAM, 0);
- purple_debug_error("upnp",
- "purple_upnp_discover(): Failed In sock creation\n");
+ g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_DEFAULT, &error); + "upnp", "purple_upnp_discover(): Failed in sock creation: %s", /* Short circuit the retry attempts */
dd->retry_count = NUM_UDP_ATTEMPTS;
dd->tima = g_timeout_add(10, purple_upnp_discover_timeout, dd);
- /* TODO: Non-blocking! */
- if((hp = gethostbyname(HTTPMU_HOST_ADDRESS)) == NULL) {
- purple_debug_error("upnp",
- "purple_upnp_discover(): Failed In gethostbyname\n");
- /* Short circuit the retry attempts */
- dd->retry_count = NUM_UDP_ATTEMPTS;
- dd->tima = g_timeout_add(10, purple_upnp_discover_timeout, dd);
- memset(&(dd->server), 0, sizeof(struct sockaddr));
- dd->server.sin_family = AF_INET;
- memcpy(&(dd->server.sin_addr), hp->h_addr_list[0], hp->h_length);
- dd->server.sin_port = htons(HTTPMU_HOST_PORT);
+ dd->server = g_inet_socket_address_new_from_string(HTTPMU_HOST_ADDRESS, control_info.status = PURPLE_UPNP_STATUS_DISCOVERING;
@@ -691,9 +691,11 @@
/* Trigger another UPnP discovery if 5 minutes have elapsed since the
* last one, and it wasn't successful */
- if (control_info.status < PURPLE_UPNP_STATUS_DISCOVERING
- && (time(NULL) - control_info.lookup_time) > 300)
+ if (control_info.status < PURPLE_UPNP_STATUS_DISCOVERING && + (g_get_monotonic_time() - control_info.lookup_time) > + 300 * G_USEC_PER_SEC) { purple_upnp_discover(NULL, NULL);
@@ -754,32 +756,66 @@
/* Trigger another UPnP discovery if 5 minutes have elapsed since the
* last one, and it wasn't successful */
- if (control_info.status < PURPLE_UPNP_STATUS_DISCOVERING
- && (time(NULL) - control_info.lookup_time) > 300)
+ if (control_info.status < PURPLE_UPNP_STATUS_DISCOVERING && + (g_get_monotonic_time() - control_info.lookup_time) > + 300 * G_USEC_PER_SEC) { purple_upnp_discover(NULL, NULL);
-looked_up_internal_ip_cb(gpointer data, gint source, const gchar *error_message)
+looked_up_internal_ip_cb(GObject *source, GAsyncResult *result, + G_GNUC_UNUSED gpointer user_data)
- g_strlcpy(control_info.internalip,
- purple_network_get_local_system_ip(source),
- sizeof(control_info.internalip));
- purple_debug_info("upnp", "Local IP: %s\n",
- control_info.internalip);
- purple_debug_error("upnp", "Unable to look up local IP\n");
+ GSocketConnection *conn; + GInetSocketAddress *inetsockaddr; + conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), + purple_debug_error("upnp", "Unable to look up local IP: %s", + g_strlcpy(control_info.internalip, "0.0.0.0", + sizeof(control_info.internalip)); + addr = g_socket_connection_get_local_address(conn, &error); + if ((inetsockaddr = G_INET_SOCKET_ADDRESS(addr)) != NULL) { + GInetAddress *inetaddr = + g_inet_socket_address_get_address(inetsockaddr); + if (g_inet_address_get_family(inetaddr) == G_SOCKET_FAMILY_IPV4 && + !g_inet_address_get_is_loopback(inetaddr)) + gchar *ip = g_inet_address_to_string(inetaddr); + g_strlcpy(control_info.internalip, ip, + sizeof(control_info.internalip)); + "upnp", "Unable to get local address of connection: %s", + error ? error->message : "unknown socket address type"); + purple_debug_info("upnp", "Local IP: %s", control_info.internalip); uri = soup_uri_new(control_info.control_url);
@@ -788,13 +824,21 @@
- if (purple_proxy_connect(NULL, NULL, uri->host, uri->port,
- looked_up_internal_ip_cb, NULL) == NULL) {
- "upnp", "Get Local IP Connect Failed: Address: %s @@@ Port %d",
+ client = purple_gio_socket_client_new(NULL, &error); + purple_debug_error("upnp", "Get Local IP Connect to %s:%d Failed: %s", + uri->host, uri->port, error->message); + purple_debug_info("upnp", "Attempting connection to %s:%u\n", uri->host, + g_socket_client_connect_to_host_async(client, uri->host, uri->port, NULL, + looked_up_internal_ip_cb, NULL); + g_object_unref(client); @@ -926,15 +970,16 @@
- /* If we haven't had a successful UPnP discovery, check if 5 minutes has
- * elapsed since the last try, try again */
- if(control_info.status == PURPLE_UPNP_STATUS_UNDISCOVERED ||
- (control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER
- && (time(NULL) - control_info.lookup_time) > 300)) {
+ if (control_info.status == PURPLE_UPNP_STATUS_UNDISCOVERED) { purple_upnp_discover(do_port_mapping_cb, ar);
- } else if(control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER) {
+ } else if (control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER) { + if (g_get_monotonic_time() - control_info.lookup_time > + 300 * G_USEC_PER_SEC) { + /* If we haven't had a successful UPnP discovery, check if 5 minutes + * has elapsed since the last try, try again */ + purple_upnp_discover(do_port_mapping_cb, ar); /* Asynchronously trigger a failed response */
ar->tima = g_timeout_add(10, fire_port_mapping_failure_cb, ar);
@@ -971,15 +1016,16 @@
- /* If we haven't had a successful UPnP discovery, check if 5 minutes has
- * elapsed since the last try, try again */
- if(control_info.status == PURPLE_UPNP_STATUS_UNDISCOVERED ||
- (control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER
- && (time(NULL) - control_info.lookup_time) > 300)) {
+ if (control_info.status == PURPLE_UPNP_STATUS_UNDISCOVERED) { purple_upnp_discover(do_port_mapping_cb, ar);
- } else if(control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER) {
+ } else if (control_info.status == PURPLE_UPNP_STATUS_UNABLE_TO_DISCOVER) { + if (g_get_monotonic_time() - control_info.lookup_time > + 300 * G_USEC_PER_SEC) { + /* If we haven't had a successful UPnP discovery, check if 5 minutes + * has elapsed since the last try, try again */ + purple_upnp_discover(do_port_mapping_cb, ar); /* Asynchronously trigger a failed response */
ar->tima = g_timeout_add(10, fire_port_mapping_failure_cb, ar);