changeset 11336:7d7dd22215ec

[gaim-migrate @ 13549] STUN NAT discovery from gaim_network_get_public_ip committer: Tailor Script <tailor@pidgin.im>
author Thomas Butter <tbutter>
date Wed, 24 Aug 2005 20:45:20 +0000
parents 59aa7080eb2d
children 1462b64f8fc9
files src/network.c src/stun.c
diffstat 2 files changed, 45 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/network.c	Wed Aug 24 19:02:59 2005 +0000
+++ b/src/network.c	Wed Aug 24 20:45:20 2005 +0000
@@ -29,6 +29,7 @@
 #include "account.h"
 #include "network.h"
 #include "prefs.h"
+#include "stun.h"
 #include "upnp.h"
 
 const unsigned char *
@@ -67,11 +68,17 @@
 gaim_network_get_public_ip(void)
 {
 	const char *ip;
-
+	struct stun_nattype *stun;
+	
 	ip = gaim_prefs_get_string("/core/network/public_ip");
 
-	if (ip == NULL || *ip == '\0')
+	if (ip == NULL || *ip == '\0') {
+		/* Check if STUN discovery was already done */
+		stun = gaim_stun_discover(NULL);
+		if(stun && stun->status>1)
+			return stun->publicip;
 		return NULL;
+	}
 
 	return ip;
 }
--- a/src/stun.c	Wed Aug 24 19:02:59 2005 +0000
+++ b/src/stun.c	Wed Aug 24 20:45:20 2005 +0000
@@ -4,6 +4,8 @@
  *
  * gaim
  *
+ * STUN implementation inspired by jstun [http://jstun.javawi.de/]
+ *
  * Gaim is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
@@ -45,17 +47,19 @@
 static GSList *callbacks = 0;
 static int fd = -1;
 gint incb = -1;
+gint timeout = -1;
 
 static void do_callbacks() {
 	while(callbacks) {
 		StunCallback cb = callbacks->data;
-		cb(&nattype);
+		if(cb)
+			cb(&nattype);
 		callbacks = g_slist_remove(callbacks, cb);
 	}
 }
 
 static void reply_cb(gpointer data, gint source, GaimInputCondition cond) {
-	char buffer[10240];
+	char buffer[1024];
 	char *tmp;
 	int len;
 	struct in_addr in;
@@ -65,7 +69,7 @@
 	struct ifreq *ifr;
 	struct sockaddr_in *sinptr;
 	
-	len = recv(source, buffer, 10240, 0);
+	len = recv(source, buffer, 1024, 0);
 
 	hdr = (struct stun_header*)buffer;
 	if(hdr->transid[0]!=transid[0] || hdr->transid[1]!=transid[1] || hdr->transid[2]!=transid[2] || hdr->transid[3]!=transid[3]) { // wrong transaction
@@ -112,28 +116,48 @@
 	}
 				
 	do_callbacks();
+	gaim_timeout_remove(timeout);
 	gaim_input_remove(incb);
 }
 
+static gboolean timeoutfunc(void *blah) {	
+	/* remove input */
+	gaim_input_remove(incb);
+	
+	/* set unknown */
+	nattype.status = 0;
+
+	/* callbacks */
+	do_callbacks();
+	
+	return FALSE;
+}
+
+	
 struct stun_nattype *gaim_stun_discover(StunCallback cb) {
 	struct sockaddr_in addr;
 	struct stun_header data;
 	int ret = 0;
 	const char *ip = gaim_prefs_get_string("/core/network/stun_ip");
 	int port = gaim_prefs_get_int("/core/network/stun_port");
+
+	if(!ip || !port) {
+		nattype.status = 0;
+		if(cb) cb(&nattype);
+		return &nattype;
+	}
 	
 	if(nattype.status == 1) { // currently discovering
-		callbacks = g_slist_append(callbacks, cb);
+		if(cb) callbacks = g_slist_append(callbacks, cb);
 		return NULL;
 	}
-	if(nattype.status == 2 || nattype.status == 0) { // already discovered
-		cb(&nattype);
+	if(nattype.status != -1) { // already discovered
+		if(cb) cb(&nattype);
 		return &nattype;
 	}
-
 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 		nattype.status = 0;
-		cb(&nattype);
+		if(cb) cb(&nattype);
 		return &nattype;
 	}
 
@@ -145,7 +169,7 @@
 	}
 	if( ret < 0 ) {
 		nattype.status = 0;
-		cb(&nattype);
+		if(cb) cb(&nattype);
 		return &nattype;
 	}
 	incb = gaim_input_add(fd, GAIM_INPUT_READ, reply_cb, NULL);
@@ -165,8 +189,10 @@
 	
 	if( sendto(fd, &data, sizeof(struct stun_header), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < sizeof(struct stun_header)) {
 			nattype.status = 0;
-			cb(&nattype);
+			if(cb) cb(&nattype);
 			return &nattype;
 	}
+	if(cb) callbacks = g_slist_append(callbacks, cb);
+	timeout = gaim_timeout_add(2000, (GSourceFunc)timeoutfunc, NULL);
 	return NULL;
 }