libpurple/protocols/qq/file_trans.c

branch
openq
changeset 24340
36ceebf026a0
parent 24314
587e97c2b707
child 24341
02abffea97fe
equal deleted inserted replaced
24339:04033035db51 24340:36ceebf026a0
28 #include "ft.h" 28 #include "ft.h"
29 #include "cipher.h" 29 #include "cipher.h"
30 30
31 #include "qq_crypt.h" 31 #include "qq_crypt.h"
32 #include "file_trans.h" 32 #include "file_trans.h"
33 #include "header_info.h" 33 #include "qq_define.h"
34 #include "im.h" 34 #include "im.h"
35 #include "packet_parse.h" 35 #include "packet_parse.h"
36 #include "proxy.h" 36 #include "proxy.h"
37 #include "qq_network.h" 37 #include "qq_network.h"
38 #include "send_file.h" 38 #include "send_file.h"
79 size_t wc; 79 size_t wc;
80 80
81 const gint QQ_MAX_FILE_MD5_LENGTH = 10002432; 81 const gint QQ_MAX_FILE_MD5_LENGTH = 10002432;
82 82
83 g_return_if_fail(filename != NULL && md5 != NULL); 83 g_return_if_fail(filename != NULL && md5 != NULL);
84 if (filelen > QQ_MAX_FILE_MD5_LENGTH) 84 if (filelen > QQ_MAX_FILE_MD5_LENGTH)
85 filelen = QQ_MAX_FILE_MD5_LENGTH; 85 filelen = QQ_MAX_FILE_MD5_LENGTH;
86 86
87 fp = fopen(filename, "rb"); 87 fp = fopen(filename, "rb");
88 g_return_if_fail(fp != NULL); 88 g_return_if_fail(fp != NULL);
89 89
159 int fd; 159 int fd;
160 if (method[0] == 'r') { 160 if (method[0] == 'r') {
161 fd = open(purple_xfer_get_local_filename(xfer), O_RDONLY); 161 fd = open(purple_xfer_get_local_filename(xfer), O_RDONLY);
162 info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ, MAP_PRIVATE, fd, 0); 162 info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ, MAP_PRIVATE, fd, 0);
163 } 163 }
164 else 164 else
165 { 165 {
166 fd = open(purple_xfer_get_local_filename(xfer), O_RDWR|O_CREAT, 0644); 166 fd = open(purple_xfer_get_local_filename(xfer), O_RDWR|O_CREAT, 0644);
167 info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE, fd, 0); 167 info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE, fd, 0);
168 } 168 }
169 169
246 246
247 raw_data = g_newa(guint8, MAX_PACKET_SIZE); 247 raw_data = g_newa(guint8, MAX_PACKET_SIZE);
248 file_key = _gen_file_key(); 248 file_key = _gen_file_key();
249 249
250 bytes += qq_put8(raw_data + bytes, packet_type); 250 bytes += qq_put8(raw_data + bytes, packet_type);
251 bytes += qq_put16(raw_data + bytes, QQ_CLIENT); 251 bytes += qq_put16(raw_data + bytes, qd->client_version);
252 bytes += qq_put8(raw_data + bytes, file_key & 0xff); 252 bytes += qq_put8(raw_data + bytes, file_key & 0xff);
253 bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(qd->uid, file_key)); 253 bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(qd->uid, file_key));
254 bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(to_uid, file_key)); 254 bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(to_uid, file_key));
255 bytes += qq_putdata(raw_data + bytes, data, len); 255 bytes += qq_putdata(raw_data + bytes, data, len);
256 256
362 purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); 362 purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
363 _qq_send_file(gc, encrypted_data, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid); 363 _qq_send_file(gc, encrypted_data, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid);
364 } 364 }
365 365
366 /* send a file to udp channel with QQ_FILE_DATA_PACKET_TAG */ 366 /* send a file to udp channel with QQ_FILE_DATA_PACKET_TAG */
367 static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type, 367 static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type,
368 guint32 fragment_index, guint16 seq, guint8 *data, gint len) 368 guint32 fragment_index, guint16 seq, guint8 *data, gint len)
369 { 369 {
370 guint8 *raw_data, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH]; 370 guint8 *raw_data, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH];
371 gint bytes; 371 gint bytes;
372 guint32 fragment_size = 1000; 372 guint32 fragment_size = 1000;
400 filename_len = strlen(filename); 400 filename_len = strlen(filename);
401 qq_get_md5(filename_md5, sizeof(filename_md5), (guint8 *)filename, filename_len); 401 qq_get_md5(filename_md5, sizeof(filename_md5), (guint8 *)filename, filename_len);
402 _fill_file_md5(purple_xfer_get_local_filename(qd->xfer), 402 _fill_file_md5(purple_xfer_get_local_filename(qd->xfer),
403 purple_xfer_get_size(qd->xfer), 403 purple_xfer_get_size(qd->xfer),
404 file_md5); 404 file_md5);
405 405
406 info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1; 406 info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1;
407 info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN; 407 info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN;
408 408
409 purple_debug_info("QQ", 409 purple_debug_info("QQ",
410 "start transfering data, %d fragments with %d length each\n", 410 "start transfering data, %d fragments with %d length each\n",
411 info->fragment_num, info->fragment_len); 411 info->fragment_num, info->fragment_len);
412 /* Unknown */ 412 /* Unknown */
413 bytes += qq_put16(raw_data + bytes, 0x0000); 413 bytes += qq_put16(raw_data + bytes, 0x0000);
414 /* Sub-operation type */ 414 /* Sub-operation type */
429 /* filename */ 429 /* filename */
430 bytes += qq_putdata(raw_data + bytes, (guint8 *) filename, 430 bytes += qq_putdata(raw_data + bytes, (guint8 *) filename,
431 filename_len); 431 filename_len);
432 break; 432 break;
433 case QQ_FILE_DATA_INFO: 433 case QQ_FILE_DATA_INFO:
434 purple_debug_info("QQ", 434 purple_debug_info("QQ",
435 "sending %dth fragment with length %d, offset %d\n", 435 "sending %dth fragment with length %d, offset %d\n",
436 fragment_index, len, (fragment_index-1)*fragment_size); 436 fragment_index, len, (fragment_index-1)*fragment_size);
437 /* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */ 437 /* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */
438 bytes += qq_put16(raw_data + bytes, info->send_seq); 438 bytes += qq_put16(raw_data + bytes, info->send_seq);
439 bytes += qq_put8(raw_data + bytes, sub_type); 439 bytes += qq_put8(raw_data + bytes, sub_type);
530 switch (packet_type) { 530 switch (packet_type) {
531 case QQ_FILE_CMD_NOTIFY_IP_ACK: 531 case QQ_FILE_CMD_NOTIFY_IP_ACK:
532 decryped_bytes = 0; 532 decryped_bytes = 0;
533 qq_get_conn_info(info, decrypted_data + decryped_bytes); 533 qq_get_conn_info(info, decrypted_data + decryped_bytes);
534 /* qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */ 534 /* qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */
535 qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0); 535 qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0);
536 break; 536 break;
537 case QQ_FILE_CMD_SENDER_SAY_HELLO: 537 case QQ_FILE_CMD_SENDER_SAY_HELLO:
538 /* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */ 538 /* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */
539 decryped_bytes += 47; 539 decryped_bytes += 47;
540 decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes); 540 decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes);
571 qq_data *qd = (qq_data *) gc->proto_data; 571 qq_data *qd = (qq_data *) gc->proto_data;
572 PurpleXfer *xfer = qd->xfer; 572 PurpleXfer *xfer = qd->xfer;
573 ft_info *info = (ft_info *) xfer->data; 573 ft_info *info = (ft_info *) xfer->data;
574 guint32 mask; 574 guint32 mask;
575 575
576 purple_debug_info("QQ", 576 purple_debug_info("QQ",
577 "receiving %dth fragment with length %d, slide window status %o, max_fragment_index %d\n", 577 "receiving %dth fragment with length %d, slide window status %o, max_fragment_index %d\n",
578 index, len, info->window, info->max_fragment_index); 578 index, len, info->window, info->max_fragment_index);
579 if (info->window == 0 && info->max_fragment_index == 0) { 579 if (info->window == 0 && info->max_fragment_index == 0) {
580 if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "wb", xfer) == -1) { 580 if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "wb", xfer) == -1) {
581 purple_xfer_cancel_local(xfer); 581 purple_xfer_cancel_local(xfer);
582 return; 582 return;
603 info->window &= ~mask; 603 info->window &= ~mask;
604 info->max_fragment_index ++; 604 info->max_fragment_index ++;
605 if (mask & 0x8000) mask = 0x0001; 605 if (mask & 0x8000) mask = 0x0001;
606 else mask = mask << 1; 606 else mask = mask << 1;
607 } 607 }
608 purple_debug_info("QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n", 608 purple_debug_info("QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n",
609 index, info->window, info->max_fragment_index); 609 index, info->window, info->max_fragment_index);
610 } 610 }
611 611
612 static void _qq_send_file_progess(PurpleConnection *gc) 612 static void _qq_send_file_progess(PurpleConnection *gc)
613 { 613 {
648 gint readbytes; 648 gint readbytes;
649 qq_data *qd = (qq_data *) gc->proto_data; 649 qq_data *qd = (qq_data *) gc->proto_data;
650 PurpleXfer *xfer = qd->xfer; 650 PurpleXfer *xfer = qd->xfer;
651 ft_info *info = (ft_info *) xfer->data; 651 ft_info *info = (ft_info *) xfer->data;
652 652
653 purple_debug_info("QQ", 653 purple_debug_info("QQ",
654 "receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n", 654 "receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n",
655 fragment_index, info->window, info->max_fragment_index); 655 fragment_index, info->window, info->max_fragment_index);
656 if (fragment_index < info->max_fragment_index || 656 if (fragment_index < info->max_fragment_index ||
657 fragment_index >= info->max_fragment_index + sizeof(info->window)) { 657 fragment_index >= info->max_fragment_index + sizeof(info->window)) {
658 purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1); 658 purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1);
659 return; 659 return;
660 } 660 }
661 mask = 0x1 << (fragment_index % sizeof(info->window)); 661 mask = 0x1 << (fragment_index % sizeof(info->window));
679 { 679 {
680 /* move the slide window */ 680 /* move the slide window */
681 info->window &= ~mask; 681 info->window &= ~mask;
682 682
683 buffer = g_newa(guint8, info->fragment_len); 683 buffer = g_newa(guint8, info->fragment_len);
684 readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window), 684 readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window),
685 info->fragment_len, xfer); 685 info->fragment_len, xfer);
686 if (readbytes > 0) 686 if (readbytes > 0)
687 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO, 687 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,
688 info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes); 688 info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes);
689 689
690 info->max_fragment_index ++; 690 info->max_fragment_index ++;
691 if (mask & 0x8000) mask = 0x0001; 691 if (mask & 0x8000) mask = 0x0001;
692 else mask = mask << 1; 692 else mask = mask << 1;
693 } 693 }
694 } 694 }
695 purple_debug_info("QQ", 695 purple_debug_info("QQ",
696 "procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n", 696 "procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n",
697 fragment_index, info->window, info->max_fragment_index); 697 fragment_index, info->window, info->max_fragment_index);
698 } 698 }
699 699
700 static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, gint len) 700 static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, gint len)
701 { 701 {
725 case QQ_FILE_BASIC_INFO: 725 case QQ_FILE_BASIC_INFO:
726 bytes += 4; /* file length, we have already known it from xfer */ 726 bytes += 4; /* file length, we have already known it from xfer */
727 bytes += qq_get32(&info->fragment_num, data + bytes); 727 bytes += qq_get32(&info->fragment_num, data + bytes);
728 bytes += qq_get32(&info->fragment_len, data + bytes); 728 bytes += qq_get32(&info->fragment_len, data + bytes);
729 729
730 /* FIXME: We must check the md5 here, 730 /* FIXME: We must check the md5 here,
731 * if md5 doesn't match we will ignore 731 * if md5 doesn't match we will ignore
732 * the packet or send sth as error number */ 732 * the packet or send sth as error number */
733 733
734 info->max_fragment_index = 0; 734 info->max_fragment_index = 0;
735 info->window = 0; 735 info->window = 0;
736 purple_debug_info("QQ", 736 purple_debug_info("QQ",
737 "start receiving data, %d fragments with %d length each\n", 737 "start receiving data, %d fragments with %d length each\n",
738 info->fragment_num, info->fragment_len); 738 info->fragment_num, info->fragment_len);
739 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, 739 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,
740 0, 0, NULL, 0); 740 0, 0, NULL, 0);
741 break; 741 break;
742 case QQ_FILE_DATA_INFO: 742 case QQ_FILE_DATA_INFO:
743 bytes += qq_get32(&fragment_index, data + bytes); 743 bytes += qq_get32(&fragment_index, data + bytes);
744 bytes += qq_get32(&fragment_offset, data + bytes); 744 bytes += qq_get32(&fragment_offset, data + bytes);
745 bytes += qq_get16(&fragment_len, data + bytes); 745 bytes += qq_get16(&fragment_len, data + bytes);
746 purple_debug_info("QQ", 746 purple_debug_info("QQ",
747 "received %dth fragment with length %d, offset %d\n", 747 "received %dth fragment with length %d, offset %d\n",
748 fragment_index, fragment_len, fragment_offset); 748 fragment_index, fragment_len, fragment_offset);
749 749
750 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, 750 _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,
751 fragment_index, packet_seq, NULL, 0); 751 fragment_index, packet_seq, NULL, 0);

mercurial