comparison libpurple/protocols/msn/directconn.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 c7fa7c7aca7d
children 2d00d29a45fd
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 "cipher.h"
27 #include "debug.h"
28
24 #include "msn.h" 29 #include "msn.h"
25 #include "directconn.h" 30 #include "directconn.h"
26 31
27 #include "slp.h" 32 #include "slp.h"
28 #include "slpmsg.h" 33 #include "slpmsg.h"
29 34 #include "p2p.h"
30 #pragma pack(push,1) 35
31 typedef struct {
32 guint32 session_id;
33 guint32 seq_id;
34 guint64 offset;
35 guint64 total_size;
36 guint32 length;
37 guint32 flags;
38 guint32 ack_id;
39 guint32 ack_uid;
40 guint64 ack_size;
41 /* guint8 body[1]; */
42 } MsnDcContext;
43 #pragma pack(pop)
44
45 #define DC_PACKET_HEADER_SIZE sizeof(MsnDcContext)
46 #define DC_MAX_BODY_SIZE 8*1024 36 #define DC_MAX_BODY_SIZE 8*1024
47 #define DC_MAX_PACKET_SIZE (DC_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE) 37 #define DC_MAX_PACKET_SIZE (P2P_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE)
48 38
49 static void 39 static void
50 msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type, 40 msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type,
51 const guchar nonce[16], gchar nonce_hash[37]) 41 const guchar nonce[16], gchar nonce_hash[37])
52 { 42 {
119 static void 109 static void
120 msn_dc_destroy_packet(MsnDirectConnPacket *p) 110 msn_dc_destroy_packet(MsnDirectConnPacket *p)
121 { 111 {
122 g_free(p->data); 112 g_free(p->data);
123 113
114 #if 0
124 if (p->msg) 115 if (p->msg)
125 msn_message_unref(p->msg); 116 msn_message_unref(p->msg);
117 #endif
118 if (p->part)
119 msn_slpmsgpart_unref(p->part);
126 120
127 g_free(p); 121 g_free(p);
128 } 122 }
129 123
130 MsnDirectConn * 124 MsnDirectConn *
189 183
190 slplink = dc->slplink; 184 slplink = dc->slplink;
191 if (slplink) { 185 if (slplink) {
192 slplink->dc = NULL; 186 slplink->dc = NULL;
193 if (slplink->swboard == NULL) 187 if (slplink->swboard == NULL)
194 msn_slplink_destroy(slplink); 188 msn_slplink_unref(slplink);
195 } 189 }
196 190
197 g_free(dc->msg_body); 191 g_free(dc->msg_body);
198 192
199 if (dc->prev_ack) { 193 if (dc->prev_ack) {
351 if (slpcall) { 345 if (slpcall) {
352 msn_slpcall_session_init(slpcall); 346 msn_slpcall_session_init(slpcall);
353 if (queue) { 347 if (queue) {
354 while (!g_queue_is_empty(queue)) { 348 while (!g_queue_is_empty(queue)) {
355 MsnDirectConnPacket *p = g_queue_pop_head(queue); 349 MsnDirectConnPacket *p = g_queue_pop_head(queue);
356 msn_slplink_send_msg(slplink, p->msg); 350 msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
357 msn_dc_destroy_packet(p); 351 msn_dc_destroy_packet(p);
358 } 352 }
359 g_queue_free(queue); 353 g_queue_free(queue);
360 } 354 }
361 } 355 }
362 msn_slplink_unref(slplink); 356 msn_slplink_unref(slplink);
363 }
364
365 static void
366 msn_dc_parse_binary_header(MsnDirectConn *dc)
367 {
368 MsnSlpHeader *h;
369 MsnDcContext *context;
370
371 g_return_if_fail(dc != NULL);
372
373 h = &dc->header;
374 /* Skip packet size */
375 context = (MsnDcContext *)(dc->in_buffer + 4);
376
377 h->session_id = GUINT32_FROM_LE(context->session_id);
378 h->id = GUINT32_FROM_LE(context->seq_id);
379 h->offset = GUINT64_FROM_LE(context->offset);
380 h->total_size = GUINT64_FROM_LE(context->total_size);
381 h->length = GUINT32_FROM_LE(context->length);
382 h->flags = GUINT32_FROM_LE(context->flags);
383 h->ack_id = GUINT32_FROM_LE(context->ack_id);
384 h->ack_sub_id = GUINT32_FROM_LE(context->ack_uid);
385 h->ack_size = GUINT64_FROM_LE(context->ack_size);
386 }
387
388 static const gchar *
389 msn_dc_serialize_binary_header(MsnDirectConn *dc) {
390 MsnSlpHeader *h;
391 static MsnDcContext bin_header;
392
393 g_return_val_if_fail(dc != NULL, NULL);
394
395 h = &dc->header;
396
397 bin_header.session_id = GUINT32_TO_LE(h->session_id);
398 bin_header.seq_id = GUINT32_TO_LE(h->id);
399 bin_header.offset = GUINT64_TO_LE(h->offset);
400 bin_header.total_size = GUINT64_TO_LE(h->total_size);
401 bin_header.length = GUINT32_TO_LE(h->length);
402 bin_header.flags = GUINT32_TO_LE(h->flags);
403 bin_header.ack_id = GUINT32_TO_LE(h->ack_id);
404 bin_header.ack_uid = GUINT32_TO_LE(h->ack_sub_id);
405 bin_header.ack_size = GUINT64_TO_LE(h->ack_size);
406
407 return (const gchar *)&bin_header;
408 } 357 }
409 358
410 static void 359 static void
411 msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond) 360 msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
412 { 361 {
500 static void 449 static void
501 msn_dc_send_handshake_with_nonce(MsnDirectConn *dc, MsnDirectConnPacket *p) 450 msn_dc_send_handshake_with_nonce(MsnDirectConn *dc, MsnDirectConnPacket *p)
502 { 451 {
503 const gchar *h; 452 const gchar *h;
504 453
505 h = msn_dc_serialize_binary_header(dc); 454 h = (gchar*) msn_p2p_header_to_wire(&dc->header);
506 memcpy(p->data, h, DC_PACKET_HEADER_SIZE); 455
507 456 memcpy(p->data, h, P2P_PACKET_HEADER_SIZE);
508 memcpy(p->data + offsetof(MsnDcContext, ack_id), dc->nonce, 16); 457
458 memcpy(p->data + offsetof(MsnP2PHeader, ack_id), dc->nonce, 16);
509 459
510 msn_dc_enqueue_packet(dc, p); 460 msn_dc_enqueue_packet(dc, p);
511 } 461 }
512 462
513 static void 463 static void
514 msn_dc_send_handshake(MsnDirectConn *dc) 464 msn_dc_send_handshake(MsnDirectConn *dc)
515 { 465 {
516 MsnDirectConnPacket *p; 466 MsnDirectConnPacket *p;
517 467
518 p = msn_dc_new_packet(DC_PACKET_HEADER_SIZE); 468 p = msn_dc_new_packet(P2P_PACKET_HEADER_SIZE);
519 469
520 dc->header.session_id = 0; 470 dc->header.session_id = 0;
521 dc->header.id = dc->slpcall->slplink->slp_seq_id++; 471 dc->header.id = dc->slpcall->slplink->slp_seq_id++;
522 dc->header.offset = 0; 472 dc->header.offset = 0;
523 dc->header.total_size = 0; 473 dc->header.total_size = 0;
530 static void 480 static void
531 msn_dc_send_handshake_reply(MsnDirectConn *dc) 481 msn_dc_send_handshake_reply(MsnDirectConn *dc)
532 { 482 {
533 MsnDirectConnPacket *p; 483 MsnDirectConnPacket *p;
534 484
535 p = msn_dc_new_packet(DC_PACKET_HEADER_SIZE); 485 p = msn_dc_new_packet(P2P_PACKET_HEADER_SIZE);
536 486
537 dc->header.id = dc->slpcall->slplink->slp_seq_id++; 487 dc->header.id = dc->slpcall->slplink->slp_seq_id++;
538 dc->header.length = 0; 488 dc->header.length = 0;
539 489
540 msn_dc_send_handshake_with_nonce(dc, p); 490 msn_dc_send_handshake_with_nonce(dc, p);
544 msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length) 494 msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
545 { 495 {
546 guchar nonce[16]; 496 guchar nonce[16];
547 gchar nonce_hash[37]; 497 gchar nonce_hash[37];
548 498
549 if (packet_length != DC_PACKET_HEADER_SIZE) 499 if (packet_length != P2P_PACKET_HEADER_SIZE)
550 return FALSE; 500 return FALSE;
551 501
552 memcpy(nonce, dc->in_buffer + 4 + offsetof(MsnDcContext, ack_id), 16); 502 memcpy(nonce, dc->in_buffer + 4 + offsetof(MsnP2PHeader, ack_id), 16);
553 503
554 if (dc->nonce_type == DC_NONCE_PLAIN) { 504 if (dc->nonce_type == DC_NONCE_PLAIN) {
555 if (memcmp(dc->nonce, nonce, 16) == 0) { 505 if (memcmp(dc->nonce, nonce, 16) == 0) {
556 purple_debug_info("msn", 506 purple_debug_info("msn",
557 "Nonce from buddy request and nonce from DC attempt match, " 507 "Nonce from buddy request and nonce from DC attempt match, "
587 } 537 }
588 538
589 static void 539 static void
590 msn_dc_send_packet_cb(MsnDirectConnPacket *p) 540 msn_dc_send_packet_cb(MsnDirectConnPacket *p)
591 { 541 {
542 if (p->part != NULL && p->part->ack_cb != NULL)
543 p->part->ack_cb(p->part, p->part->ack_data);
544 }
545
546 #if 0
547 static void
548 msn_dc_send_packet_cb(MsnDirectConnPacket *p)
549 {
592 if (p->msg != NULL && p->msg->ack_cb != NULL) 550 if (p->msg != NULL && p->msg->ack_cb != NULL)
593 p->msg->ack_cb(p->msg, p->msg->ack_data); 551 p->msg->ack_cb(p->msg, p->msg->ack_data);
594 } 552 }
595 553
596 void 554 void
597 msn_dc_enqueue_msg(MsnDirectConn *dc, MsnMessage *msg) 555 msn_dc_enqueue_msg(MsnDirectConn *dc, MsnMessage *msg)
598 { 556 {
599 MsnDirectConnPacket *p; 557 MsnDirectConnPacket *p;
600 guint32 length; 558 guint32 length;
601 559
602 length = msg->body_len + DC_PACKET_HEADER_SIZE; 560 length = msg->body_len + P2P_PACKET_HEADER_SIZE;
603 p = msn_dc_new_packet(length); 561 p = msn_dc_new_packet(length);
604 562
605 memcpy(p->data, &msg->msnslp_header, DC_PACKET_HEADER_SIZE); 563 memcpy(p->data, msg->slpmsg->header, P2P_PACKET_HEADER_SIZE);
606 memcpy(p->data + DC_PACKET_HEADER_SIZE, msg->body, msg->body_len); 564 memcpy(p->data + P2P_PACKET_HEADER_SIZE, msg->body, msg->body_len);
607 565
608 p->sent_cb = msn_dc_send_packet_cb; 566 p->sent_cb = msn_dc_send_packet_cb;
609 p->msg = msn_message_ref(msg); 567 p->msg = msn_message_ref(msg);
568
569 msn_dc_enqueue_packet(dc, p);
570 }
571 #endif
572
573 void
574 msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part)
575 {
576 MsnDirectConnPacket *p;
577 guint32 length;
578
579 length = part->size + P2P_PACKET_HEADER_SIZE;
580 p = msn_dc_new_packet(length);
581
582 memcpy(p->data, part->header, P2P_PACKET_HEADER_SIZE);
583 memcpy(p->data + P2P_PACKET_HEADER_SIZE, part->buffer, part->size);
584
585 p->sent_cb = msn_dc_send_packet_cb;
586 p->part = part;
610 587
611 msn_dc_enqueue_packet(dc, p); 588 msn_dc_enqueue_packet(dc, p);
612 } 589 }
613 590
614 static int 591 static int
651 628
652 case DC_STATE_ESTABLISHED: 629 case DC_STATE_ESTABLISHED:
653 msn_slplink_process_msg( 630 msn_slplink_process_msg(
654 dc->slplink, 631 dc->slplink,
655 &dc->header, 632 &dc->header,
656 dc->in_buffer + 4 + DC_PACKET_HEADER_SIZE, 633 dc->in_buffer + 4 + P2P_PACKET_HEADER_SIZE,
657 dc->header.length 634 dc->header.length
658 ); 635 );
659 636
660 /* 637 /*
661 if (dc->num_calls == 0) { 638 if (dc->num_calls == 0) {
725 /* Wait for the whole packet to arrive */ 702 /* Wait for the whole packet to arrive */
726 if (dc->in_pos < 4 + packet_length) 703 if (dc->in_pos < 4 + packet_length)
727 return; 704 return;
728 705
729 if (dc->state != DC_STATE_FOO) { 706 if (dc->state != DC_STATE_FOO) {
730 msn_dc_parse_binary_header(dc); 707 MsnP2PHeader *context;
708 MsnP2PHeader *h;
709
710 /* Skip packet size */
711 context = (MsnP2PHeader *)(dc->in_buffer + 4);
712
713 h = msn_p2p_header_from_wire(context);
714 memcpy(&dc->header, h, P2P_PACKET_HEADER_SIZE);
715 g_free(h);
731 } 716 }
732 717
733 switch (msn_dc_process_packet(dc, packet_length)) { 718 switch (msn_dc_process_packet(dc, packet_length)) {
734 case DC_PROCESS_CLOSE: 719 case DC_PROCESS_CLOSE:
735 return; 720 return;