libpurple/protocols/qq/recv_core.c

branch
release-2.4.3
changeset 23190
ce258cadbd9e
parent 22685
f3a524370c38
child 23191
4e69ad828497
equal deleted inserted replaced
23188:eab7aad90c95 23190:ce258cadbd9e
92 92
93 _qq_show_packet("Processing unknown packet", buf, len); 93 _qq_show_packet("Processing unknown packet", buf, len);
94 if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { 94 if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
95 gchar *hex_dump = hex_dump_to_str(data, len); 95 gchar *hex_dump = hex_dump_to_str(data, len);
96 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 96 purple_debug(PURPLE_DEBUG_WARNING, "QQ",
97 ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s", 97 ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
98 seq, qq_get_cmd_desc(cmd), buf_len, hex_dump); 98 seq, qq_get_cmd_desc(cmd), buf_len, hex_dump);
99 g_free(hex_dump); 99 g_free(hex_dump);
100 try_dump_as_gbk(data, len); 100 try_dump_as_gbk(data, len);
101 } else { 101 } else {
102 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n"); 102 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n");
103 } 103 }
105 105
106 /* process the incoming packet from qq_pending */ 106 /* process the incoming packet from qq_pending */
107 static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc) 107 static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc)
108 { 108 {
109 qq_data *qd; 109 qq_data *qd;
110 gint len, bytes_expected, bytes_read; 110 gint bytes_notread, bytes_expected, bytes;
111 guint16 buf_len_read; /* two bytes in the begining of TCP packet */ 111 guint16 buf_len_read; /* two bytes in the begining of TCP packet */
112 guint8 *cursor;
113 qq_recv_msg_header header; 112 qq_recv_msg_header header;
114 packet_before_login *b4_packet; 113 packet_before_login *b4_packet;
115 114
116 g_return_if_fail(buf != NULL && buf_len > 0); 115 g_return_if_fail(buf != NULL && buf_len > 0);
117 116
119 bytes_expected = qd->use_tcp ? QQ_TCP_HEADER_LENGTH : QQ_UDP_HEADER_LENGTH; 118 bytes_expected = qd->use_tcp ? QQ_TCP_HEADER_LENGTH : QQ_UDP_HEADER_LENGTH;
120 119
121 if (buf_len < bytes_expected) { 120 if (buf_len < bytes_expected) {
122 gchar *hex_dump = hex_dump_to_str(buf, buf_len); 121 gchar *hex_dump = hex_dump_to_str(buf, buf_len);
123 purple_debug(PURPLE_DEBUG_ERROR, 122 purple_debug(PURPLE_DEBUG_ERROR,
124 "QQ", "Received packet is too short, dump and drop\n%s", hex_dump); 123 "QQ", "Received packet is too short, dump and drop\n%s", hex_dump);
125 g_free(hex_dump); 124 g_free(hex_dump);
126 return; 125 return;
127 } 126 }
127
128 /* initialize */ 128 /* initialize */
129 cursor = buf; 129 bytes = 0;
130 bytes_read = 0;
131
132 /* QQ TCP packet returns first 2 bytes the length of this packet */ 130 /* QQ TCP packet returns first 2 bytes the length of this packet */
133 if (qd->use_tcp) { 131 if (qd->use_tcp) {
134 bytes_read += read_packet_w(buf, &cursor, buf_len, &buf_len_read); 132 bytes += qq_get16(&buf_len_read, buf + bytes);
135 if (buf_len_read != buf_len) { /* wrong */ 133 if (buf_len_read != buf_len) { /* wrong */
136 purple_debug 134 purple_debug
137 (PURPLE_DEBUG_ERROR, 135 (PURPLE_DEBUG_ERROR,
138 "QQ", 136 "QQ",
139 "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read); 137 "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read);
140 buf_len = buf_len_read; /* we believe header is more accurate */ 138 buf_len = buf_len_read; /* we believe header is more accurate */
141 } 139 }
142 } 140 }
143 141
144 /* now goes the normal QQ packet as UDP packet */ 142 /* now goes the normal QQ packet as UDP packet */
145 bytes_read += read_packet_b(buf, &cursor, buf_len, &header.header_tag); 143 bytes += qq_get8(&header.header_tag, buf + bytes);
146 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.source_tag); 144 bytes += qq_get16(&header.source_tag, buf + bytes);
147 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.cmd); 145 bytes += qq_get16(&header.cmd, buf + bytes);
148 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.seq); 146 bytes += qq_get16(&header.seq, buf + bytes);
149 147
150 if (bytes_read != bytes_expected) { /* read error */ 148 if (bytes != bytes_expected) { /* read error */
151 purple_debug(PURPLE_DEBUG_ERROR, "QQ", 149 purple_debug(PURPLE_DEBUG_ERROR, "QQ",
152 "Fail reading packet header, expect %d bytes, read %d bytes\n", 150 "Fail reading packet header, expect %d bytes, read %d bytes\n",
153 bytes_expected, bytes_read); 151 bytes_expected, bytes);
154 return; 152 return;
155 } 153 }
156 154
157 if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) { 155 if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) {
158 gchar *hex_dump = hex_dump_to_str(buf, buf_len); 156 gchar *hex_dump = hex_dump_to_str(buf, buf_len);
159 purple_debug(PURPLE_DEBUG_ERROR, 157 purple_debug(PURPLE_DEBUG_ERROR,
160 "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump); 158 "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump);
161 g_free(hex_dump); 159 g_free(hex_dump);
162 return; 160 return;
163 } 161 }
164 162
165 if (QQ_DEBUG) 163 if (QQ_DEBUG)
166 purple_debug(PURPLE_DEBUG_INFO, "QQ", 164 purple_debug(PURPLE_DEBUG_INFO, "QQ",
167 "==> [%05d] %s, from (%s)\n", 165 "==> [%05d] %s, from (%s)\n",
168 header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag)); 166 header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag));
169 167
170 if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) { 168 if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) {
171 if (!qd->logged_in) { /* packets before login */ 169 if (!qd->logged_in) { /* packets before login */
172 b4_packet = g_new0(packet_before_login, 1); 170 b4_packet = g_new0(packet_before_login, 1);
173 /* must duplicate, buffer will be freed after exiting this function */ 171 /* must duplicate, buffer will be freed after exiting this function */
178 g_queue_push_head(qd->before_login_packets, b4_packet); 176 g_queue_push_head(qd->before_login_packets, b4_packet);
179 return; /* do not process it now */ 177 return; /* do not process it now */
180 } else if (!g_queue_is_empty(qd->before_login_packets)) { 178 } else if (!g_queue_is_empty(qd->before_login_packets)) {
181 /* logged_in, but we have packets before login */ 179 /* logged_in, but we have packets before login */
182 b4_packet = (packet_before_login *) 180 b4_packet = (packet_before_login *)
183 g_queue_pop_head(qd->before_login_packets); 181 g_queue_pop_head(qd->before_login_packets);
184 _qq_packet_process(b4_packet->buf, b4_packet->len, gc); 182 _qq_packet_process(b4_packet->buf, b4_packet->len, gc);
185 /* in fact this is a recursive call, 183 /* in fact this is a recursive call,
186 * all packets before login will be processed before goes on */ 184 * all packets before login will be processed before goes on */
187 g_free(b4_packet->buf); /* the buf is duplicated, need to be freed */ 185 g_free(b4_packet->buf); /* the buf is duplicated, need to be freed */
188 g_free(b4_packet); 186 g_free(b4_packet);
189 } 187 }
190 } 188 }
191 189
192 /* this is the length of all the encrypted data (also remove tail tag */ 190 /* this is the length of all the encrypted data (also remove tail tag */
193 len = buf_len - (bytes_read) - 1; 191 bytes_notread = buf_len - bytes - 1;
194 192
195 /* whether it is an ack */ 193 /* whether it is an ack */
196 switch (header.cmd) { 194 switch (header.cmd) {
197 case QQ_CMD_RECV_IM: 195 case QQ_CMD_RECV_IM:
198 case QQ_CMD_RECV_MSG_SYS: 196 case QQ_CMD_RECV_MSG_SYS:
199 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS: 197 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
200 /* server intiated packet, we need to send ack and check duplicaion 198 /* server intiated packet, we need to send ack and check duplicaion
201 * this must be put after processing b4_packet 199 * this must be put after processing b4_packet
202 * as these packets will be passed in twice */ 200 * as these packets will be passed in twice */
203 if (_qq_check_packet_set_window(header.seq, gc)) { 201 if (_qq_check_packet_set_window(header.seq, gc)) {
204 purple_debug(PURPLE_DEBUG_WARNING, 202 purple_debug(PURPLE_DEBUG_WARNING,
205 "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd)); 203 "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd));
206 return; 204 return;
207 } 205 }
208 break; 206 break;
209 default:{ /* ack packet, we need to update sendqueue */ 207 default:{ /* ack packet, we need to update sendqueue */
210 /* we do not check duplication for server ack */ 208 /* we do not check duplication for server ack */
211 qq_sendqueue_remove(qd, header.seq); 209 qq_sendqueue_remove(qd, header.seq);
212 if (QQ_DEBUG) 210 if (QQ_DEBUG)
213 purple_debug(PURPLE_DEBUG_INFO, "QQ", 211 purple_debug(PURPLE_DEBUG_INFO, "QQ",
214 "ack [%05d] %s, remove from sendqueue\n", 212 "ack [%05d] %s, remove from sendqueue\n",
215 header.seq, qq_get_cmd_desc(header.cmd)); 213 header.seq, qq_get_cmd_desc(header.cmd));
216 } 214 }
217 } 215 }
218 216
219 /* now process the packet */ 217 /* now process the packet */
220 switch (header.cmd) { 218 switch (header.cmd) {
221 case QQ_CMD_KEEP_ALIVE: 219 case QQ_CMD_KEEP_ALIVE:
222 qq_process_keep_alive_reply(cursor, len, gc); 220 qq_process_keep_alive_reply(buf + bytes, bytes_notread, gc);
223 break; 221 break;
224 case QQ_CMD_UPDATE_INFO: 222 case QQ_CMD_UPDATE_INFO:
225 qq_process_modify_info_reply(cursor, len, gc); 223 qq_process_modify_info_reply(buf + bytes, bytes_notread, gc);
226 break; 224 break;
227 case QQ_CMD_ADD_FRIEND_WO_AUTH: 225 case QQ_CMD_ADD_FRIEND_WO_AUTH:
228 qq_process_add_buddy_reply(cursor, len, header.seq, gc); 226 qq_process_add_buddy_reply(buf + bytes, bytes_notread, header.seq, gc);
229 break; 227 break;
230 case QQ_CMD_DEL_FRIEND: 228 case QQ_CMD_DEL_FRIEND:
231 qq_process_remove_buddy_reply(cursor, len, gc); 229 qq_process_remove_buddy_reply(buf + bytes, bytes_notread, gc);
232 break; 230 break;
233 case QQ_CMD_REMOVE_SELF: 231 case QQ_CMD_REMOVE_SELF:
234 qq_process_remove_self_reply(cursor, len, gc); 232 qq_process_remove_self_reply(buf + bytes, bytes_notread, gc);
235 break; 233 break;
236 case QQ_CMD_BUDDY_AUTH: 234 case QQ_CMD_BUDDY_AUTH:
237 qq_process_add_buddy_auth_reply(cursor, len, gc); 235 qq_process_add_buddy_auth_reply(buf + bytes, bytes_notread, gc);
238 break; 236 break;
239 case QQ_CMD_GET_USER_INFO: 237 case QQ_CMD_GET_USER_INFO:
240 qq_process_get_info_reply(cursor, len, gc); 238 qq_process_get_info_reply(buf + bytes, bytes_notread, gc);
241 break; 239 break;
242 case QQ_CMD_CHANGE_ONLINE_STATUS: 240 case QQ_CMD_CHANGE_ONLINE_STATUS:
243 qq_process_change_status_reply(cursor, len, gc); 241 qq_process_change_status_reply(buf + bytes, bytes_notread, gc);
244 break; 242 break;
245 case QQ_CMD_SEND_IM: 243 case QQ_CMD_SEND_IM:
246 qq_process_send_im_reply(cursor, len, gc); 244 qq_process_send_im_reply(buf + bytes, bytes_notread, gc);
247 break; 245 break;
248 case QQ_CMD_RECV_IM: 246 case QQ_CMD_RECV_IM:
249 qq_process_recv_im(cursor, len, header.seq, gc); 247 qq_process_recv_im(buf + bytes, bytes_notread, header.seq, gc);
250 break; 248 break;
251 case QQ_CMD_LOGIN: 249 case QQ_CMD_LOGIN:
252 qq_process_login_reply(cursor, len, gc); 250 qq_process_login_reply(buf + bytes, bytes_notread, gc);
253 break; 251 break;
254 case QQ_CMD_GET_FRIENDS_LIST: 252 case QQ_CMD_GET_FRIENDS_LIST:
255 qq_process_get_buddies_list_reply(cursor, len, gc); 253 qq_process_get_buddies_list_reply(buf + bytes, bytes_notread, gc);
256 break; 254 break;
257 case QQ_CMD_GET_FRIENDS_ONLINE: 255 case QQ_CMD_GET_FRIENDS_ONLINE:
258 qq_process_get_buddies_online_reply(cursor, len, gc); 256 qq_process_get_buddies_online_reply(buf + bytes, bytes_notread, gc);
259 break; 257 break;
260 case QQ_CMD_GROUP_CMD: 258 case QQ_CMD_GROUP_CMD:
261 qq_process_group_cmd_reply(cursor, len, header.seq, gc); 259 qq_process_group_cmd_reply(buf + bytes, bytes_notread, header.seq, gc);
262 break; 260 break;
263 case QQ_CMD_GET_ALL_LIST_WITH_GROUP: 261 case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
264 qq_process_get_all_list_with_group_reply(cursor, len, gc); 262 qq_process_get_all_list_with_group_reply(buf + bytes, bytes_notread, gc);
265 break; 263 break;
266 case QQ_CMD_GET_LEVEL: 264 case QQ_CMD_GET_LEVEL:
267 qq_process_get_level_reply(cursor, len, gc); 265 qq_process_get_level_reply(buf + bytes, bytes_notread, gc);
268 break; 266 break;
269 case QQ_CMD_REQUEST_LOGIN_TOKEN: 267 case QQ_CMD_REQUEST_LOGIN_TOKEN:
270 qq_process_request_login_token_reply(cursor, len, gc); 268 qq_process_request_login_token_reply(buf + bytes, bytes_notread, gc);
271 break; 269 break;
272 case QQ_CMD_RECV_MSG_SYS: 270 case QQ_CMD_RECV_MSG_SYS:
273 qq_process_msg_sys(cursor, len, header.seq, gc); 271 qq_process_msg_sys(buf + bytes, bytes_notread, header.seq, gc);
274 break; 272 break;
275 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS: 273 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
276 qq_process_friend_change_status(cursor, len, gc); 274 qq_process_friend_change_status(buf + bytes, bytes_notread, gc);
277 break; 275 break;
278 default: 276 default:
279 _qq_process_packet_default(cursor, len, header.cmd, header.seq, gc); 277 _qq_process_packet_default(buf + bytes, bytes_notread, header.cmd, header.seq, gc);
280 break; 278 break;
281 } 279 }
282 } 280 }
283 281
284 /* clean up the packets before login */ 282 /* clean up the packets before login */
285 void qq_b4_packets_free(qq_data *qd) 283 void qq_b4_packets_free(qq_data *qd)
305 303
306 gc = (PurpleConnection *) data; 304 gc = (PurpleConnection *) data;
307 305
308 if(cond != PURPLE_INPUT_READ) { 306 if(cond != PURPLE_INPUT_READ) {
309 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 307 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
310 _("Socket error")); 308 _("Socket error"));
311 return; 309 return;
312 } 310 }
313 311
314 qd = (qq_data *) gc->proto_data; 312 qd = (qq_data *) gc->proto_data;
315 buf = g_newa(guint8, MAX_PACKET_SIZE); 313 buf = g_newa(guint8, MAX_PACKET_SIZE);
316 314
317 /* here we have UDP proxy suppport */ 315 /* here we have UDP proxy suppport */
318 len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE); 316 len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE);
319 if (len <= 0) { 317 if (len <= 0) {
320 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 318 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
321 _("Unable to read from socket")); 319 _("Unable to read from socket"));
322 return; 320 return;
323 } else { 321 } else {
324 _qq_packet_process(buf, len, gc); 322 _qq_packet_process(buf, len, gc);
325 } 323 }
326 } 324 }

mercurial