changeset 25617:f16aba67b685

Sending of p2p packet, providing peer with our IP address to make a connection to us.
author Sulabh Mahajan <sulabh@soc.pidgin.im>
date Fri, 27 Jun 2008 13:34:44 +0000
parents ccbded331513
children d6247d2d6c47
files libpurple/protocols/yahoo/yahoo.c libpurple/protocols/yahoo/yahoo_friend.c libpurple/protocols/yahoo/yahoo_friend.h
diffstat 3 files changed, 119 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/yahoo/yahoo.c	Sat Jun 21 14:34:38 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Fri Jun 27 13:34:44 2008 +0000
@@ -38,6 +38,7 @@
 #include "server.h"
 #include "util.h"
 #include "version.h"
+#include "network.h"
 
 #include "yahoo.h"
 #include "yahoochat.h"
@@ -515,6 +516,10 @@
 					purple_blist_add_buddy(b, NULL, g, NULL);
 				}
 				yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp);
+				
+				/*set p2p status not connected and no p2p packet sent*/
+				yahoo_friend_set_p2p_status(f, NOT_CONNECTED);
+				f->p2p_packet_sent = 0;
 
 			} else {
 				/* This buddy is on the ignore list (and therefore in no group) */
@@ -629,6 +634,10 @@
 				}
 
 				yahoo_do_group_check(account, ht, norm_bud, grp);
+				/*set p2p status not connected and no p2p packet sent*/
+				yahoo_friend_set_p2p_status(f, NOT_CONNECTED);
+				f->p2p_packet_sent = 0;
+
 				g_free(norm_bud);
 			}
 			g_strfreev(buddies);
@@ -2176,6 +2185,7 @@
 	char *buf;
 	YahooFriend *f;
 	GSList *l = pkt->hash;
+	struct yahoo_data *yd = gc->proto_data;
 
 	while (l) {
 		struct yahoo_pair *pair = l->data;
@@ -2203,6 +2213,14 @@
 	if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */
 		f = yahoo_friend_find_or_new(gc, who);
 		yahoo_update_status(gc, who, f);
+		
+		if( !g_hash_table_lookup(yd->peers, who) )	{
+			/*we are not connected as client, so set friend to not connected*/
+			yahoo_friend_set_p2p_status(f, NOT_CONNECTED);
+			f->p2p_packet_sent = 0;
+		}
+		else	/*we are already connected. set friend to CONNECTED_AS_CLIENT*/
+			yahoo_friend_set_p2p_status(f, CONNECTED_AS_CLIENT);
 		return;
 	}
 
@@ -2215,15 +2233,70 @@
 	g_free(decoded_group);
 }
 
+/*send p2p pkt containing our encoded ip, asking peer to connect to us*/
+static void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13)
+{
+	const char *public_ip;
+	guint32 temp[4];	
+	guint32 ip;
+	char temp_str[100];
+	gchar *base64_ip = NULL;
+	YahooFriend *f;
+	struct yahoo_packet *pkt;
+	PurpleAccount *account;
+	struct yahoo_data *yd = gc->proto_data;
+
+	public_ip = purple_network_get_public_ip();
+	if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 )
+		return ;
+
+	ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0];
+	sprintf(temp_str, "%d", ip);
+	base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) );
+
+	f = yahoo_friend_find(gc, who);
+	account = purple_connection_get_account(gc);
+
+	/*send packet to only those friends who arent p2p connected and to whom we havent already sent. Do not send if this condition doesn't hold good*/ 
+	if( !( f && (yahoo_friend_get_p2p_status(f) == NOT_CONNECTED) && (f->p2p_packet_sent == 0)) )
+		return;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_packet_hash(pkt, "sssissis",
+		1, purple_normalize(account, purple_account_get_username(account)),
+		4, purple_normalize(account, purple_account_get_username(account)),
+		12, base64_ip,	/*base64 encode ip*/
+		61, 0,		/*To-do : whats 61 for??*/
+		2, "",
+		5, who,
+		13, val_13,		/*Start 13 from 0*/
+		49, "PEERTOPEER");
+	yahoo_packet_send_and_free(pkt, yd);
+
+	f->p2p_packet_sent = 1;	/*set p2p_packet_sent to sent*/ 
+
+	g_free(base64_ip);
+}
+
 /*destroy p2p_data associated with a peer and close p2p connection*/
 static void yahoo_p2p_disconnect_destroy_data(gpointer data)
 {
 	struct yahoo_p2p_data *user_data;
 	struct yahoo_data *yd;
+	YahooFriend *f;
+
 	if(!(user_data = data))
 		return ;
+
+	/*If friend, set him not connected*/
+	f = yahoo_friend_find(user_data->gc, user_data->host_username);
+	if (f)	{
+		yahoo_friend_set_p2p_status(f, NOT_CONNECTED);
+		f->p2p_packet_sent = 0;
+	}
+
 	yd = user_data->gc->proto_data;
-	
+
 	purple_input_remove(user_data->input_event);
 	close(user_data->source);
 	g_free(user_data->host_ip);
@@ -2302,7 +2375,7 @@
 
 }
 
