soc.2008.yahoo: 782ffab6: resolved conflict -- merged im.pidgin.pi...
sulabh at soc.pidgin.im
sulabh at soc.pidgin.im
Wed Nov 12 05:38:10 EST 2008
-----------------------------------------------------------------
Revision: 782ffab65c8cf17234cc352d99e0aa94600829fe
Ancestor: 76073ee6b6c5e33a843321b0f35d89eeb88f2031
Author: sulabh at soc.pidgin.im
Date: 2008-11-12T10:23:13
Branch: im.pidgin.soc.2008.yahoo
URL: http://d.pidgin.im/viewmtn/revision/info/782ffab65c8cf17234cc352d99e0aa94600829fe
Modified files:
libpurple/protocols/yahoo/yahoo.c
libpurple/protocols/yahoo/yahoo.h
libpurple/protocols/yahoo/yahoo_packet.h
ChangeLog:
resolved conflict -- merged im.pidgin.pidgin to im.pidgin.soc.2008.yahoo
-------------- next part --------------
============================================================
--- libpurple/protocols/yahoo/yahoo.c 7e5229419ad9251d0903c281223a7b90d319ec21
+++ libpurple/protocols/yahoo/yahoo.c 60ad355e7cafe82f713c110939ff60aa298f8822
@@ -30,6 +30,7 @@
#include "cmds.h"
#include "core.h"
#include "debug.h"
+#include "network.h"
#include "notify.h"
#include "privacy.h"
#include "prpl.h"
@@ -38,6 +39,7 @@
#include "server.h"
#include "util.h"
#include "version.h"
+#include "xmlnode.h"
#include "yahoo.h"
#include "yahoochat.h"
@@ -235,6 +237,8 @@ static void yahoo_process_status(PurpleC
message = pair->value;
break;
case 11: /* this is the buddy's session id */
+ if (f)
+ f->session_id = strtol(pair->value, NULL, 10);
break;
case 17: /* in chat? */
break;
@@ -521,6 +525,10 @@ static void yahoo_process_list_15(Purple
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, YAHOO_P2PSTATUS_NOT_CONNECTED);
+ f->p2p_packet_sent = 0;
} else {
/* This buddy is on the ignore list (and therefore in no group) */
@@ -635,6 +643,10 @@ static void yahoo_process_list(PurpleCon
}
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, YAHOO_P2PSTATUS_NOT_CONNECTED);
+ f->p2p_packet_sent = 0;
+
g_free(norm_bud);
}
g_strfreev(buddies);
@@ -691,7 +703,8 @@ static void yahoo_process_list(PurpleCon
yahoo_fetch_aliases(gc);
}
-static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt)
+/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
+static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
{
PurpleAccount *account;
char *msg = NULL;
@@ -700,12 +713,14 @@ static void yahoo_process_notify(PurpleC
char *game = NULL;
YahooFriend *f = NULL;
GSList *l = pkt->hash;
+ gint val_11 = 0;
+ struct yahoo_data *yd = gc->proto_data;
account = purple_connection_get_account(gc);
while (l) {
struct yahoo_pair *pair = l->data;
- if (pair->key == 4)
+ if (pair->key == 4 || pair->key == 1)
from = pair->value;
if (pair->key == 49)
msg = pair->value;
@@ -713,12 +728,22 @@ static void yahoo_process_notify(PurpleC
stat = pair->value;
if (pair->key == 14)
game = pair->value;
+ if (pair->key == 11)
+ val_11 = strtol(pair->value, NULL, 10);
l = l->next;
}
if (!from || !msg)
return;
+ /* disconnect the peer if connected through p2p and sends wrong value for session id */
+ if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
+ purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from);
+ /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+ g_hash_table_remove(yd->peers, from);
+ return;
+ }
+
if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
&& (purple_privacy_check(account, from)))
{
@@ -764,21 +789,85 @@ struct _yahoo_im {
char *msg;
};
-static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt)
+static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
{
PurpleAccount *account;
+ GSList *l = pkt->hash;
+ struct _yahoo_im *sms = NULL;
+ struct yahoo_data *yd;
+ char *server_msg = NULL;
+ char *m;
+
+ yd = gc->proto_data;
+ account = purple_connection_get_account(gc);
+
+ while (l != NULL) {
+ struct yahoo_pair *pair = l->data;
+ if (pair->key == 4) {
+ sms = g_new0(struct _yahoo_im, 1);
+ sms->from = g_strdup_printf("+%s", pair->value);
+ sms->time = time(NULL);
+ sms->utf8 = TRUE;
+ }
+ if (pair->key == 14) {
+ if (sms)
+ sms->msg = pair->value;
+ }
+ if (pair->key == 68)
+ if(sms)
+ g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value));
+ if (pair->key == 16)
+ server_msg = pair->value;
+ l = l->next;
+ }
+
+ if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) {
+ if (server_msg) {
+ PurpleConversation *c;
+ c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account);
+ if (c == NULL)
+ c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from);
+ purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ }
+ else
+ purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL);
+
+ g_free(sms->from);
+ g_free(sms);
+ return ;
+ }
+
+ if (!sms->from || !sms->msg) {
+ g_free(sms);
+ return;
+ }
+
+ m = yahoo_string_decode(gc, sms->msg, sms->utf8);
+ serv_got_im(gc, sms->from, m, 0, sms->time);
+
+ g_free(m);
+ g_free(sms->from);
+ g_free(sms);
+}
+
+/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
+static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
+{
+ PurpleAccount *account;
struct yahoo_data *yd = gc->proto_data;
GSList *l = pkt->hash;
GSList *list = NULL;
struct _yahoo_im *im = NULL;
const char *imv = NULL;
+ gint val_11 = 0;
account = purple_connection_get_account(gc);
- if (pkt->status <= 1 || pkt->status == 5) {
+ if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) {
+ /* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */
while (l != NULL) {
struct yahoo_pair *pair = l->data;
- if (pair->key == 4) {
+ if (pair->key == 4 || pair->key == 1) {
im = g_new0(struct _yahoo_im, 1);
list = g_slist_append(list, im);
im->from = pair->value;
@@ -798,6 +887,11 @@ static void yahoo_process_message(Purple
if (im)
im->msg = pair->value;
}
+ /* peer session id */
+ if (pair->key == 11) {
+ if (im)
+ val_11 = strtol(pair->value, NULL, 10);
+ }
/* IMV key */
if (pair->key == 63)
{
@@ -810,6 +904,14 @@ static void yahoo_process_message(Purple
_("Your Yahoo! message did not get sent."), NULL);
}
+ /* disconnect the peer if connected through p2p and sends wrong value for session id */
+ if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
+ purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->from);
+ /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+ g_hash_table_remove(yd->peers, im->from);
+ return;
+ }
+
/** TODO: It seems that this check should be per IM, not global */
/* Check for the Doodle IMV */
if (im != NULL && imv!= NULL && im->from != NULL)
@@ -2187,6 +2289,8 @@ static void yahoo_process_addbuddy(Purpl
char *buf;
YahooFriend *f;
GSList *l = pkt->hash;
+ struct yahoo_data *yd = gc->proto_data;
+ int protocol = 0;
while (l) {
struct yahoo_pair *pair = l->data;
@@ -2201,6 +2305,9 @@ static void yahoo_process_addbuddy(Purpl
case 65:
group = pair->value;
break;
+ case 241:
+ protocol = strtol(pair->value, NULL, 10);
+ break;
}
l = l->next;
@@ -2214,6 +2321,16 @@ static void yahoo_process_addbuddy(Purpl
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(protocol)
+ f->protocol = protocol;
+
+ 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, YAHOO_P2PSTATUS_NOT_CONNECTED);
+ f->p2p_packet_sent = 0;
+ }
+ else /* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */
+ yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
return;
}
@@ -2226,6 +2343,426 @@ static void yahoo_process_addbuddy(Purpl
g_free(decoded_group);
}
+/* write pkt to the source */
+static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
+{
+ size_t pkt_len;
+ guchar *raw_packet;
+
+ /*build the raw packet and send it to the host*/
+ pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet);
+ if(write(source, raw_packet, pkt_len) != pkt_len)
+ purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
+ g_free(raw_packet);
+}
+
+static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data)
+{
+ struct yahoo_p2p_data *p2p_data = value;
+ PurpleConnection *gc = user_data;
+ struct yahoo_packet *pkt_to_send;
+ PurpleAccount *account;
+ struct yahoo_data *yd = gc->proto_data;
+
+ account = purple_connection_get_account(gc);
+
+ pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+ yahoo_packet_hash(pkt_to_send, "ssisi",
+ 4, purple_normalize(account, purple_account_get_username(account)),
+ 5, p2p_data->host_username,
+ 241, 0, /* Protocol identifier */
+ 49, "PEERTOPEER",
+ 13, 7);
+ yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send);
+
+ yahoo_packet_free(pkt_to_send);
+}
+
+static gboolean yahoo_p2p_keepalive(gpointer data)
+{
+ PurpleConnection *gc = data;
+ struct yahoo_data *yd = gc->proto_data;
+
+ g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
+
+ return TRUE;
+}
+
+/* destroy p2p_data associated with a peer and close p2p connection.
+ * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer,
+ * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */
+static void yahoo_p2p_disconnect_destroy_data(gpointer data)
+{
+ struct yahoo_p2p_data *p2p_data;
+ YahooFriend *f;
+
+ if(!(p2p_data = data))
+ return ;
+
+ /* If friend, set him not connected */
+ f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
+ if (f)
+ yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
+
+ if(p2p_data->source >= 0)
+ close(p2p_data->source);
+ purple_input_remove(p2p_data->input_event);
+ g_free(p2p_data->host_ip);
+ g_free(p2p_data->host_username);
+ g_free(p2p_data);
+}
+
+/* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */
+static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt)
+{
+ struct yahoo_p2p_data *p2p_data;
+ char *who = NULL;
+ GSList *l = pkt->hash;
+ struct yahoo_packet *pkt_to_send;
+ PurpleAccount *account;
+ int val_13_to_send = 0;
+ struct yahoo_data *yd;
+ YahooFriend *f;
+
+ if(!(p2p_data = data))
+ return ;
+
+ yd = p2p_data->gc->proto_data;
+
+ /* lets see whats in the packet */
+ while (l) {
+ struct yahoo_pair *pair = l->data;
+
+ switch (pair->key) {
+ case 4:
+ who = pair->value;
+ if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) {
+ /* from whom are we receiving the packets ?? */
+ purple_debug_warning("yahoo","p2p: received data from wrong user\n");
+ return;
+ }
+ break;
+ case 13:
+ p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */
+ break;
+ /* case 5, 49 look laters, no use right now */
+ }
+ l = l->next;
+ }
+
+ account = purple_connection_get_account(p2p_data->gc);
+
+ /* key_13: sort of a counter.
+ * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5,
+ * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive.
+ * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5,
+ * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */
+
+ switch(p2p_data->val_13) {
+ case 1 : val_13_to_send = 5; break;
+ case 5 : val_13_to_send = 6; break;
+ case 6 : val_13_to_send = 7; break;
+ case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
+ return;
+ val_13_to_send = 7; break;
+ default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n");
+ return;
+ }
+
+ /* Build the yahoo packet */
+ pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+ yahoo_packet_hash(pkt_to_send, "ssisi",
+ 4, purple_normalize(account, purple_account_get_username(account)),
+ 5, p2p_data->host_username,
+ 241, 0, /* Protocol identifier */
+ 49, "PEERTOPEER",
+ 13, val_13_to_send);
+
+ /* build the raw packet and send it to the host */
+ yahoo_p2p_write_pkt(source, pkt_to_send);
+ yahoo_packet_free(pkt_to_send);
+
+ if( val_13_to_send == 7 )
+ if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) {
+ g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data);
+ /* If the peer is a friend, set him connected */
+ f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
+ if (f) {
+ if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) {
+ p2p_data->session_id = f->session_id;
+ yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER);
+ }
+ else
+ yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
+ }
+ }
+}
+
+/* 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 ?? */
+ int len;
+ int pos = 0;
+ int pktlen;
+ struct yahoo_packet *pkt;
+ guchar *start = NULL;
+ struct yahoo_p2p_data *p2p_data;
+ struct yahoo_data *yd;
+
+ if(!(p2p_data = data))
+ return ;
+ yd = p2p_data->gc->proto_data;
+
+ len = read(source, buf, sizeof(buf));
+ if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ return ; /* No Worries*/
+ else if (len <= 0)
+ {
+ purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n");
+ /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+ if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
+ g_hash_table_remove(yd->peers,p2p_data->host_username);
+ else
+ yahoo_p2p_disconnect_destroy_data(data);
+ return;
+ }
+
+ if(len < YAHOO_PACKET_HDRLEN)
+ return;
+
+ if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) {
+ /* Not a YMSG packet */
+ purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n");
+
+ start = memchr(buf + 1, 'Y', len - 1);
+ if(start) {
+ g_memmove(buf, start, len - (start - buf));
+ len -= start - buf;
+ } else {
+ g_free(buf);
+ return;
+ }
+ }
+
+ pos += 4; /* YMSG */
+ pos += 2;
+ pos += 2;
+
+ pktlen = yahoo_get16(buf + pos); pos += 2;
+ purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len);
+
+ pkt = yahoo_packet_new(0, 0, 0);
+ pkt->service = yahoo_get16(buf + pos); pos += 2;
+ pkt->status = yahoo_get32(buf + pos); pos += 4;
+ pkt->id = yahoo_get32(buf + pos); pos += 4;
+
+ purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status);
+ yahoo_packet_read(pkt, buf + pos, pktlen);
+
+ /* packet processing */
+ switch(pkt->service) {
+ case YAHOO_SERVICE_P2PFILEXFER:
+ yahoo_p2p_process_p2pfilexfer(data, source, pkt);
+ break;
+ case YAHOO_SERVICE_MESSAGE:
+ yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
+ break;
+ case YAHOO_SERVICE_NOTIFY:
+ yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
+ break;
+ default:
+ purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service);
+ }
+
+ yahoo_packet_free(pkt);
+}
+
+static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+ int acceptfd;
+ struct yahoo_p2p_data *p2p_data;
+ struct yahoo_data *yd;
+
+ if(!(p2p_data = data))
+ return ;
+ yd = p2p_data->gc->proto_data;
+
+ acceptfd = accept(source, NULL, 0);
+ if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ return;
+ else if(acceptfd == -1) {
+ purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
+ yahoo_p2p_disconnect_destroy_data(data);
+ return;
+ }
+
+ /* remove watcher and close p2p server */
+ purple_input_remove(yd->yahoo_p2p_server_watcher);
+ close(yd->yahoo_local_p2p_server_fd);
+ yd->yahoo_local_p2p_server_fd = -1;
+
+ /* Add an Input Read event to the file descriptor */
+ p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
+ p2p_data->source = acceptfd;
+}
+
+static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data)
+{
+ struct yahoo_p2p_data *p2p_data;
+ struct yahoo_data *yd;
+
+ if(!(p2p_data = data))
+ return FALSE;
+
+ yd = p2p_data->gc->proto_data;
+
+ purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect");
+ yahoo_p2p_disconnect_destroy_data(data);
+ purple_input_remove(yd->yahoo_p2p_server_watcher);
+ yd->yahoo_p2p_server_watcher = 0;
+ close(yd->yahoo_local_p2p_server_fd);
+ yd->yahoo_local_p2p_server_fd = -1;
+ yd->yahoo_p2p_server_timeout_handle = 0;
+
+ return FALSE;
+}
+
+static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
+{
+ struct yahoo_p2p_data *p2p_data;
+ struct yahoo_data *yd;
+
+ if(!(p2p_data = data))
+ return ;
+
+ if(listenfd == -1) {
+ purple_debug_warning("yahoo","p2p: error starting p2p server\n");
+ yahoo_p2p_disconnect_destroy_data(data);
+ return;
+ }
+
+ yd = p2p_data->gc->proto_data;
+
+ /* Add an Input Read event to the file descriptor */
+ yd->yahoo_local_p2p_server_fd = listenfd;
+ yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data);
+
+ /* add timeout */
+ yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data);
+}
+
+/* send p2p pkt containing our encoded ip, asking peer to connect to us */
+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;
+ struct yahoo_p2p_data *p2p_data;
+
+ f = yahoo_friend_find(gc, who);
+ account = purple_connection_get_account(gc);
+
+ /* Do not send invitation if already listening for other connection */
+ if(yd->yahoo_local_p2p_server_fd >= 0)
+ return;
+
+ /* One shouldn't try to connect to self */
+ if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0)
+ return;
+
+ /* 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) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) )
+ return;
+
+ /* Dont send p2p packet to buddies of other protocols */
+ if(f->protocol)
+ return;
+
+ /* Finally, don't try to connect to buddies not online or on sms */
+ if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms )
+ return;
+
+ 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) );
+
+ 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 : figure out what is 61 for?? */
+ 2, "",
+ 5, who,
+ 13, val_13,
+ 49, "PEERTOPEER");
+ yahoo_packet_send_and_free(pkt, yd);
+
+ f->p2p_packet_sent = 1; /* set p2p_packet_sent to sent */
+
+ p2p_data = g_new0(struct yahoo_p2p_data, 1);
+
+ p2p_data->gc = gc;
+ p2p_data->host_ip = NULL;
+ p2p_data->host_username = g_strdup(who);
+ p2p_data->val_13 = val_13;
+ p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER;
+
+ purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data);
+
+ g_free(base64_ip);
+}
+
+/* function called when connection to p2p host is setup */
+static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message)
+{
+ struct yahoo_p2p_data *p2p_data;
+ struct yahoo_packet *pkt_to_send;
+ PurpleAccount *account;
+ struct yahoo_data *yd;
+
+ if(!(p2p_data = data))
+ return ;
+ yd = p2p_data->gc->proto_data;
+
+ if(error_message != NULL) {
+ purple_debug_warning("yahoo","p2p: %s\n",error_message);
+ yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */
+
+ yahoo_p2p_disconnect_destroy_data(p2p_data);
+ return;
+ }
+
+ /* Add an Input Read event to the file descriptor */
+ p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
+ p2p_data->source = source;
+
+ account = purple_connection_get_account(p2p_data->gc);
+
+ /* Build the yahoo packet */
+ pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+ yahoo_packet_hash(pkt_to_send, "ssisi",
+ 4, purple_normalize(account, purple_account_get_username(account)),
+ 5, p2p_data->host_username,
+ 241, 0, /* Protocol identifier */
+ 49, "PEERTOPEER",
+ 13, 1); /* we receive key13= 0 or 2, we send key13=1 */
+
+ yahoo_p2p_write_pkt(source, pkt_to_send); /* build raw packet and send */
+ yahoo_packet_free(pkt_to_send);
+}
+
static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
{
GSList *l = pkt->hash;
@@ -2233,7 +2770,15 @@ static void yahoo_process_p2p(PurpleConn
char *base64 = NULL;
guchar *decoded;
gsize len;
+ gint val_13 = 0;
+ gint val_11 = 0;
+ PurpleAccount *account;
+ YahooFriend *f;
+ /* if status is YAHOO_STATUS_BUSY, don't do anything, peer wont connect */
+ if(pkt->status == YAHOO_STATUS_BUSY)
+ return ;
+
while (l) {
struct yahoo_pair *pair = l->data;
@@ -2252,14 +2797,21 @@ static void yahoo_process_p2p(PurpleConn
/* so, this is an ip address. in base64. decoded it's in ascii.
after strtol, it's in reversed byte order. Who thought this up?*/
break;
+ case 13:
+ val_13 = strtol(pair->value, NULL, 10);
+ break;
+ case 11:
+ val_11 = strtol(pair->value, NULL, 10); /* session id of peer */
+ if( (f = yahoo_friend_find(gc, who)) )
+ f->session_id = val_11;
+ break;
/*
TODO: figure these out
yahoo: Key: 61 Value: 0
yahoo: Key: 2 Value:
- yahoo: Key: 13 Value: 0
+ yahoo: Key: 13 Value: 0 packet count ??
yahoo: Key: 49 Value: PEERTOPEER
yahoo: Key: 140 Value: 1
- yahoo: Key: 11 Value: -1786225828
*/
}
@@ -2271,6 +2823,8 @@ static void yahoo_process_p2p(PurpleConn
guint32 ip;
char *tmp2;
YahooFriend *f;
+ char *host_ip;
+ struct yahoo_p2p_data *p2p_data = g_new0(struct yahoo_p2p_data, 1);
decoded = purple_base64_decode(base64, &len);
if (len) {
@@ -2283,12 +2837,34 @@ static void yahoo_process_p2p(PurpleConn
ip = strtol(tmp2, NULL, 10);
g_free(tmp2);
g_free(decoded);
- tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
+ host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
(ip >> 24) & 0xff);
f = yahoo_friend_find(gc, who);
if (f)
- yahoo_friend_set_ip(f, tmp2);
- g_free(tmp2);
+ yahoo_friend_set_ip(f, host_ip);
+ purple_debug_info("yahoo", "IP : %s\n", host_ip);
+
+ account = purple_connection_get_account(gc);
+
+ if(val_11==0) {
+ if(!f)
+ return;
+ else
+ val_11 = f->session_id;
+ }
+
+ p2p_data->host_username = g_strdup(who);
+ p2p_data->val_13 = val_13;
+ p2p_data->session_id = val_11;
+ p2p_data->host_ip = host_ip;
+ p2p_data->gc = gc;
+ p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT;
+
+ /* connect to host */
+ if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) {
+ yahoo_p2p_disconnect_destroy_data(p2p_data);
+ purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
+ }
}
}
@@ -2368,12 +2944,12 @@ static void yahoo_packet_process(PurpleC
yahoo_process_status(gc, pkt);
break;
case YAHOO_SERVICE_NOTIFY:
- yahoo_process_notify(gc, pkt);
+ yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER);
break;
case YAHOO_SERVICE_MESSAGE:
case YAHOO_SERVICE_GAMEMSG:
case YAHOO_SERVICE_CHATMSG:
- yahoo_process_message(gc, pkt);
+ yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER);
break;
case YAHOO_SERVICE_SYSMESSAGE:
yahoo_process_sysmessage(gc, pkt);
@@ -2450,7 +3026,8 @@ static void yahoo_packet_process(PurpleC
break;
case YAHOO_SERVICE_P2PFILEXFER:
/* This case had no break and continued; thus keeping it this way.*/
- yahoo_process_p2pfilexfer(gc, pkt);
+ yahoo_process_p2p(gc, pkt); /* P2PFILEXFER handled the same way as process_p2p */
+ yahoo_process_p2pfilexfer(gc, pkt); /* redundant ??, need to have a break now */
case YAHOO_SERVICE_FILETRANSFER:
yahoo_process_filetransfer(gc, pkt);
break;
@@ -2484,6 +3061,9 @@ static void yahoo_packet_process(PurpleC
case YAHOO_SERVICE_FILETRANS_ACC_15:
yahoo_process_filetrans_acc_15(gc, pkt);
break;
+ case YAHOO_SERVICE_SMS_MSG:
+ yahoo_process_sms_message(gc, pkt);
+ break;
default:
purple_debug(PURPLE_DEBUG_ERROR, "yahoo",
@@ -3005,6 +3585,9 @@ static void yahoo_login(PurpleAccount *a
yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+ yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_p2p_disconnect_destroy_data);
+ yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS, yahoo_p2p_keepalive, gc);
yd->confs = NULL;
yd->conf_id = 2;
yd->last_keepalive = yd->last_ping = time(NULL);
@@ -3070,6 +3653,17 @@ static void yahoo_close(PurpleConnection
if (yd->in_chat)
yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
+ purple_timeout_remove(yd->yahoo_p2p_timer);
+ if(yd->yahoo_p2p_server_timeout_handle != 0)
+ purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
+
+ /* close p2p server if it is waiting for a peer to connect */
+ purple_input_remove(yd->yahoo_p2p_server_watcher);
+ close(yd->yahoo_local_p2p_server_fd);
+ yd->yahoo_local_p2p_server_fd = -1;
+
+ g_hash_table_destroy(yd->sms_carrier);
+ g_hash_table_destroy(yd->peers);
g_hash_table_destroy(yd->friends);
g_hash_table_destroy(yd->imvironments);
g_hash_table_destroy(yd->xfer_peer_idstring_map);
@@ -3609,22 +4203,195 @@ static GList *yahoo_actions(PurplePlugin
return m;
}
+struct yahoo_sms_carrier_cb_data {
+ PurpleConnection *gc;
+ char *who;
+ char *what;
+};
+
+static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags);
+
+static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+ const gchar *webdata, size_t len, const gchar *error_message)
+{
+ struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
+ PurpleConnection *gc = sms_cb_data->gc;
+ struct yahoo_data *yd = gc->proto_data;
+ char *mobile_no = NULL;
+ char *status = NULL;
+ char *carrier = NULL;
+ PurpleAccount *account = purple_connection_get_account(gc);
+ PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
+
+ if (error_message != NULL) {
+ purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+ g_free(sms_cb_data->who);
+ g_free(sms_cb_data->what);
+ g_free(sms_cb_data);
+ return ;
+ }
+ else if (len > 0 && webdata && *webdata) {
+ xmlnode *validate_data_root = xmlnode_from_str(webdata, -1);
+ xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no");
+ mobile_no = (char *)xmlnode_get_attrib(validate_data_child, "msisdn");
+
+ validate_data_root = xmlnode_copy(validate_data_child);
+ validate_data_child = xmlnode_get_child(validate_data_root, "status");
+ status = xmlnode_get_data(validate_data_child);
+
+ validate_data_child = xmlnode_get_child(validate_data_root, "carrier");
+ carrier = xmlnode_get_data(validate_data_child);
+
+ purple_debug_info("yahoo","SMS validate data: Mobile:%s, Status:%s, Carrier:%s\n", mobile_no, status, carrier);
+
+ if( strcmp(status, "Valid") == 0) {
+ g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup(carrier));
+ yahoo_send_im(sms_cb_data->gc, sms_cb_data->who, sms_cb_data->what, PURPLE_MESSAGE_SEND);
+ }
+ else {
+ g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup("Unknown"));
+ purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL));
+ }
+
+ xmlnode_free(validate_data_child);
+ xmlnode_free(validate_data_root);
+ g_free(sms_cb_data->who);
+ g_free(sms_cb_data->what);
+ g_free(sms_cb_data);
+ g_free(mobile_no);
+ g_free(status);
+ g_free(carrier);
+ }
+}
+
+static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
+{
+ struct yahoo_data *yd = gc->proto_data;
+ PurpleUtilFetchUrlData *url_data;
+ struct yahoo_sms_carrier_cb_data *sms_cb_data;
+ char *validate_request_str = NULL;
+ char *request = NULL;
+ gboolean use_whole_url = FALSE;
+ xmlnode *validate_request_root = NULL;
+ xmlnode *validate_request_child = NULL;
+
+ if(!(sms_cb_data = data))
+ return;
+
+ validate_request_root = xmlnode_new("validate");
+ xmlnode_set_attrib(validate_request_root, "intl", "us");
+ xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION);
+ xmlnode_set_attrib(validate_request_root, "qos", "0");
+
+ validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no");
+ xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1);
+
+ validate_request_str = xmlnode_to_str(validate_request_root, NULL);
+
+ xmlnode_free(validate_request_child);
+ xmlnode_free(validate_request_root);
+
+ request = g_strdup_printf(
+ "POST /mobileno?intl=us&version=%s HTTP/1.1\r\n"
+ "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n"
+ "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n"
+ "Host: validate.msg.yahoo.com\r\n"
+ "Content-Length: %d\r\n"
+ "Cache-Control: no-cache\r\n\r\n%s",
+ YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
+
+ /* use whole URL if using HTTP Proxy */
+ if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+ use_whole_url = TRUE;
+
+ url_data = purple_util_fetch_url_request(YAHOO_SMS_CARRIER_URL, use_whole_url,
+ "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE,
+ yahoo_get_sms_carrier_cb, data);
+
+ g_free(request);
+ g_free(validate_request_str);
+
+ if (!url_data) {
+ PurpleAccount *account = purple_connection_get_account(gc);
+ PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
+ purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL));
+ g_free(sms_cb_data->who);
+ g_free(sms_cb_data->what);
+ g_free(sms_cb_data);
+ }
+}
+
static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
{
struct yahoo_data *yd = gc->proto_data;
- struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0);
+ struct yahoo_packet *pkt;
char *msg = yahoo_html_to_codes(what);
char *msg2;
gboolean utf8 = TRUE;
PurpleWhiteboard *wb;
int ret = 1;
YahooFriend *f = NULL;
+ struct yahoo_p2p_data *p2p_data;
msg2 = yahoo_string_encode(gc, msg, &utf8);
+ if( strncmp(who, "+", 1) == 0 ) {
+ /* we have an sms to be sent */
+ gchar *carrier = NULL;
+ const char *alias = NULL;
+ PurpleAccount *account = purple_connection_get_account(gc);
+ PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
+
+ carrier = g_hash_table_lookup(yd->sms_carrier, who);
+ if (!carrier) {
+ struct yahoo_sms_carrier_cb_data *sms_cb_data;
+ sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data));
+ sms_cb_data->gc = gc;
+ sms_cb_data->who = g_malloc(strlen(who));
+ sms_cb_data->what = g_malloc(strlen(what));
+ strcpy(sms_cb_data->who, who);
+ strcpy(sms_cb_data->what, what);
+
+ purple_conversation_write(conv, NULL, "Getting mobile carrier to send the sms", PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+ yahoo_get_sms_carrier(gc, sms_cb_data);
+
+ g_free(msg);
+ g_free(msg2);
+ return ret;
+ }
+ else if( strcmp(carrier,"Unknown") == 0 ) {
+ purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+ g_free(msg);
+ g_free(msg2);
+ return -1;
+ }
+
+ alias = purple_account_get_alias(account);
+ pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, 0);
+ yahoo_packet_hash(pkt, "sssss",
+ 1, purple_connection_get_display_name(gc),
+ 69, alias,
+ 5, who + 1,
+ 68, carrier,
+ 14, msg2);
+ yahoo_packet_send_and_free(pkt, yd);
+
+ g_free(msg);
+ g_free(msg2);
+
+ return ret;
+ }
+
+ pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0);
yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who);
if ((f = yahoo_friend_find(gc, who)) && f->protocol)
yahoo_packet_hash_int(pkt, 241, f->protocol);
+ else
+ if(strchr(who,'@'))
+ yahoo_packet_hash_int(pkt, 241, 2);
if (utf8)
yahoo_packet_hash_str(pkt, 97, "1");
@@ -3663,8 +4430,17 @@ static int yahoo_send_im(PurpleConnectio
yahoo_packet_hash_str(pkt, 206, "2");
/* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */
- if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000)
- yahoo_packet_send(pkt, yd);
+ if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) {
+ /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */
+ if( (p2p_data = g_hash_table_lookup(yd->peers, who)) ) {
+ yahoo_packet_hash_int(pkt, 11, p2p_data->session_id);
+ yahoo_p2p_write_pkt(p2p_data->source, pkt);
+ }
+ else {
+ yahoo_packet_send(pkt, yd);
+ yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */
+ }
+ }
else
ret = -E2BIG;
@@ -3679,13 +4455,29 @@ static unsigned int yahoo_send_typing(Pu
static unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
{
struct yahoo_data *yd = gc->proto_data;
+ struct yahoo_p2p_data *p2p_data;
+
struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0);
- yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
+
+ /* Don't do anything if sms is being typed */
+ if( strncmp(who, "+", 1) == 0 )
+ return 0;
+
+ /* check to see if p2p link exists, send through it */
+ if( (p2p_data = g_hash_table_lookup(yd->peers, who)) ) {
+ yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc),
14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
+ 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */
+ yahoo_p2p_write_pkt(p2p_data->source, pkt);
+ yahoo_packet_free(pkt);
+ }
+ else { /* send through yahoo server */
+ yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
+ 14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
5, who, 1002, "1");
+ yahoo_packet_send_and_free(pkt, yd);
+ }
- yahoo_packet_send_and_free(pkt, yd);
-
return 0;
}
@@ -3935,18 +4727,36 @@ static void yahoo_add_buddy(PurpleConnec
group2 = yahoo_string_encode(gc, group, NULL);
pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0);
- yahoo_packet_hash(pkt, "ssssssssss",
- 14, "",
- 65, group2,
- 97, "1",
- 1, purple_connection_get_display_name(gc),
- 302, "319",
- 300, "319",
- 7, buddy->name,
- 334, "0",
- 301, "319",
- 303, "319"
- );
+ if(strchr(buddy->name, '@')) {
+ yahoo_packet_hash(pkt, "sssssssssss",
+ 14, "",
+ 65, group2,
+ 97, "1",
+ 1, purple_connection_get_display_name(gc),
+ 302, "319",
+ 300, "319",
+ 7, buddy->name,
+ 241, "2",
+ 334, "0",
+ 301, "319",
+ 303, "319"
+ );
+ }
+ else {
+ yahoo_packet_hash(pkt, "ssssssssss",
+ 14, "",
+ 65, group2,
+ 97, "1",
+ 1, purple_connection_get_display_name(gc),
+ 302, "319",
+ 300, "319",
+ 7, buddy->name,
+ 334, "0",
+ 301, "319",
+ 303, "319"
+ );
+ }
+
if (f && f->protocol)
yahoo_packet_hash_int(pkt, 241, f->protocol);
yahoo_packet_send_and_free(pkt, yd);
@@ -3961,8 +4771,9 @@ static void yahoo_remove_buddy(PurpleCon
PurpleGroup *g;
gboolean remove = TRUE;
char *cg;
+ YahooFriend *f = yahoo_friend_find(gc, buddy->name);
- if (!(yahoo_friend_find(gc, buddy->name)))
+ if (!f)
return;
buddies = purple_find_buddies(purple_connection_get_account(gc), buddy->name);
@@ -3983,6 +4794,8 @@ static void yahoo_remove_buddy(PurpleCon
pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0);
yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
7, buddy->name, 65, cg);
+ if(f->protocol)
+ yahoo_packet_hash_int(pkt, 241, f->protocol);
yahoo_packet_send_and_free(pkt, yd);
g_free(cg);
}
@@ -4055,11 +4868,12 @@ static void yahoo_change_buddys_group(Pu
struct yahoo_data *yd = gc->proto_data;
struct yahoo_packet *pkt;
char *gpn, *gpo;
+ YahooFriend *f = yahoo_friend_find(gc, who);
/* Step 0: If they aren't on the server list anyway,
* don't bother letting the server know.
*/
- if (!yahoo_friend_find(gc, who))
+ if (!f)
return;
/* If old and new are the same, we would probably
@@ -4075,7 +4889,12 @@ static void yahoo_change_buddys_group(Pu
}
pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, 0);
- yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc),
+ if(f->protocol)
+ yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc),
+ 302, "240", 300, "240", 7, who, 241, f->protocol, 224, gpo, 264, gpn, 301,
+ "240", 303, "240");
+ else
+ yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc),
302, "240", 300, "240", 7, who, 224, gpo, 264, gpn, 301,
"240", 303, "240");
yahoo_packet_send_and_free(pkt, yd);
@@ -4289,10 +5108,10 @@ static gboolean yahoo_uri_handler(const
purple_conv_send_confirm(conv, message);
}
}
- /*else
+ /* else
**If pidgindialogs_im() was in the core, we could use it here.
* It is all purple_request_* based, but I'm not sure it really belongs in the core
- pidgindialogs_im();*/
+ pidgindialogs_im(); */
return TRUE;
}
@@ -4306,7 +5125,7 @@ static gboolean yahoo_uri_handler(const
g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat"));
serv_join_chat(purple_account_get_connection(acct), params);
}
- /*else
+ /* else
** Same as above (except that this would have to be re-written using purple_request_*)
pidgin_blist_joinchat_show(); */
@@ -4376,7 +5195,7 @@ static PurplePluginProtocolInfo prpl_inf
yahoo_add_buddy,
NULL, /* add_buddies */
yahoo_remove_buddy,
- NULL, /*remove_buddies */
+ NULL, /* remove_buddies */
NULL, /* add_permit */
yahoo_add_deny,
NULL, /* rem_permit */
============================================================
--- libpurple/protocols/yahoo/yahoo.h 50bc84d9e9f5c3f1da265c8ef93ed880a403a218
+++ libpurple/protocols/yahoo/yahoo.h 765244b00e3c05701c9e43181254242dd4d45772
@@ -30,6 +30,9 @@
#define YAHOO_PAGER_HOST "scs.msg.yahoo.com"
#define YAHOO_PAGER_PORT 5050
+#define YAHOO_PAGER_PORT_P2P 5101
+#define YAHOO_P2P_KEEPALIVE_SECS 300
+#define YAHOO_P2P_SERVER_TIMEOUT 10
#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
#define YAHOO_MAIL_URL "https://login.yahoo.com/config/login?.src=ym"
#define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com"
@@ -45,7 +48,7 @@
#define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/"
#define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp"
#define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp"
-/*not sure, must test:*/
+/* not sure, must test: */
#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.co.jp"
#define YAHOOJP_XFER_RELAY_PORT 80
#define YAHOOJP_ROOMLIST_URL "http://insider.msg.yahoo.co.jp/ycontent/"
@@ -55,6 +58,8 @@
#define WEBMESSENGER_URL "http://login.yahoo.com/config/login?.src=pg"
+#define YAHOO_SMS_CARRIER_URL "http://lookup.msg.vip.mud.yahoo.com"
+
#define YAHOO_PICURL_SETTING "picture_url"
#define YAHOO_PICCKSUM_SETTING "picture_checksum"
#define YAHOO_PICEXPIRE_SETTING "picture_expire"
@@ -80,10 +85,19 @@
#define YAHOOJP_CLIENT_VERSION_ID "524223"
#define YAHOOJP_CLIENT_VERSION "7,0,1,1"
-
/* Index into attention types list. */
#define YAHOO_BUZZ 0
+typedef enum {
+ YAHOO_PKT_TYPE_SERVER = 0,
+ YAHOO_PKT_TYPE_P2P
+} yahoo_pkt_type;
+
+typedef enum {
+ YAHOO_P2P_WE_ARE_CLIENT =0,
+ YAHOO_P2P_WE_ARE_SERVER
+} yahoo_p2p_connection_type;
+
enum yahoo_status {
YAHOO_STATUS_AVAILABLE = 0,
YAHOO_STATUS_BRB,
@@ -113,6 +127,17 @@ struct yahoo_buddy_icon_upload_data {
guint watcher;
};
+struct yahoo_p2p_data {
+ PurpleConnection *gc;
+ char *host_ip;
+ char *host_username;
+ int val_13;
+ guint input_event;
+ gint source;
+ int session_id;
+ yahoo_p2p_connection_type connection_type;
+};
+
struct _YchtConn;
struct yahoo_data {
@@ -168,8 +193,8 @@ struct yahoo_data {
* for when we lookup people profile or photo information.
*/
GSList *url_datas;
- GHashTable *xfer_peer_idstring_map;/*Hey, i dont know, but putting this HashTable next to friends gives a run time fault...*/
- GSList *cookies;/*contains all cookies, including _y and _t*/
+ GHashTable *xfer_peer_idstring_map;/* Hey, i dont know, but putting this HashTable next to friends gives a run time fault... */
+ GSList *cookies;/* contains all cookies, including _y and _t */
/**
* We may receive a list15 in multiple packets with no prior warning as to how many we'll be getting;
@@ -178,6 +203,12 @@ struct yahoo_data {
char *current_list15_grp;
time_t last_ping;
time_t last_keepalive;
+ GHashTable *peers; /* information about p2p data */
+ int yahoo_p2p_timer;
+ int yahoo_local_p2p_server_fd;
+ int yahoo_p2p_server_watcher;
+ GHashTable *sms_carrier; /* sms carrier data */
+ guint yahoo_p2p_server_timeout_handle;
};
#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
@@ -250,4 +281,7 @@ GList *yahoo_attention_types(PurpleAccou
gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
GList *yahoo_attention_types(PurpleAccount *account);
+/* send p2p pkt containing our encoded ip, asking peer to connect to us */
+void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13);
+
#endif /* _YAHOO_H_ */
============================================================
--- libpurple/protocols/yahoo/yahoo_packet.h 73ca2470ec14b98bfa34d11bb2634e83039c3b30
+++ libpurple/protocols/yahoo/yahoo_packet.h 8e9c2ff523731785e8d9ad1f5d9c04fd9a920ee6
@@ -98,15 +98,18 @@ enum yahoo_service { /* these are easier
YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
YAHOO_SERVICE_AUDIBLE = 0xd0,
+ /* YAHOO_SERVICE_CHAT_SESSION = 0xd4,?? Reports start of chat session, gets an id from server */
YAHOO_SERVICE_AUTH_REQ_15 = 0xd6,
+ YAHOO_SERVICE_FILETRANS_15 = 0xdc,
+ YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd,
+ YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde,
+ /* photo sharing services ?? - 0xd2, 0xd7, 0xd8, 0xda */
YAHOO_SERVICE_CHGRP_15 = 0xe7,
YAHOO_SERVICE_STATUS_15 = 0xf0,
YAHOO_SERVICE_LIST_15 = 0xf1,
- YAHOO_SERVICE_FILETRANS_15 = 0xdc,
- YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd,
- YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde,
YAHOO_SERVICE_WEBLOGIN = 0x0226,
YAHOO_SERVICE_SMS_MSG = 0x02ea
+ /* YAHOO_SERVICE_DISCONNECT = 0x07d1 Server forces us to disconnect. Is sent with TCP FIN flag set */
};
struct yahoo_pair {
More information about the Commits
mailing list