📄 packethelper.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 + -