--- a/libpurple/protocols/qq/qq_trans.c Thu Jun 16 04:37:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ -/** - * @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 "qq_define.h" -#include "qq_network.h" -#include "qq_process.h" -#include "qq_trans.h" - -enum { - QQ_TRANS_IS_SERVER = 0x01, /* Is server command or client command */ - QQ_TRANS_IS_IMPORT = 0x02, /* Only notice if not get reply; or resend, disconn if reties get 0*/ - QQ_TRANS_REMAINED = 0x04, /* server command before login*/ - QQ_TRANS_IS_REPLY = 0x08 /* server command before login*/ -}; - -struct _qq_transaction { - guint8 flag; - guint16 seq; - guint16 cmd; - - guint8 room_cmd; - guint32 room_id; - - guint8 *data; - gint data_len; - - gint fd; - gint send_retries; - gint rcved_times; - gint scan_times; - - guint32 update_class; - guint32 ship32; -}; - -gboolean qq_trans_is_server(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - - if (trans->flag & QQ_TRANS_IS_SERVER) - return TRUE; - else - return FALSE; -} - -gboolean qq_trans_is_dup(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, TRUE); - - if (trans->rcved_times > 1) - return TRUE; - else - return FALSE; -} - -guint8 qq_trans_get_room_cmd(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->room_cmd; -} - -guint32 qq_trans_get_room_id(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->room_id; -} - -guint32 qq_trans_get_class(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, QQ_CMD_CLASS_NONE); - return trans->update_class; -} - -guint32 qq_trans_get_ship(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->ship32; -} - -static qq_transaction *trans_create(PurpleConnection *gc, gint fd, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, guint32 update_class, guint32 ship32) -{ - qq_data *qd; - qq_transaction *trans; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - trans = g_new0(qq_transaction, 1); - - memset(trans, 0, sizeof(qq_transaction)); - trans->fd = fd; - trans->cmd = cmd; - trans->seq = seq; - - trans->data = NULL; - trans->data_len = 0; - if (data != NULL && data_len > 0) { - /* don't use g_strdup, may have 0x00 */ - trans->data = g_memdup(data, data_len); - trans->data_len = data_len; - } - - trans->update_class = update_class; - trans->ship32 = ship32; - return trans; -} - -/* Remove a packet with seq from send trans */ -static void trans_remove(PurpleConnection *gc, qq_transaction *trans) -{ - qq_data *qd = (qq_data *)gc->proto_data; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(trans != NULL); -#if 0 - purple_debug_info("QQ_TRANS", - "Remove [%s%05d] retry %d rcved %d scan %d %s\n", - (trans->flag & QQ_TRANS_IS_SERVER) ? "SRV-" : "", - trans->seq, - trans->send_retries, trans->rcved_times, trans->scan_times, - qq_get_cmd_desc(trans->cmd)); -#endif - if (trans->data) g_free(trans->data); - qd->transactions = g_list_remove(qd->transactions, trans); - g_free(trans); -} - -static qq_transaction *trans_find(PurpleConnection *gc, guint16 cmd, guint16 seq) -{ - qq_data *qd; - GList *list; - qq_transaction *trans; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - list = qd->transactions; - while (list != NULL) { - trans = (qq_transaction *) list->data; - if(trans->cmd == cmd && trans->seq == seq) { - return trans; - } - list = list->next; - } - - return NULL; -} - -void qq_trans_add_client_cmd(PurpleConnection *gc, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, guint32 update_class, guint32 ship32) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, update_class, ship32); - - if (cmd == QQ_CMD_TOKEN || cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_KEEP_ALIVE) { - trans->flag |= QQ_TRANS_IS_IMPORT; - } - trans->send_retries = qd->resend_times; -#if 0 - purple_debug_info("QQ_TRANS", "Add client cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq) -{ - qq_transaction *trans; - - trans = trans_find(gc, cmd, seq); - if (trans == NULL) { - return NULL; - } - - if (trans->rcved_times == 0) { - trans->scan_times = 0; - } - trans->rcved_times++; - /* server may not get our confirm reply before, send reply again*/ - if (qq_trans_is_server(trans) && (trans->flag & QQ_TRANS_IS_REPLY)) { - if (trans->data != NULL && trans->data_len > 0) { - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); - } - } - return trans; -} - -void qq_trans_add_room_cmd(PurpleConnection *gc, - guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len, - guint32 update_class, guint32 ship32) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, QQ_CMD_ROOM, seq, data, data_len, - update_class, ship32); - - trans->room_cmd = room_cmd; - trans->room_id = room_id; - trans->send_retries = qd->resend_times; -#if 0 - purple_debug_info("QQ_TRANS", "Add room cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, rcved, rcved_len, QQ_CMD_CLASS_NONE, 0); - - trans->flag = QQ_TRANS_IS_SERVER; - trans->send_retries = 0; - trans->rcved_times = 1; -#if 0 - purple_debug_info("QQ_TRANS", "Add server cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_add_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *reply, gint reply_len) -{ - qq_transaction *trans; - - g_return_if_fail(reply != NULL && reply_len > 0); - - trans = trans_find(gc, cmd, seq); - if (trans == NULL) { - return; - } - - g_return_if_fail(trans->flag & QQ_TRANS_IS_SERVER); - trans->flag |= QQ_TRANS_IS_REPLY; - - if (trans->data) g_free(trans->data); - - trans->data = g_memdup(reply, reply_len); - trans->data_len = reply_len; -} - -void qq_trans_add_remain(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, QQ_CMD_CLASS_NONE, 0); - - trans->flag = QQ_TRANS_IS_SERVER; - trans->flag |= QQ_TRANS_REMAINED; - trans->send_retries = 0; - trans->rcved_times = 1; -#if 1 - purple_debug_info("QQ_TRANS", "Add server cmd and remained, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_process_remained(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - GList *curr; - GList *next; - qq_transaction *trans; - - g_return_if_fail(qd != NULL); - - next = qd->transactions; - while( (curr = next) ) { - next = curr->next; - trans = (qq_transaction *) (curr->data); -#if 0 - purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); -#endif - if ( !(trans->flag & QQ_TRANS_IS_SERVER) ) { - continue; - } - if ( !(trans->flag & QQ_TRANS_REMAINED) ) { - continue; - } - /* set QQ_TRANS_REMAINED off */ - trans->flag &= ~QQ_TRANS_REMAINED; - -#if 1 - purple_debug_info("QQ_TRANS", - "Process server cmd remained, seq %d, data %p, len %d, send_retries %d\n", - trans->seq, trans->data, trans->data_len, trans->send_retries); -#endif - qq_proc_server_cmd(gc, trans->cmd, trans->seq, trans->data, trans->data_len); - } - - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ - return; -} - -gboolean qq_trans_scan(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - GList *curr; - GList *next; - qq_transaction *trans; - - g_return_val_if_fail(qd != NULL, FALSE); - - next = qd->transactions; - while( (curr = next) ) { - next = curr->next; - trans = (qq_transaction *) (curr->data); - /* purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); */ - - if (trans->flag & QQ_TRANS_REMAINED) { - /* keep server cmd before login*/ - continue; - } - - trans->scan_times++; - if (trans->scan_times <= 1) { - /* skip in 10 seconds */ - continue; - } - - if (trans->rcved_times > 0) { - /* Has been received */ - trans_remove(gc, trans); - continue; - } - - if (trans->flag & QQ_TRANS_IS_SERVER) { - continue; - } - - /* Never get reply */ - trans->send_retries--; - if (trans->send_retries <= 0) { - purple_debug_warning("QQ_TRANS", - "[%d] %s is lost.\n", - trans->seq, qq_get_cmd_desc(trans->cmd)); - if (trans->flag & QQ_TRANS_IS_IMPORT) { - return TRUE; - } - - qd->net_stat.lost++; - purple_debug_error("QQ_TRANS", - "Lost [%d] %s, data %p, len %d, retries %d\n", - trans->seq, qq_get_cmd_desc(trans->cmd), - trans->data, trans->data_len, trans->send_retries); - trans_remove(gc, trans); - continue; - } - - qd->net_stat.resend++; - purple_debug_warning("QQ_TRANS", - "Resend [%d] %s data %p, len %d, send_retries %d\n", - trans->seq, qq_get_cmd_desc(trans->cmd), - trans->data, trans->data_len, trans->send_retries); - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); - } - - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ - return FALSE; -} - -/* clean up send trans and free all contents */ -void qq_trans_remove_all(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans; - gint count = 0; - - while(qd->transactions != NULL) { - trans = (qq_transaction *) (qd->transactions->data); - qd->transactions = g_list_remove(qd->transactions, trans); - - if (trans->data) g_free(trans->data); - g_free(trans); - - count++; - } - if (count > 0) { - purple_debug_info("QQ_TRANS", "Free all %d packets\n", count); - } -}