⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packethelper.java

📁 类似于MSN
💻 JAVA
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 notXX
*                    luma <stubma@163.com>
*
* 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
*/
package edu.tsinghua.lumaqq.qq.packets;

import java.nio.ByteBuffer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.tsinghua.lumaqq.qq.PacketMonitor;
import edu.tsinghua.lumaqq.qq.PacketParseException;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.Utils;
import edu.tsinghua.lumaqq.qq.packets.in.AddFriendAuthReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.AddFriendReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ChangeStatusReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ClusterCommandReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.DeleteFriendReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.DownloadGroupFriendReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.FriendChangeStatusPacket;
import edu.tsinghua.lumaqq.qq.packets.in.FriendRemarkOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetFriendListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetFriendOnlineReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetUserInfoReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GroupNameOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.KeepAliveReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.LoginReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ModifyInfoReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.in.RemoveSelfReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.RequestKeyReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SearchUserReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SendIMReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SystemNotificationPacket;
import edu.tsinghua.lumaqq.qq.packets.in.UploadGroupFriendReplyPacket;

/**
 * @author notXX
 * @author 马若劼
 */
public final class PacketHelper {
    // Log对象
    static Log log = LogFactory.getLog(PacketHelper.class);
    // monitor
    private static PacketMonitor monitor = PacketMonitor.getInstance();
    // 临时用途
    private static char command, sequence;
    
	/**
	 * 把ByteBuffer中的内容解析成一个InPacket子类,从buf的当前位置开始解析,直到limit为止
	 * 不论解析成功或者失败,要把buf的position至于length后
	 * 
	 * @param buf 
	 * 				ByteBuffer对象
	 * @param type
	 * 				包类型
	 * @return InPacket
	 * @throws BadQQPacketException
	 * 					如果包格式不对
	 */
	public static InPacket proceed(ByteBuffer buf, int type) throws PacketParseException {
	    return proceed(buf, type, buf.limit() - buf.position());
	}
	
	/**
	 * 把ByteBuffer中的内容解析成一个InPacket子类,从buf的当前位置开始解析length字节
	 * 不论解析成功或者失败,buf的position将位于length后
	 * 
	 * @param buf
	 * 				ByteBuffer对象
	 * @param type
	 * 				包类型
	 * @param length
	 * 				包长度
	 * @return InPacket
	 * @throws BadQQPacketException
	 * 					如果包格式不对
	 */
	public static InPacket proceed(ByteBuffer buf, int type, int length) throws PacketParseException {
	    // 保存当前位置
	    int pos = buf.position();
	    //log.debug("Pos = " + pos);
	    //log.debug("Length = " + length);
	    // 检查重复性
	    if(checkDuplicate(pos, buf, type, length)) {
	        buf.position(pos + length);
	        //log.debug("New Pos = " + buf.position());
	        log.debug("包" + Utils.getCommandString(command) + " 序号 " + (int)sequence + "重复到达,忽略");
	        return null;
	    }
	    // 检查有效性
	    if(checkValidate(pos, buf, type, length)) {
	        InPacket ret = parse(buf, length);
	        buf.position(pos + length);
	        return ret;
	    } else {	        
	        buf.position(pos + length);
	        log.error("包" + Utils.getCommandString(command) + " 序号 " + (int)sequence + "格式有误,抛弃该包");
	        return null;
	    }
	}
	
	/**
	 * 对包进行格式检查,如果格式不对,返回false,
	 * 检查通过返回true
	 * 
	 * @param pos
	 * 				buffer的当前位置
	 * @param buf
	 * 				ByteBuffer对象
	 * @param type
	 * 				包类型
	 * @param length
	 * 				包长度
	 * @return true表示通过
	 */
	private static boolean checkValidate(int pos, ByteBuffer buf, int type, int length) {
	    // 检查包头
	    if(buf.get((type == Packet.TCP) ? (pos + 2) : pos) != QQ.QQ_PACKET_TAG) 
	        return false;
	    // 检查包尾
	    return buf.get(pos + length - 1) == QQ.QQ_PACKET_TAIL;
	}
	
