comparison libpurple/protocols/yahoo/yahoo.c @ 25011:9b16249bfbe6

Support for YAHOO_PROCESS_MESSAGE and YAHOO_PROCESS_NOTIFY over p2p links. The patch enables initialization of p2p, and use of p2p link to RECEIVE IM messages.
author Sulabh Mahajan <sulabh@soc.pidgin.im>
date Sun, 08 Jun 2008 17:40:04 +0000
parents afb1b5f1dc84
children 193093790ada
comparison
equal deleted inserted replaced
25010:afb1b5f1dc84 25011:9b16249bfbe6
697 697
698 account = purple_connection_get_account(gc); 698 account = purple_connection_get_account(gc);
699 699
700 while (l) { 700 while (l) {
701 struct yahoo_pair *pair = l->data; 701 struct yahoo_pair *pair = l->data;
702 if (pair->key == 4) 702 if (pair->key == 4 || pair->key == 1)
703 from = pair->value; 703 from = pair->value;
704 if (pair->key == 49) 704 if (pair->key == 49)
705 msg = pair->value; 705 msg = pair->value;
706 if (pair->key == 13) 706 if (pair->key == 13)
707 stat = pair->value; 707 stat = pair->value;
767 struct _yahoo_im *im = NULL; 767 struct _yahoo_im *im = NULL;
768 const char *imv = NULL; 768 const char *imv = NULL;
769 769
770 account = purple_connection_get_account(gc); 770 account = purple_connection_get_account(gc);
771 771
772 if (pkt->status <= 1 || pkt->status == 5) { 772 if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) {
773 /* messages are reveived with status YAHOO_STATUS_OFFLINE in case of p2p */
773 while (l != NULL) { 774 while (l != NULL) {
774 struct yahoo_pair *pair = l->data; 775 struct yahoo_pair *pair = l->data;
775 if (pair->key == 4) { 776 if (pair->key == 4 || pair->key == 1) {
776 im = g_new0(struct _yahoo_im, 1); 777 im = g_new0(struct _yahoo_im, 1);
777 list = g_slist_append(list, im); 778 list = g_slist_append(list, im);
778 im->from = pair->value; 779 im->from = pair->value;
779 im->time = time(NULL); 780 im->time = time(NULL);
780 } 781 }
2211 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); 2212 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf);
2212 g_free(buf); 2213 g_free(buf);
2213 g_free(decoded_group); 2214 g_free(decoded_group);
2214 } 2215 }
2215 2216
2216 static void yahoo_write_p2p_packet(gpointer data, gint source) 2217 /*write pkt to the source*/
2217 { 2218 static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
2218 struct yahoo_p2p_data *user_data; 2219 {
2219 struct yahoo_packet *pkt_to_send;
2220 size_t pkt_len; 2220 size_t pkt_len;
2221 guchar *raw_packet; 2221 guchar *raw_packet;
2222
2223 /*build the raw packet and send it to the host*/
2224 pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet);
2225 if(write(source, raw_packet, pkt_len) != pkt_len)
2226 purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
2227 g_free(raw_packet);
2228 }
2229
2230 /*exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER*/
2231 static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt)
2232 {
2233 struct yahoo_p2p_data *user_data;
2234 char *who = NULL;
2235 GSList *l = pkt->hash;
2236 struct yahoo_packet *pkt_to_send;
2222 PurpleAccount *account; 2237 PurpleAccount *account;
2223 int val_13_to_send = 0; 2238 int val_13_to_send = 0;
2224 2239
2225 if(!(user_data = data)) 2240 if(!(user_data = data))
2226 return ; 2241 return ;
2242
2243 /* lets see whats in the packet */
2244 while (l) {
2245 struct yahoo_pair *pair = l->data;
2246
2247 switch (pair->key) {
2248 case 4:
2249 who = pair->value;
2250 if(strncmp(who, user_data->host_username, strlen(user_data->host_username)) != 0) {
2251 /* from whom are we receiving the packets ?? */
2252 purple_debug_warning("yahoo","p2p: received data from wrong user\n");
2253 return;
2254 }
2255 break;
2256 case 13:
2257 user_data->val_13 = strtol(pair->value, NULL, 10); /*Value should be 5-7*/
2258 break;
2259 /*case 5, 49 look laters, no use right now*/
2260 }
2261 l = l->next;
2262 }
2227 2263
2228 account = purple_connection_get_account(user_data->gc); 2264 account = purple_connection_get_account(user_data->gc);
2229 2265
2230 /*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*/ 2266 /*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*/
2231 2267
2241 5, user_data->host_username, 2277 5, user_data->host_username,
2242 241, 0, /*Protocol identifier*/ 2278 241, 0, /*Protocol identifier*/
2243 49, "PEERTOPEER", 2279 49, "PEERTOPEER",
2244 13, val_13_to_send); 2280 13, val_13_to_send);
2245 2281
2246 /*build the packet and send it to the host*/ 2282 /*build the raw packet and send it to the host*/
2247 pkt_len = yahoo_packet_build(pkt_to_send, 0, 0, 0, &raw_packet); 2283 yahoo_p2p_write_pkt(source, pkt_to_send);
2248 if(write(source, raw_packet, pkt_len) != pkt_len)
2249 purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
2250 yahoo_packet_free(pkt_to_send); 2284 yahoo_packet_free(pkt_to_send);
2251 g_free(raw_packet); 2285
2252 2286 }
2253 /*if written packet has val_13 equal to 7, we dont send any other packet but dont close the connection, connection seems to exist long after the p2p processes are over*/ 2287
2254 if(val_13_to_send == 7) { 2288 /*callback function associated with receiving of data on the source, not considering receipt of multiple YMSG packets in a single TCP packet*/
2255 /*cant figure out when to close the connection, not closing connection right now, misbehaves if host logs out, to be fixed soon*/ 2289 static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
2256 /*free user_data, do we need it now*/
2257 g_free(user_data->host_ip);
2258 g_free(user_data->host_username);
2259 g_free(user_data);
2260 }
2261 }
2262
2263 static void yahoo_p2p_packet_process(gpointer data, gint source, struct yahoo_packet *pkt)
2264 {
2265 struct yahoo_p2p_data *user_data;
2266 char *who = NULL;
2267 GSList *l = pkt->hash;
2268
2269 if(!(user_data = data))
2270 return ;
2271
2272 /* lets see whats in the packet */
2273 while (l) {
2274 struct yahoo_pair *pair = l->data;
2275
2276 switch (pair->key) {
2277 case 4:
2278 who = pair->value;
2279 if(strncmp(who, user_data->host_username, strlen(user_data->host_username)) != 0) {
2280 /* from whom are we receiving the packets ?? */
2281 purple_debug_warning("yahoo","p2p: received data from wrong user");
2282 return;
2283 }
2284 break;
2285 case 13:
2286 user_data->val_13 = strtol(pair->value, NULL, 10); /*Value should be 5-7*/
2287 break;
2288 /*case 5, 49 look laters, no use right now*/
2289 }
2290 l = l->next;
2291 }
2292
2293 yahoo_write_p2p_packet(data, source); /*udpated the value of key 13, now write data*/
2294 }
2295
2296 static void yahoo_read_p2p_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
2297 { 2290 {
2298 guchar buf[1024]; /*is it safe to assume a fixed array length of 1024 ??*/ 2291 guchar buf[1024]; /*is it safe to assume a fixed array length of 1024 ??*/
2299 int len; 2292 int len;
2300 int pos = 0; 2293 int pos = 0;
2301 int pktlen; 2294 int pktlen;
2302 struct yahoo_packet *pkt; 2295 struct yahoo_packet *pkt;
2303 guchar *start = NULL; 2296 guchar *start = NULL;
2297 struct yahoo_p2p_data *user_data;
2298
2299 user_data = data;
2304 2300
2305 if((len = read(source, buf, sizeof(buf))) <= 0 ) 2301 if((len = read(source, buf, sizeof(buf))) <= 0 )
2306 purple_debug_warning("yahoo","p2p: Error in connection to p2p host\n"); 2302 purple_debug_warning("yahoo","p2p: Error in connection to p2p host\n");
2307 2303
2308 if(len < YAHOO_PACKET_HDRLEN) 2304 if(len < YAHOO_PACKET_HDRLEN)
2327 2323
2328 pktlen = yahoo_get16(buf + pos); pos += 2; 2324 pktlen = yahoo_get16(buf + pos); pos += 2;
2329 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len); 2325 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len);
2330 2326
2331 pkt = yahoo_packet_new(0, 0, 0); 2327 pkt = yahoo_packet_new(0, 0, 0);
2332
2333 pkt->service = yahoo_get16(buf + pos); pos += 2; 2328 pkt->service = yahoo_get16(buf + pos); pos += 2;
2334 if(pkt->service != YAHOO_SERVICE_P2PFILEXFER) {
2335 /* Shouldn't we be getting p2p filexfer packets only*/
2336 /* Should we break connection if this happens ??*/
2337 return;
2338 }
2339 purple_debug_info("yahoo", "p2p: received packet recognized as a p2p, Status: %d\n", pkt->status);
2340
2341 pkt->status = yahoo_get32(buf + pos); pos += 4; 2329 pkt->status = yahoo_get32(buf + pos); pos += 4;
2342 pkt->id = yahoo_get32(buf + pos); pos += 4; 2330 pkt->id = yahoo_get32(buf + pos); pos += 4;
2343 2331
2332 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status);
2344 yahoo_packet_read(pkt, buf + pos, pktlen); 2333 yahoo_packet_read(pkt, buf + pos, pktlen);
2345 2334
2346 yahoo_p2p_packet_process(data, source, pkt); 2335 /*packet processing*/
2336 switch(pkt->service) {
2337 case YAHOO_SERVICE_P2PFILEXFER:
2338 yahoo_p2p_process_p2pfilexfer(data, source, pkt);
2339 break;
2340 case YAHOO_SERVICE_MESSAGE:
2341 yahoo_process_message(user_data->gc, pkt);
2342 break;
2343 case YAHOO_SERVICE_NOTIFY:
2344 yahoo_process_notify(user_data->gc, pkt);
2345 break;
2346 default:
2347 purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service);
2348 }
2349
2347 yahoo_packet_free(pkt); 2350 yahoo_packet_free(pkt);
2348 } 2351 }
2349 2352
2353 /*function called when connection to p2p host is setup*/
2350 static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message) 2354 static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message)
2351 { 2355 {
2356 struct yahoo_p2p_data *user_data;
2357 struct yahoo_packet *pkt_to_send;
2358 PurpleAccount *account;
2359
2352 if(error_message != NULL) { 2360 if(error_message != NULL) {
2353 purple_debug_warning("yahoo","p2p: %s\n",error_message); 2361 purple_debug_warning("yahoo","p2p: %s\n",error_message);
2354 return; 2362 return;
2355 } 2363 }
2356
2357 /*Add an Input Read event to the file descriptor*/ 2364 /*Add an Input Read event to the file descriptor*/
2358 purple_input_add(source, PURPLE_INPUT_READ, yahoo_read_p2p_pkt_cb, data); 2365 purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
2359 2366
2360 yahoo_write_p2p_packet(data, source); /*create and send packet*/ 2367 if(!(user_data = data))
2368 return ;
2369
2370 account = purple_connection_get_account(user_data->gc);
2371
2372 /*Build the yahoo packet*/
2373 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, user_data->session_id);
2374 yahoo_packet_hash(pkt_to_send, "ssisi",
2375 4, purple_normalize(account, purple_account_get_username(account)),
2376 5, user_data->host_username,
2377 241, 0, /*Protocol identifier*/
2378 49, "PEERTOPEER",
2379 13, 1); /*we receive key13=0, we send key13=1*/
2380
2381 yahoo_p2p_write_pkt(source, pkt_to_send); /*build raw packet and send*/
2382 yahoo_packet_free(pkt_to_send);
2361 } 2383 }
2362 2384
2363 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) 2385 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
2364 { 2386 {
2365 GSList *l = pkt->hash; 2387 GSList *l = pkt->hash;
2367 char *base64 = NULL; 2389 char *base64 = NULL;
2368 guchar *decoded; 2390 guchar *decoded;
2369 gsize len; 2391 gsize len;
2370 gint val_13 = 0; 2392 gint val_13 = 0;
2371 PurpleAccount *account; 2393 PurpleAccount *account;
2372 struct yahoo_p2p_data *user_data = g_new0(struct yahoo_p2p_data, 1); 2394 struct yahoo_p2p_data *user_data = g_new0(struct yahoo_p2p_data, 1); /*yet to decide when to free this up*/
2373 2395
2374 while (l) { 2396 while (l) {
2375 struct yahoo_pair *pair = l->data; 2397 struct yahoo_pair *pair = l->data;
2376 2398
2377 switch (pair->key) { 2399 switch (pair->key) {
2440 user_data->host_ip = host_ip; 2462 user_data->host_ip = host_ip;
2441 user_data->session_id = pkt->id; 2463 user_data->session_id = pkt->id;
2442 user_data->gc = gc; 2464 user_data->gc = gc;
2443 2465
2444 /*connect to host*/ 2466 /*connect to host*/
2445 /*use an handle ??*/
2446 if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, user_data))==NULL) 2467 if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, user_data))==NULL)
2447 purple_debug_info("yahoo","p2p: Connection to %s failed", host_ip); 2468 purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
2448 2469
2449 } 2470 }
2450 } 2471 }
2451 2472
2452 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) 2473 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)