pidgin.2.4.3: a6a8a0f2: patch-05-reconnect-and-code-cleanup
csyfek at gmail.com
csyfek at gmail.com
Tue Jun 24 08:41:06 EDT 2008
-----------------------------------------------------------------
Revision: a6a8a0f2b45006944916446be22cb8e56f0fca3f
Ancestor: fcd04238bea0560e8077f1f3f052119c00305e5f
Author: csyfek at gmail.com
Date: 2008-06-24T12:28:38
Branch: im.pidgin.pidgin.2.4.3
URL: http://d.pidgin.im/viewmtn/revision/info/a6a8a0f2b45006944916446be22cb8e56f0fca3f
Deleted entries:
libpurple/protocols/qq/sendqueue.c
libpurple/protocols/qq/sendqueue.h
Added files:
libpurple/protocols/qq/qq_trans.c
libpurple/protocols/qq/qq_trans.h
Modified files:
libpurple/protocols/qq/ChangeLog
libpurple/protocols/qq/Makefile.am
libpurple/protocols/qq/Makefile.mingw
libpurple/protocols/qq/buddy_info.c
libpurple/protocols/qq/buddy_list.c
libpurple/protocols/qq/buddy_opt.c
libpurple/protocols/qq/buddy_status.c
libpurple/protocols/qq/group_im.c
libpurple/protocols/qq/group_im.h
libpurple/protocols/qq/group_network.c
libpurple/protocols/qq/im.c
libpurple/protocols/qq/keep_alive.c
libpurple/protocols/qq/login_logout.c
libpurple/protocols/qq/packet_parse.c
libpurple/protocols/qq/packet_parse.h
libpurple/protocols/qq/qq.c libpurple/protocols/qq/qq.h
libpurple/protocols/qq/qq_network.c
libpurple/protocols/qq/qq_network.h
libpurple/protocols/qq/send_file.c
libpurple/protocols/qq/sys_msg.c
libpurple/protocols/qq/utils.c
ChangeLog:
patch-05-reconnect-and-code-cleanup
-------------- next part --------------
============================================================
--- libpurple/protocols/qq/qq_trans.c f88e7f28beaef9d40a60caac32d0eac9ab81730f
+++ libpurple/protocols/qq/qq_trans.c f88e7f28beaef9d40a60caac32d0eac9ab81730f
@@ -0,0 +1,246 @@
+/**
+ * @file qq_trans.c
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "internal.h"
+
+#include "connection.h"
+#include "debug.h"
+#include "notify.h"
+#include "prefs.h"
+#include "request.h"
+
+#include "header_info.h"
+#include "qq_network.h"
+#include "qq_trans.h"
+
+#define QQ_RESEND_MAX 8 /* max resend per packet */
+
+typedef struct _transaction {
+ guint16 seq;
+ guint16 cmd;
+ guint8 *buf;
+ gint buf_len;
+
+ gint fd;
+ gint retries;
+ time_t create_time;
+} transaction;
+
+void qq_send_trans_append(qq_data *qd, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq)
+{
+ transaction *trans = g_new0(transaction, 1);
+
+ g_return_if_fail(trans != NULL);
+
+ trans->fd = qd->fd;
+ trans->cmd = cmd;
+ trans->seq = seq;
+ trans->retries = QQ_RESEND_MAX;
+ trans->create_time = time(NULL);
+ trans->buf = g_memdup(buf, buf_len); /* don't use g_strdup, may have 0x00 */
+ trans->buf_len = buf_len;
+
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Add to transaction, seq = %d, buf = %p, len = %d\n",
+ trans->seq, trans->buf, trans->buf_len);
+ qd->send_trans = g_list_append(qd->send_trans, trans);
+}
+
+/* Remove a packet with seq from send trans */
+void qq_send_trans_remove(qq_data *qd, gpointer data)
+{
+ transaction *trans = (transaction *)data;
+
+ g_return_if_fail(qd != NULL && data != NULL);
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "ack [%05d] %s, remove from send tranactions\n",
+ trans->seq, qq_get_cmd_desc(trans->cmd));
+
+ if (trans->buf) g_free(trans->buf);
+ qd->send_trans = g_list_remove(qd->send_trans, trans);
+ g_free(trans);
+}
+
+gpointer qq_send_trans_find(qq_data *qd, guint16 seq)
+{
+ GList *curr;
+ GList *next;
+ transaction *trans;
+
+ curr = qd->send_trans;
+ while(curr) {
+ next = curr->next;
+ trans = (transaction *) (curr->data);
+ if(trans->seq == seq) {
+ return trans;
+ }
+ curr = next;
+ }
+
+ return NULL;
+}
+
+/* clean up send trans and free all contents */
+void qq_send_trans_remove_all(qq_data *qd)
+{
+ GList *curr;
+ GList *next;
+ transaction *trans;
+ gint count = 0;
+
+ curr = qd->send_trans;
+ while(curr) {
+ next = curr->next;
+
+ trans = (transaction *) (curr->data);
+ /*
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Remove to transaction, seq = %d, buf = %p, len = %d\n",
+ trans->seq, trans->buf, trans->len);
+ */
+ qq_send_trans_remove(qd, trans);
+
+ count++;
+ curr = next;
+ }
+ g_list_free(qd->send_trans);
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d packets in send tranactions are freed!\n", count);
+}
+
+gint qq_send_trans_scan(qq_data *qd, gint *start,
+ guint8 *buf, gint maxlen, guint16 *cmd, gint *retries)
+{
+ GList *curr;
+ GList *next = NULL;
+ transaction *trans;
+ gint copylen;
+
+ g_return_val_if_fail(qd != NULL && *start >= 0 && maxlen > 0, -1);
+
+ /* purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Scan from %d\n", *start); */
+ curr = g_list_nth(qd->send_trans, *start);
+ while(curr) {
+ next = curr->next;
+ *start = g_list_position(qd->send_trans, next);
+
+ trans = (transaction *) (curr->data);
+ if (trans->buf == NULL || trans->buf_len <= 0) {
+ qq_send_trans_remove(qd, trans);
+ curr = next;
+ continue;
+ }
+
+ if (trans->retries < 0) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Remove transaction, seq %d, buf %p, len %d, retries %d, next %d\n",
+ trans->seq, trans->buf, trans->buf_len, trans->retries, *start);
+ qq_send_trans_remove(qd, trans);
+ curr = next;
+ continue;
+ }
+
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Resend transaction, seq %d, buf %p, len %d, retries %d, next %d\n",
+ trans->seq, trans->buf, trans->buf_len, trans->retries, *start);
+ copylen = MIN(trans->buf_len, maxlen);
+ g_memmove(buf, trans->buf, copylen);
+
+ *cmd = trans->cmd;
+ *retries = trans->retries;
+ trans->retries--;
+ return copylen;
+ }
+
+ /* purple_debug(PURPLE_DEBUG_INFO, "QQ", "Scan finished\n"); */
+ return -1;
+}
+
+void qq_rcv_trans_push(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+{
+ transaction *trans = g_new0(transaction, 1);
+
+ g_return_if_fail(data != NULL && data_len > 0);
+ g_return_if_fail(trans != NULL);
+
+ trans->cmd = cmd;
+ trans->seq = seq;
+ trans->buf = g_memdup(data, data_len);
+ trans->buf_len = data_len;
+ trans->create_time = time(NULL);
+
+ if (qd->rcv_trans == NULL)
+ qd->rcv_trans = g_queue_new();
+
+ g_queue_push_head(qd->rcv_trans, trans);
+}
+
+gint qq_rcv_trans_pop(qq_data *qd, guint16 *cmd, guint16 *seq, guint8 *data, gint max_len)
+{
+ transaction *trans = NULL;
+ gint copy_len;
+
+ g_return_val_if_fail(data != NULL && max_len > 0, -1);
+
+ if (g_queue_is_empty(qd->rcv_trans)) {
+ return -1;
+ }
+ trans = (transaction *) g_queue_pop_head(qd->rcv_trans);
+ if (trans == NULL) {
+ return 0;
+ }
+ if (trans->buf == NULL || trans->buf_len <= 0) {
+ return 0;
+ }
+
+ copy_len = MIN(max_len, trans->buf_len);
+ g_memmove(data, trans->buf, copy_len);
+ *cmd = trans->cmd;
+ *seq = trans->seq;
+
+ g_free(trans->buf);
+ g_free(trans);
+ return copy_len;
+}
+
+/* clean up the packets before login */
+void qq_rcv_trans_remove_all(qq_data *qd)
+{
+ transaction *trans = NULL;
+ gint count = 0;
+
+ g_return_if_fail(qd != NULL);
+
+ /* now clean up my own data structures */
+ if (qd->rcv_trans != NULL) {
+ while (NULL != (trans = g_queue_pop_tail(qd->rcv_trans))) {
+ g_free(trans->buf);
+ g_free(trans);
+ count++;
+ }
+ g_queue_free(qd->rcv_trans);
+ }
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d packets in receive tranactions are freed!\n", count);
+}
============================================================
--- libpurple/protocols/qq/qq_trans.h 80f8f5efcf8181555ed864d4a9cf3ebcf93154c2
+++ libpurple/protocols/qq/qq_trans.h 80f8f5efcf8181555ed864d4a9cf3ebcf93154c2
@@ -0,0 +1,42 @@
+/**
+ * @file qq_trans.h
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef _QQ_SEND_QUEUE_H_
+#define _QQ_SEND_QUEUE_H_
+
+#include <glib.h>
+#include "qq.h"
+
+void qq_send_trans_append(qq_data *qd, guint8 *buf, gint bus_len, guint16 cmd, guint16 seq);
+void qq_send_trans_remove(qq_data *qd, gpointer data);
+gpointer qq_send_trans_find(qq_data *qd, guint16 seq);
+void qq_send_trans_remove_all(qq_data *qd);
+
+gint qq_send_trans_scan(qq_data *qd, gint *start, guint8 *buf, gint maxlen, guint16 *cmd, gint *retries);
+
+void qq_rcv_trans_push(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len);
+gint qq_rcv_trans_pop(qq_data *qd, guint16 *cmd, guint16* seq, guint8 *data, gint max_len);
+void qq_rcv_trans_remove_all(qq_data *qd);
+
+#endif
============================================================
--- libpurple/protocols/qq/ChangeLog c71777eb23741e23437cac84a09b8bb0bd8692cb
+++ libpurple/protocols/qq/ChangeLog 00098aecec67a7c79feb8f74898b88d600da9a33
@@ -1,3 +1,13 @@
+2008.06.07 - ccpaging <ecc_hy(at)hotmail.com>, csyfek <csyfek(at)gmail.com>
+ * Clean code and apply patches from QuLogic
+
+2008.05.19 - ccpaging <ecc_hy(at)hotmail.com>, csyfek <csyfek(at)gmail.com>
+ * Reconnect server 5 time in 5000 ms, when connect failed
+ * Rename sendqueue.c/sendqueue.h to qq_trans.c/qq_trans.h
+ * Rewrite packet_process
+ * Rewrite qq_send_cmd
+ * Create server list, try to connect every server when failed
+
2008.05.14 - ccpaging <ecc_hy(at)hotmail.com>
* Move function for before login packets storing to sendqueue
* Use transaction data structure to store before login packets
============================================================
--- libpurple/protocols/qq/Makefile.am 5f9cc460a8b169911e15ca4b55bbb68fd456acb7
+++ libpurple/protocols/qq/Makefile.am a9b20ab3e91464d161b7c78ba9cfc9d25bd1bcdc
@@ -56,8 +56,8 @@ QQSOURCES = \
qq_network.h \
send_file.c \
send_file.h \
- sendqueue.c \
- sendqueue.h \
+ qq_trans.c \
+ qq_trans.h \
sys_msg.c \
sys_msg.h \
utils.c \
============================================================
--- libpurple/protocols/qq/Makefile.mingw 0cd549b5aa0bb7745db1f61f3aa19b223f7a6e6a
+++ libpurple/protocols/qq/Makefile.mingw 23928c33a77a8e87581e0641e317e9314a2279b6
@@ -65,7 +65,7 @@ C_SRC = \
qq.c \
qq_network.c \
send_file.c \
- sendqueue.c \
+ qq_trans.c \
sys_msg.c \
utils.c
============================================================
--- libpurple/protocols/qq/buddy_info.c b7646da7a807e77ea2391025491833f5a0b2df52
+++ libpurple/protocols/qq/buddy_info.c 504fbb2f1055b3d5f890990f0b85351596e51722
@@ -283,7 +283,7 @@ void qq_send_packet_get_info(PurpleConne
qd = (qq_data *) gc->proto_data;
g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
- qq_send_cmd(gc, QQ_CMD_GET_USER_INFO, TRUE, 0, TRUE, (guint8 *) uid_str, strlen(uid_str));
+ qq_send_cmd(qd, QQ_CMD_GET_USER_INFO, (guint8 *) uid_str, strlen(uid_str));
query = g_new0(qq_info_query, 1);
query->uid = uid;
@@ -313,6 +313,7 @@ static void qq_send_packet_modify_info(P
/* send packet to modify personal information */
static void qq_send_packet_modify_info(PurpleConnection *gc, contact_info *info)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
gint bytes = 0;
guint8 raw_data[MAX_PACKET_SIZE - 128] = {0};
guint8 bar;
@@ -444,7 +445,7 @@ static void qq_send_packet_modify_info(P
bytes += qq_put8(raw_data + bytes, bar);
- qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_UPDATE_INFO, raw_data, bytes);
}
@@ -932,13 +933,15 @@ void qq_send_packet_get_level(PurpleConn
void qq_send_packet_get_level(PurpleConnection *gc, guint32 uid)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
guint8 buf[16] = {0};
gint bytes = 0;
bytes += qq_put8(buf + bytes, 0x00);
bytes += qq_put32(buf + bytes, uid);
- qq_send_cmd(gc, QQ_CMD_GET_LEVEL, TRUE, 0, TRUE, buf, bytes);
+ qd = (qq_data *) gc->proto_data;
+ qq_send_cmd(qd, QQ_CMD_GET_LEVEL, buf, bytes);
}
void qq_send_packet_get_buddies_levels(PurpleConnection *gc)
@@ -964,7 +967,7 @@ void qq_send_packet_get_buddies_levels(P
}
node = node->next;
}
- qq_send_cmd(gc, QQ_CMD_GET_LEVEL, TRUE, 0, TRUE, buf, size);
+ qq_send_cmd(qd, QQ_CMD_GET_LEVEL, buf, size);
g_free(buf);
}
}
============================================================
--- libpurple/protocols/qq/buddy_list.c fd6a60ef4a37d22cd31438bde3f338ba290bd2b8
+++ libpurple/protocols/qq/buddy_list.c 5a74ee6ca079793e853a137df42d507aa9897523
@@ -81,7 +81,7 @@ void qq_send_packet_get_buddies_online(P
/* 003-004 */
bytes += qq_put16(raw_data + bytes, 0x0000);
- qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_ONLINE, TRUE, 0, TRUE, raw_data, 5);
+ qq_send_cmd(qd, QQ_CMD_GET_FRIENDS_ONLINE, raw_data, 5);
qd->last_get_online = time(NULL);
}
@@ -89,6 +89,7 @@ void qq_send_packet_get_buddies_list(Pur
* server may return a position tag if list is too long for one packet */
void qq_send_packet_get_buddies_list(PurpleConnection *gc, guint16 position)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
guint8 raw_data[16] = {0};
gint bytes = 0;
@@ -101,12 +102,13 @@ void qq_send_packet_get_buddies_list(Pur
* March 22, found the 00,00,00 starts to work as well */
bytes += qq_put8(raw_data + bytes, 0x00);
- qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_LIST, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_GET_FRIENDS_LIST, raw_data, bytes);
}
/* get all list, buddies & Quns with groupsid support */
void qq_send_packet_get_all_list_with_group(PurpleConnection *gc, guint32 position)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
guint8 raw_data[16] = {0};
gint bytes = 0;
@@ -118,7 +120,7 @@ void qq_send_packet_get_all_list_with_gr
bytes += qq_put32(raw_data + bytes, 0x00000000);
bytes += qq_put32(raw_data + bytes, position);
- qq_send_cmd(gc, QQ_CMD_GET_ALL_LIST_WITH_GROUP, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_GET_ALL_LIST_WITH_GROUP, raw_data, bytes);
}
static void _qq_buddies_online_reply_dump_unclear(qq_friends_online_entry *fe)
============================================================
--- libpurple/protocols/qq/buddy_opt.c 19e35c2fca88964688857a8d3b9d2501e3d7f503
+++ libpurple/protocols/qq/buddy_opt.c 146cf2fc1c753795a8600427c2ebf102594a087d
@@ -61,18 +61,19 @@ static void _qq_send_packet_remove_buddy
/* send packet to remove a buddy from my buddy list */
static void _qq_send_packet_remove_buddy(PurpleConnection *gc, guint32 uid)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
gchar uid_str[11];
g_return_if_fail(uid > 0);
g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
- qq_send_cmd(gc, QQ_CMD_DEL_FRIEND, TRUE, 0,
- TRUE, (guint8 *) uid_str, strlen(uid_str));
+ qq_send_cmd(qd, QQ_CMD_DEL_FRIEND, (guint8 *) uid_str, strlen(uid_str));
}
/* try to remove myself from someone's buddy list */
static void _qq_send_packet_remove_self_from(PurpleConnection *gc, guint32 uid)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
guint8 raw_data[16] = {0};
gint bytes = 0;
@@ -80,13 +81,13 @@ static void _qq_send_packet_remove_self_
bytes += qq_put32(raw_data + bytes, uid);
- qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_REMOVE_SELF, raw_data, bytes);
}
/* try to add a buddy without authentication */
static void _qq_send_packet_add_buddy(PurpleConnection *gc, guint32 uid)
{
- qq_data *qd;
+ qq_data *qd = (qq_data *) gc->proto_data;
qq_add_buddy_request *req;
gchar uid_str[11];
@@ -94,11 +95,9 @@ static void _qq_send_packet_add_buddy(Pu
/* we need to send the ascii code of this uid to qq server */
g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
- qq_send_cmd(gc, QQ_CMD_ADD_FRIEND_WO_AUTH, TRUE, 0,
- TRUE, (guint8 *) uid_str, strlen(uid_str));
+ qq_send_cmd(qd, QQ_CMD_ADD_FRIEND_WO_AUTH, (guint8 *) uid_str, strlen(uid_str));
/* must be set after sending packet to get the correct send_seq */
- qd = (qq_data *) gc->proto_data;
req = g_new0(qq_add_buddy_request, 1);
req->seq = qd->send_seq;
req->uid = uid;
@@ -108,6 +107,7 @@ static void _qq_send_packet_buddy_auth(P
/* this buddy needs authentication, text conversion is done at lowest level */
static void _qq_send_packet_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text)
{
+ qq_data *qd = (qq_data *) gc->proto_data;
gchar *text_qq, uid_str[11];
guint8 bar, *raw_data;
gint bytes = 0;
@@ -129,7 +129,7 @@ static void _qq_send_packet_buddy_auth(P
g_free(text_qq);
}
- qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_BUDDY_AUTH, raw_data, bytes);
}
static void _qq_send_packet_add_buddy_auth_with_gc_and_uid(gc_and_uid *g, const gchar *text)
============================================================
--- libpurple/protocols/qq/buddy_status.c 0632ad56e2f8b1700583f2bec90d4b2655036141
+++ libpurple/protocols/qq/buddy_status.c 515b95f95274e31f9956938e55f12998ebc0e9fc
@@ -171,7 +171,7 @@ void qq_send_packet_change_status(Purple
bytes += qq_put8(raw_data + bytes, away_cmd);
bytes += qq_put32(raw_data + bytes, misc_status);
- qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_CHANGE_ONLINE_STATUS, raw_data, bytes);
}
/* parse the reply packet for change_status */
============================================================
--- libpurple/protocols/qq/group_im.c 78175de05126d2650ef372a672f84bb81ec6e833
+++ libpurple/protocols/qq/group_im.c 49ed251aa1f57b3bc77d439219c5cd39d6f52495
@@ -110,7 +110,7 @@ void qq_process_recv_group_im_apply_join
g_return_if_fail(internal_group_id > 0 && data != NULL && len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
bytes += qq_get32(&external_group_id, data + bytes);
bytes += qq_get8(&group_type, data + bytes);
@@ -160,7 +160,7 @@ void qq_process_recv_group_im_been_rejec
g_return_if_fail(data != NULL && len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
bytes += qq_get32(&external_group_id, data + bytes);
bytes += qq_get8(&group_type, data + bytes);
@@ -198,7 +198,7 @@ void qq_process_recv_group_im_been_appro
g_return_if_fail(data != NULL && len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
bytes += qq_get32(&external_group_id, data + bytes);
bytes += qq_get8(&group_type, data + bytes);
@@ -234,7 +234,7 @@ void qq_process_recv_group_im_been_remov
g_return_if_fail(data != NULL && len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
bytes += qq_get32(&external_group_id, data + bytes);
bytes += qq_get8(&group_type, data + bytes);
@@ -265,7 +265,7 @@ void qq_process_recv_group_im_been_added
g_return_if_fail(data != NULL && len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
bytes += qq_get32(&external_group_id, data + bytes);
bytes += qq_get8(&group_type, data + bytes);
@@ -307,7 +307,7 @@ void qq_process_recv_group_im(guint8 *da
g_return_if_fail(data != NULL && data_len > 0);
- // Fixme: check length here
+ /* FIXME: check length here */
qd = (qq_data *) gc->proto_data;
============================================================
--- libpurple/protocols/qq/group_im.h d5646d54d4a8ed98ecf599577163d475d0b4d66f
+++ libpurple/protocols/qq/group_im.h 7d1e2fc8b103b68c616a2e27ad10d129a052f1ad
@@ -31,30 +31,30 @@ void qq_send_packet_group_im(PurpleConne
void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar *msg);
-//void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+/* void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc); */
void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc);
-//void qq_process_recv_group_im(guint8 *data,
-// guint8 **cursor, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type);
+/* void qq_process_recv_group_im(guint8 *data, guint8 **cursor,
+ * gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type); */
void qq_process_recv_group_im(guint8 *data, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type);
-//void qq_process_recv_group_im_apply_join(guint8 *data,
-// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+/* void qq_process_recv_group_im_apply_join(guint8 *data, guint8 **cursor, gint len,
+ * guint32 internal_group_id, PurpleConnection *gc); */
void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
-//void qq_process_recv_group_im_been_rejected(guint8 *data,
-// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+/* void qq_process_recv_group_im_been_rejected(guint8 *data, guint8 **cursor, gint len,
+ * guint32 internal_group_id, PurpleConnection *gc); */
void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
-//void qq_process_recv_group_im_been_approved(guint8 *data,
-// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+/* void qq_process_recv_group_im_been_approved(guint8 *data, guint8 **cursor, gint len,
+ * guint32 internal_group_id, PurpleConnection *gc); */
void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
-//void qq_process_recv_group_im_been_removed(guint8 *data,
-// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+/* void qq_process_recv_group_im_been_removed(guint8 *data, guint8 **cursor, gint len,
+ * guint32 internal_group_id, PurpleConnection *gc); */
void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
-//void qq_process_recv_group_im_been_added(guint8 *data,
-// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+/* void qq_process_recv_group_im_been_added(guint8 *data, guint8 **cursor, gint len,
+ * guint32 internal_group_id, PurpleConnection *gc); */
void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/group_network.c 80d18884793457839a0acb6771b7be36aacaa832
+++ libpurple/protocols/qq/group_network.c 7a8524aa1a8ffa073f272f1f14757f681784f18f
@@ -115,7 +115,7 @@ void qq_send_group_cmd(PurpleConnection
qd = (qq_data *) gc->proto_data;
- qq_send_cmd(gc, QQ_CMD_GROUP_CMD, TRUE, 0, TRUE, raw_data, data_len);
+ qq_send_cmd(qd, QQ_CMD_GROUP_CMD, raw_data, data_len);
p = g_new0(group_packet, 1);
============================================================
--- libpurple/protocols/qq/im.c e91f72d83ec7c15b2f2680116206653e6c0507d1
+++ libpurple/protocols/qq/im.c e0de1b7f4c8b8b66f0d4193fc0b5071f409b22bc
@@ -219,7 +219,10 @@ static void _qq_send_packet_recv_im_ack(
* we send an ACK which is the first 16 bytes of incoming packet */
static void _qq_send_packet_recv_im_ack(PurpleConnection *gc, guint16 seq, guint8 *data)
{
- qq_send_cmd(gc, QQ_CMD_RECV_IM, FALSE, seq, FALSE, data, 16);
+ qq_data *qd;
+
+ qd = (qq_data *) gc->proto_data;
+ qq_send_cmd_detail(qd, QQ_CMD_RECV_IM, seq, FALSE, data, 16);
}
/* read the common parts of the normal_im,
@@ -520,7 +523,7 @@ void qq_send_packet_im(PurpleConnection
qq_show_packet("QQ_raw_data debug", raw_data, bytes);
if (bytes == raw_len) /* create packet OK */
- qq_send_cmd(gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_SEND_IM, raw_data, bytes);
else
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"Fail creating send_im packet, expect %d bytes, build %d bytes\n", raw_len, bytes);
============================================================
--- libpurple/protocols/qq/keep_alive.c 8577d0e6e583940cb85a8e3162d2c297c16c6843
+++ libpurple/protocols/qq/keep_alive.c 19862c1e3f239c13a647e8034bcf54ddd3e455fa
@@ -59,7 +59,7 @@ void qq_send_packet_keep_alive(PurpleCon
* the amount of online QQ users, my ip and port */
bytes += qq_put32(raw_data + bytes, qd->uid);
- qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, TRUE, 0, TRUE, raw_data, 4);
+ qq_send_cmd(qd, QQ_CMD_KEEP_ALIVE, raw_data, 4);
}
/* parse the return of keep-alive packet, it includes some system information */
============================================================
--- libpurple/protocols/qq/login_logout.c 2aff209621bedc661e18371eb42f7aee94676f3a
+++ libpurple/protocols/qq/login_logout.c 22730060416dcfded5c391d85fb57ee4e6ac65c5
@@ -70,7 +70,7 @@ static const guint8 login_23_51[29] = {
*/
/* for QQ 2005? copy from lumaqq */
-// Fixme: change to guint8
+/* FIXME: change to guint8 */
static const guint8 login_23_51[29] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x86, 0xcc, 0x4c, 0x35,
@@ -150,8 +150,9 @@ static guint8 *gen_session_md5(gint uid,
PurpleCipherContext *context;
src = g_newa(guint8, 20);
- memcpy(src, &uid, 4);
- memcpy(src, session_key, QQ_KEY_LENGTH);
+ /* bug found by QuLogic */
+ memcpy(src, &uid, sizeof(uid));
+ memcpy(src + sizeof(uid), session_key, QQ_KEY_LENGTH);
cipher = purple_ciphers_find_cipher("md5");
context = purple_cipher_context_new(cipher, NULL);
@@ -170,6 +171,7 @@ static gint _qq_process_login_ok(PurpleC
qq_login_reply_ok_packet lrop;
qd = (qq_data *) gc->proto_data;
+ /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */
bytes = 0;
/* 000-000: reply code */
@@ -281,8 +283,8 @@ static gint _qq_process_login_redirect(P
QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes);
ret = QQ_LOGIN_REPLY_MISC_ERROR;
} else {
- // redirect to new server, do not disconnect or connect here
- // those connect should be called at packet_process
+ /* redirect to new server, do not disconnect or connect here
+ * those connect should be called at packet_process */
if (qd->real_hostname) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n");
g_free(qd->real_hostname);
@@ -327,7 +329,7 @@ void qq_send_packet_request_login_token(
bytes += qq_put8(buf + bytes, 0);
- qq_send_data(gc, QQ_CMD_REQUEST_LOGIN_TOKEN, buf, bytes);
+ qq_send_data(qd, QQ_CMD_REQUEST_LOGIN_TOKEN, buf, bytes);
}
/* send login packet to QQ server */
@@ -384,7 +386,7 @@ static void qq_send_packet_login(PurpleC
bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH);
bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len);
- qq_send_data(gc, QQ_CMD_LOGIN, buf, bytes);
+ qq_send_data(qd, QQ_CMD_LOGIN, buf, bytes);
}
void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
@@ -431,7 +433,7 @@ void qq_send_packet_logout(PurpleConnect
qd = (qq_data *) gc->proto_data;
for (i = 0; i < 4; i++)
- qq_send_cmd(gc, QQ_CMD_LOGOUT, FALSE, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH);
+ qq_send_cmd_detail(qd, QQ_CMD_LOGOUT, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH);
qd->logged_in = FALSE; /* update login status AFTER sending logout packets */
}
============================================================
--- libpurple/protocols/qq/packet_parse.c 6bd97b798f0597efd5d94216e7168874fbaa622d
+++ libpurple/protocols/qq/packet_parse.c feec9428b30781aa23b804a7011a7923558de6a0
@@ -33,9 +33,7 @@
/* note:
* 1, in these functions, 'b' stands for byte, 'w' stands for word, 'dw' stands for double word.
* 2, we use '*cursor' and 'buf' as two addresses to calculate the length.
- * 3, fixed obscure bugs, thanks ccpaging.
- * 4, change '0' to '1', if want to get more info about the packet parsing.
- * by s3e, 20070717 */
+ * 3, change '0' to '1', if want to get more info about the packet parsing. */
#if 0
#define PARSER_DEBUG
@@ -49,8 +47,8 @@ gint qq_get8(guint8 *b, guint8 *buf)
memcpy(&b_dest, buf, sizeof(b_dest));
*b = b_dest;
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get8] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get8] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b);
#endif
return sizeof(b_dest);
}
@@ -64,8 +62,8 @@ gint qq_get16(guint16 *w, guint8 *buf)
memcpy(&w_dest, buf, sizeof(w_dest));
*w = g_ntohs(w_dest);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get16] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get16] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w);
#endif
return sizeof(w_dest);
}
@@ -79,8 +77,8 @@ gint qq_get32(guint32 *dw, guint8 *buf)
memcpy(&dw_dest, buf, sizeof(dw_dest));
*dw = g_ntohl(dw_dest);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get32] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get32] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw);
#endif
return sizeof(dw_dest);
}
@@ -92,7 +90,7 @@ gint qq_getdata(guint8 *data, gint datal
{
memcpy(data, buf, datalen);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getdata] buf %lu\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getdata] buf %p\n", (void *)buf);
#endif
return datalen;
}
@@ -106,12 +104,12 @@ gint qq_getime(time_t *t, guint8 *buf)
guint32 dw_dest;
memcpy(&dw_dest, buf, sizeof(dw_dest));
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest);
#endif
dw_dest = g_ntohl(dw_dest);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest);
#endif
memcpy(t, &dw_dest, sizeof(dw_dest));
return sizeof(dw_dest);
@@ -124,8 +122,8 @@ gint qq_put8(guint8 *buf, guint8 b)
{
memcpy(buf, &b, sizeof(b));
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put8] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put8] b 0x%02x\n", b);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put8] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put8] b 0x%02x\n", b);
#endif
return sizeof(b);
}
@@ -138,8 +136,8 @@ gint qq_put16(guint8 *buf, guint16 w)
guint16 w_porter;
w_porter = g_htons(w);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put16] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put16] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter);
#endif
memcpy(buf, &w_porter, sizeof(w_porter));
return sizeof(w_porter);
@@ -153,8 +151,8 @@ gint qq_put32(guint8 *buf, guint32 dw)
guint32 dw_porter;
dw_porter = g_htonl(dw);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put32] buf %lu\n", (void *)buf);
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put32] buf %p\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter);
#endif
memcpy(buf, &dw_porter, sizeof(dw_porter));
return sizeof(dw_porter);
@@ -167,7 +165,7 @@ gint qq_putdata(guint8 *buf, const guint
{
memcpy(buf, data, datalen);
#ifdef PARSER_DEBUG
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][putdata] buf %lu\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][putdata] buf %p\n", (void *)buf);
#endif
return datalen;
}
============================================================
--- libpurple/protocols/qq/packet_parse.h a7e348bfde7cdd37680633be4c2746d684ca5aa1
+++ libpurple/protocols/qq/packet_parse.h 3da5208644cd48d00eb4f39622119a237a14d023
@@ -48,15 +48,17 @@ gint qq_putdata(guint8 *buf, const guint
gint qq_put32(guint8 *buf, guint32 dw);
gint qq_putdata(guint8 *buf, const guint8 *data, const int datalen);
-//gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
-//gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
-//gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
-//gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
-//gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
+/*
+gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
+gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
+gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
+gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
-//gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
-//gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
-//gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw);
-//gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen);
+gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
+gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
+gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw);
+gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen);
+*/
#endif
============================================================
--- libpurple/protocols/qq/qq.c 9efff1f2f37bd0d7c71c21fb505b31ac76246e90
+++ libpurple/protocols/qq/qq.c ec0c1145646c14c17ea491407e2cc6ac75adac39
@@ -62,47 +62,22 @@
#define OPENQ_AUTHOR "Puzzlebird"
#define OPENQ_WEBSITE "http://openq.sourceforge.net"
+
#define QQ_TCP_PORT 8000
#define QQ_UDP_PORT 8000
-const gchar *udp_server_list[] = {
- "sz.tencent.com",
- "sz2.tencent.com",
- "sz3.tencent.com",
- "sz4.tencent.com",
- "sz5.tencent.com",
- "sz6.tencent.com",
- "sz7.tencent.com",
- "sz8.tencent.com",
- "sz9.tencent.com"
-};
-const gint udp_server_amount = (sizeof(udp_server_list) / sizeof(udp_server_list[0]));
-
-
-const gchar *tcp_server_list[] = {
- "tcpconn.tencent.com",
- "tcpconn2.tencent.com",
- "tcpconn3.tencent.com",
- "tcpconn4.tencent.com",
- "tcpconn5.tencent.com",
- "tcpconn6.tencent.com"
-};
-const gint tcp_server_amount = (sizeof(tcp_server_list) / sizeof(tcp_server_list[0]));
-
-static void srv_resolved(PurpleSrvResponse *resp, int results, gpointer account)
-{
+static void server_list_create(PurpleAccount *account) {
PurpleConnection *gc;
qq_data *qd;
- gchar *hostname;
+ const gchar *user_server;
int port;
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Create server list\n");
gc = purple_account_get_connection(account);
- g_return_if_fail(gc != NULL && gc->proto_data != NULL);
- qd = (qq_data *) gc->proto_data;
+ g_return_if_fail(gc != NULL && gc->proto_data != NULL);
+ qd = gc->proto_data;
- qd->srv_query_data = NULL;
-
- /* find the host to connect to */
+ qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE);
port = purple_account_get_int(account, "port", 0);
if (port == 0) {
if (qd->use_tcp) {
@@ -111,38 +86,62 @@ static void srv_resolved(PurpleSrvRespon
port = QQ_UDP_PORT;
}
}
+ qd->user_port = port;
- if(results) {
- hostname = g_strdup(resp->hostname);
- if(!port)
- port = resp->port;
- g_free(resp);
- } else {
- if(!purple_account_get_bool(account, "useproxy", FALSE)) {
- hostname = g_strdup(qd->server_name);
- } else {
- hostname = g_strdup(purple_account_get_string(account,
- "proxy", qd->server_name));
- }
+ g_return_if_fail(qd->user_server == NULL);
+ user_server = purple_account_get_string(account, "server", NULL);
+ if (user_server != NULL && strlen(user_server) > 0) {
+ qd->user_server = g_strdup(user_server);
}
- /*
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "using with server %s and port %d\n", hostname, port);
- */
- qd->real_hostname = g_strdup(hostname);
- qd->real_port = port;
- qq_connect(account);
+ if (qd->user_server != NULL) {
+ qd->servers = g_list_append(qd->servers, qd->user_server);
+ return;
+ }
+ if (qd->use_tcp) {
+ qd->servers = g_list_append(qd->servers, "tcpconn.tencent.com");
+ qd->servers = g_list_append(qd->servers, "tcpconn2.tencent.com");
+ qd->servers = g_list_append(qd->servers, "tcpconn3.tencent.com");
+ qd->servers = g_list_append(qd->servers, "tcpconn4.tencent.com");
+ qd->servers = g_list_append(qd->servers, "tcpconn5.tencent.com");
+ qd->servers = g_list_append(qd->servers, "tcpconn6.tencent.com");
+ return;
+ }
+
+ qd->servers = g_list_append(qd->servers, "sz.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz2.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz3.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz4.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz5.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz6.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz7.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz8.tencent.com");
+ qd->servers = g_list_append(qd->servers, "sz9.tencent.com");
+}
- g_free(hostname);
+static void server_list_remove_all(qq_data *qd) {
+ g_return_if_fail(qd != NULL);
+
+ if (qd->real_hostname) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n");
+ g_free(qd->real_hostname);
+ qd->real_hostname = NULL;
+ }
+
+ if (qd->user_server != NULL) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "free user_server\n");
+ g_free(qd->user_server);
+ qd->user_server = NULL;
+ }
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "free server list\n");
+ g_list_free(qd->servers);
}
static void qq_login(PurpleAccount *account)
{
- const gchar *userserver;
+ PurpleConnection *gc;
qq_data *qd;
- gchar *host2connect;
- PurpleConnection *gc;
PurplePresence *presence;
g_return_if_fail(account != NULL);
@@ -166,30 +165,11 @@ static void qq_login(PurpleAccount *acco
qd->login_mode = QQ_LOGIN_MODE_NORMAL;
}
- userserver = purple_account_get_string(account, "server", NULL);
- qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE);
+ server_list_create(account);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Server list has %d\n", g_list_length(qd->servers));
- if (userserver == NULL || strlen(userserver) == 0) {
- if (qd->use_tcp) {
- qd->server_name = g_strdup(tcp_server_list[random() % tcp_server_amount]);
- } else {
- qd->server_name = g_strdup(udp_server_list[random() % udp_server_amount]);
- }
- } else {
- qd->server_name = g_strdup(userserver);
- }
-
- purple_connection_update_progress(gc, _("Connecting"), 0, QQ_CONNECT_STEPS);
-
- if(!purple_account_get_bool(account, "useproxy", FALSE)) {
- host2connect = g_strdup(qd->server_name);
- } else {
- host2connect = g_strdup(purple_account_get_string(account, "proxy", qd->server_name));
- }
-
- qd->srv_query_data = purple_srv_resolve("QQ",
- qd->use_tcp ? "tcp" : "udp", host2connect, srv_resolved, account);
- g_free(host2connect);
+ qq_connect(account);
}
/* clean up the given QQ connection and free all resources */
@@ -197,20 +177,13 @@ static void qq_close(PurpleConnection *g
{
qq_data *qd;
- g_return_if_fail(gc != NULL);
+ g_return_if_fail(gc != NULL && gc->proto_data);
qd = gc->proto_data;
qq_disconnect(gc);
- if (qd->real_hostname) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n");
- g_free(qd->real_hostname);
- qd->real_hostname = NULL;
- }
- if (qd->srv_query_data != NULL)
- purple_srv_cancel(qd->srv_query_data);
+ server_list_remove_all(qd);
- g_free(qd->server_name);
g_free(qd);
gc->proto_data = NULL;
============================================================
--- libpurple/protocols/qq/qq.h 3aefba86630400977aec225e0d7926696edb9cef
+++ libpurple/protocols/qq/qq.h 94529661816228150ae7d79580c7007509cc9afc
@@ -70,31 +70,36 @@ struct _qq_data {
struct _qq_data {
PurpleConnection *gc;
- gchar *server_name;
- // common network resource
- PurpleSrvQueryData *srv_query_data; // srv resolve
+ /* common network resource */
+ GList *servers;
+ gchar *user_server;
+ gint user_port;
+ gboolean use_tcp; /* network in tcp or udp */
+
+ gchar *server_name;
gboolean is_redirect;
- gchar *real_hostname; // from real connction
+ gchar *real_hostname; /* from real connction */
guint16 real_port;
- gboolean use_tcp; // network in tcp or udp
-
+ guint reconnect_timeout;
+ gint reconnect_times;
+
PurpleProxyConnectData *connect_data;
- gint fd; // socket file handler
- gint tx_handler; // socket can_write handle, use in udp connecting and tcp send out
+ gint fd; /* socket file handler */
+ gint tx_handler; /* socket can_write handle, use in udp connecting and tcp send out */
- GList *transactions; // check ack packet and resend
+ GList *send_trans; /* check ack packet and resend */
guint resend_timeout;
- guint8 rcv_window[1 << 13]; // windows for check duplicate packet
- GQueue *rcv_trans; // queue to store packet can not process before login
+ guint8 rcv_window[1 << 13]; /* windows for check duplicate packet */
+ GQueue *rcv_trans; /* queue to store packet can not process before login */
- // tcp related
+ /* tcp related */
PurpleCircBuffer *tcp_txbuf;
guint8 *tcp_rxqueue;
int tcp_rxlen;
- // udp related
+ /* udp related */
PurpleDnsQueryData *udp_query_data;
guint32 uid; /* QQ number */
@@ -108,7 +113,6 @@ struct _qq_data {
gboolean logged_in; /* used by qq-add_buddy */
PurpleXfer *xfer; /* file transfer handler */
- struct sockaddr_in dest_sin;
/* get from login reply packet */
time_t login_time;
@@ -140,6 +144,4 @@ struct _qq_data {
gboolean modifying_face;
};
-void qq_function_not_implemented(PurpleConnection *gc);
-
#endif
============================================================
--- libpurple/protocols/qq/qq_network.c 51d45db61522e346a2d4ccbcaacc7b9861a5a236
+++ libpurple/protocols/qq/qq_network.c 58de8478d42cd07d5cbea9ef6c44edea10f37ed2
@@ -45,21 +45,68 @@
#include "login_logout.h"
#include "packet_parse.h"
#include "qq_network.h"
-#include "sendqueue.h"
+#include "qq_trans.h"
#include "sys_msg.h"
#include "utils.h"
-/* These functions are used only in development phase */
-/*
- static void _qq_show_socket(gchar *desc, gint fd) {
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
- getsockname(fd, (struct sockaddr *)&sin, &len);
- purple_debug(PURPLE_DEBUG_INFO, desc, "%s:%d\n",
- inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
- }
- */
+/* set QQ_RECONNECT_MAX to 1, when test reconnecting */
+#define QQ_RECONNECT_MAX 4
+#define QQ_RECONNECT_INTERVAL 5000
+static gboolean set_new_server(qq_data *qd)
+{
+ gint count;
+ gint index;
+ GList *it = NULL;
+
+ g_return_val_if_fail(qd != NULL, FALSE);
+
+ if (qd->servers == NULL) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server list is NULL\n");
+ return FALSE;
+ }
+
+ if (qd->real_hostname) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n");
+ g_free(qd->real_hostname);
+ qd->real_hostname = NULL;
+ }
+
+ /* remove server used before */
+ if (qd->server_name != NULL) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Remove previous server [%s]\n", qd->server_name);
+ qd->servers = g_list_remove(qd->servers, qd->server_name);
+ qd->server_name = NULL;
+ }
+
+ count = g_list_length(qd->servers);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server list has %d\n", count);
+ if (count <= 0) {
+ /* no server left, disconnect when result is false */
+ qd->servers = NULL;
+ return FALSE;
+ }
+
+ /* get new server */
+ index = random() % count;
+ it = g_list_nth(qd->servers, index);
+ qd->server_name = it->data; /* do not free server_name */
+ if (qd->server_name == NULL || strlen(qd->server_name) <= 0 ) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server name at %d is empty\n", index);
+ return FALSE;
+ }
+
+ qd->real_hostname = g_strdup(qd->server_name);
+ qd->real_port = qd->user_port;
+
+ qd->reconnect_times = QQ_RECONNECT_MAX;
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "set new server to %s:%d\n", qd->real_hostname, qd->real_port);
+ return TRUE;
+}
+
/* QQ 2003iii uses double MD5 for the pwkey to get the session key */
static guint8 *encrypt_account_password(const gchar *pwd)
{
@@ -82,7 +129,7 @@ static guint8 *encrypt_account_password(
}
/* default process, decrypt and dump */
-static void packet_process_unknow(PurpleConnection *gc, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq)
+static void process_cmd_unknow(PurpleConnection *gc, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq)
{
qq_data *qd;
guint8 *data;
@@ -148,20 +195,80 @@ static gboolean packet_check_ack(qq_data
g_return_val_if_fail(qd != NULL, FALSE);
- trans = qq_trans_find(qd, seq);
+ trans = qq_send_trans_find(qd, seq);
if (trans == NULL) {
return FALSE;
}
- qq_trans_remove(qd, trans);
+ qq_send_trans_remove(qd, trans);
return TRUE;
}
-static void packet_process_cmd(
+static gboolean reconnect_later_cb(gpointer data)
+{
+ PurpleConnection *gc;
+ qq_data *qd;
+
+ gc = (PurpleConnection *) data;
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE);
+ qd = (qq_data *) gc->proto_data;
+
+ qd->reconnect_timeout = 0;
+
+ qq_connect(gc->account);
+ return FALSE; /* timeout callback stops */
+}
+
+static void reconnect_later(PurpleConnection *gc)
+{
+ qq_data *qd;
+
+ g_return_if_fail(gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ qd->reconnect_times--;
+ if (qd->reconnect_times < 0) {
+ if ( set_new_server(qd) != TRUE) {
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Failed to connect server"));
+ return;
+ }
+ }
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Reconnect to server %s:%d next retries %d in %d ms\n",
+ qd->real_hostname, qd->real_port,
+ qd->reconnect_times, QQ_RECONNECT_INTERVAL);
+
+ qd->reconnect_timeout = purple_timeout_add(QQ_RECONNECT_INTERVAL,
+ reconnect_later_cb, gc);
+}
+
+static void process_cmd_server(
PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
{
/* now process the packet */
switch (cmd) {
+ case QQ_CMD_RECV_IM:
+ qq_process_recv_im(data, data_len, seq, gc);
+ break;
+ case QQ_CMD_RECV_MSG_SYS:
+ qq_process_msg_sys(data, data_len, seq, gc);
+ break;
+ case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
+ qq_process_friend_change_status(data, data_len, gc);
+ break;
+ default:
+ process_cmd_unknow(gc, data, data_len, cmd, seq);
+ break;
+ }
+}
+
+static void process_cmd_reply(
+ PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+{
+ /* now process the packet */
+ switch (cmd) {
case QQ_CMD_KEEP_ALIVE:
qq_process_keep_alive_reply(data, data_len, gc);
break;
@@ -189,9 +296,6 @@ static void packet_process_cmd(
case QQ_CMD_SEND_IM:
qq_process_send_im_reply(data, data_len, gc);
break;
- case QQ_CMD_RECV_IM:
- qq_process_recv_im(data, data_len, seq, gc);
- break;
case QQ_CMD_LOGIN:
qq_process_login_reply(data, data_len, gc);
break;
@@ -213,14 +317,8 @@ static void packet_process_cmd(
case QQ_CMD_REQUEST_LOGIN_TOKEN:
qq_process_request_login_token_reply(data, data_len, gc);
break;
- case QQ_CMD_RECV_MSG_SYS:
- qq_process_msg_sys(data, data_len, seq, gc);
- break;
- case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
- qq_process_friend_change_status(data, data_len, gc);
- break;
default:
- packet_process_unknow(gc, data, data_len, cmd, seq);
+ process_cmd_unknow(gc, data, data_len, cmd, seq);
break;
}
}
@@ -238,15 +336,17 @@ static void packet_process(PurpleConnect
guint8 header_tag;
guint16 source_tag;
guint16 cmd;
- guint16 seq; // May be ack_seq or send_seq, depends on cmd
+ guint16 seq; /* May be ack_seq or send_seq, depends on cmd */
+ gboolean is_reply;
+
g_return_if_fail(buf != NULL && buf_len > 0);
qd = (qq_data *) gc->proto_data;
prev_login_status = qd->logged_in;
- // Len, header and tail tag have been checked before
+ /* Len, header and tail tag have been checked before */
bytes = 0;
bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes);
@@ -258,42 +358,37 @@ static void packet_process(PurpleConnect
bytes_not_read = buf_len - bytes - 1;
- if ( !qd->logged_in ) {
- if (cmd != QQ_CMD_LOGIN && cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) {
+ /* ack packet, we need to update send tranactions */
+ /* we do not check duplication for server ack */
+ is_reply = packet_check_ack(qd, seq);
+ if ( !is_reply ) {
+ if ( !qd->logged_in ) {
/* packets before login */
- qq_packet_push(qd, cmd, seq, buf + bytes, bytes_not_read);
+ qq_rcv_trans_push(qd, cmd, seq, buf + bytes, bytes_not_read);
return; /* do not process it now */
- }
+ }
+
+ /* server intiated packet, we need to send ack and check duplicaion
+ * this must be put after processing b4_packet
+ * as these packets will be passed in twice */
+ if (packet_is_dup(qd, seq)) {
+ purple_debug(PURPLE_DEBUG_WARNING,
+ "QQ", "dup [%05d] %s, discard...\n", seq, qq_get_cmd_desc(cmd));
+ return;
+ }
+ process_cmd_server(gc, cmd, seq, buf + bytes, bytes_not_read);
+ return;
}
- /* whether it is an ack */
- switch (cmd) {
- case QQ_CMD_RECV_IM:
- case QQ_CMD_RECV_MSG_SYS:
- case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
- /* server intiated packet, we need to send ack and check duplicaion
- * this must be put after processing b4_packet
- * as these packets will be passed in twice */
- if (packet_is_dup(qd, seq)) {
- purple_debug(PURPLE_DEBUG_WARNING,
- "QQ", "dup [%05d] %s, discard...\n", seq, qq_get_cmd_desc(cmd));
- return;
- }
- break;
- default:
- /* ack packet, we need to update sendqueue */
- /* we do not check duplication for server ack */
- packet_check_ack(qd, seq);
- }
-
/* this is the length of all the encrypted data (also remove tail tag */
- packet_process_cmd(gc, cmd, seq, buf + bytes, bytes_not_read);
+ process_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read);
- // check is redirect or not, and do it now
+ /* check is redirect or not, and do it now */
if (qd->is_redirect) {
- // free resource except real_hostname and port
+ /* free resource except real_hostname and port */
qq_disconnect(gc);
- qq_connect(gc->account);
+ qd->reconnect_times = QQ_RECONNECT_MAX;
+ reconnect_later(gc);
return;
}
@@ -301,14 +396,15 @@ static void packet_process(PurpleConnect
/* logged_in, but we have packets before login */
new_data = g_newa(guint8, MAX_PACKET_SIZE);
while (1) {
- new_data_len = qq_packet_pop(qd, &cmd, &seq, new_data, MAX_PACKET_SIZE);
+ memset(new_data, 0, MAX_PACKET_SIZE);
+ new_data_len = qq_rcv_trans_pop(qd, &cmd, &seq, new_data, MAX_PACKET_SIZE);
if (new_data_len < 0) {
break;
}
if (new_data_len == 0) {
continue;
}
- packet_process_cmd(gc, seq, cmd, new_data, new_data_len);
+ process_cmd_reply(gc, seq, cmd, new_data, new_data_len);
}
}
}
@@ -317,7 +413,7 @@ static void tcp_pending(gpointer data, g
{
PurpleConnection *gc;
qq_data *qd;
- guint8 buf[1024]; // set to 16 when test tcp_rxqueue
+ guint8 buf[1024]; /* set to 16 when test tcp_rxqueue */
gint buf_len;
gint bytes;
@@ -389,7 +485,7 @@ static void tcp_pending(gpointer data, g
if ( pkt_len < QQ_TCP_HEADER_LENGTH
|| *(qd->tcp_rxqueue + bytes) != QQ_PACKET_TAG
|| *(qd->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) {
- // HEY! This isn't even a QQ. What are you trying to pull?
+ /* HEY! This isn't even a QQ. What are you trying to pull? */
purple_debug(PURPLE_DEBUG_ERROR, "TCP_PENDING",
"Packet error, failed to check header and tail tag\n");
@@ -404,7 +500,7 @@ static void tcp_pending(gpointer data, g
return;
}
- // jump and over QQ_PACKET_TAIL
+ /* jump and over QQ_PACKET_TAIL */
jump_len = (jump - qd->tcp_rxqueue) + 1;
purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING",
"Find next QQ_PACKET_TAIL at %d, jump %d bytes\n", jump_len, jump_len + 1);
@@ -416,7 +512,7 @@ static void tcp_pending(gpointer data, g
memset(pkt, 0, MAX_PACKET_SIZE);
g_memmove(pkt, qd->tcp_rxqueue + bytes, pkt_len - bytes);
- // jump to next packet
+ /* jump to next packet */
qd->tcp_rxlen -= pkt_len;
if (qd->tcp_rxlen) {
purple_debug(PURPLE_DEBUG_ERROR, "TCP_PENDING",
@@ -434,8 +530,8 @@ static void tcp_pending(gpointer data, g
if (pkt == NULL) {
continue;
}
- // do not call packet_process before jump
- // packet_process may call disconnect and destory tcp_rxqueue
+ /* do not call packet_process before jump
+ * packet_process may call disconnect and destory tcp_rxqueue */
packet_process(gc, pkt, pkt_len - bytes);
}
}
@@ -539,7 +635,9 @@ static gint tcp_send_out(qq_data *qd, gu
g_return_val_if_fail(qd != NULL && qd->fd >= 0 && data != NULL && data_len > 0, -1);
- // purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd);
+ /*
+ * purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd);
+ */
if (qd->tx_handler == 0) {
ret = write(qd->fd, data, data_len);
@@ -551,11 +649,13 @@ static gint tcp_send_out(qq_data *qd, gu
purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT",
"Socket %d, total %d bytes is sent %d\n", qd->fd, data_len, ret);
if (ret < 0 && errno == EAGAIN) {
- // socket is busy, send later
- // purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Socket is busy and send later\n");
+ /* socket is busy, send later */
+ /*
+ * purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Socket is busy and send later\n");
+ */
ret = 0;
} else if (ret <= 0) {
- // TODO: what to do here - do we really have to disconnect?
+ /* TODO: what to do here - do we really have to disconnect? */
purple_debug(PURPLE_DEBUG_ERROR, "TCP_SEND_OUT",
"Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno));
purple_connection_error_reason(qd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno));
@@ -593,19 +693,19 @@ static gboolean trans_timeout(gpointer d
while (1) {
if (index < 0) {
- // next record is NULL
+ /* next record is NULL */
break;
}
- // purple_debug(PURPLE_DEBUG_ERROR, "QQ", "scan begin %d\n", index);
+ /* purple_debug(PURPLE_DEBUG_ERROR, "QQ", "scan begin %d\n", index); */
memset(buf, 0, MAX_PACKET_SIZE);
- buf_len = qq_trans_scan(qd, &index, buf, MAX_PACKET_SIZE, &cmd, &retries);
+ buf_len = qq_send_trans_scan(qd, &index, buf, MAX_PACKET_SIZE, &cmd, &retries);
if (buf_len <= 0) {
- // curr record is empty, whole trans is NULL
+ /* curr record is empty, whole trans is NULL */
break;
}
- // index = -1, when get last record of transactions
+ /* index = -1, when get last record of transactions */
- // purple_debug(PURPLE_DEBUG_ERROR, "QQ", "retries %d next index %d\n", retries, index);
+ /* purple_debug(PURPLE_DEBUG_ERROR, "QQ", "retries %d next index %d\n", retries, index); */
if (retries > 0) {
if (qd->use_tcp) {
tcp_send_out(qd, buf, buf_len);
@@ -615,7 +715,7 @@ static gboolean trans_timeout(gpointer d
continue;
}
- // retries <= 0
+ /* retries <= 0 */
switch (cmd) {
case QQ_CMD_KEEP_ALIVE:
if (qd->logged_in) {
@@ -648,7 +748,7 @@ static void qq_connect_cb(gpointer data,
{
qq_data *qd;
PurpleConnection *gc;
- gchar *buf;
+ gchar *conn_msg;
const gchar *passwd;
gc = (PurpleConnection *) data;
@@ -667,12 +767,13 @@ static void qq_connect_cb(gpointer data,
qd->connect_data = NULL;
if (source < 0) { /* socket returns -1 */
- purple_debug(PURPLE_DEBUG_INFO, "QQ_CONN", "Source is < 0\n");
- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_CONN", "Invalid connection, source is < 0\n");
+ qq_disconnect(gc);
+ reconnect_later(gc);
return;
}
- // _qq_show_socket("Got login socket", source);
+ /* _qq_show_socket("Got login socket", source); */
/* QQ use random seq, to minimize duplicated packets */
srandom(time(NULL));
@@ -697,9 +798,9 @@ static void qq_connect_cb(gpointer data,
gc->inpa = purple_input_add(qd->fd, PURPLE_INPUT_READ, udp_pending, gc);
/* Update the login progress status display */
- buf = g_strdup_printf("Login as %d", qd->uid);
- purple_connection_update_progress(gc, buf, 1, QQ_CONNECT_STEPS);
- g_free(buf);
+ conn_msg = g_strdup_printf("Login as %d", qd->uid);
+ purple_connection_update_progress(gc, conn_msg, QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS);
+ g_free(conn_msg);
qq_send_packet_request_login_token(gc);
}
@@ -765,8 +866,8 @@ static void udp_host_resolved(GSList *ho
qd = (qq_data *) gc->proto_data;
- // udp_query_data must be set as NULL.
- // Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error
+ /* udp_query_data must be set as NULL.
+ * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */
qd->udp_query_data = NULL;
if (!hosts || !hosts->data) {
@@ -842,18 +943,44 @@ void qq_connect(PurpleAccount *account)
{
PurpleConnection *gc;
qq_data *qd;
+ gchar *conn_msg;
gc = purple_account_get_connection(account);
g_return_if_fail(gc != NULL && gc->proto_data != NULL);
qd = (qq_data *) gc->proto_data;
+
+ /* test set_new_server
+ while (set_new_server(qd)) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_TEST",
+ "New server %s:%d Real server %s:%d\n",
+ qd->server_name, qd->user_port, qd->real_hostname, qd->real_port);
+ }
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_TEST", "qd->servers %lu\n",
+ qd->servers);
+ exit(1);
+ */
+ if (qd->server_name == NULL) {
+ /* must be first call this function */
+ if ( set_new_server(qd) != TRUE) {
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Failed to connect server"));
+ return;
+ }
+ }
+
if (qd->real_hostname == NULL || qd->real_port == 0) {
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("hostname is NULL or port is 0"));
return;
}
+ conn_msg = g_strdup_printf( _("Connecting server %s, retries %d"),
+ qd->real_hostname, qd->reconnect_times);
+ purple_connection_update_progress(gc, conn_msg, 1, QQ_CONNECT_STEPS);
+ g_free(conn_msg);
+
if (qd->is_redirect) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Redirect to %s:%d\n",
qd->real_hostname, qd->real_port);
@@ -863,8 +990,6 @@ void qq_connect(PurpleAccount *account)
qd->fd = -1;
qd->tx_handler = 0;
- g_return_if_fail(qd->real_hostname != NULL);
-
/* QQ connection via UDP/TCP.
* Now use Purple proxy function to provide TCP proxy support,
* and qq_udp_proxy.c to add UDP proxy support (thanks henry) */
@@ -928,6 +1053,11 @@ void qq_disconnect(PurpleConnection *gc)
qd->fd = -1;
}
+ if (qd->reconnect_timeout > 0) {
+ purple_timeout_remove(qd->reconnect_timeout);
+ qd->reconnect_timeout = 0;
+ }
+
if (qd->connect_data != NULL) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Cancel connect_data\n");
purple_proxy_connect_cancel(qd->connect_data);
@@ -936,6 +1066,7 @@ void qq_disconnect(PurpleConnection *gc)
if(qd->tcp_txbuf != NULL) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "destroy tcp_txbuf\n");
purple_circ_buffer_destroy(qd->tcp_txbuf);
+ qd->tcp_txbuf = NULL;
}
if (qd->tx_handler) {
@@ -955,8 +1086,9 @@ void qq_disconnect(PurpleConnection *gc)
qd->udp_query_data = NULL;
}
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "destroy transactions\n");
- qq_trans_remove_all(qd);
+ memset(qd->rcv_window, 0, sizeof(qd->rcv_window));
+ qq_rcv_trans_remove_all(qd);
+ qq_send_trans_remove_all(qd);
if (qd->inikey) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "free inikey\n");
@@ -984,7 +1116,6 @@ void qq_disconnect(PurpleConnection *gc)
qd->my_ip = NULL;
}
- qq_packet_remove_all(qd);
qq_group_packets_free(qd);
qq_group_free_all(qd);
qq_add_buddy_request_free(qd);
@@ -1023,7 +1154,7 @@ static gint encap(qq_data *qd, guint8 *b
bytes += qq_putdata(buf + bytes, data, data_len);
bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL);
- // set TCP packet length at begin of the packet
+ /* set TCP packet length at begin of the packet */
if (qd->use_tcp) {
qq_put16(buf, bytes);
}
@@ -1031,17 +1162,16 @@ static gint encap(qq_data *qd, guint8 *b
return bytes;
}
-gint qq_send_data(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len)
+gint qq_send_data(qq_data *qd, guint16 cmd, guint8 *data, gint data_len)
{
- qq_data *qd;
guint8 *buf;
gint buf_len;
gint bytes_sent;
gint seq;
- g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
- qd = (qq_data *) gc->proto_data;
-
+ g_return_val_if_fail(qd != NULL, -1);
+ g_return_val_if_fail(data != NULL && data_len > 0, -1);
+
buf = g_newa(guint8, MAX_PACKET_SIZE);
memset(buf, 0, MAX_PACKET_SIZE);
seq = ++(qd->send_seq);
@@ -1056,8 +1186,8 @@ gint qq_send_data(PurpleConnection *gc,
bytes_sent = udp_send_out(qd, buf, buf_len);
}
- // always need ack
- qq_trans_append(qd, buf, buf_len, cmd, seq);
+ /* always need ack */
+ qq_send_trans_append(qd, buf, buf_len, cmd, seq);
if (QQ_DEBUG) {
qq_show_packet("QQ_SEND_DATA", buf, buf_len);
@@ -1071,31 +1201,26 @@ gint qq_send_data(PurpleConnection *gc,
/* send the packet generated with the given cmd and data
* return the number of bytes sent to socket if succeeds
* return -1 if there is any error */
-gint qq_send_cmd(PurpleConnection *gc, guint16 cmd,
- gboolean is_auto_seq, guint16 seq, gboolean need_ack, guint8 *data, gint data_len)
+gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack,
+ guint8 *data, gint data_len)
{
- qq_data *qd;
guint8 *buf;
gint buf_len;
guint8 *encrypted_data;
gint encrypted_len;
- gint real_seq;
gint bytes_sent;
- qd = (qq_data *) gc->proto_data;
- g_return_val_if_fail(qd->session_key != NULL, -1);
+ g_return_val_if_fail(qd != NULL && qd->session_key != NULL, -1);
+ g_return_val_if_fail(data != NULL && data_len > 0, -1);
encrypted_len = data_len + 16; /* at most 16 bytes more */
encrypted_data = g_newa(guint8, encrypted_len);
qq_encrypt(data, data_len, qd->session_key, encrypted_data, &encrypted_len);
- real_seq = seq;
- if (is_auto_seq) real_seq = ++(qd->send_seq);
-
buf = g_newa(guint8, MAX_PACKET_SIZE);
memset(buf, 0, MAX_PACKET_SIZE);
- buf_len = encap(qd, buf, MAX_PACKET_SIZE, cmd, real_seq, encrypted_data, encrypted_len);
+ buf_len = encap(qd, buf, MAX_PACKET_SIZE, cmd, seq, encrypted_data, encrypted_len);
if (buf_len <= 0) {
return -1;
}
@@ -1111,14 +1236,23 @@ gint qq_send_cmd(PurpleConnection *gc, g
/* if it does not need ACK, we send ACK manually several times */
if (need_ack) {
- qq_trans_append(qd, buf, buf_len, cmd, real_seq);
+ qq_send_trans_append(qd, buf, buf_len, cmd, seq);
}
if (QQ_DEBUG) {
qq_show_packet("QQ_SEND_CMD", buf, buf_len);
purple_debug(PURPLE_DEBUG_INFO, "QQ",
"<== [%05d], %s, total %d bytes is sent %d\n",
- real_seq, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
+ seq, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
}
return bytes_sent;
}
+
+gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint data_len)
+{
+ g_return_val_if_fail(qd != NULL, -1);
+ g_return_val_if_fail(data != NULL && data_len > 0, -1);
+
+ qd->send_seq++;
+ return qq_send_cmd_detail(qd, cmd, qd->send_seq, TRUE, data, data_len);
+}
============================================================
--- libpurple/protocols/qq/qq_network.h 13121110b5e9ac5f28a4198374a9714c2ea9731b
+++ libpurple/protocols/qq/qq_network.h c90f2507036e9f1dddd640837bf37d61fd08ea7a
@@ -30,13 +30,15 @@
#include "qq.h"
-#define QQ_CONNECT_STEPS 2 /* steps in connection */
+#define QQ_CONNECT_STEPS 3 /* steps in connection */
void qq_connect(PurpleAccount *account);
void qq_disconnect(PurpleConnection *gc);
+void qq_connect_later(PurpleConnection *gc);
-gint qq_send_data(PurpleConnection *gc, guint16 cmd, guint8 *data, gint datalen);
-gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 seq,
- gboolean need_ack, guint8 *data, gint datalen);
+gint qq_send_data(qq_data *qd, guint16 cmd, guint8 *data, gint datalen);
+gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint datalen);
+gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack,
+ guint8 *data, gint data_len);
#endif
============================================================
--- libpurple/protocols/qq/send_file.c 8c9ea7e61190ec46f24629c714c638f130b05a33
+++ libpurple/protocols/qq/send_file.c d11d0018e84e3afb67be3475bd9c19ea974711ca
@@ -476,7 +476,7 @@ static void _qq_send_packet_file_request
bytes += qq_putdata (raw_data + bytes, (guint8 *) filelen_str, filelen_strlen);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_request",
"%d bytes expected but got %d bytes\n",
@@ -517,7 +517,7 @@ static void _qq_send_packet_file_accept(
info->local_real_ip = real_ip;
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_accept",
"%d bytes expected but got %d bytes\n",
@@ -544,7 +544,7 @@ static void _qq_send_packet_file_notifyi
bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE);
bytes += qq_fill_conn_info(raw_data + bytes, info);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_notify",
"%d bytes expected but got %d bytes\n",
@@ -572,7 +572,7 @@ static void _qq_send_packet_file_reject
bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file",
"%d bytes expected but got %d bytes\n",
@@ -599,7 +599,7 @@ static void _qq_send_packet_file_cancel
if (packet_len == bytes) {
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "before send cmd\n");
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
+ qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes);
}
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file",
@@ -938,7 +938,7 @@ static void qq_send_packet_request_key(P
/*
static void qq_send_packet_request_key(PurpleConnection *gc, guint8 key)
{
- qq_send_cmd(gc, QQ_CMD_REQUEST_KEY, TRUE, 0, TRUE, &key, 1);
+ qq_send_cmd(gc, QQ_CMD_REQUEST_KEY, &key, 1);
}
static void qq_process_recv_request_key(PurpleConnection *gc)
============================================================
--- libpurple/protocols/qq/sys_msg.c 3ef548df58374cb00964e1c6db64894fc87858ab
+++ libpurple/protocols/qq/sys_msg.c 119ebdf9d586b1690044ac4ac828225ae8d48958
@@ -120,10 +120,13 @@ static void _qq_send_packet_ack_msg_sys(
/* Send ACK if the sys message needs an ACK */
static void _qq_send_packet_ack_msg_sys(PurpleConnection *gc, guint8 code, guint32 from, guint16 seq)
{
+ qq_data *qd;
guint8 bar, *ack;
gchar *str;
gint ack_len, bytes;
+ qd = (qq_data *) gc->proto_data;
+
str = g_strdup_printf("%d", from);
bar = 0x1e;
ack_len = 1 + 1 + strlen(str) + 1 + 2;
@@ -139,7 +142,7 @@ static void _qq_send_packet_ack_msg_sys(
g_free(str);
if (bytes == ack_len) /* creation OK */
- qq_send_cmd(gc, QQ_CMD_ACK_SYS_MSG, TRUE, 0, FALSE, ack, ack_len);
+ qq_send_cmd_detail(qd, QQ_CMD_ACK_SYS_MSG, 0, FALSE, ack, ack_len);
else
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"Fail creating sys msg ACK, expect %d bytes, build %d bytes\n", ack_len, bytes);
============================================================
--- libpurple/protocols/qq/utils.c 5acca45660aa1851f55504bd6af49fba5b2b3cd4
+++ libpurple/protocols/qq/utils.c 6551e63eec5a6b5658004e318ffadf5c036f8fca
@@ -39,6 +39,17 @@
#define QQ_NAME_FORMAT "%d"
+/* These functions are used only in development phase */
+/*
+ static void _qq_show_socket(gchar *desc, gint fd) {
+ struct sockaddr_in sin;
+ socklen_t len = sizeof(sin);
+ getsockname(fd, (struct sockaddr *)&sin, &len);
+ purple_debug(PURPLE_DEBUG_INFO, desc, "%s:%d\n",
+ inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
+ }
+ */
+
gchar *get_name_by_index_str(gchar **array, const gchar *index_str, gint amount)
{
gint index;
More information about the Commits
mailing list