Mercurial > pidgin
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) |