-/*callback function associated with receiving of data on the source, not considering receipt of multiple YMSG packets in a single TCP packet*/
+/*callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet*/
 static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	guchar buf[1024];	/*is it safe to assume a fixed array length of 1024 ??*/
@@ -2387,18 +2460,32 @@
 	struct yahoo_p2p_data *user_data;
 	struct yahoo_packet *pkt_to_send;
 	PurpleAccount *account;
+	YahooFriend *f;
+	struct yahoo_data *yd;
+
+	if(!(user_data = data))
+		return ;
+	yd = user_data->gc->proto_data;
 
 	if(error_message != NULL)	{
 		purple_debug_warning("yahoo","p2p: %s\n",error_message);
+		yahoo_send_p2p_pkt(user_data->gc, user_data->host_username, 2);/*send p2p init packet with val_13=2*/
+		
+		yahoo_p2p_disconnect_destroy_data(user_data);
 		return;
 	}
-	if(!(user_data = data))
-		return ;
 
 	/*Add an Input Read event to the file descriptor*/
 	user_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
 	user_data->source = source;
 
+	g_hash_table_insert(yd->peers, g_strdup(user_data->host_username), user_data);
+	
+	/*If the peer is a friend, set him connected*/
+	f = yahoo_friend_find(user_data->gc, user_data->host_username);
+	if (f)
+		yahoo_friend_set_p2p_status(f, CONNECTED_AS_CLIENT);
+
 	account = purple_connection_get_account(user_data->gc);
 
 	/*Build the yahoo packet*/
@@ -2416,7 +2503,6 @@
 
 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	struct yahoo_data *yd = gc->proto_data;
 	GSList *l = pkt->hash;
 	char *who = NULL;
 	char *base64 = NULL;
@@ -2448,7 +2534,7 @@
 			   after strtol, it's in reversed byte order. Who thought this up?*/
 			break;
 		case 13:
-			val_13 = strtol(pair->value, NULL, 10);		/*Value always 0*/
+			val_13 = strtol(pair->value, NULL, 10);
 			user_data->val_13 = val_13;
 			break;
 		case 11:
@@ -2499,12 +2585,9 @@
 		user_data->session_id = pkt->id;
 		user_data->gc = gc;
 
-		g_hash_table_insert(yd->peers, g_strdup(who), user_data);
-
 		/*connect to host*/
 		if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, user_data))==NULL)
 			purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
-
 	}
 }
 
@@ -3899,8 +3982,10 @@
 			yahoo_packet_hash_int(pkt, 11, user_data->val_11);
 			yahoo_p2p_write_pkt(user_data->source, pkt);
 		}
-		else
+		else	{
 			yahoo_packet_send(pkt, yd);
+			yahoo_send_p2p_pkt(gc, who, 0);		/*send p2p packet, with val_13=0*/
+		}
 	}
 	else
 		ret = -E2BIG;
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Sat Jun 21 14:34:38 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_friend.c	Fri Jun 27 13:34:44 2008 +0000
@@ -35,6 +35,8 @@
 	ret = g_new0(YahooFriend, 1);
 	ret->status = YAHOO_STATUS_OFFLINE;
 	ret->presence = YAHOO_PRESENCE_DEFAULT;
+	ret->p2p_packet_sent = 0;
+	ret->p2p_status = NOT_CONNECTED;
 
 	return ret;
 }
@@ -264,3 +266,13 @@
 		yahoo_packet_send_and_free(pkt, yd);
 	}
 }
+
+void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status)
+{
+	f->p2p_status = p2p_status;
+}
+
+YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f)
+{
+	return f->p2p_status;
+}
--- a/libpurple/protocols/yahoo/yahoo_friend.h	Sat Jun 21 14:34:38 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_friend.h	Fri Jun 27 13:34:44 2008 +0000
@@ -34,6 +34,13 @@
 	YAHOO_PRESENCE_PERM_OFFLINE
 } YahooPresenceVisibility;
 
+typedef enum {
+	NOT_CONNECTED = 0,
+	DO_NOT_CONNECT,
+	CONNECTED_AS_SERVER,	/*We are server*/
+	CONNECTED_AS_CLIENT	/*We are client*/
+} YahooP2PStatus;
+
 /* these are called friends instead of buddies mainly so I can use variables
  * named f and not confuse them with variables named b
  */
@@ -50,6 +57,8 @@
 	int protocol; /* 1=LCS, 2=MSN*/
 	long int version_id;
 	gchar *alias_id;
+	YahooP2PStatus p2p_status;
+	gboolean p2p_packet_sent;	/*0:not sent, 1=sent*/ 
 } YahooFriend;
 
 YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
@@ -76,4 +85,7 @@
 void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
 		YahooPresenceVisibility presence);
 
+void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status);
+YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f);
+
 #endif /* _YAHOO_FRIEND_H_ */