	/**
	 * 检查包的重复性
	 * @param pos buffer的当前位置
	 * @param buf ByteBuffer对象
	 * @param type 包类型 
	 * @param length 包长度
	 * @return true表示包重复到达
	 */
	private static boolean checkDuplicate(int pos, ByteBuffer buf, int type, int length) {
	    // 检查重复性
	    if(type == Packet.TCP) {
	        command = buf.getChar(pos + 5);
	        sequence = buf.getChar(pos + 7);
	    } else {
	        command = buf.getChar(pos + 3);
	        sequence = buf.getChar(pos + 5);
	    }
	    int hash = command | (sequence << 16);
	    return monitor.check(new Integer(hash), true); 
	}
	
	/**
	 * 解析包内容,根据具体的命令类型调用不同的类解析
	 * @param buf 缓冲区
	 * @param length 包长度
	 * @return InPacket
	 * @throws PacketParseException
	 */
	private static InPacket parse(ByteBuffer buf, int length) throws PacketParseException {
	    switch(command) {
        	case QQ.QQ_CMD_KEEP_ALIVE:
        	    return new KeepAliveReplyPacket(buf, length);
        	case QQ.QQ_CMD_MODIFY_INFO:
        	    return new ModifyInfoReplyPacket(buf, length);
        	case QQ.QQ_CMD_SEARCH_USER:
        	    return new SearchUserReplyPacket(buf, length);
        	case QQ.QQ_CMD_ADD_FRIEND:
        	    return new AddFriendReplyPacket(buf, length);
        	case QQ.QQ_CMD_DELETE_FRIEND:
        	    return new DeleteFriendReplyPacket(buf, length);
        	case QQ.QQ_CMD_REMOVE_SELF:
        	    return new RemoveSelfReplyPacket(buf, length);
        	case QQ.QQ_CMD_ADD_FRIEND_AUTH:
        	    return new AddFriendAuthReplyPacket(buf, length);
        	case QQ.QQ_CMD_GET_USER_INFO:
        		return new GetUserInfoReplyPacket(buf, length);
        	case QQ.QQ_CMD_CHANGE_STATUS:
        		return new ChangeStatusReplyPacket(buf, length);
        	case QQ.QQ_CMD_SEND_IM:
        		return new SendIMReplyPacket(buf, length);
        	case QQ.QQ_CMD_RECV_IM:
        	    return new ReceiveIMPacket(buf, length);
        	case QQ.QQ_CMD_LOGIN:
        		return new LoginReplyPacket(buf, length);
        	case QQ.QQ_CMD_GET_FRIEND_LIST:
        		return new GetFriendListReplyPacket(buf, length);
        	case QQ.QQ_CMD_GET_FRIEND_ONLINE:
        		return new GetFriendOnlineReplyPacket(buf, length);
        	case QQ.QQ_CMD_RECV_MSG_SYS:
        	    return new SystemNotificationPacket(buf, length);
        	case QQ.QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
        		return new FriendChangeStatusPacket(buf, length);
        	case QQ.QQ_CMD_UPLOAD_GROUP_FRIEND:
        		return new UploadGroupFriendReplyPacket(buf, length);
        	case QQ.QQ_CMD_DOWNLOAD_GROUP_FRIEND:
        		return new DownloadGroupFriendReplyPacket(buf, length);
        	case QQ.QQ_CMD_GROUP_NAME_OP:
        		return new GroupNameOpReplyPacket(buf, length);
        	case QQ.QQ_CMD_FRIEND_REMARK_OP:
        		return new FriendRemarkOpReplyPacket(buf, length);
        	case QQ.QQ_CMD_CLUSTER_CMD:
        		return new ClusterCommandReplyPacket(buf, length);
        	case QQ.QQ_CMD_REQUEST_KEY:
        		return new RequestKeyReplyPacket(buf, length);
        	default:
        		return null;
	    }
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -