src/protocols/qq/recv_core.c

changeset 14253
b63ebf84c42b
parent 14252
d10dda2777a9
child 14254
77edc7a6191a
--- a/src/protocols/qq/recv_core.c	Sat Aug 19 00:24:14 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/**
-* The QQ2003C protocol plugin
- *
- * for gaim
- *
- * Copyright (C) 2004 Puzzlebird
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "debug.h"
-#include "internal.h"
-
-#include "buddy_info.h"
-#include "buddy_list.h"
-#include "buddy_opt.h"
-#include "buddy_status.h"
-#include "char_conv.h"
-#include "crypt.h"
-#include "group_network.h"
-#include "header_info.h"
-#include "keep_alive.h"
-#include "im.h"
-#include "login_logout.h"
-#include "packet_parse.h"
-#include "qq_proxy.h"
-#include "recv_core.h"
-#include "sendqueue.h"
-#include "sys_msg.h"
-#include "utils.h"
-
-typedef struct _packet_before_login packet_before_login;
-typedef struct _qq_recv_msg_header qq_recv_msg_header;
-
-struct _packet_before_login {
-	guint8 *buf;
-	gint len;
-};
-
-struct _qq_recv_msg_header {
-	guint8 header_tag;
-	guint16 source_tag;
-	guint16 cmd;
-	guint16 seq;		/* can be ack_seq or send_seq, depends on cmd */
-};
-
-/* check whether one sequence number is duplicated or not
- * return TRUE if it is duplicated, otherwise FALSE */
-static gboolean _qq_check_packet_set_window(guint16 seq, GaimConnection *gc)
-{
-	qq_data *qd;
-	guint8 *byte, mask;
-
-	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE);
-	qd = (qq_data *) gc->proto_data;
-	byte = &(qd->window[seq / 8]);
-	mask = (1 << (seq % 8));
-
-	if ((*byte) & mask)
-		return TRUE;	/* check mask */
-	(*byte) |= mask;
-	return FALSE;		/* set mask */
-}				/* _qq_check_packet_set_window */
-
-/* default process, decrypt and dump */
-static void _qq_process_packet_default(guint8 *buf, gint buf_len, guint16 cmd, guint16 seq, GaimConnection *gc)
-{
-	qq_data *qd;
-	guint8 *data;
-	gchar *msg_utf8;
-	gint len;
-
-	g_return_if_fail(gc != NULL && gc->proto_data != NULL);
-	g_return_if_fail(buf != NULL && buf_len != 0);
-
-	qd = (qq_data *) gc->proto_data;
-	len = buf_len;
-	data = g_newa(guint8, len);
-	msg_utf8 = NULL;
-
-	_qq_show_packet("Processing unknown packet", buf, len);
-	if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
-		gaim_debug(GAIM_DEBUG_WARNING, "QQ",
-			   ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
-			   seq, qq_get_cmd_desc(cmd), buf_len, hex_dump_to_str(data, len));
-		try_dump_as_gbk(data, len);
-	} else {
-		gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n");
-	}
-}
-
-/* process the incoming packet from qq_pending */
-static void _qq_packet_process(guint8 *buf, gint buf_len, GaimConnection *gc)
-{
-	qq_data *qd;
-	gint len, bytes_expected, bytes_read;
-	guint16 buf_len_read;	/* two bytes in the begining of TCP packet */
-	guint8 *cursor;
-	qq_recv_msg_header header;
-	packet_before_login *b4_packet;
-
-	g_return_if_fail(gc != NULL && gc->proto_data != NULL);
-	g_return_if_fail(buf != NULL && buf_len > 0);
-
-	qd = (qq_data *) gc->proto_data;
-	bytes_expected = qd->use_tcp ? QQ_TCP_HEADER_LENGTH : QQ_UDP_HEADER_LENGTH;
-
-	if (buf_len < bytes_expected) {
-		gaim_debug(GAIM_DEBUG_ERROR,
-			   "QQ", "Received packet is too short, dump and drop\n%s", hex_dump_to_str(buf, buf_len));
-		return;
-	}
-	/* initialize */
-	cursor = buf;
-	bytes_read = 0;
-
-	/* QQ TCP packet returns first 2 bytes the length of this packet */
-	if (qd->use_tcp) {
-		bytes_read += read_packet_w(buf, &cursor, buf_len, &buf_len_read);
-		if (buf_len_read != buf_len) {	/* wrong */
-			gaim_debug
-			    (GAIM_DEBUG_ERROR,
-			     "QQ",
-			     "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read);
-			buf_len = buf_len_read;	/* we believe header is more accurate */
-		}
-	}
-
-	/* now goes the normal QQ packet as UDP packet */
-	bytes_read += read_packet_b(buf, &cursor, buf_len, &header.header_tag);
-	bytes_read += read_packet_w(buf, &cursor, buf_len, &header.source_tag);
-	bytes_read += read_packet_w(buf, &cursor, buf_len, &header.cmd);
-	bytes_read += read_packet_w(buf, &cursor, buf_len, &header.seq);
-
-	if (bytes_read != bytes_expected) {	/* read error */
-		gaim_debug(GAIM_DEBUG_ERROR, "QQ",
-			   "Fail reading packet header, expect %d bytes, read %d bytes\n", 
-			   bytes_expected, bytes_read);
-		return;
-	}
-
-	if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) {
-		gaim_debug(GAIM_DEBUG_ERROR,
-			   "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump_to_str(buf, buf_len));
-		return;
-	}
-
-	if (QQ_DEBUG)
-		gaim_debug(GAIM_DEBUG_INFO, "QQ",
-			   "==> [%05d] %s, from (%s)\n",
-			   header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag));
-
-	if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) {
-		if (!qd->logged_in) {	/* packets before login */
-			b4_packet = g_new0(packet_before_login, 1);
-			/* must duplicate, buffer will be freed after exiting this function */
-			b4_packet->buf = g_memdup(buf, buf_len);
-			b4_packet->len = buf_len;
-			if (qd->before_login_packets == NULL)
-				qd->before_login_packets = g_queue_new();
-			g_queue_push_head(qd->before_login_packets, b4_packet);
-			return;	/* do not process it now */
-		} else if (!g_queue_is_empty(qd->before_login_packets)) {
-			/* logged_in, but we have packets before login */
-			b4_packet = (packet_before_login *)
-			    g_queue_pop_head(qd->before_login_packets);
-			_qq_packet_process(b4_packet->buf, b4_packet->len, gc);
-			/* in fact this is a recursive call,  
-			 * all packets before login will be processed before goes on */
-			g_free(b4_packet->buf);	/* the buf is duplicated, need to be freed */
-			g_free(b4_packet);
-		}
-	}
-
-	/* this is the length of all the encrypted data (also remove tail tag */
-	len = buf_len - (bytes_read) - 1;
-
-	/* whether it is an ack */
-	switch (header.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 (_qq_check_packet_set_window(header.seq, gc)) {
-			gaim_debug(GAIM_DEBUG_WARNING,
-				   "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd));
-			return;
-		}
-		break;
-	default:{	/* ack packet, we need to update sendqueue */
-			/* we do not check duplication for server ack */
-			qq_sendqueue_remove(qd, header.seq);
-			if (QQ_DEBUG)
-				gaim_debug(GAIM_DEBUG_INFO, "QQ",
-					   "ack [%05d] %s, remove from sendqueue\n",
-					   header.seq, qq_get_cmd_desc(header.cmd));
-		}
-	}
-
-	/* now process the packet */
-	switch (header.cmd) {
-	case QQ_CMD_KEEP_ALIVE:
-		qq_process_keep_alive_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_UPDATE_INFO:
-		qq_process_modify_info_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_ADD_FRIEND_WO_AUTH:
-		qq_process_add_buddy_reply(cursor, len, header.seq, gc);
-		break;
-	case QQ_CMD_DEL_FRIEND:
-		qq_process_remove_buddy_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_REMOVE_SELF:
-		qq_process_remove_self_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_BUDDY_AUTH:
-		qq_process_add_buddy_auth_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_GET_USER_INFO:
-		qq_process_get_info_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_CHANGE_ONLINE_STATUS:
-		qq_process_change_status_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_SEND_IM:
-		qq_process_send_im_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_RECV_IM:
-		qq_process_recv_im(cursor, len, header.seq, gc);
-		break;
-	case QQ_CMD_LOGIN:
-		qq_process_login_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_GET_FRIENDS_LIST:
-		qq_process_get_buddies_list_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_GET_FRIENDS_ONLINE:
-		qq_process_get_buddies_online_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_GROUP_CMD:
-		qq_process_group_cmd_reply(cursor, len, header.seq, gc);
-		break;
-	case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
-		qq_process_get_all_list_with_group_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_REQUEST_LOGIN_TOKEN:
-		qq_process_request_login_token_reply(cursor, len, gc);
-		break;
-	case QQ_CMD_RECV_MSG_SYS:
-		qq_process_msg_sys(cursor, len, header.seq, gc);
-		break;
-	case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
-		qq_process_friend_change_status(cursor, len, gc);
-		break;
-	default:
-		_qq_process_packet_default(cursor, len, header.cmd, header.seq, gc);
-		break;
-	}
-}
-
-/* clean up the packets before login */
-void qq_b4_packets_free(qq_data *qd)
-{
-	packet_before_login *b4_packet;
-	g_return_if_fail(qd != NULL);
-	/* now clean up my own data structures */
-	if (qd->before_login_packets != NULL) {
-		while (NULL != (b4_packet = g_queue_pop_tail(qd->before_login_packets))) {
-			g_free(b4_packet->buf);
-			g_free(b4_packet);
-		}
-		g_queue_free(qd->before_login_packets);
-	}
-}
-
-void qq_input_pending(gpointer data, gint source, GaimInputCondition cond)
-{
-	GaimConnection *gc;
-	qq_data *qd;
-	guint8 *buf;
-	gint len;
-
-	gc = (GaimConnection *) data;
-	g_return_if_fail(gc != NULL && gc->proto_data != NULL && cond == GAIM_INPUT_READ);
-
-	qd = (qq_data *) gc->proto_data;
-	buf = g_newa(guint8, MAX_PACKET_SIZE);
-
-	/* here we have UDP proxy suppport */
-	len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE);
-	if (len <= 0) {
-		gaim_connection_error(gc, _("Unable to read from socket"));
-		return;
-	} else {
-		_qq_packet_process(buf, len, gc);
-	}
-}

mercurial