comparison libpurple/protocols/msn/slplink.c @ 31558:ce968e115c95

propagate from branch 'im.pidgin.cpw.masca.p2p' (head 33ca865dacb9e5bcf763d06f6a42cbaca337cc64) to branch 'im.pidgin.pidgin' (head 92f47f4e8b0cbb107fd97e1ab814d1cedbf109ad)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 06 May 2011 06:25:14 +0000
parents 8cf9270acf4c
children 50ca9e64186b
comparison
equal deleted inserted replaced
31557:f021d93a1f9b 31558:ce968e115c95
279 279
280 void 280 void
281 msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) 281 msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
282 { 282 {
283 MsnSlpMessagePart *part; 283 MsnSlpMessagePart *part;
284 MsnP2PInfo *info;
284 long long real_size; 285 long long real_size;
285 size_t len = 0; 286 size_t len = 0;
287 guint64 offset;
286 288
287 /* Maybe we will want to create a new msg for this slpmsg instead of 289 /* Maybe we will want to create a new msg for this slpmsg instead of
288 * reusing the same one all the time. */ 290 * reusing the same one all the time. */
289 part = msn_slpmsgpart_new(slpmsg->header, slpmsg->footer); 291 info = slpmsg->p2p_info;
292 part = msn_slpmsgpart_new(msn_p2p_info_dup(info));
290 part->ack_data = slpmsg; 293 part->ack_data = slpmsg;
291 294
292 real_size = (slpmsg->header->flags == P2P_ACK) ? 0 : slpmsg->size; 295 real_size = (msn_p2p_info_get_flags(info) == P2P_ACK) ? 0 : slpmsg->size;
293 296
294 if (slpmsg->header->offset < real_size) 297 offset = msn_p2p_info_get_offset(info);
298 if (offset < real_size)
295 { 299 {
296 if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND && 300 if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
297 purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) 301 purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
298 { 302 {
299 len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len); 303 len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len);
300 msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len); 304 msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len);
301 } 305 }
302 else 306 else
303 { 307 {
304 len = slpmsg->size - slpmsg->header->offset; 308 len = slpmsg->size - offset;
305 309
306 if (len > MSN_SBCONN_MAX_SIZE) 310 if (len > MSN_SBCONN_MAX_SIZE)
307 len = MSN_SBCONN_MAX_SIZE; 311 len = MSN_SBCONN_MAX_SIZE;
308 312
309 msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + slpmsg->header->offset, len); 313 msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + offset, len);
310 } 314 }
311 315
312 slpmsg->header->length = len; 316 msn_p2p_info_set_length(slpmsg->p2p_info, len);
313 } 317 }
314 318
315 #if 0 319 #if 0
316 /* TODO: port this function to SlpMessageParts */ 320 /* TODO: port this function to SlpMessageParts */
317 if (purple_debug_is_verbose()) 321 if (purple_debug_is_verbose())
324 328
325 slpmsg->parts = g_list_append(slpmsg->parts, part); 329 slpmsg->parts = g_list_append(slpmsg->parts, part);
326 msn_slplink_send_part(slplink, part); 330 msn_slplink_send_part(slplink, part);
327 331
328 332
329 if (msn_p2p_msg_is_data(slpmsg->header->flags) && 333 if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(info)) &&
330 (slpmsg->slpcall != NULL)) 334 (slpmsg->slpcall != NULL))
331 { 335 {
332 slpmsg->slpcall->progress = TRUE; 336 slpmsg->slpcall->progress = TRUE;
333 337
334 if (slpmsg->slpcall->progress_cb != NULL) 338 if (slpmsg->slpcall->progress_cb != NULL)
335 { 339 {
336 slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, 340 slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
337 len, slpmsg->header->offset); 341 len, offset);
338 } 342 }
339 } 343 }
340 344
341 /* slpmsg->offset += len; */ 345 /* slpmsg->offset += len; */
342 } 346 }
343 347
344 static void 348 static void
345 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) 349 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
346 { 350 {
347 slpmsg = slpmsg; 351 MsnP2PInfo *info;
348 slpmsg->footer = g_new0(MsnP2PFooter, 1); 352 guint32 flags;
349 353
350 if (slpmsg->header->flags == P2P_NO_FLAG) 354 info = slpmsg->p2p_info;
351 { 355
352 slpmsg->header->ack_id = rand() % 0xFFFFFF00; 356 flags = msn_p2p_info_get_flags(info);
353 } 357 if (flags == P2P_NO_FLAG)
354 else if (msn_p2p_msg_is_data(slpmsg->header->flags)) 358 {
359 msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
360 }
361 else if (msn_p2p_msg_is_data(flags))
355 { 362 {
356 MsnSlpCall *slpcall; 363 MsnSlpCall *slpcall;
357 slpcall = slpmsg->slpcall; 364 slpcall = slpmsg->slpcall;
358 365
359 g_return_if_fail(slpcall != NULL); 366 g_return_if_fail(slpcall != NULL);
360 slpmsg->header->session_id = slpcall->session_id; 367 msn_p2p_info_set_session_id(info, slpcall->session_id);
361 slpmsg->footer->value = slpcall->app_id; 368 msn_p2p_info_set_app_id(info, slpcall->app_id);
362 slpmsg->header->ack_id = rand() % 0xFFFFFF00; 369 msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
363 } 370 }
364 371
365 slpmsg->header->id = slpmsg->id; 372 msn_p2p_info_set_id(info, slpmsg->id);
366 373
367 slpmsg->header->total_size = slpmsg->size; 374 msn_p2p_info_set_total_size(info, slpmsg->size);
368 375
369 msn_slplink_send_msgpart(slplink, slpmsg); 376 msn_slplink_send_msgpart(slplink, slpmsg);
370 } 377 }
371 378
372 void 379 void
398 msn_slplink_release_slpmsg(slplink, slpmsg); 405 msn_slplink_release_slpmsg(slplink, slpmsg);
399 } 406 }
400 } 407 }
401 408
402 static MsnSlpMessage * 409 static MsnSlpMessage *
403 msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PHeader *header) 410 msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
404 { 411 {
405 MsnSlpMessage *slpmsg; 412 MsnSlpMessage *slpmsg;
406 413
407 slpmsg = msn_slpmsg_ack_new(header); 414 slpmsg = msn_slpmsg_ack_new(info);
408 msn_slpmsg_set_slplink(slpmsg, slplink); 415 msn_slpmsg_set_slplink(slpmsg, slplink);
409 416
410 return slpmsg; 417 return slpmsg;
411 } 418 }
412 419
413 static void 420 static void
414 msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PHeader *header) 421 msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
415 { 422 {
416 MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, header); 423 MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, info);
417 424
418 msn_slplink_send_slpmsg(slplink, slpmsg); 425 msn_slplink_send_slpmsg(slplink, slpmsg);
419 msn_slpmsg_destroy(slpmsg); 426 msn_slpmsg_destroy(slpmsg);
420 } 427 }
421 428
426 433
427 for (e = slplink->slp_msgs; e != NULL; e = e->next) 434 for (e = slplink->slp_msgs; e != NULL; e = e->next)
428 { 435 {
429 MsnSlpMessage *slpmsg = e->data; 436 MsnSlpMessage *slpmsg = e->data;
430 437
431 if ((slpmsg->header->session_id == session_id) && (slpmsg->id == id)) 438 if ((msn_p2p_info_get_session_id(slpmsg->p2p_info) == session_id) && (slpmsg->id == id))
432 return slpmsg; 439 return slpmsg;
433 } 440 }
434 441
435 return NULL; 442 return NULL;
436 } 443 }
437 444
438 static MsnSlpMessage * 445 static MsnSlpMessage *
439 init_first_msg(MsnSlpLink *slplink, MsnP2PHeader *header) 446 init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
440 { 447 {
441 MsnSlpMessage *slpmsg; 448 MsnSlpMessage *slpmsg;
449 guint32 session_id;
450 guint32 flags;
442 451
443 slpmsg = msn_slpmsg_new(slplink); 452 slpmsg = msn_slpmsg_new(slplink);
444 slpmsg->id = header->id; 453 slpmsg->id = msn_p2p_info_get_id(info);
445 slpmsg->header->session_id = header->session_id; 454 session_id = msn_p2p_info_get_session_id(info);
446 slpmsg->size = header->total_size; 455 msn_p2p_info_set_session_id(slpmsg->p2p_info, session_id);
447 slpmsg->header->flags = header->flags; 456 slpmsg->size = msn_p2p_info_get_total_size(info);
448 457 flags = msn_p2p_info_get_flags(info);
449 if (slpmsg->header->session_id) 458 msn_p2p_info_set_flags(slpmsg->p2p_info, flags);
450 { 459
451 slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->header->session_id); 460 if (session_id)
461 {
462 slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
452 if (slpmsg->slpcall != NULL) 463 if (slpmsg->slpcall != NULL)
453 { 464 {
454 if (msn_p2p_msg_is_data(header->flags)) 465 if (msn_p2p_msg_is_data(flags))
455 { 466 {
456 PurpleXfer *xfer = slpmsg->slpcall->xfer; 467 PurpleXfer *xfer = slpmsg->slpcall->xfer;
457 if (xfer != NULL) 468 if (xfer != NULL)
458 { 469 {
459 slpmsg->ft = TRUE; 470 slpmsg->ft = TRUE;
486 497
487 return slpmsg; 498 return slpmsg;
488 } 499 }
489 500
490 static void 501 static void
491 process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PHeader *header) 502 process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
492 { 503 {
493 MsnSlpCall *slpcall; 504 MsnSlpCall *slpcall;
505 guint32 flags;
494 506
495 slpcall = msn_slp_process_msg(slplink, slpmsg); 507 slpcall = msn_slp_process_msg(slplink, slpmsg);
496 508
497 if (slpcall == NULL) { 509 if (slpcall == NULL) {
498 msn_slpmsg_destroy(slpmsg); 510 msn_slpmsg_destroy(slpmsg);
499 return; 511 return;
500 } 512 }
501 513
502 purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n"); 514 purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
503 515
504 if (/* !slpcall->wasted && */ slpmsg->header->flags == P2P_DC_HANDSHAKE) 516 flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
505 { 517
506 #if 0 518 if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
507 MsnDirectConn *directconn; 519 msn_p2p_msg_is_data(flags))
508
509 directconn = slplink->directconn;
510 if (!directconn->acked)
511 msn_directconn_send_handshake(directconn);
512 #endif
513 }
514 else if (slpmsg->header->flags == P2P_NO_FLAG || slpmsg->header->flags == P2P_WLM2009_COMP ||
515 msn_p2p_msg_is_data(slpmsg->header->flags))
516 { 520 {
517 /* Release all the messages and send the ACK */ 521 /* Release all the messages and send the ACK */
518 522
519 if (slpcall->wait_for_socket) { 523 if (slpcall->wait_for_socket) {
520 /* 524 /*
523 * invitation before ACK but the listening socket isn't 527 * invitation before ACK but the listening socket isn't
524 * created yet. 528 * created yet.
525 */ 529 */
526 purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n"); 530 purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
527 531
528 slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header); 532 slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, info);
529 } else if (!slpcall->wasted) { 533 } else if (!slpcall->wasted) {
530 purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n"); 534 purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
531 535
532 msn_slplink_send_ack(slplink, header); 536 msn_slplink_send_ack(slplink, info);
533 msn_slplink_send_queued_slpmsgs(slplink); 537 msn_slplink_send_queued_slpmsgs(slplink);
534 } 538 }
535 } 539 }
536 540
537 msn_slpmsg_destroy(slpmsg); 541 msn_slpmsg_destroy(slpmsg);
547 slpmsg->slpcall->u.incoming_data = 551 slpmsg->slpcall->u.incoming_data =
548 g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size); 552 g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size);
549 purple_xfer_prpl_ready(slpmsg->slpcall->xfer); 553 purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
550 } 554 }
551 else if (slpmsg->size && slpmsg->buffer) { 555 else if (slpmsg->size && slpmsg->buffer) {
552 if (G_MAXSIZE - part->size < part->header->offset 556 guint64 offset = msn_p2p_info_get_offset(part->info);
553 || (part->header->offset + part->size) > slpmsg->size 557 if (G_MAXSIZE - part->size < offset
554 || slpmsg->header->offset != part->header->offset) { 558 || (offset + part->size) > slpmsg->size
559 || msn_p2p_info_get_offset(slpmsg->p2p_info) != offset) {
555 purple_debug_error("msn", 560 purple_debug_error("msn",
556 "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n", 561 "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
557 slpmsg->size, part->header->offset, part->size); 562 slpmsg->size, offset, part->size);
558 g_return_if_reached(); 563 g_return_if_reached();
559 } else { 564 } else {
560 memcpy(slpmsg->buffer + part->header->offset, part->buffer, part->size); 565 memcpy(slpmsg->buffer + offset, part->buffer, part->size);
561 slpmsg->header->offset += part->size; 566 msn_p2p_info_set_offset(slpmsg->p2p_info, offset + part->size);
562 } 567 }
563 } 568 }
564 } 569 }
565 570
566 void 571 void
567 msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part) 572 msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part)
568 { 573 {
569 MsnSlpMessage *slpmsg; 574 MsnSlpMessage *slpmsg;
570 MsnP2PHeader *header; 575 MsnP2PInfo *info;
571 guint64 offset; 576 guint64 offset;
572 577
573 header = part->header; 578 info = part->info;
574 579
575 if (header->total_size < header->length) 580 if (!msn_p2p_info_is_valid(info))
576 { 581 {
577 /* We seem to have received a bad header */ 582 /* We seem to have received a bad header */
578 purple_debug_warning("msn", "Total size listed in SLP binary header " 583 purple_debug_warning("msn", "Total size listed in SLP binary header "
579 "was less than length of this particular message. This " 584 "was less than length of this particular message. This "
580 "should not happen. Dropping message.\n"); 585 "should not happen. Dropping message.\n");
581 return; 586 return;
582 } 587 }
583 588
584 offset = header->offset; 589 offset = msn_p2p_info_get_offset(info);
585 590
586 if (offset == 0) 591 if (offset == 0)
587 slpmsg = init_first_msg(slplink, header); 592 slpmsg = init_first_msg(slplink, info);
588 else { 593 else {
589 slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id); 594 guint32 session_id, id;
595 session_id = msn_p2p_info_get_session_id(info);
596 id = msn_p2p_info_get_id(info);
597 slpmsg = msn_slplink_message_find(slplink, session_id, id);
590 if (slpmsg == NULL) 598 if (slpmsg == NULL)
591 { 599 {
592 /* Probably the transfer was cancelled */ 600 /* Probably the transfer was cancelled */
593 purple_debug_error("msn", "Couldn't find slpmsg\n"); 601 purple_debug_error("msn", "Couldn't find slpmsg\n");
594 return; 602 return;
595 } 603 }
596 } 604 }
597 605
598 slpmsg_add_part(slpmsg, part); 606 slpmsg_add_part(slpmsg, part);
599 607
600 608 if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)) &&
601 if (msn_p2p_msg_is_data(slpmsg->header->flags) &&
602 (slpmsg->slpcall != NULL)) 609 (slpmsg->slpcall != NULL))
603 { 610 {
604 slpmsg->slpcall->progress = TRUE; 611 slpmsg->slpcall->progress = TRUE;
605 612
606 if (slpmsg->slpcall->progress_cb != NULL) 613 if (slpmsg->slpcall->progress_cb != NULL)
614 if (slpmsg->buffer == NULL) 621 if (slpmsg->buffer == NULL)
615 return; 622 return;
616 #endif 623 #endif
617 624
618 /* All the pieces of the slpmsg have been received */ 625 /* All the pieces of the slpmsg have been received */
619 if (header->offset + header->length >= header->total_size) 626 if (msn_p2p_info_is_final(info))
620 process_complete_msg(slplink, slpmsg, header); 627 process_complete_msg(slplink, slpmsg, info);
621 628
622 /* NOTE: The slpmsg will be destroyed in process_complete_msg or left in 629 /* NOTE: The slpmsg will be destroyed in process_complete_msg or left in
623 the slplink until fully received. Don't free it here! 630 the slplink until fully received. Don't free it here!
624 */ 631 */
625 } 632 }