Mercurial > pidgin
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 } |