Mercurial > pidgin
comparison libpurple/protocols/qq/qq_network.c @ 24135:dbc7a9742f8d
2008.09.26 - ccpaging <ccpaging(at)gmail.com>
* Added 'Request/Add/Remove Buddy' functions
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Wed, 22 Oct 2008 14:35:05 +0000 |
parents | bdfcfd71449c |
children | 87e61a85f5dd |
comparison
equal
deleted
inserted
replaced
24134:bdfcfd71449c | 24135:dbc7a9742f8d |
---|---|
200 qd->connect_retry = QQ_CONNECT_MAX; | 200 qd->connect_retry = QQ_CONNECT_MAX; |
201 } | 201 } |
202 | 202 |
203 if (qd->curr_server == NULL || strlen (qd->curr_server) == 0 || qd->connect_retry <= 0) { | 203 if (qd->curr_server == NULL || strlen (qd->curr_server) == 0 || qd->connect_retry <= 0) { |
204 if ( set_new_server(qd) != TRUE) { | 204 if ( set_new_server(qd) != TRUE) { |
205 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 205 purple_connection_error_reason(gc, |
206 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
206 _("Failed to connect all servers")); | 207 _("Failed to connect all servers")); |
207 return FALSE; | 208 return FALSE; |
208 } | 209 } |
209 qd->connect_retry = QQ_CONNECT_MAX; | 210 qd->connect_retry = QQ_CONNECT_MAX; |
210 } | 211 } |
218 } | 219 } |
219 g_strfreev(segments); | 220 g_strfreev(segments); |
220 | 221 |
221 qd->connect_retry--; | 222 qd->connect_retry--; |
222 if ( !connect_to_server(gc, server, port) ) { | 223 if ( !connect_to_server(gc, server, port) ) { |
223 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 224 purple_connection_error_reason(gc, |
225 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
224 _("Unable to connect.")); | 226 _("Unable to connect.")); |
225 } | 227 } |
226 | 228 |
227 qd->check_watcher = purple_timeout_add_seconds(QQ_CONNECT_CHECK, connect_check, gc); | 229 qd->check_watcher = purple_timeout_add_seconds(QQ_CONNECT_CHECK, connect_check, gc); |
228 return FALSE; /* timeout callback stops */ | 230 return FALSE; /* timeout callback stops */ |
351 | 353 |
352 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | 354 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
353 qd = (qq_data *) gc->proto_data; | 355 qd = (qq_data *) gc->proto_data; |
354 | 356 |
355 if(cond != PURPLE_INPUT_READ) { | 357 if(cond != PURPLE_INPUT_READ) { |
356 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 358 purple_connection_error_reason(gc, |
359 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
357 _("Socket error")); | 360 _("Socket error")); |
358 return; | 361 return; |
359 } | 362 } |
360 | 363 |
361 conn = connection_find(qd, source); | 364 conn = connection_find(qd, source); |
375 if (errno == EAGAIN) | 378 if (errno == EAGAIN) |
376 /* No worries */ | 379 /* No worries */ |
377 return; | 380 return; |
378 | 381 |
379 error_msg = g_strdup_printf(_("Lost connection with server:\n%d, %s"), errno, g_strerror(errno)); | 382 error_msg = g_strdup_printf(_("Lost connection with server:\n%d, %s"), errno, g_strerror(errno)); |
380 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); | 383 purple_connection_error_reason(gc, |
384 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
385 error_msg); | |
381 g_free(error_msg); | 386 g_free(error_msg); |
382 return; | 387 return; |
383 } else if (buf_len == 0) { | 388 } else if (buf_len == 0) { |
384 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 389 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
385 _("Server closed the connection.")); | 390 _("Server closed the connection.")); |
477 gc = (PurpleConnection *) data; | 482 gc = (PurpleConnection *) data; |
478 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | 483 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
479 qd = (qq_data *) gc->proto_data; | 484 qd = (qq_data *) gc->proto_data; |
480 | 485 |
481 if(cond != PURPLE_INPUT_READ) { | 486 if(cond != PURPLE_INPUT_READ) { |
482 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 487 purple_connection_error_reason(gc, |
488 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
483 _("Socket error")); | 489 _("Socket error")); |
484 return; | 490 return; |
485 } | 491 } |
486 | 492 |
487 buf = g_newa(guint8, MAX_PACKET_SIZE); | 493 buf = g_newa(guint8, MAX_PACKET_SIZE); |
488 | 494 |
489 /* here we have UDP proxy suppport */ | 495 /* here we have UDP proxy suppport */ |
490 buf_len = read(source, buf, MAX_PACKET_SIZE); | 496 buf_len = read(source, buf, MAX_PACKET_SIZE); |
491 if (buf_len <= 0) { | 497 if (buf_len <= 0) { |
492 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 498 purple_connection_error_reason(gc, |
499 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
493 _("Unable to read from socket")); | 500 _("Unable to read from socket")); |
494 return; | 501 return; |
495 } | 502 } |
496 | 503 |
497 /* keep alive will be sent in 30 seconds since last_receive | 504 /* keep alive will be sent in 30 seconds since last_receive |
535 } | 542 } |
536 | 543 |
537 if (ret < 0) { | 544 if (ret < 0) { |
538 /* TODO: what to do here - do we really have to disconnect? */ | 545 /* TODO: what to do here - do we really have to disconnect? */ |
539 purple_debug_error("UDP_SEND_OUT", "Send failed: %d, %s\n", errno, g_strerror(errno)); | 546 purple_debug_error("UDP_SEND_OUT", "Send failed: %d, %s\n", errno, g_strerror(errno)); |
540 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); | 547 purple_connection_error_reason(gc, |
548 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
549 g_strerror(errno)); | |
541 } | 550 } |
542 return ret; | 551 return ret; |
543 } | 552 } |
544 | 553 |
545 static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) | 554 static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) |
567 | 576 |
568 if (ret < 0 && errno == EAGAIN) | 577 if (ret < 0 && errno == EAGAIN) |
569 return; | 578 return; |
570 else if (ret < 0) { | 579 else if (ret < 0) { |
571 /* TODO: what to do here - do we really have to disconnect? */ | 580 /* TODO: what to do here - do we really have to disconnect? */ |
572 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 581 purple_connection_error_reason(gc, |
573 _("Write Error")); | 582 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
583 _("Write Error")); | |
574 return; | 584 return; |
575 } | 585 } |
576 | 586 |
577 purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); | 587 purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); |
578 } | 588 } |
612 ret = 0; | 622 ret = 0; |
613 } else if (ret <= 0) { | 623 } else if (ret <= 0) { |
614 /* TODO: what to do here - do we really have to disconnect? */ | 624 /* TODO: what to do here - do we really have to disconnect? */ |
615 purple_debug_error("TCP_SEND_OUT", | 625 purple_debug_error("TCP_SEND_OUT", |
616 "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); | 626 "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); |
617 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); | 627 purple_connection_error_reason(gc, |
628 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
629 g_strerror(errno)); | |
618 return ret; | 630 return ret; |
619 } | 631 } |
620 | 632 |
621 if (ret < data_len) { | 633 if (ret < data_len) { |
622 purple_debug_info("TCP_SEND_OUT", | 634 purple_debug_info("TCP_SEND_OUT", |
639 qd = (qq_data *) gc->proto_data; | 651 qd = (qq_data *) gc->proto_data; |
640 | 652 |
641 is_lost_conn = qq_trans_scan(gc); | 653 is_lost_conn = qq_trans_scan(gc); |
642 if (is_lost_conn) { | 654 if (is_lost_conn) { |
643 purple_connection_error_reason(gc, | 655 purple_connection_error_reason(gc, |
644 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection lost")); | 656 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
657 _("Connection lost")); | |
645 return TRUE; | 658 return TRUE; |
646 } | 659 } |
647 | 660 |
648 if ( !qd->is_login ) { | 661 if ( !qd->is_login ) { |
649 return TRUE; | 662 return TRUE; |
672 | 685 |
673 static void set_all_keys(PurpleConnection *gc) | 686 static void set_all_keys(PurpleConnection *gc) |
674 { | 687 { |
675 qq_data *qd; | 688 qq_data *qd; |
676 const gchar *passwd; | 689 const gchar *passwd; |
690 guint8 *dest; | |
691 int dest_len = QQ_KEY_LENGTH; | |
677 | 692 |
678 /* _qq_show_socket("Got login socket", source); */ | 693 /* _qq_show_socket("Got login socket", source); */ |
679 | 694 |
680 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | 695 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
681 qd = (qq_data *) gc->proto_data; | 696 qd = (qq_data *) gc->proto_data; |
687 qd->is_login = FALSE; | 702 qd->is_login = FALSE; |
688 qd->channel = 1; | 703 qd->channel = 1; |
689 qd->uid = strtol(purple_account_get_username(purple_connection_get_account(gc)), NULL, 10); | 704 qd->uid = strtol(purple_account_get_username(purple_connection_get_account(gc)), NULL, 10); |
690 | 705 |
691 #ifdef DEBUG | 706 #ifdef DEBUG |
692 memset(qd->ld.init_key, 0x01, sizeof(qd->ld.init_key)); | 707 memset(qd->ld.random_key, 0x01, sizeof(qd->ld.random_key)); |
693 memset(qd->ld.captcha_key, 0x02, sizeof(qd->ld.captcha_key)); | |
694 #else | 708 #else |
695 for (bytes = 0; bytes < sizeof(qd->ld.init_key); bytes++) { | 709 for (bytes = 0; bytes < sizeof(qd->ld.random_key); bytes++) { |
696 qd->ld.init_key[bytes] = (guint8) (rand() & 0xff); | 710 qd->ld.random_key[bytes] = (guint8) (rand() & 0xff); |
697 } | |
698 for (bytes = 0; bytes < sizeof(qd->captcha_key); bytes++) { | |
699 qd->captcha_key[bytes] = (guint8) (rand() & 0xff); | |
700 } | 711 } |
701 #endif | 712 #endif |
702 | 713 |
703 /* now generate md5 processed passwd */ | 714 /* now generate md5 processed passwd */ |
704 passwd = purple_account_get_password(purple_connection_get_account(gc)); | 715 passwd = purple_account_get_password(purple_connection_get_account(gc)); |
705 | 716 |
706 /* use twice-md5 of user password as session key since QQ 2003iii */ | 717 /* use twice-md5 of user password as session key since QQ 2003iii */ |
707 qq_get_md5(qd->ld.pwd_twice_md5, sizeof(qd->ld.pwd_twice_md5), | 718 dest = qd->ld.pwd_2nd_md5; |
708 (guint8 *)passwd, strlen(passwd)); | 719 qq_get_md5(dest, dest_len, (guint8 *)passwd, strlen(passwd)); |
709 qq_get_md5(qd->ld.pwd_twice_md5, sizeof(qd->ld.pwd_twice_md5), | 720 qq_get_md5(dest, dest_len, dest, dest_len); |
710 qd->ld.pwd_twice_md5, sizeof(qd->ld.pwd_twice_md5)); | 721 |
711 | 722 dest = qd->ld.pwd_4th_md5; |
723 qq_get_md5(dest, dest_len, qd->ld.pwd_2nd_md5, dest_len); | |
724 qq_get_md5(dest, dest_len, dest, dest_len); | |
712 } | 725 } |
713 | 726 |
714 /* the callback function after socket is built | 727 /* the callback function after socket is built |
715 * we setup the qq protocol related configuration here */ | 728 * we setup the qq protocol related configuration here */ |
716 static void connect_cb(gpointer data, gint source, const gchar *error_message) | 729 static void connect_cb(gpointer data, gint source, const gchar *error_message) |
756 g_return_if_fail(qd->network_watcher == 0); | 769 g_return_if_fail(qd->network_watcher == 0); |
757 qd->network_watcher = purple_timeout_add_seconds(qd->itv_config.resend, network_timeout, gc); | 770 qd->network_watcher = purple_timeout_add_seconds(qd->itv_config.resend, network_timeout, gc); |
758 | 771 |
759 set_all_keys( gc ); | 772 set_all_keys( gc ); |
760 | 773 |
761 if (qd->is_above_2007) { | 774 if (qd->client_version > 2005) { |
762 purple_connection_update_progress(gc, _("Get server ..."), 2, QQ_CONNECT_STEPS); | 775 purple_connection_update_progress(gc, _("Get server ..."), 2, QQ_CONNECT_STEPS); |
763 qq_request_get_server(gc); | 776 qq_request_get_server(gc); |
764 return; | 777 return; |
765 } | 778 } |
766 | 779 |
834 * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */ | 847 * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */ |
835 qd->udp_query_data = NULL; | 848 qd->udp_query_data = NULL; |
836 | 849 |
837 if (!hosts || !hosts->data) { | 850 if (!hosts || !hosts->data) { |
838 purple_connection_error_reason(gc, | 851 purple_connection_error_reason(gc, |
839 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 852 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
840 _("Couldn't resolve host")); | 853 _("Couldn't resolve host")); |
841 return; | 854 return; |
842 } | 855 } |
843 | 856 |
844 addr_size = GPOINTER_TO_INT(hosts->data); | 857 addr_size = GPOINTER_TO_INT(hosts->data); |
845 hosts = g_slist_remove(hosts, hosts->data); | 858 hosts = g_slist_remove(hosts, hosts->data); |
913 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); | 926 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); |
914 account = purple_connection_get_account(gc); | 927 account = purple_connection_get_account(gc); |
915 qd = (qq_data *) gc->proto_data; | 928 qd = (qq_data *) gc->proto_data; |
916 | 929 |
917 if (server == NULL || strlen(server) == 0 || port == 0) { | 930 if (server == NULL || strlen(server) == 0 || port == 0) { |
918 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 931 purple_connection_error_reason(gc, |
932 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
919 _("Invalid server or port")); | 933 _("Invalid server or port")); |
920 return FALSE; | 934 return FALSE; |
921 } | 935 } |
922 | 936 |
923 purple_connection_update_progress(gc, _("Connecting server ..."), 1, QQ_CONNECT_STEPS); | 937 purple_connection_update_progress(gc, _("Connecting server ..."), 1, QQ_CONNECT_STEPS); |
1004 connection_free_all(qd); | 1018 connection_free_all(qd); |
1005 qd->fd = -1; | 1019 qd->fd = -1; |
1006 | 1020 |
1007 qq_trans_remove_all(gc); | 1021 qq_trans_remove_all(gc); |
1008 | 1022 |
1009 memset(qd->ld.init_key, 0, sizeof(qd->ld.init_key)); | 1023 memset(qd->ld.random_key, 0, sizeof(qd->ld.random_key)); |
1010 memset(qd->ld.captcha_key, 0, sizeof(qd->ld.captcha_key)); | 1024 memset(qd->ld.pwd_2nd_md5, 0, sizeof(qd->ld.pwd_2nd_md5)); |
1011 memset(qd->ld.pwd_twice_md5, 0, sizeof(qd->ld.pwd_twice_md5)); | 1025 memset(qd->ld.pwd_4th_md5, 0, sizeof(qd->ld.pwd_4th_md5)); |
1026 memset(qd->ld.login_key, 0, sizeof(qd->ld.login_key)); | |
1012 memset(qd->session_key, 0, sizeof(qd->session_key)); | 1027 memset(qd->session_key, 0, sizeof(qd->session_key)); |
1013 memset(qd->session_md5, 0, sizeof(qd->session_md5)); | 1028 memset(qd->session_md5, 0, sizeof(qd->session_md5)); |
1014 | 1029 |
1015 qd->my_ip.s_addr = 0; | 1030 qd->my_ip.s_addr = 0; |
1016 | 1031 |
1030 if (qd->use_tcp) { | 1045 if (qd->use_tcp) { |
1031 bytes += qq_put16(buf + bytes, 0x0000); | 1046 bytes += qq_put16(buf + bytes, 0x0000); |
1032 } | 1047 } |
1033 /* now comes the normal QQ packet as UDP */ | 1048 /* now comes the normal QQ packet as UDP */ |
1034 bytes += qq_put8(buf + bytes, QQ_PACKET_TAG); | 1049 bytes += qq_put8(buf + bytes, QQ_PACKET_TAG); |
1035 bytes += qq_put16(buf + bytes, qd->client_version); | 1050 bytes += qq_put16(buf + bytes, qd->client_tag); |
1036 bytes += qq_put16(buf + bytes, cmd); | 1051 bytes += qq_put16(buf + bytes, cmd); |
1037 | 1052 |
1038 bytes += qq_put16(buf + bytes, seq); | 1053 bytes += qq_put16(buf + bytes, seq); |
1039 | 1054 |
1040 bytes += qq_put32(buf + bytes, qd->uid); | 1055 bytes += qq_put32(buf + bytes, qd->uid); |
1077 | 1092 |
1078 return bytes_sent; | 1093 return bytes_sent; |
1079 } | 1094 } |
1080 | 1095 |
1081 gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, | 1096 gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, |
1082 guint8 *encrypted_data, gint encrypted_len, gboolean is_save2trans) | 1097 guint8 *encrypted, gint encrypted_len, gboolean is_save2trans) |
1083 { | 1098 { |
1084 gint sent_len; | 1099 gint sent_len; |
1085 | 1100 |
1086 #if 1 | 1101 #if 1 |
1087 /* qq_show_packet("qq_send_cmd_encrypted", data, data_len); */ | 1102 /* qq_show_packet("qq_send_cmd_encrypted", data, data_len); */ |
1088 purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n", | 1103 purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n", |
1089 seq, qq_get_cmd_desc(cmd), cmd, encrypted_len); | 1104 seq, qq_get_cmd_desc(cmd), cmd, encrypted_len); |
1090 #endif | 1105 #endif |
1091 | 1106 |
1092 sent_len = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len); | 1107 sent_len = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); |
1093 if (is_save2trans) { | 1108 if (is_save2trans) { |
1094 qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len, 0, 0); | 1109 qq_trans_add_client_cmd(gc, cmd, seq, encrypted, encrypted_len, 0, 0); |
1095 } | 1110 } |
1096 return sent_len; | 1111 return sent_len; |
1097 } | 1112 } |
1098 | 1113 |
1099 /* Encrypt data with session_key, and send packet out */ | 1114 /* Encrypt data with session_key, and send packet out */ |
1100 static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq, | 1115 static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq, |
1101 guint8 *data, gint data_len, gboolean is_save2trans, gint update_class, guint32 ship32) | 1116 guint8 *data, gint data_len, gboolean is_save2trans, gint update_class, guint32 ship32) |
1102 { | 1117 { |
1103 qq_data *qd; | 1118 qq_data *qd; |
1104 guint8 *encrypted_data; | 1119 guint8 *encrypted; |
1105 gint encrypted_len; | 1120 gint encrypted_len; |
1106 gint bytes_sent; | 1121 gint bytes_sent; |
1107 | 1122 |
1108 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); | 1123 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); |
1109 qd = (qq_data *)gc->proto_data; | 1124 qd = (qq_data *)gc->proto_data; |
1110 g_return_val_if_fail(data != NULL && data_len > 0, -1); | 1125 g_return_val_if_fail(data != NULL && data_len > 0, -1); |
1111 | 1126 |
1112 /* at most 16 bytes more */ | 1127 /* at most 16 bytes more */ |
1113 encrypted_data = g_newa(guint8, data_len + 16); | 1128 encrypted = g_newa(guint8, data_len + 16); |
1114 encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key); | 1129 encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key); |
1115 if (encrypted_len < 16) { | 1130 if (encrypted_len < 16) { |
1116 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", | 1131 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", |
1117 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); | 1132 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); |
1118 return -1; | 1133 return -1; |
1119 } | 1134 } |
1120 | 1135 |
1121 bytes_sent = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len); | 1136 bytes_sent = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); |
1122 | 1137 |
1123 if (is_save2trans) { | 1138 if (is_save2trans) { |
1124 qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len, | 1139 qq_trans_add_client_cmd(gc, cmd, seq, encrypted, encrypted_len, |
1125 update_class, ship32); | 1140 update_class, ship32); |
1126 } | 1141 } |
1127 return bytes_sent; | 1142 return bytes_sent; |
1128 } | 1143 } |
1129 | 1144 |
1172 | 1187 |
1173 /* set seq and is_save2trans, then call send_cmd_detail */ | 1188 /* set seq and is_save2trans, then call send_cmd_detail */ |
1174 gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) | 1189 gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) |
1175 { | 1190 { |
1176 qq_data *qd; | 1191 qq_data *qd; |
1177 guint8 *encrypted_data; | 1192 guint8 *encrypted; |
1178 gint encrypted_len; | 1193 gint encrypted_len; |
1179 gint bytes_sent; | 1194 gint bytes_sent; |
1180 | 1195 |
1181 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); | 1196 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); |
1182 qd = (qq_data *)gc->proto_data; | 1197 qd = (qq_data *)gc->proto_data; |
1185 #if 1 | 1200 #if 1 |
1186 purple_debug_info("QQ", "<== [SRV-%05d], %s(0x%04X), datalen %d\n", | 1201 purple_debug_info("QQ", "<== [SRV-%05d], %s(0x%04X), datalen %d\n", |
1187 seq, qq_get_cmd_desc(cmd), cmd, data_len); | 1202 seq, qq_get_cmd_desc(cmd), cmd, data_len); |
1188 #endif | 1203 #endif |
1189 /* at most 16 bytes more */ | 1204 /* at most 16 bytes more */ |
1190 encrypted_data = g_newa(guint8, data_len + 16); | 1205 encrypted = g_newa(guint8, data_len + 16); |
1191 encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key); | 1206 encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key); |
1192 if (encrypted_len < 16) { | 1207 if (encrypted_len < 16) { |
1193 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", | 1208 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", |
1194 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); | 1209 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); |
1195 return -1; | 1210 return -1; |
1196 } | 1211 } |
1197 | 1212 |
1198 bytes_sent = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len); | 1213 bytes_sent = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); |
1199 qq_trans_add_server_reply(gc, cmd, seq, encrypted_data, encrypted_len); | 1214 qq_trans_add_server_reply(gc, cmd, seq, encrypted, encrypted_len); |
1200 | 1215 |
1201 return bytes_sent; | 1216 return bytes_sent; |
1202 } | 1217 } |
1203 | 1218 |
1204 static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, | 1219 static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, |
1205 guint8 *data, gint data_len, gint update_class, guint32 ship32) | 1220 guint8 *data, gint data_len, gint update_class, guint32 ship32) |
1206 { | 1221 { |
1207 qq_data *qd; | 1222 qq_data *qd; |
1208 guint8 *buf; | 1223 guint8 *buf; |
1209 gint buf_len; | 1224 gint buf_len; |
1210 guint8 *encrypted_data; | 1225 guint8 *encrypted; |
1211 gint encrypted_len; | 1226 gint encrypted_len; |
1212 gint bytes_sent; | 1227 gint bytes_sent; |
1213 guint16 seq; | 1228 guint16 seq; |
1214 | 1229 |
1215 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); | 1230 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); |
1230 } | 1245 } |
1231 | 1246 |
1232 qd->send_seq++; | 1247 qd->send_seq++; |
1233 seq = qd->send_seq; | 1248 seq = qd->send_seq; |
1234 | 1249 |
1235 /* Encrypt to encrypted_data with session_key */ | 1250 /* Encrypt to encrypted with session_key */ |
1236 /* at most 16 bytes more */ | 1251 /* at most 16 bytes more */ |
1237 encrypted_data = g_newa(guint8, buf_len + 16); | 1252 encrypted = g_newa(guint8, buf_len + 16); |
1238 encrypted_len = qq_encrypt(encrypted_data, buf, buf_len, qd->session_key); | 1253 encrypted_len = qq_encrypt(encrypted, buf, buf_len, qd->session_key); |
1239 if (encrypted_len < 16) { | 1254 if (encrypted_len < 16) { |
1240 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n", | 1255 purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n", |
1241 encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd); | 1256 encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd); |
1242 return -1; | 1257 return -1; |
1243 } | 1258 } |
1244 | 1259 |
1245 bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len); | 1260 bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted, encrypted_len); |
1246 #if 1 | 1261 #if 1 |
1247 /* qq_show_packet("send_room_cmd", buf, buf_len); */ | 1262 /* qq_show_packet("send_room_cmd", buf, buf_len); */ |
1248 purple_debug_info("QQ", | 1263 purple_debug_info("QQ", |
1249 "<== [%05d], %s (0x%02X) to room %d, datalen %d\n", | 1264 "<== [%05d], %s (0x%02X) to room %d, datalen %d\n", |
1250 seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); | 1265 seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); |
1251 #endif | 1266 #endif |
1252 | 1267 |
1253 qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted_data, encrypted_len, | 1268 qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted, encrypted_len, |
1254 update_class, ship32); | 1269 update_class, ship32); |
1255 return bytes_sent; | 1270 return bytes_sent; |
1256 } | 1271 } |
1257 | 1272 |
1258 gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, | 1273 gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, |
1259 guint8 *data, gint data_len, gint update_class, guint32 ship32) | 1274 guint8 *data, gint data_len, gint update_class, guint32 ship32) |
1260 { | 1275 { |
1276 g_return_val_if_fail(room_id > 0, -1); | |
1261 return send_room_cmd(gc, room_cmd, room_id, data, data_len, update_class, ship32); | 1277 return send_room_cmd(gc, room_cmd, room_id, data, data_len, update_class, ship32); |
1262 } | 1278 } |
1263 | 1279 |
1264 gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, | 1280 gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, |
1265 guint8 *data, gint data_len) | 1281 guint8 *data, gint data_len) |