Mercurial > pidgin.yaz
comparison libpurple/protocols/msn/slplink.c @ 31292:47b6eda87723
propagate from branch 'im.pidgin.pidgin' (head 07d0765c444a097af45c2650f54323afb900a07b)
to branch 'im.pidgin.soc.2010.msn-tlc' (head f3998422a4724ab424e4e2328f58fc0504856557)
author | masca@cpw.pidgin.im |
---|---|
date | Mon, 19 Jul 2010 21:11:32 +0000 |
parents | 8c1a2ef5a713 e0c374ad8fd3 |
children | 6814678f3c63 |
comparison
equal
deleted
inserted
replaced
30698:e874875a74a7 | 31292:47b6eda87723 |
---|---|
19 * | 19 * |
20 * You should have received a copy of the GNU General Public License | 20 * You should have received a copy of the GNU General Public License |
21 * along with this program; if not, write to the Free Software | 21 * along with this program; if not, write to the Free Software |
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA | 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
23 */ | 23 */ |
24 | |
25 #include "internal.h" | |
26 #include "debug.h" | |
27 | |
24 #include "msn.h" | 28 #include "msn.h" |
25 #include "slplink.h" | 29 #include "slplink.h" |
26 | 30 #include "slpmsg_part.h" |
31 | |
32 #include "sbconn.h" | |
27 #include "switchboard.h" | 33 #include "switchboard.h" |
28 #include "slp.h" | 34 #include "slp.h" |
35 #include "p2p.h" | |
29 | 36 |
30 #ifdef MSN_DEBUG_SLP_FILES | 37 #ifdef MSN_DEBUG_SLP_FILES |
31 static int m_sc = 0; | 38 static int m_sc = 0; |
32 static int m_rc = 0; | 39 static int m_rc = 0; |
33 | 40 |
34 static void | 41 static void |
35 debug_msg_to_file(MsnMessage *msg, gboolean send) | 42 debug_part_to_file(MsnSlpMessage *msg, gboolean send) |
36 { | 43 { |
37 char *tmp; | 44 char *tmp; |
38 char *dir; | 45 char *dir; |
39 char *pload; | 46 char *data; |
40 int c; | 47 int c; |
41 gsize pload_size; | 48 gsize data_size; |
42 | 49 |
43 dir = send ? "send" : "recv"; | 50 dir = send ? "send" : "recv"; |
44 c = send ? m_sc++ : m_rc++; | 51 c = send ? m_sc++ : m_rc++; |
45 tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c); | 52 tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c); |
46 pload = msn_message_gen_payload(msg, &pload_size); | 53 data = msn_slpmsg_serialize(msg, &data_size); |
47 if (!purple_util_write_data_to_file_absolute(tmp, pload, pload_size)) | 54 if (!purple_util_write_data_to_file_absolute(tmp, data, data_size)) |
48 { | 55 { |
49 purple_debug_error("msn", "could not save debug file\n"); | 56 purple_debug_error("msn", "could not save debug file\n"); |
50 } | 57 } |
51 g_free(tmp); | 58 g_free(tmp); |
52 } | 59 } |
79 g_list_append(session->slplinks, slplink); | 86 g_list_append(session->slplinks, slplink); |
80 | 87 |
81 return msn_slplink_ref(slplink); | 88 return msn_slplink_ref(slplink); |
82 } | 89 } |
83 | 90 |
84 void | 91 static void |
85 msn_slplink_destroy(MsnSlpLink *slplink) | 92 msn_slplink_destroy(MsnSlpLink *slplink) |
86 { | 93 { |
87 MsnSession *session; | 94 MsnSession *session; |
88 | 95 |
89 if (purple_debug_is_verbose()) | 96 if (purple_debug_is_verbose()) |
263 | 270 |
264 return NULL; | 271 return NULL; |
265 } | 272 } |
266 | 273 |
267 void | 274 void |
268 msn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg) | 275 msn_slplink_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part) |
269 { | 276 { |
270 if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED) | 277 if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED) |
271 { | 278 { |
272 msn_dc_enqueue_msg(slplink->dc, msg); | 279 msn_dc_enqueue_part(slplink->dc, part); |
273 } | 280 } |
274 else | 281 else |
275 { | 282 { |
276 if (slplink->swboard == NULL) | 283 msn_sbconn_send_part(slplink, part); |
277 { | |
278 slplink->swboard = msn_session_get_swboard(slplink->session, | |
279 slplink->remote_user, MSN_SB_FLAG_FT); | |
280 | |
281 g_return_if_fail(slplink->swboard != NULL); | |
282 | |
283 /* If swboard is destroyed we will be too */ | |
284 slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); | |
285 } | |
286 | |
287 msn_switchboard_send_msg(slplink->swboard, msg, TRUE); | |
288 } | 284 } |
289 } | 285 } |
290 | 286 |
291 void | 287 void |
292 msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) | 288 msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) |
293 { | 289 { |
294 MsnMessage *msg; | 290 MsnSlpMessagePart *part; |
295 long long real_size; | 291 long long real_size; |
296 size_t len = 0; | 292 size_t len = 0; |
297 | 293 |
298 /* Maybe we will want to create a new msg for this slpmsg instead of | 294 /* Maybe we will want to create a new msg for this slpmsg instead of |
299 * reusing the same one all the time. */ | 295 * reusing the same one all the time. */ |
300 msg = slpmsg->msg; | 296 part = msn_slpmsgpart_new(slpmsg->header, slpmsg->footer); |
301 | 297 part->ack_data = slpmsg; |
302 real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; | 298 |
299 real_size = (slpmsg->flags == P2P_ACK) ? 0 : slpmsg->size; | |
303 | 300 |
304 if (slpmsg->offset < real_size) | 301 if (slpmsg->offset < real_size) |
305 { | 302 { |
306 if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND && | 303 if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND && |
307 purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) | 304 purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) |
308 { | 305 { |
309 len = MIN(1202, slpmsg->slpcall->u.outgoing.len); | 306 len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len); |
310 msn_message_set_bin_data(msg, slpmsg->slpcall->u.outgoing.data, len); | 307 msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len); |
311 } | 308 } |
312 else | 309 else |
313 { | 310 { |
314 len = slpmsg->size - slpmsg->offset; | 311 len = slpmsg->size - slpmsg->offset; |
315 | 312 |
316 if (len > 1202) | 313 if (len > MSN_SBCONN_MAX_SIZE) |
317 len = 1202; | 314 len = MSN_SBCONN_MAX_SIZE; |
318 | 315 |
319 msn_message_set_bin_data(msg, slpmsg->buffer + slpmsg->offset, len); | 316 msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + slpmsg->offset, len); |
320 } | 317 } |
321 | 318 |
322 msg->msnslp_header.offset = slpmsg->offset; | 319 slpmsg->header->offset = slpmsg->offset; |
323 msg->msnslp_header.length = len; | 320 slpmsg->header->length = len; |
324 } | 321 } |
325 | 322 |
323 #if 0 | |
324 /* TODO: port this function to SlpMessageParts */ | |
326 if (purple_debug_is_verbose()) | 325 if (purple_debug_is_verbose()) |
327 msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body); | 326 msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body); |
327 #endif | |
328 | 328 |
329 #ifdef MSN_DEBUG_SLP_FILES | 329 #ifdef MSN_DEBUG_SLP_FILES |
330 debug_msg_to_file(msg, TRUE); | 330 debug_part_to_file(slpmsg, TRUE); |
331 #endif | 331 #endif |
332 | 332 |
333 slpmsg->msgs = | 333 slpmsg->parts = g_list_append(slpmsg->parts, part); |
334 g_list_append(slpmsg->msgs, msn_message_ref(msg)); | 334 msn_slplink_send_part(slplink, part); |
335 msn_slplink_send_msg(slplink, msg); | 335 |
336 | 336 if ((slpmsg->flags == P2P_MSN_OBJ_DATA || |
337 if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || | 337 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) || |
338 slpmsg->flags == 0x1000030) && | 338 slpmsg->flags == P2P_FILE_DATA) && |
339 (slpmsg->slpcall != NULL)) | 339 (slpmsg->slpcall != NULL)) |
340 { | 340 { |
341 slpmsg->slpcall->progress = TRUE; | 341 slpmsg->slpcall->progress = TRUE; |
342 | 342 |
343 if (slpmsg->slpcall->progress_cb != NULL) | 343 if (slpmsg->slpcall->progress_cb != NULL) |
348 } | 348 } |
349 | 349 |
350 /* slpmsg->offset += len; */ | 350 /* slpmsg->offset += len; */ |
351 } | 351 } |
352 | 352 |
353 /* We have received the message ack */ | |
354 static void | |
355 msg_ack(MsnMessage *msg, void *data) | |
356 { | |
357 MsnSlpMessage *slpmsg; | |
358 long long real_size; | |
359 | |
360 slpmsg = data; | |
361 | |
362 real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; | |
363 | |
364 slpmsg->offset += msg->msnslp_header.length; | |
365 | |
366 slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); | |
367 | |
368 if (slpmsg->offset < real_size) | |
369 { | |
370 if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) | |
371 { | |
372 slpmsg->slpcall->xfer_msg = slpmsg; | |
373 msn_message_ref(msg); | |
374 purple_xfer_prpl_ready(slpmsg->slpcall->xfer); | |
375 } | |
376 else | |
377 msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); | |
378 } | |
379 else | |
380 { | |
381 /* The whole message has been sent */ | |
382 if (slpmsg->flags == 0x20 || | |
383 slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) | |
384 { | |
385 if (slpmsg->slpcall != NULL) | |
386 { | |
387 if (slpmsg->slpcall->cb) | |
388 slpmsg->slpcall->cb(slpmsg->slpcall, | |
389 NULL, 0); | |
390 } | |
391 } | |
392 } | |
393 | |
394 msn_message_unref(msg); | |
395 } | |
396 | |
397 /* We have received the message nak. */ | |
398 static void | |
399 msg_nak(MsnMessage *msg, void *data) | |
400 { | |
401 MsnSlpMessage *slpmsg; | |
402 | |
403 slpmsg = data; | |
404 | |
405 msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); | |
406 | |
407 slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); | |
408 msn_message_unref(msg); | |
409 } | |
410 | |
411 static void | 353 static void |
412 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) | 354 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) |
413 { | 355 { |
414 MsnMessage *msg; | 356 slpmsg = slpmsg; |
415 const char *passport; | 357 slpmsg->header = g_new0(MsnP2PHeader, 1); |
416 | 358 slpmsg->footer = g_new0(MsnP2PFooter, 1); |
417 slpmsg->msg = msg = msn_message_new_msnslp(); | 359 |
418 | 360 if (slpmsg->flags == P2P_NO_FLAG) |
419 if (slpmsg->flags == 0x0) | 361 { |
420 { | 362 slpmsg->header->session_id = slpmsg->session_id; |
421 msg->msnslp_header.session_id = slpmsg->session_id; | 363 slpmsg->header->ack_id = rand() % 0xFFFFFF00; |
422 msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; | 364 } |
423 } | 365 else if (slpmsg->flags == P2P_ACK) |
424 else if (slpmsg->flags == 0x2) | 366 { |
425 { | 367 slpmsg->header->session_id = slpmsg->session_id; |
426 msg->msnslp_header.session_id = slpmsg->session_id; | 368 slpmsg->header->ack_id = slpmsg->ack_id; |
427 msg->msnslp_header.ack_id = slpmsg->ack_id; | 369 slpmsg->header->ack_size = slpmsg->ack_size; |
428 msg->msnslp_header.ack_size = slpmsg->ack_size; | 370 slpmsg->header->ack_sub_id = slpmsg->ack_sub_id; |
429 msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; | 371 } |
430 } | 372 else if (slpmsg->flags == P2P_MSN_OBJ_DATA || |
431 else if (slpmsg->flags == 0x20 || | 373 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) || |
432 slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) | 374 slpmsg->flags == P2P_FILE_DATA) |
433 { | 375 { |
434 MsnSlpCall *slpcall; | 376 MsnSlpCall *slpcall; |
435 slpcall = slpmsg->slpcall; | 377 slpcall = slpmsg->slpcall; |
436 | 378 |
437 g_return_if_fail(slpcall != NULL); | 379 g_return_if_fail(slpcall != NULL); |
438 msg->msnslp_header.session_id = slpcall->session_id; | 380 slpmsg->header->session_id = slpcall->session_id; |
439 msg->msnslp_footer.value = slpcall->app_id; | 381 slpmsg->footer->value = slpcall->app_id; |
440 msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; | 382 slpmsg->header->ack_id = rand() % 0xFFFFFF00; |
441 } | 383 } |
442 else if (slpmsg->flags == 0x100) | 384 else if (slpmsg->flags == 0x100) |
443 { | 385 { |
444 msg->msnslp_header.ack_id = slpmsg->ack_id; | 386 slpmsg->header->ack_id = slpmsg->ack_id; |
445 msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; | 387 slpmsg->header->ack_sub_id = slpmsg->ack_sub_id; |
446 msg->msnslp_header.ack_size = slpmsg->ack_size; | 388 slpmsg->header->ack_size = slpmsg->ack_size; |
447 } | 389 } |
448 | 390 |
449 msg->msnslp_header.id = slpmsg->id; | 391 slpmsg->header->id = slpmsg->id; |
450 msg->msnslp_header.flags = slpmsg->flags; | 392 slpmsg->header->flags = (guint32)slpmsg->flags; |
451 | 393 |
452 msg->msnslp_header.total_size = slpmsg->size; | 394 slpmsg->header->total_size = slpmsg->size; |
453 | |
454 passport = purple_normalize(slplink->session->account, slplink->remote_user); | |
455 msn_message_set_attr(msg, "P2P-Dest", passport); | |
456 | |
457 msg->ack_cb = msg_ack; | |
458 msg->nak_cb = msg_nak; | |
459 msg->ack_data = slpmsg; | |
460 | 395 |
461 msn_slplink_send_msgpart(slplink, slpmsg); | 396 msn_slplink_send_msgpart(slplink, slpmsg); |
462 | |
463 msn_message_destroy(msg); | |
464 } | 397 } |
465 | 398 |
466 void | 399 void |
467 msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) | 400 msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) |
468 { | 401 { |
492 msn_slplink_release_slpmsg(slplink, slpmsg); | 425 msn_slplink_release_slpmsg(slplink, slpmsg); |
493 } | 426 } |
494 } | 427 } |
495 | 428 |
496 static MsnSlpMessage * | 429 static MsnSlpMessage * |
497 msn_slplink_create_ack(MsnSlpLink *slplink, MsnSlpHeader *header) | 430 msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PHeader *header) |
498 { | 431 { |
499 MsnSlpMessage *slpmsg; | 432 MsnSlpMessage *slpmsg; |
500 | 433 |
501 slpmsg = msn_slpmsg_new(slplink); | 434 slpmsg = msn_slpmsg_ack_new(header); |
502 | 435 msn_slpmsg_set_slplink(slpmsg, slplink); |
503 slpmsg->session_id = header->session_id; | |
504 slpmsg->size = header->total_size; | |
505 slpmsg->flags = 0x02; | |
506 slpmsg->ack_id = header->id; | |
507 slpmsg->ack_sub_id = header->ack_id; | |
508 slpmsg->ack_size = header->total_size; | |
509 slpmsg->info = "SLP ACK"; | |
510 | 436 |
511 return slpmsg; | 437 return slpmsg; |
512 } | 438 } |
513 | 439 |
514 static void | 440 static void |
515 msn_slplink_send_ack(MsnSlpLink *slplink, MsnSlpHeader *header) | 441 msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PHeader *header) |
516 { | 442 { |
517 MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, header); | 443 MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, header); |
518 | 444 |
519 msn_slplink_send_slpmsg(slplink, slpmsg); | 445 msn_slplink_send_slpmsg(slplink, slpmsg); |
520 msn_slpmsg_destroy(slpmsg); | 446 msn_slpmsg_destroy(slpmsg); |
521 } | 447 } |
522 | 448 |
523 static void | |
524 send_file_cb(MsnSlpCall *slpcall) | |
525 { | |
526 MsnSlpMessage *slpmsg; | |
527 PurpleXfer *xfer; | |
528 | |
529 xfer = (PurpleXfer *)slpcall->xfer; | |
530 if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED) | |
531 return; | |
532 | |
533 purple_xfer_ref(xfer); | |
534 purple_xfer_start(xfer, -1, NULL, 0); | |
535 if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) { | |
536 purple_xfer_unref(xfer); | |
537 return; | |
538 } | |
539 purple_xfer_unref(xfer); | |
540 | |
541 slpmsg = msn_slpmsg_new(slpcall->slplink); | |
542 slpmsg->slpcall = slpcall; | |
543 slpmsg->flags = 0x1000030; | |
544 slpmsg->info = "SLP FILE"; | |
545 slpmsg->size = purple_xfer_get_size(xfer); | |
546 | |
547 msn_slplink_send_slpmsg(slpcall->slplink, slpmsg); | |
548 } | |
549 | |
550 static MsnSlpMessage * | 449 static MsnSlpMessage * |
551 msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id) | 450 msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id) |
552 { | 451 { |
553 GList *e; | 452 GList *e; |
554 | 453 |
562 | 461 |
563 return NULL; | 462 return NULL; |
564 } | 463 } |
565 | 464 |
566 void | 465 void |
567 msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpHeader *header, const char *data, gsize len) | 466 msn_slplink_process_msg(MsnSlpLink *slplink, MsnP2PHeader *header, const char *data, gsize len) |
568 { | 467 { |
569 MsnSlpMessage *slpmsg; | 468 MsnSlpMessage *slpmsg; |
570 guint64 offset; | 469 guint64 offset; |
571 PurpleXfer *xfer = NULL; | |
572 | 470 |
573 if (header->total_size < header->length) | 471 if (header->total_size < header->length) |
574 { | 472 { |
575 purple_debug_error("msn", "This can't be good\n"); | 473 /* We seem to have received a bad header */ |
576 g_return_if_reached(); | 474 purple_debug_warning("msn", "Total size listed in SLP binary header " |
475 "was less than length of this particular message. This " | |
476 "should not happen. Dropping message.\n"); | |
477 return; | |
577 } | 478 } |
578 | 479 |
579 offset = header->offset; | 480 offset = header->offset; |
580 | 481 |
581 if (offset == 0) | 482 if (offset == 0) |
586 slpmsg->size = header->total_size; | 487 slpmsg->size = header->total_size; |
587 slpmsg->flags = header->flags; | 488 slpmsg->flags = header->flags; |
588 | 489 |
589 if (slpmsg->session_id) | 490 if (slpmsg->session_id) |
590 { | 491 { |
591 if (slpmsg->slpcall == NULL) | 492 slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); |
592 slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); | |
593 | |
594 if (slpmsg->slpcall != NULL) | 493 if (slpmsg->slpcall != NULL) |
595 { | 494 { |
596 if (slpmsg->flags == 0x20 || | 495 if (slpmsg->flags == P2P_MSN_OBJ_DATA || |
597 slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) | 496 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) || |
497 slpmsg->flags == P2P_FILE_DATA) | |
598 { | 498 { |
599 xfer = slpmsg->slpcall->xfer; | 499 PurpleXfer *xfer = slpmsg->slpcall->xfer; |
600 if (xfer != NULL) | 500 if (xfer != NULL) |
601 { | 501 { |
602 slpmsg->ft = TRUE; | 502 slpmsg->ft = TRUE; |
603 slpmsg->slpcall->xfer_msg = slpmsg; | 503 slpmsg->slpcall->xfer_msg = slpmsg; |
604 | 504 |
638 } | 538 } |
639 } | 539 } |
640 | 540 |
641 if (slpmsg->ft) | 541 if (slpmsg->ft) |
642 { | 542 { |
643 xfer = slpmsg->slpcall->xfer; | |
644 slpmsg->slpcall->u.incoming_data = | 543 slpmsg->slpcall->u.incoming_data = |
645 g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len); | 544 g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len); |
646 purple_xfer_prpl_ready(xfer); | 545 purple_xfer_prpl_ready(slpmsg->slpcall->xfer); |
647 } | 546 } |
648 else if (slpmsg->size && slpmsg->buffer) | 547 else if (slpmsg->size && slpmsg->buffer) |
649 { | 548 { |
650 if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size || slpmsg->offset != offset) | 549 if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size || slpmsg->offset != offset) |
651 { | 550 { |
657 memcpy(slpmsg->buffer + offset, data, len); | 556 memcpy(slpmsg->buffer + offset, data, len); |
658 slpmsg->offset += len; | 557 slpmsg->offset += len; |
659 } | 558 } |
660 } | 559 } |
661 | 560 |
662 if ((slpmsg->flags == 0x20 || | 561 if ((slpmsg->flags == P2P_MSN_OBJ_DATA || |
663 slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) && | 562 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) || |
563 slpmsg->flags == P2P_FILE_DATA) && | |
664 (slpmsg->slpcall != NULL)) | 564 (slpmsg->slpcall != NULL)) |
665 { | 565 { |
666 slpmsg->slpcall->progress = TRUE; | 566 slpmsg->slpcall->progress = TRUE; |
667 | 567 |
668 if (slpmsg->slpcall->progress_cb != NULL) | 568 if (slpmsg->slpcall->progress_cb != NULL) |
699 directconn = slplink->directconn; | 599 directconn = slplink->directconn; |
700 if (!directconn->acked) | 600 if (!directconn->acked) |
701 msn_directconn_send_handshake(directconn); | 601 msn_directconn_send_handshake(directconn); |
702 #endif | 602 #endif |
703 } | 603 } |
704 else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 || | 604 else if (slpmsg->flags == P2P_NO_FLAG || slpmsg->flags == P2P_WML2009_COMP || |
705 slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || | 605 slpmsg->flags == P2P_MSN_OBJ_DATA || |
706 slpmsg->flags == 0x1000030) | 606 slpmsg->flags == (P2P_WML2009_COMP | P2P_MSN_OBJ_DATA) || |
607 slpmsg->flags == P2P_FILE_DATA) | |
707 { | 608 { |
708 /* Release all the messages and send the ACK */ | 609 /* Release all the messages and send the ACK */ |
709 | 610 |
710 if (slpcall->wait_for_socket) { | 611 if (slpcall->wait_for_socket) { |
711 /* | 612 /* |
730 if (!slpcall->wait_for_socket && slpcall->wasted) | 631 if (!slpcall->wait_for_socket && slpcall->wasted) |
731 msn_slpcall_destroy(slpcall); | 632 msn_slpcall_destroy(slpcall); |
732 } | 633 } |
733 } | 634 } |
734 | 635 |
735 static gchar * | |
736 gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) | |
737 { | |
738 gsize size = 0; | |
739 MsnFileContext *header; | |
740 gchar *u8 = NULL; | |
741 gchar *ret; | |
742 gunichar2 *uni = NULL; | |
743 glong currentChar = 0; | |
744 glong len = 0; | |
745 const char *preview; | |
746 gsize preview_len; | |
747 | |
748 size = purple_xfer_get_size(xfer); | |
749 | |
750 purple_xfer_prepare_thumbnail(xfer, "png"); | |
751 | |
752 if (!file_name) { | |
753 gchar *basename = g_path_get_basename(file_path); | |
754 u8 = purple_utf8_try_convert(basename); | |
755 g_free(basename); | |
756 file_name = u8; | |
757 } | |
758 | |
759 uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL); | |
760 | |
761 if (u8) { | |
762 g_free(u8); | |
763 file_name = NULL; | |
764 u8 = NULL; | |
765 } | |
766 | |
767 preview = purple_xfer_get_thumbnail(xfer, &preview_len); | |
768 header = g_malloc(sizeof(MsnFileContext) + preview_len); | |
769 | |
770 header->length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1); | |
771 header->version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */ | |
772 header->file_size = GUINT64_TO_LE(size); | |
773 if (preview) | |
774 header->type = GUINT32_TO_LE(0); | |
775 else | |
776 header->type = GUINT32_TO_LE(1); | |
777 | |
778 len = MIN(len, MAX_FILE_NAME_LEN); | |
779 for (currentChar = 0; currentChar < len; currentChar++) { | |
780 header->file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]); | |
781 } | |
782 memset(&header->file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2); | |
783 | |
784 memset(&header->unknown1, 0, sizeof(header->unknown1)); | |
785 header->unknown2 = GUINT32_TO_LE(0xffffffff); | |
786 if (preview) { | |
787 memcpy(&header->preview, preview, preview_len); | |
788 } | |
789 header->preview[preview_len] = '\0'; | |
790 | |
791 g_free(uni); | |
792 ret = purple_base64_encode((const guchar *)header, sizeof(MsnFileContext) + preview_len); | |
793 g_free(header); | |
794 return ret; | |
795 } | |
796 | |
797 void | |
798 msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer) | |
799 { | |
800 MsnSlpCall *slpcall; | |
801 char *context; | |
802 const char *fn; | |
803 const char *fp; | |
804 | |
805 fn = purple_xfer_get_filename(xfer); | |
806 fp = purple_xfer_get_local_filename(xfer); | |
807 | |
808 g_return_if_fail(slplink != NULL); | |
809 g_return_if_fail(fp != NULL); | |
810 | |
811 slpcall = msn_slpcall_new(slplink); | |
812 msn_slpcall_init(slpcall, MSN_SLPCALL_DC); | |
813 | |
814 slpcall->session_init_cb = send_file_cb; | |
815 slpcall->end_cb = msn_xfer_end_cb; | |
816 slpcall->cb = msn_xfer_completed_cb; | |
817 slpcall->xfer = xfer; | |
818 purple_xfer_ref(slpcall->xfer); | |
819 | |
820 slpcall->pending = TRUE; | |
821 | |
822 purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel); | |
823 purple_xfer_set_read_fnc(xfer, msn_xfer_read); | |
824 purple_xfer_set_write_fnc(xfer, msn_xfer_write); | |
825 | |
826 xfer->data = slpcall; | |
827 | |
828 context = gen_context(xfer, fn, fp); | |
829 | |
830 msn_slpcall_invite(slpcall, MSN_FT_GUID, 2, context); | |
831 | |
832 g_free(context); | |
833 } | |
834 | |
835 void | 636 void |
836 msn_slplink_request_object(MsnSlpLink *slplink, | 637 msn_slplink_request_object(MsnSlpLink *slplink, |
837 const char *info, | 638 const char *info, |
838 MsnSlpCb cb, | 639 MsnSlpCb cb, |
839 MsnSlpEndCb end_cb, | 640 MsnSlpEndCb end_cb, |
855 | 656 |
856 slpcall->data_info = g_strdup(info); | 657 slpcall->data_info = g_strdup(info); |
857 slpcall->cb = cb; | 658 slpcall->cb = cb; |
858 slpcall->end_cb = end_cb; | 659 slpcall->end_cb = end_cb; |
859 | 660 |
860 msn_slpcall_invite(slpcall, MSN_OBJ_GUID, 1, msnobj_base64); | 661 msn_slpcall_invite(slpcall, MSN_OBJ_GUID, P2P_APPID_OBJ, msnobj_base64); |
861 | 662 |
862 g_free(msnobj_base64); | 663 g_free(msnobj_base64); |
863 } | 664 } |