pidgin.next.minor: a3f7a4c3: Add a function to enumerate all local IP...
malu at pidgin.im
malu at pidgin.im
Wed Sep 9 15:06:36 EDT 2009
-----------------------------------------------------------------
Revision: a3f7a4c3280716f828ba129e718bbf16b1a691f4
Ancestor: 0e7acf32357c38a563c6428eee1e27fbb39caccc
Author: malu at pidgin.im
Date: 2009-09-09T19:01:03
Branch: im.pidgin.pidgin.next.minor
URL: http://d.pidgin.im/viewmtn/revision/info/a3f7a4c3280716f828ba129e718bbf16b1a691f4
Modified files:
ChangeLog.API libpurple/network.c libpurple/network.h
libpurple/protocols/jabber/si.c
ChangeLog:
Add a function to enumerate all local IPs
Adapted the XMPP prpl to include all local IPs as local streamhosts.
I haven't had the chance to test if this actually works using a "non-default"
interface, such as a VPN connection...
Refs #10160
-------------- next part --------------
============================================================
--- ChangeLog.API 99ecc5217e0f0affec5666271ccad30b52c1d4ab
+++ ChangeLog.API 21d058413be3a081ed5824f03180a72fe6493bfe
@@ -1,6 +1,9 @@ version 2.7.0 (??/??/????):
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
version 2.7.0 (??/??/????):
+ libpurple:
+ Added:
+ * purple_network_get_all_local_system_ips
version 2.6.1 (08/18/2009):
No changes
============================================================
--- libpurple/network.c 14ce71dc03dff47e6c4a2d6efc9642c4299eeb13
+++ libpurple/network.c 6e231d9f4e9f0dc2f86d417d2c9db4e6e9beb8b2
@@ -200,6 +200,82 @@ purple_network_get_local_system_ip(int f
return "0.0.0.0";
}
+GList *
+purple_network_get_all_local_system_ips(int fd)
+{
+ GList *result = NULL;
+ int source = fd;
+ char buffer[1024];
+ char *tmp;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+
+ if (fd < 0)
+ source = socket(PF_INET,SOCK_STREAM, 0);
+
+ ifc.ifc_len = sizeof(buffer);
+ ifc.ifc_req = (struct ifreq *)buffer;
+ ioctl(source, SIOCGIFCONF, &ifc);
+
+ if (fd < 0)
+ close(source);
+
+ /* enumerate the interfaces on IPv4 (or from source given by fd) */
+ tmp = buffer;
+ while (tmp < buffer + ifc.ifc_len) {
+ char dst[INET6_ADDRSTRLEN];
+
+ ifr = (struct ifreq *)tmp;
+ tmp += HX_SIZE_OF_IFREQ(*ifr);
+
+ if (ifr->ifr_addr.sa_family == AF_INET) {
+ struct sockaddr_in *sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
+
+ inet_ntop(AF_INET, &sinptr->sin_addr, dst,
+ sizeof(dst));
+ purple_debug_info("network",
+ "found local i/f with address %s on IPv4\n", dst);
+ if (!purple_strequal(dst, "127.0.0.1")) {
+ result = g_list_append(result, g_strdup(dst));
+ }
+ }
+ }
+
+ /* enumerate IPv6 interfaces (done when NOT specifying an fd,
+ in that case use it (see above)) */
+ if (fd < 0) {
+ source = socket(PF_INET6, SOCK_STREAM, 0);
+
+ ifc.ifc_len = sizeof(buffer);
+ ifc.ifc_req = (struct ifreq *)buffer;
+ ioctl(source, SIOCGIFCONF, &ifc);
+
+ close(source);
+
+ tmp = buffer;
+ while (tmp < buffer + ifc.ifc_len) {
+ char dst[INET6_ADDRSTRLEN];
+
+ ifr = (struct ifreq *)tmp;
+ tmp += HX_SIZE_OF_IFREQ(*ifr);
+
+ if (ifr->ifr_addr.sa_family == AF_INET6) {
+ struct sockaddr_in6 *sinptr =
+ (struct sockaddr_in6 *)&ifr->ifr_addr;
+
+ inet_ntop(AF_INET6, &sinptr->sin6_addr, dst, sizeof(dst));
+ purple_debug_info("network",
+ "found local i/f with address %s on IPv4\n", dst);
+ if (!purple_strequal(dst, "::1")) {
+ result = g_list_append(result, g_strdup(dst));
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
const char *
purple_network_get_my_ip(int fd)
{
============================================================
--- libpurple/network.h d0f48ebf86652fe313c6459f130f886c3b663461
+++ libpurple/network.h 0692729dcd6a63f697121778e64901d8b8595670
@@ -88,6 +88,16 @@ const char *purple_network_get_local_sys
const char *purple_network_get_local_system_ip(int fd);
/**
+ * Returns all IP addresses of the local system.
+ *
+ * @note The caller must free this list
+ *
+ * @param fd The fd to use to help figure out the IPs, or else -1.
+ * @return A list of local IP addresses.
+ */
+GList *purple_network_get_all_local_system_ips(int fd);
+
+/**
* Returns the IP address that should be used anywhere a
* public IP addresses is needed (listening for an incoming
* file transfer, etc).
============================================================
--- libpurple/protocols/jabber/si.c 90609b8a58493beeea0b2b02ec3648f8d0a9a075
+++ libpurple/protocols/jabber/si.c 95f735f395ac622f9a5d33f549b84fe1c20d1c00
@@ -853,8 +853,11 @@ jabber_si_xfer_bytestreams_listen_cb(int
/* If we successfully started listening locally */
if (sock >= 0) {
gchar *jid;
- const char *local_ip, *public_ip;
-
+ GList *local_ips =
+ purple_network_get_all_local_system_ips(jsx->js->fd);
+ const char *public_ip;
+ gboolean has_public_ip = FALSE;
+
jsx->local_streamhost_fd = sock;
jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
@@ -862,19 +865,24 @@ jabber_si_xfer_bytestreams_listen_cb(int
xfer->local_port = purple_network_get_port_from_fd(sock);
g_snprintf(port, sizeof(port), "%hu", xfer->local_port);
- /* Include the localhost's IP (for in-network transfers) */
- local_ip = purple_network_get_local_system_ip(jsx->js->fd);
- if (strcmp(local_ip, "0.0.0.0") != 0) {
+ public_ip = purple_network_get_my_ip(jsx->js->fd);
+
+ /* Include the localhost's IPs (for in-network transfers) */
+ while (local_ips) {
+ gchar *local_ip = local_ips->data;
streamhost_count++;
streamhost = xmlnode_new_child(query, "streamhost");
xmlnode_set_attrib(streamhost, "jid", jid);
xmlnode_set_attrib(streamhost, "host", local_ip);
xmlnode_set_attrib(streamhost, "port", port);
+ if (purple_strequal(local_ip, public_ip))
+ has_public_ip = TRUE;
+ g_free(local_ip);
+ local_ips = g_list_delete_link(local_ips, local_ips);
}
/* Include the public IP (assuming that there is a port mapped somehow) */
- public_ip = purple_network_get_my_ip(jsx->js->fd);
- if (strcmp(public_ip, local_ip) != 0 && strcmp(public_ip, "0.0.0.0") != 0) {
+ if (!has_public_ip && strcmp(public_ip, "0.0.0.0") != 0) {
streamhost_count++;
streamhost = xmlnode_new_child(query, "streamhost");
xmlnode_set_attrib(streamhost, "jid", jid);
More information about the Commits
mailing list