comparison libpurple/protocols/qq/qq_network.c @ 23695:5f454b975a99

2008.08.10 - csyfek <csyfek(at)gmail.com> * Commit to Pidgin 2008.08.06 - ccpaging <ecc_hy(at)hotmail.com> * Rename names of variables, Group, to Room * Functions of group_network merged into qq_network and qq_process * Canceled managing glist of group packet, add sub_cmdd and room_id to transaction * Fixed error of demo group: If 'room list' and 'room infor' are not setup, response received from server will emits 'room_id = 0' packet. 2008.08.04 - ccpaging <ecc_hy(at)hotmail.com> * Use new crypt/decrypt functions * Rename crypt.c/h to qq_crypt.c/h * Clean code of decrypt functions * Fixed decryption failure 2008.08.04 - csyfek <csyfek(at)gmail.com> * Update AUTHORS
author SHiNE CsyFeK <csyfek@gmail.com>
date Sun, 10 Aug 2008 04:32:14 +0000
parents 1c50f12b1c52
children 91169093449d 967344bc404d
comparison
equal deleted inserted replaced
23690:107166bb2a64 23695:5f454b975a99
32 #endif 32 #endif
33 33
34 #include "buddy_info.h" 34 #include "buddy_info.h"
35 #include "group_info.h" 35 #include "group_info.h"
36 #include "group_free.h" 36 #include "group_free.h"
37 #include "crypt.h" 37 #include "qq_crypt.h"
38 #include "header_info.h" 38 #include "header_info.h"
39 #include "qq_base.h" 39 #include "qq_base.h"
40 #include "buddy_list.h" 40 #include "buddy_list.h"
41 #include "packet_parse.h" 41 #include "packet_parse.h"
42 #include "qq_network.h" 42 #include "qq_network.h"
165 165
166 guint8 header_tag; 166 guint8 header_tag;
167 guint16 source_tag; 167 guint16 source_tag;
168 guint16 cmd; 168 guint16 cmd;
169 guint16 seq; /* May be ack_seq or send_seq, depends on cmd */ 169 guint16 seq; /* May be ack_seq or send_seq, depends on cmd */
170
171 guint8 room_cmd;
172 guint32 room_id;
170 173
171 qq_transaction *trans; 174 qq_transaction *trans;
172 175
173 g_return_if_fail(buf != NULL && buf_len > 0); 176 g_return_if_fail(buf != NULL && buf_len > 0);
174 177
178 181
179 /* Len, header and tail tag have been checked before */ 182 /* Len, header and tail tag have been checked before */
180 bytes = 0; 183 bytes = 0;
181 bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes); 184 bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes);
182 185
183 if (QQ_DEBUG) { 186 #if 1
184 purple_debug(PURPLE_DEBUG_INFO, "QQ", 187 purple_debug(PURPLE_DEBUG_INFO, "QQ",
185 "==> [%05d] 0x%04X %s, from (0x%04X %s)\n", 188 "==> [%05d] 0x%04X %s, from (0x%04X %s) len %d\n",
186 seq, cmd, qq_get_cmd_desc(cmd), source_tag, qq_get_ver_desc(source_tag)); 189 seq, cmd, qq_get_cmd_desc(cmd), source_tag, qq_get_ver_desc(source_tag), buf_len);
187 } 190 #endif
188
189 bytes_not_read = buf_len - bytes - 1; 191 bytes_not_read = buf_len - bytes - 1;
190 192
191 /* ack packet, we need to update send tranactions */ 193 /* ack packet, we need to update send tranactions */
192 /* we do not check duplication for server ack */ 194 /* we do not check duplication for server ack */
193 trans = qq_trans_find_rcved(qd, cmd, seq); 195 trans = qq_trans_find_rcved(qd, cmd, seq);
212 } 214 }
213 return; 215 return;
214 } 216 }
215 217
216 /* this is the length of all the encrypted data (also remove tail tag */ 218 /* this is the length of all the encrypted data (also remove tail tag */
217 qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read); 219 if (cmd == QQ_CMD_ROOM) {
218 220 room_cmd = qq_trans_get_room_cmd(trans);
221 room_id = qq_trans_get_room_id(trans);
222 #if 1
223 purple_debug(PURPLE_DEBUG_INFO, "QQ",
224 "%s (0x%02X ) for room %d, len %d\n",
225 qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len);
226 #endif
227 qq_proc_room_cmd_reply(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read);
228 } else {
229 qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read);
230 }
231
219 /* check is redirect or not, and do it now */ 232 /* check is redirect or not, and do it now */
220 if (qd->is_redirect) { 233 if (qd->is_redirect) {
221 /* free resource except real_hostname and port */ 234 /* free resource except real_hostname and port */
222 qq_disconnect(gc); 235 qq_disconnect(gc);
223 qd->reconnect_times = QQ_RECONNECT_MAX; 236 qd->reconnect_times = QQ_RECONNECT_MAX;
931 memset(qd->session_key, 0, sizeof(qd->session_key)); 944 memset(qd->session_key, 0, sizeof(qd->session_key));
932 memset(qd->session_md5, 0, sizeof(qd->session_md5)); 945 memset(qd->session_md5, 0, sizeof(qd->session_md5));
933 946
934 qd->my_ip.s_addr = 0; 947 qd->my_ip.s_addr = 0;
935 948
936 qq_group_packets_free(qd);
937 qq_group_free_all(qd); 949 qq_group_free_all(qd);
938 qq_add_buddy_request_free(qd); 950 qq_add_buddy_request_free(qd);
939 qq_info_query_free(qd); 951 qq_info_query_free(qd);
940 qq_buddies_list_free(gc->account, qd); 952 qq_buddies_list_free(gc->account, qd);
941 } 953 }
943 static gint encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq, 955 static gint encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq,
944 guint8 *data, gint data_len) 956 guint8 *data, gint data_len)
945 { 957 {
946 gint bytes = 0; 958 gint bytes = 0;
947 g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1); 959 g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1);
948 960 g_return_val_if_fail(data != NULL && data_len > 0, -1);
949 if (data == NULL) { 961
950 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail encap packet, data is NULL\n");
951 return -1;
952 }
953 if (data_len <= 0) {
954 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail encap packet, data len <= 0\n");
955 return -1;
956 }
957
958 /* QQ TCP packet has two bytes in the begining defines packet length 962 /* QQ TCP packet has two bytes in the begining defines packet length
959 * so leave room here to store packet size */ 963 * so leave room here to store packet size */
960 if (qd->use_tcp) { 964 if (qd->use_tcp) {
961 bytes += qq_put16(buf + bytes, 0x0000); 965 bytes += qq_put16(buf + bytes, 0x0000);
962 } 966 }
1005 1009
1006 if (need_ack) { 1010 if (need_ack) {
1007 qq_trans_add_client_cmd(qd, cmd, seq, data, data_len); 1011 qq_trans_add_client_cmd(qd, cmd, seq, data, data_len);
1008 } 1012 }
1009 1013
1010 if (QQ_DEBUG) { 1014 #if 1
1011 /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */ 1015 /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */
1012 purple_debug(PURPLE_DEBUG_INFO, "QQ", 1016 purple_debug(PURPLE_DEBUG_INFO, "QQ",
1013 "<== [%05d], %s, total %d bytes is sent %d\n", 1017 "<== [%05d], 0x%04X %s, total %d bytes is sent %d\n",
1014 seq, qq_get_cmd_desc(cmd), buf_len, bytes_sent); 1018 seq, cmd, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
1015 } 1019 #endif
1016 return bytes_sent; 1020 return bytes_sent;
1017 } 1021 }
1018 1022
1019 /* Encrypt data with session_key, then call qq_send_data */ 1023 /* Encrypt data with session_key, then call qq_send_data */
1020 gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack, 1024 gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack,
1024 gint encrypted_len; 1028 gint encrypted_len;
1025 1029
1026 g_return_val_if_fail(qd != NULL, -1); 1030 g_return_val_if_fail(qd != NULL, -1);
1027 g_return_val_if_fail(data != NULL && data_len > 0, -1); 1031 g_return_val_if_fail(data != NULL && data_len > 0, -1);
1028 1032
1029 encrypted_len = data_len + 16; /* at most 16 bytes more */ 1033 /* at most 16 bytes more */
1030 encrypted_data = g_newa(guint8, encrypted_len); 1034 encrypted_data = g_newa(guint8, data_len + 16);
1031 1035 #if 0
1032 qq_encrypt(data, data_len, qd->session_key, encrypted_data, &encrypted_len); 1036 purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT",
1033 1037 "Before %d: [%05d] 0x%04X %s\n",
1038 data_len, seq, cmd, qq_get_cmd_desc(cmd));
1039 #endif
1040 encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key);
1041 if (encrypted_len < 16) {
1042 purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT",
1043 "Error len %d: [%05d] 0x%04X %s\n",
1044 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd));
1045 return -1;
1046 }
1047
1048 #if 0
1049 purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT",
1050 "After %d: [%05d] 0x%04X %s\n",
1051 encrypted_len, seq, cmd, qq_get_cmd_desc(cmd));
1052 #endif
1034 return qq_send_data(qd, cmd, seq, need_ack, encrypted_data, encrypted_len); 1053 return qq_send_data(qd, cmd, seq, need_ack, encrypted_data, encrypted_len);
1035 } 1054 }
1036 1055
1037 /* set seq and need_ack, then call qq_send_cmd_detail */ 1056 /* set seq and need_ack, then call qq_send_cmd_detail */
1038 gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint data_len) 1057 gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint data_len)
1041 g_return_val_if_fail(data != NULL && data_len > 0, -1); 1060 g_return_val_if_fail(data != NULL && data_len > 0, -1);
1042 1061
1043 qd->send_seq++; 1062 qd->send_seq++;
1044 return qq_send_cmd_detail(qd, cmd, qd->send_seq, TRUE, data, data_len); 1063 return qq_send_cmd_detail(qd, cmd, qd->send_seq, TRUE, data, data_len);
1045 } 1064 }
1065
1066 gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd,
1067 guint8 *data, gint data_len)
1068 {
1069 return qq_send_room_cmd(gc, room_cmd, 0, data, data_len);
1070 }
1071
1072 gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id)
1073 {
1074 g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1);
1075 return qq_send_room_cmd(gc, room_cmd, room_id, NULL, 0);
1076 }
1077
1078 gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id,
1079 guint8 *data, gint data_len)
1080 {
1081 qq_data *qd;
1082
1083 guint8 *buf;
1084 gint buf_len;
1085 guint8 *encrypted_data;
1086 gint encrypted_len;
1087 gint bytes_sent;
1088 guint16 seq;
1089
1090 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
1091 qd = (qq_data *) gc->proto_data;
1092
1093 buf = g_newa(guint8, MAX_PACKET_SIZE);
1094 memset(buf, 0, MAX_PACKET_SIZE);
1095
1096 /* encap room_cmd and room id to buf*/
1097 buf_len = 0;
1098 buf_len += qq_put8(buf + buf_len, room_cmd);
1099 if (room_id != 0) {
1100 /* id 0 is for QQ Demo Group, now there are not existed*/
1101 buf_len += qq_put32(buf + buf_len, room_id);
1102 }
1103 if (data != NULL && data_len > 0) {
1104 buf_len += qq_putdata(buf + buf_len, data, data_len);
1105 }
1106 qd->send_seq++;
1107 seq = qd->send_seq;
1108
1109 /* Encrypt to encrypted_data with session_key */
1110 /* at most 16 bytes more */
1111 encrypted_data = g_newa(guint8, buf_len + 16);
1112 encrypted_len = qq_encrypt(encrypted_data, buf, buf_len, qd->session_key);
1113 if (encrypted_len < 16) {
1114 purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT",
1115 "Error len %d: [%05d] QQ_CMD_ROOM.(0x%02X %s)\n",
1116 encrypted_len, seq, room_cmd, qq_get_room_cmd_desc(room_cmd));
1117 return -1;
1118 }
1119
1120 /* Encap header to buf */
1121 buf_len = encap(qd, buf, MAX_PACKET_SIZE, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len);
1122 if (buf_len <= 0) {
1123 return -1;
1124 }
1125
1126 if (qd->use_tcp) {
1127 bytes_sent = tcp_send_out(qd, buf, buf_len);
1128 } else {
1129 bytes_sent = udp_send_out(qd, buf, buf_len);
1130 }
1131
1132 qq_trans_add_room_cmd(qd, seq, room_cmd, room_id, buf, buf_len);
1133
1134 #if 1
1135 /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */
1136 purple_debug(PURPLE_DEBUG_INFO, "QQ",
1137 "<== [%05d], QQ_CMD_ROOM.(0x%02X %s) to room %d, total %d bytes is sent %d\n",
1138 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id,
1139 buf_len, bytes_sent);
1140 #endif
1141 return bytes_sent;
1142 }