Mercurial > pidgin
comparison libpurple/protocols/qq/qq_base.c @ 24095:25f62d21b3f8
disapproval of revision '8cebefbc6cd5d84acb69c74e69e8821f11dd225d'
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Mon, 15 Sep 2008 03:04:07 +0000 |
parents | 147ada94a1d8 |
children | bcfc98c7a55f |
comparison
equal
deleted
inserted
replaced
24088:147ada94a1d8 | 24095:25f62d21b3f8 |
---|---|
46 /* for QQ 2003iii 0117, fixed value */ | 46 /* for QQ 2003iii 0117, fixed value */ |
47 /* static const guint8 login_23_51[29] = { | 47 /* static const guint8 login_23_51[29] = { |
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
49 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20, | 49 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20, |
50 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13, | 50 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13, |
51 0x95, 0x67, 0xda, 0x2c, 0x01 | 51 0x95, 0x67, 0xda, 0x2c, 0x01 |
52 }; */ | 52 }; */ |
53 | 53 |
54 /* for QQ 2003iii 0304, fixed value */ | 54 /* for QQ 2003iii 0304, fixed value */ |
55 /* | 55 /* |
56 static const guint8 login_23_51[29] = { | 56 static const guint8 login_23_51[29] = { |
137 /* generate a md5 key using uid and session_key */ | 137 /* generate a md5 key using uid and session_key */ |
138 static void get_session_md5(guint8 *session_md5, guint32 uid, guint8 *session_key) | 138 static void get_session_md5(guint8 *session_md5, guint32 uid, guint8 *session_key) |
139 { | 139 { |
140 guint8 src[QQ_KEY_LENGTH + QQ_KEY_LENGTH]; | 140 guint8 src[QQ_KEY_LENGTH + QQ_KEY_LENGTH]; |
141 gint bytes = 0; | 141 gint bytes = 0; |
142 | 142 |
143 bytes += qq_put32(src + bytes, uid); | 143 bytes += qq_put32(src + bytes, uid); |
144 bytes += qq_putdata(src + bytes, session_key, QQ_KEY_LENGTH); | 144 bytes += qq_putdata(src + bytes, session_key, QQ_KEY_LENGTH); |
145 | 145 |
146 qq_get_md5(session_md5, QQ_KEY_LENGTH, src, bytes); | 146 qq_get_md5(session_md5, QQ_KEY_LENGTH, src, bytes); |
147 } | 147 } |
159 | 159 |
160 /* 000-000: reply code */ | 160 /* 000-000: reply code */ |
161 bytes += qq_get8(&lrop.result, data + bytes); | 161 bytes += qq_get8(&lrop.result, data + bytes); |
162 /* 001-016: session key */ | 162 /* 001-016: session key */ |
163 bytes += qq_getdata(lrop.session_key, sizeof(lrop.session_key), data + bytes); | 163 bytes += qq_getdata(lrop.session_key, sizeof(lrop.session_key), data + bytes); |
164 purple_debug_info("QQ", "Got session_key\n"); | 164 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Got session_key\n"); |
165 /* 017-020: login uid */ | 165 /* 017-020: login uid */ |
166 bytes += qq_get32(&lrop.uid, data + bytes); | 166 bytes += qq_get32(&lrop.uid, data + bytes); |
167 /* 021-024: server detected user public IP */ | 167 /* 021-024: server detected user public IP */ |
168 bytes += qq_getIP(&lrop.client_ip, data + bytes); | 168 bytes += qq_getIP(&lrop.client_ip, data + bytes); |
169 /* 025-026: server detected user port */ | 169 /* 025-026: server detected user port */ |
198 bytes += qq_getime(&lrop.last_login_time, data + bytes); | 198 bytes += qq_getime(&lrop.last_login_time, data + bytes); |
199 /* 131-138: 8 bytes unknown */ | 199 /* 131-138: 8 bytes unknown */ |
200 bytes += qq_getdata((guint8 *) &lrop.unknown6, 8, data + bytes); | 200 bytes += qq_getdata((guint8 *) &lrop.unknown6, 8, data + bytes); |
201 | 201 |
202 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ | 202 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ |
203 purple_debug_warning("QQ", | 203 purple_debug(PURPLE_DEBUG_WARNING, "QQ", |
204 "Fail parsing login info, expect %d bytes, read %d bytes\n", | 204 "Fail parsing login info, expect %d bytes, read %d bytes\n", |
205 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); | 205 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); |
206 } /* but we still go on as login OK */ | 206 } /* but we still go on as login OK */ |
207 | 207 |
208 memcpy(qd->session_key, lrop.session_key, sizeof(qd->session_key)); | 208 memcpy(qd->session_key, lrop.session_key, sizeof(qd->session_key)); |
209 get_session_md5(qd->session_md5, qd->uid, qd->session_key); | 209 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
210 | 210 |
211 qd->my_ip.s_addr = lrop.client_ip.s_addr; | 211 qd->my_ip.s_addr = lrop.client_ip.s_addr; |
212 | 212 |
213 qd->my_port = lrop.client_port; | 213 qd->my_port = lrop.client_port; |
214 qd->login_time = lrop.login_time; | 214 qd->login_time = lrop.login_time; |
215 qd->last_login_time = lrop.last_login_time; | 215 qd->last_login_time = lrop.last_login_time; |
216 qd->last_login_ip = g_strdup( inet_ntoa(lrop.last_client_ip) ); | 216 qd->last_login_ip = g_strdup( inet_ntoa(lrop.last_client_ip) ); |
217 | 217 |
235 bytes += qq_getIP(&lrrp.new_server_ip, data + bytes); | 235 bytes += qq_getIP(&lrrp.new_server_ip, data + bytes); |
236 /* 009-010: redirected new server port */ | 236 /* 009-010: redirected new server port */ |
237 bytes += qq_get16(&lrrp.new_server_port, data + bytes); | 237 bytes += qq_get16(&lrrp.new_server_port, data + bytes); |
238 | 238 |
239 if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { | 239 if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { |
240 purple_debug_error("QQ", | 240 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
241 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", | 241 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", |
242 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); | 242 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); |
243 return QQ_LOGIN_REPLY_ERR_MISC; | 243 return QQ_LOGIN_REPLY_ERR_MISC; |
244 } | 244 } |
245 | 245 |
246 /* redirect to new server, do not disconnect or connect here | 246 /* redirect to new server, do not disconnect or connect here |
247 * those connect should be called at packet_process */ | 247 * those connect should be called at packet_process */ |
248 qd->redirect_ip.s_addr = lrrp.new_server_ip.s_addr; | 248 if (qd->real_hostname) { |
249 qd->redirect_port = lrrp.new_server_port; | 249 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); |
250 g_free(qd->real_hostname); | |
251 qd->real_hostname = NULL; | |
252 } | |
253 qd->real_hostname = g_strdup( inet_ntoa(lrrp.new_server_ip) ); | |
254 qd->real_port = lrrp.new_server_port; | |
255 | |
250 return QQ_LOGIN_REPLY_REDIRECT; | 256 return QQ_LOGIN_REPLY_REDIRECT; |
257 } | |
258 | |
259 /* process login reply which says wrong password */ | |
260 static gint8 process_login_wrong_pwd(PurpleConnection *gc, guint8 *data, gint len) | |
261 { | |
262 gchar *server_reply, *server_reply_utf8; | |
263 server_reply = g_new0(gchar, len); | |
264 g_memmove(server_reply, data + 1, len - 1); | |
265 server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); | |
266 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Wrong password, server msg in UTF8: %s\n", server_reply_utf8); | |
267 g_free(server_reply); | |
268 g_free(server_reply_utf8); | |
269 | |
270 return QQ_LOGIN_REPLY_ERR_PWD; | |
251 } | 271 } |
252 | 272 |
253 /* request before login */ | 273 /* request before login */ |
254 void qq_send_packet_token(PurpleConnection *gc) | 274 void qq_send_packet_token(PurpleConnection *gc) |
255 { | 275 { |
259 | 279 |
260 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | 280 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
261 qd = (qq_data *) gc->proto_data; | 281 qd = (qq_data *) gc->proto_data; |
262 | 282 |
263 bytes += qq_put8(buf + bytes, 0); | 283 bytes += qq_put8(buf + bytes, 0); |
264 | 284 |
265 qd->send_seq++; | 285 qd->send_seq++; |
266 qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN, qd->send_seq, buf, bytes, TRUE); | 286 qq_send_data(qd, QQ_CMD_TOKEN, qd->send_seq, TRUE, buf, bytes); |
267 } | 287 } |
268 | 288 |
269 /* send login packet to QQ server */ | 289 /* send login packet to QQ server */ |
270 void qq_send_packet_login(PurpleConnection *gc) | 290 void qq_send_packet_login(PurpleConnection *gc) |
271 { | 291 { |
290 | 310 |
291 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); | 311 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); |
292 memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); | 312 memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); |
293 | 313 |
294 encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ | 314 encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ |
295 | 315 |
296 bytes = 0; | 316 bytes = 0; |
297 /* now generate the encrypted data | 317 /* now generate the encrypted data |
298 * 000-015 use password_twice_md5 as key to encrypt empty string */ | 318 * 000-015 use password_twice_md5 as key to encrypt empty string */ |
299 encrypted_len = qq_encrypt(raw_data + bytes, (guint8 *) "", 0, qd->password_twice_md5); | 319 encrypted_len = qq_encrypt(raw_data + bytes, (guint8 *) "", 0, qd->password_twice_md5); |
300 g_return_if_fail(encrypted_len == 16); | 320 g_return_if_fail(encrypted_len == 16); |
301 bytes += encrypted_len; | 321 bytes += encrypted_len; |
302 | 322 |
303 /* 016-016 */ | 323 /* 016-016 */ |
304 bytes += qq_put8(raw_data + bytes, 0x00); | 324 bytes += qq_put8(raw_data + bytes, 0x00); |
305 /* 017-020, used to be IP, now zero */ | 325 /* 017-020, used to be IP, now zero */ |
306 bytes += qq_put32(raw_data + bytes, 0x00000000); | 326 bytes += qq_put32(raw_data + bytes, 0x00000000); |
307 /* 021-022, used to be port, now zero */ | 327 /* 021-022, used to be port, now zero */ |
327 bytes = 0; | 347 bytes = 0; |
328 bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH); | 348 bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH); |
329 bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len); | 349 bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len); |
330 | 350 |
331 qd->send_seq++; | 351 qd->send_seq++; |
332 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); | 352 qq_send_data(qd, QQ_CMD_LOGIN, qd->send_seq, TRUE, buf, bytes); |
333 } | 353 } |
334 | 354 |
335 guint8 qq_process_token_reply(PurpleConnection *gc, guint8 *buf, gint buf_len) | 355 guint8 qq_process_token_reply(PurpleConnection *gc, gchar *error_msg, guint8 *buf, gint buf_len) |
336 { | 356 { |
337 qq_data *qd; | 357 qq_data *qd; |
338 guint8 ret; | 358 guint8 ret; |
339 int token_len; | 359 int token_len; |
340 gchar *error_msg; | |
341 | 360 |
342 g_return_val_if_fail(buf != NULL && buf_len != 0, -1); | 361 g_return_val_if_fail(buf != NULL && buf_len != 0, -1); |
343 | 362 |
344 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); | 363 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); |
345 qd = (qq_data *) gc->proto_data; | 364 qd = (qq_data *) gc->proto_data; |
346 | 365 |
347 ret = buf[0]; | 366 ret = buf[0]; |
348 | 367 |
349 if (ret != QQ_TOKEN_REPLY_OK) { | 368 if (ret != QQ_TOKEN_REPLY_OK) { |
350 purple_debug_error("QQ", "Failed to request token: %d\n", buf[0]); | 369 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown request login token reply code : %d\n", buf[0]); |
351 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", | 370 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", |
352 buf, buf_len, | 371 buf, buf_len, |
353 ">>> [default] decrypt and dump"); | 372 ">>> [default] decrypt and dump"); |
354 error_msg = try_dump_as_gbk(buf, buf_len); | 373 error_msg = try_dump_as_gbk(buf, buf_len); |
355 if (error_msg == NULL) { | |
356 error_msg = g_strdup_printf( _("Invalid token reply code, 0x%02X"), ret); | |
357 } | |
358 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); | |
359 g_free(error_msg); | |
360 return ret; | 374 return ret; |
361 } | 375 } |
362 | 376 |
363 token_len = buf_len-2; | 377 token_len = buf_len-2; |
364 if (token_len <= 0) { | 378 if (token_len <= 0) { |
365 error_msg = g_strdup_printf( _("Invalid token len, %d"), token_len); | 379 error_msg = g_strdup_printf( _("Invalid token len, %d"), token_len); |
366 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); | |
367 g_free(error_msg); | |
368 return -1; | 380 return -1; |
369 } | 381 } |
370 | 382 |
371 if (buf[1] != token_len) { | 383 if (buf[1] != token_len) { |
372 purple_debug_info("QQ", | 384 purple_debug(PURPLE_DEBUG_INFO, "QQ", |
373 "Invalid token len. Packet specifies length of %d, actual length is %d\n", buf[1], buf_len-2); | 385 "Invalid token len. Packet specifies length of %d, actual length is %d\n", buf[1], buf_len-2); |
374 } | 386 } |
375 qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", | 387 qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", |
376 buf+2, token_len, | 388 buf+2, token_len, |
377 "<<< got a token -> [default] decrypt and dump"); | 389 "<<< got a token -> [default] decrypt and dump"); |
378 | 390 |
379 qd->token = g_new0(guint8, token_len); | 391 qd->token = g_new0(guint8, token_len); |
380 qd->token_len = token_len; | 392 qd->token_len = token_len; |
381 g_memmove(qd->token, buf + 2, qd->token_len); | 393 g_memmove(qd->token, buf + 2, qd->token_len); |
382 return ret; | 394 return ret; |
383 } | 395 } |
388 gint i; | 400 gint i; |
389 qq_data *qd; | 401 qq_data *qd; |
390 | 402 |
391 qd = (qq_data *) gc->proto_data; | 403 qd = (qq_data *) gc->proto_data; |
392 for (i = 0; i < 4; i++) | 404 for (i = 0; i < 4; i++) |
393 qq_send_cmd(gc, QQ_CMD_LOGOUT, qd->password_twice_md5, QQ_KEY_LENGTH); | 405 qq_send_cmd_detail(qd, QQ_CMD_LOGOUT, 0xffff, FALSE, qd->password_twice_md5, QQ_KEY_LENGTH); |
394 | 406 |
395 qd->is_login = FALSE; /* update login status AFTER sending logout packets */ | 407 qd->logged_in = FALSE; /* update login status AFTER sending logout packets */ |
396 } | 408 } |
397 | 409 |
398 /* process the login reply packet */ | 410 /* process the login reply packet */ |
399 guint8 qq_process_login_reply( PurpleConnection *gc, guint8 *data, gint data_len) | 411 guint8 qq_process_login_reply(guint8 *data, gint data_len, PurpleConnection *gc) |
400 { | 412 { |
401 qq_data *qd; | 413 qq_data *qd; |
402 guint8 ret = data[0]; | 414 gchar* error_msg; |
403 gchar *server_reply, *server_reply_utf8; | |
404 gchar *error_msg; | |
405 | 415 |
406 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR_MISC); | 416 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR_MISC); |
407 | 417 |
408 qd = (qq_data *) gc->proto_data; | 418 qd = (qq_data *) gc->proto_data; |
409 | 419 |
410 switch (ret) { | 420 switch (data[0]) { |
411 case QQ_LOGIN_REPLY_OK: | 421 case QQ_LOGIN_REPLY_OK: |
412 purple_debug_info("QQ", "Login OK\n"); | 422 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is OK\n"); |
413 return process_login_ok(gc, data, data_len); | 423 return process_login_ok(gc, data, data_len); |
414 case QQ_LOGIN_REPLY_REDIRECT: | 424 case QQ_LOGIN_REPLY_REDIRECT: |
415 purple_debug_info("QQ", "Redirect new server\n"); | 425 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is redirect\n"); |
416 return process_login_redirect(gc, data, data_len); | 426 return process_login_redirect(gc, data, data_len); |
417 | 427 case QQ_LOGIN_REPLY_ERR_PWD: |
428 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is error password\n"); | |
429 return process_login_wrong_pwd(gc, data, data_len); | |
430 case QQ_LOGIN_REPLY_NEED_REACTIVE: | |
418 case QQ_LOGIN_REPLY_REDIRECT_EX: | 431 case QQ_LOGIN_REPLY_REDIRECT_EX: |
419 purple_debug_error("QQ", "Extend redirect new server, not supported yet\n"); | 432 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is not actived or redirect extend\n"); |
420 error_msg = g_strdup( _("Unable login for not support Redirect_EX now") ); | 433 default: |
421 return QQ_LOGIN_REPLY_REDIRECT_EX; | 434 break; |
422 | 435 } |
423 case QQ_LOGIN_REPLY_ERR_PWD: | 436 |
424 server_reply = g_strndup((gchar *)data + 1, data_len - 1); | 437 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown reply code: 0x%02X\n", data[0]); |
425 server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); | 438 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", |
426 | 439 data, data_len, |
427 purple_debug_error("QQ", "Error password: %s\n", server_reply_utf8); | 440 ">>> [default] decrypt and dump"); |
428 error_msg = g_strdup_printf( _("Error password: %s"), server_reply_utf8); | 441 error_msg = try_dump_as_gbk(data, data_len); |
429 | 442 if (error_msg) { |
430 g_free(server_reply); | 443 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); |
431 g_free(server_reply_utf8); | |
432 | |
433 if (!purple_account_get_remember_password(gc->account)) { | |
434 purple_account_set_password(gc->account, NULL); | |
435 } | |
436 | |
437 purple_connection_error_reason(gc, | |
438 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, error_msg); | |
439 g_free(error_msg); | 444 g_free(error_msg); |
440 | 445 } |
441 return QQ_LOGIN_REPLY_ERR_PWD; | 446 return QQ_LOGIN_REPLY_ERR_MISC; |
442 | |
443 case QQ_LOGIN_REPLY_NEED_REACTIVE: | |
444 server_reply = g_strndup((gchar *)data + 1, data_len - 1); | |
445 server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); | |
446 | |
447 purple_debug_error("QQ", "Need active: %s\n", server_reply_utf8); | |
448 error_msg = g_strdup_printf( _("Need active: %s"), server_reply_utf8); | |
449 | |
450 g_free(server_reply); | |
451 g_free(server_reply_utf8); | |
452 break; | |
453 | |
454 default: | |
455 purple_debug_error("QQ", | |
456 "Unable login for unknow reply code 0x%02X\n", data[0]); | |
457 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", | |
458 data, data_len, | |
459 ">>> [default] decrypt and dump"); | |
460 error_msg = try_dump_as_gbk(data, data_len); | |
461 if (error_msg == NULL) { | |
462 error_msg = g_strdup_printf( | |
463 _("Unable login for unknow reply code 0x%02X"), data[0] ); | |
464 } | |
465 break; | |
466 } | |
467 | |
468 purple_connection_error_reason(gc, | |
469 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); | |
470 g_free(error_msg); | |
471 return ret; | |
472 } | 447 } |
473 | 448 |
474 /* send keep-alive packet to QQ server (it is a heart-beat) */ | 449 /* send keep-alive packet to QQ server (it is a heart-beat) */ |
475 void qq_send_packet_keep_alive(PurpleConnection *gc) | 450 void qq_send_packet_keep_alive(PurpleConnection *gc) |
476 { | 451 { |
483 /* In fact, we can send whatever we like to server | 458 /* In fact, we can send whatever we like to server |
484 * with this command, server return the same result including | 459 * with this command, server return the same result including |
485 * the amount of online QQ users, my ip and port */ | 460 * the amount of online QQ users, my ip and port */ |
486 bytes += qq_put32(raw_data + bytes, qd->uid); | 461 bytes += qq_put32(raw_data + bytes, qd->uid); |
487 | 462 |
488 qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, 4); | 463 qq_send_cmd(qd, QQ_CMD_KEEP_ALIVE, raw_data, 4); |
489 } | 464 } |
490 | 465 |
491 /* parse the return of keep-alive packet, it includes some system information */ | 466 /* parse the return of keep-alive packet, it includes some system information */ |
492 gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc) | 467 gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc) |
493 { | 468 { |
494 qq_data *qd; | 469 qq_data *qd; |
495 gchar **segments; | 470 gchar **segments; |
496 | 471 |
497 g_return_val_if_fail(data != NULL && data_len != 0, FALSE); | 472 g_return_val_if_fail(data != NULL && data_len != 0, FALSE); |
501 /* qq_show_packet("Keep alive reply packet", data, len); */ | 476 /* qq_show_packet("Keep alive reply packet", data, len); */ |
502 | 477 |
503 /* the last one is 60, don't know what it is */ | 478 /* the last one is 60, don't know what it is */ |
504 if (NULL == (segments = split_data(data, data_len, "\x1f", 6))) | 479 if (NULL == (segments = split_data(data, data_len, "\x1f", 6))) |
505 return TRUE; | 480 return TRUE; |
506 | 481 |
507 /* segments[0] and segment[1] are all 0x30 ("0") */ | 482 /* segments[0] and segment[1] are all 0x30 ("0") */ |
508 qd->total_online = strtol(segments[2], NULL, 10); | 483 qd->total_online = strtol(segments[2], NULL, 10); |
509 if(0 == qd->total_online) { | 484 if(0 == qd->total_online) { |
510 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 485 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
511 _("Keep alive error")); | 486 _("Keep alive error")); |
512 } | 487 } |
513 qd->my_ip.s_addr = inet_addr(segments[3]); | 488 qd->my_ip.s_addr = inet_addr(segments[3]); |
514 qd->my_port = strtol(segments[4], NULL, 10); | 489 qd->my_port = strtol(segments[4], NULL, 10); |
515 | 490 |
516 purple_debug_info("QQ", "keep alive, %s:%d\n", | 491 purple_debug(PURPLE_DEBUG_INFO, "QQ", "keep alive, %s:%d\n", |
517 inet_ntoa(qd->my_ip), qd->my_port); | 492 inet_ntoa(qd->my_ip), qd->my_port); |
518 | 493 |
519 g_strfreev(segments); | 494 g_strfreev(segments); |
520 return TRUE; | 495 return TRUE; |
521 } | 496 } |