Mercurial > pidgin.yaz
comparison libpurple/protocols/yahoo/yahoo.c @ 25568:afb1b5f1dc84
Implementation of initial exchange of p2pxfer packets that initiates p2p file transfer. Some connection
and stability issues exists, soon to be looked into.
author | Sulabh Mahajan <sulabh@soc.pidgin.im> |
---|---|
date | Fri, 06 Jun 2008 17:28:37 +0000 |
parents | 5ec08738906c |
children | 9b16249bfbe6 |
comparison
equal
deleted
inserted
replaced
25567:185bd4679ad1 | 25568:afb1b5f1dc84 |
---|---|
2211 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); | 2211 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); |
2212 g_free(buf); | 2212 g_free(buf); |
2213 g_free(decoded_group); | 2213 g_free(decoded_group); |
2214 } | 2214 } |
2215 | 2215 |
2216 static void yahoo_write_p2p_packet(gpointer data, gint source) | |
2217 { | |
2218 struct yahoo_p2p_data *user_data; | |
2219 struct yahoo_packet *pkt_to_send; | |
2220 size_t pkt_len; | |
2221 guchar *raw_packet; | |
2222 PurpleAccount *account; | |
2223 int val_13_to_send = 0; | |
2224 | |
2225 if(!(user_data = data)) | |
2226 return ; | |
2227 | |
2228 account = purple_connection_get_account(user_data->gc); | |
2229 | |
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*/ | |
2231 | |
2232 if(user_data->val_13 != 7) | |
2233 val_13_to_send = user_data->val_13 + 1; | |
2234 else | |
2235 val_13_to_send = user_data->val_13; /* haven't ever received values other than 0, 5, 6, 7*/ | |
2236 | |
2237 /*Build the yahoo packet*/ | |
2238 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, user_data->session_id); | |
2239 yahoo_packet_hash(pkt_to_send, "ssisi", | |
2240 4, purple_normalize(account, purple_account_get_username(account)), | |
2241 5, user_data->host_username, | |
2242 241, 0, /*Protocol identifier*/ | |
2243 49, "PEERTOPEER", | |
2244 13, val_13_to_send); | |
2245 | |
2246 /*build the packet and send it to the host*/ | |
2247 pkt_len = yahoo_packet_build(pkt_to_send, 0, 0, 0, &raw_packet); | |
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); | |
2251 g_free(raw_packet); | |
2252 | |
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*/ | |
2254 if(val_13_to_send == 7) { | |
2255 /*cant figure out when to close the connection, not closing connection right now, misbehaves if host logs out, to be fixed soon*/ | |
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 { | |
2298 guchar buf[1024]; /*is it safe to assume a fixed array length of 1024 ??*/ | |
2299 int len; | |
2300 int pos = 0; | |
2301 int pktlen; | |
2302 struct yahoo_packet *pkt; | |
2303 guchar *start = NULL; | |
2304 | |
2305 if((len = read(source, buf, sizeof(buf))) <= 0 ) | |
2306 purple_debug_warning("yahoo","p2p: Error in connection to p2p host\n"); | |
2307 | |
2308 if(len < YAHOO_PACKET_HDRLEN) | |
2309 return; | |
2310 if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) { | |
2311 /* Not a YMSG packet */ | |
2312 purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n"); | |
2313 | |
2314 start = memchr(buf + 1, 'Y', len - 1); | |
2315 if(start) { | |
2316 g_memmove(buf, start, len - (start - buf)); | |
2317 len -= start - buf; | |
2318 } else { | |
2319 g_free(buf); | |
2320 return; | |
2321 } | |
2322 } | |
2323 | |
2324 pos += 4; /* YMSG */ | |
2325 pos += 2; | |
2326 pos += 2; | |
2327 | |
2328 pktlen = yahoo_get16(buf + pos); pos += 2; | |
2329 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len); | |
2330 | |
2331 pkt = yahoo_packet_new(0, 0, 0); | |
2332 | |
2333 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; | |
2342 pkt->id = yahoo_get32(buf + pos); pos += 4; | |
2343 | |
2344 yahoo_packet_read(pkt, buf + pos, pktlen); | |
2345 | |
2346 yahoo_p2p_packet_process(data, source, pkt); | |
2347 yahoo_packet_free(pkt); | |
2348 } | |
2349 | |
2350 static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message) | |
2351 { | |
2352 if(error_message != NULL) { | |
2353 purple_debug_warning("yahoo","p2p: %s\n",error_message); | |
2354 return; | |
2355 } | |
2356 | |
2357 /*Add an Input Read event to the file descriptor*/ | |
2358 purple_input_add(source, PURPLE_INPUT_READ, yahoo_read_p2p_pkt_cb, data); | |
2359 | |
2360 yahoo_write_p2p_packet(data, source); /*create and send packet*/ | |
2361 } | |
2362 | |
2216 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) | 2363 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) |
2217 { | 2364 { |
2218 GSList *l = pkt->hash; | 2365 GSList *l = pkt->hash; |
2219 char *who = NULL; | 2366 char *who = NULL; |
2220 char *base64 = NULL; | 2367 char *base64 = NULL; |
2221 guchar *decoded; | 2368 guchar *decoded; |
2222 gsize len; | 2369 gsize len; |
2370 gint val_13 = 0; | |
2371 PurpleAccount *account; | |
2372 struct yahoo_p2p_data *user_data = g_new0(struct yahoo_p2p_data, 1); | |
2223 | 2373 |
2224 while (l) { | 2374 while (l) { |
2225 struct yahoo_pair *pair = l->data; | 2375 struct yahoo_pair *pair = l->data; |
2226 | 2376 |
2227 switch (pair->key) { | 2377 switch (pair->key) { |
2228 case 5: | 2378 case 5: |
2229 /* our identity */ | 2379 /* our identity */ |
2230 break; | 2380 break; |
2231 case 4: | 2381 case 4: |
2232 who = pair->value; | 2382 who = (char *)g_malloc(strlen(pair->value)); |
2383 strcpy(who, pair->value); | |
2384 user_data->host_username = who; | |
2233 break; | 2385 break; |
2234 case 1: | 2386 case 1: |
2235 /* who again, the master identity this time? */ | 2387 /* who again, the master identity this time? */ |
2236 break; | 2388 break; |
2237 case 12: | 2389 case 12: |
2238 base64 = pair->value; | 2390 base64 = pair->value; |
2239 /* so, this is an ip address. in base64. decoded it's in ascii. | 2391 /* so, this is an ip address. in base64. decoded it's in ascii. |
2240 after strtol, it's in reversed byte order. Who thought this up?*/ | 2392 after strtol, it's in reversed byte order. Who thought this up?*/ |
2241 break; | 2393 break; |
2394 case 13: | |
2395 val_13 = strtol(pair->value, NULL, 10); /*Value always 0*/ | |
2396 user_data->val_13 = val_13; | |
2397 break; | |
2398 | |
2242 /* | 2399 /* |
2243 TODO: figure these out | 2400 TODO: figure these out |
2244 yahoo: Key: 61 Value: 0 | 2401 yahoo: Key: 61 Value: 0 |
2245 yahoo: Key: 2 Value: | 2402 yahoo: Key: 2 Value: |
2246 yahoo: Key: 13 Value: 0 | 2403 yahoo: Key: 13 Value: 0 packet count ?? |
2247 yahoo: Key: 49 Value: PEERTOPEER | 2404 yahoo: Key: 49 Value: PEERTOPEER |
2248 yahoo: Key: 140 Value: 1 | 2405 yahoo: Key: 140 Value: 1 |
2249 yahoo: Key: 11 Value: -1786225828 | 2406 yahoo: Key: 11 Value: -1786225828 |
2250 */ | 2407 */ |
2251 | 2408 |
2256 | 2413 |
2257 if (base64) { | 2414 if (base64) { |
2258 guint32 ip; | 2415 guint32 ip; |
2259 char *tmp2; | 2416 char *tmp2; |
2260 YahooFriend *f; | 2417 YahooFriend *f; |
2418 char *host_ip; | |
2261 | 2419 |
2262 decoded = purple_base64_decode(base64, &len); | 2420 decoded = purple_base64_decode(base64, &len); |
2263 if (len) { | 2421 if (len) { |
2264 char *tmp = purple_str_binary_to_ascii(decoded, len); | 2422 char *tmp = purple_str_binary_to_ascii(decoded, len); |
2265 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); | 2423 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); |
2268 | 2426 |
2269 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ | 2427 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ |
2270 ip = strtol(tmp2, NULL, 10); | 2428 ip = strtol(tmp2, NULL, 10); |
2271 g_free(tmp2); | 2429 g_free(tmp2); |
2272 g_free(decoded); | 2430 g_free(decoded); |
2273 tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, | 2431 host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, |
2274 (ip >> 24) & 0xff); | 2432 (ip >> 24) & 0xff); |
2275 f = yahoo_friend_find(gc, who); | 2433 f = yahoo_friend_find(gc, who); |
2276 if (f) | 2434 if (f) |
2277 yahoo_friend_set_ip(f, tmp2); | 2435 yahoo_friend_set_ip(f, host_ip); |
2278 g_free(tmp2); | 2436 purple_debug_info("yahoo", "IP : %s\n", host_ip); |
2437 | |
2438 account = purple_connection_get_account(gc); | |
2439 | |
2440 user_data->host_ip = host_ip; | |
2441 user_data->session_id = pkt->id; | |
2442 user_data->gc = gc; | |
2443 | |
2444 /*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) | |
2447 purple_debug_info("yahoo","p2p: Connection to %s failed", host_ip); | |
2448 | |
2279 } | 2449 } |
2280 } | 2450 } |
2281 | 2451 |
2282 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) | 2452 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) |
2283 { | 2453 { |