Mercurial > pidgin
changeset 25061:048a53891afd
Act as a YMSG server on port 5101 for IMs and Notifications
author | Sulabh Mahajan <sulabh@soc.pidgin.im> |
---|---|
date | Wed, 02 Jul 2008 06:58:57 +0000 |
parents | d6247d2d6c47 |
children | 6da23dc3000d |
files | libpurple/protocols/yahoo/yahoo.c libpurple/protocols/yahoo/yahoo.h |
diffstat | 2 files changed, 145 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/yahoo/yahoo.c Fri Jun 27 16:02:30 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Wed Jul 02 06:58:57 2008 +0000 @@ -2233,56 +2233,10 @@ 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)) @@ -2290,15 +2244,12 @@ /*If friend, set him not connected*/ f = yahoo_friend_find(user_data->gc, user_data->host_username); - if (f) { + if (f) yahoo_friend_set_p2p_status(f, NOT_CONNECTED); - f->p2p_packet_sent = 0; - } - - yd = user_data->gc->proto_data; - + + if(user_data->source) + close(user_data->source); purple_input_remove(user_data->input_event); - close(user_data->source); g_free(user_data->host_ip); g_free(user_data->host_username); g_free(user_data); @@ -2326,10 +2277,13 @@ struct yahoo_packet *pkt_to_send; PurpleAccount *account; int val_13_to_send = 0; + struct yahoo_data *yd; if(!(user_data = data)) return ; + yd = user_data->gc->proto_data; + /* lets see whats in the packet */ while (l) { struct yahoo_pair *pair = l->data; @@ -2353,15 +2307,23 @@ account = purple_connection_get_account(user_data->gc); - /*key_13 appears to be a sort of a counter,yahoo server sends with val_13=0, we send packet to host with val_13=1, receive back with val_13=5, we send with val_13=6, receive back with val_13=7, we send with val_13=7, then break the connection. So we keep the value for 7 and increment for not 7*/ - - if(user_data->val_13 != 7) - val_13_to_send = user_data->val_13 + 1; - else - val_13_to_send = user_data->val_13; /* haven't ever received values other than 0, 5, 6, 7*/ - + /*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(user_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 : 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, user_data->session_id); + 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, user_data->host_username, @@ -2372,7 +2334,6 @@ /*build the raw packet and send it to the host*/ yahoo_p2p_write_pkt(source, pkt_to_send); yahoo_packet_free(pkt_to_send); - } /*callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet*/ @@ -2392,10 +2353,8 @@ yd = user_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"); @@ -2454,6 +2413,120 @@ yahoo_packet_free(pkt); } +static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond) +{ + int acceptfd; + struct yahoo_p2p_data *user_data; + YahooFriend *f; + struct yahoo_data *yd; + + if(!(user_data = data)) + return ; + yd = user_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; + + if( (f = yahoo_friend_find(user_data->gc, user_data->host_username)) ) { + /*To-Do: we should disconnect if not a friend*/ + user_data->val_11 = f->val_11; + yahoo_friend_set_p2p_status(f, CONNECTED_AS_SERVER); + } + + /*Add an Input Read event to the file descriptor*/ + user_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data); + user_data->source = acceptfd; + + g_hash_table_insert(yd->peers, g_strdup(user_data->host_username), user_data); +} + +static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data) +{ + struct yahoo_p2p_data *user_data; + struct yahoo_data *yd; + + if(!(user_data = data)) + return ; + + if(listenfd == -1) { + purple_debug_warning("yahoo","p2p: error starting p2p server\n"); + yahoo_p2p_disconnect_destroy_data(data); + return; + } + + yd = user_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); +} + +/*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; + struct yahoo_p2p_data *user_data = g_new0(struct yahoo_p2p_data, 1); + + 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, + 49, "PEERTOPEER"); + yahoo_packet_send_and_free(pkt, yd); + + f->p2p_packet_sent = 1; /*set p2p_packet_sent to sent*/ + + user_data->gc = gc; + user_data->host_ip = NULL; + user_data->host_username = (char *)g_malloc(strlen(who)); + strcpy(user_data->host_username, who); + user_data->val_13 = val_13; + user_data->connection_type = 1; /*0:we are server*/ + + purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, user_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) { @@ -2489,7 +2562,7 @@ account = purple_connection_get_account(user_data->gc); /*Build the yahoo packet*/ - pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, user_data->session_id); + 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, user_data->host_username, @@ -2592,12 +2665,14 @@ user_data->val_13 = val_13; user_data->val_11 = val_11; user_data->host_ip = host_ip; - user_data->session_id = pkt->id; user_data->gc = gc; + user_data->connection_type = 0; /*0:peer is server*/ /*connect to host*/ - if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, user_data))==NULL) + if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, user_data))==NULL) { + yahoo_p2p_disconnect_destroy_data(user_data); purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip); + } } }
--- a/libpurple/protocols/yahoo/yahoo.h Fri Jun 27 16:02:30 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Wed Jul 02 06:58:57 2008 +0000 @@ -117,12 +117,12 @@ struct yahoo_p2p_data { PurpleConnection *gc; char *host_ip; - int session_id; char *host_username; int val_13; guint input_event; gint source; int val_11; + gboolean connection_type; /* 0: peer is server, 1: we are server*/ }; struct _YchtConn; @@ -189,6 +189,8 @@ */ char *current_list15_grp; GHashTable *peers; /*information about p2p data*/ + int yahoo_local_p2p_server_fd; + int yahoo_p2p_server_watcher; }; #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)