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

📄 diskfamilyparser.java

📁 lumaQQ的源文件
💻 JAVA
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 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 edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.packets.in.disk.ApplyReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.AuthenticateReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.BeginSessionPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.CreateReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.DeleteReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.DiskInPacketFragment;
import edu.tsinghua.lumaqq.qq.packets.in.disk.DownloadReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.FinalizeReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.GetServerListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.GetShareListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.GetSharedDiskReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.GetSizeReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.ListMyDiskDirReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.ListSharedDiskDirReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.MoveReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.PasswordOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.PrepareReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.RenameReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.SetShareListReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.UnknownDiskInPacket;
import edu.tsinghua.lumaqq.qq.packets.in.disk.UploadFileReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.UnknownOutPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.ApplyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.AuthenticatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.CreatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.DeletePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.FinalizePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.GetServerListPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.GetShareListPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.GetSharedDiskPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.GetSizePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.ListMyDiskDirPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.ListSharedDiskDirPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.MovePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.PasswordOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.PreparePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.RenamePacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.SetShareListPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.UnknownDiskOutPacket;
import edu.tsinghua.lumaqq.qq.packets.out.disk.UploadFilePacket;

/**
 * disk协议族包解析器
 *
 * @author luma
 */
public class DiskFamilyParser implements IParser {
	private int offset, length;
	private char command, source;
	private int remaining;
	private PacketHistory history;
	
	public DiskFamilyParser() {
		history = new PacketHistory();
		remaining = 0;
	}

	public boolean accept(ByteBuffer buf) {
		// 大于0说明一个超长包还没有解析完成
		if(remaining > 0)
			return buf.hasRemaining();
		
		// 可用长度小于包头长度的,拒绝
		offset = buf.position();
        int bufferLength = buf.limit() - offset;
        if(bufferLength < QQ.QQ_LENGTH_DISK_FAMILY_IN_HEADER)
        	return false;
        length = buf.getInt(offset) + 4;
        // 包长大于最大大小的,接受
        if(length > QQ.QQ_MAX_PACKET_SIZE) {
        	remaining = length;
        	source = buf.getChar(offset + 4);
        	command = buf.getChar(offset + 8);
        	return true;
        }
        // 可用长度小于包长的,拒绝
        if(bufferLength < length)
        	return false;
        
        return true;
	}

	public int getLength(ByteBuffer buf) {
		if(length > QQ.QQ_MAX_PACKET_SIZE) {
			return Math.min(remaining, buf.remaining());
		} else
			return length;
	}

	public InPacket parseIncoming(ByteBuffer buf, int length, QQUser user) throws PacketParseException {
		if(this.length > QQ.QQ_MAX_PACKET_SIZE) {
			// 相等说明这是第一个片断,所有有包头,要跳过
			int actLen = length;
			if(remaining == this.length) {
				buf.position(offset + QQ.QQ_LENGTH_DISK_FAMILY_IN_HEADER);
				actLen -= QQ.QQ_LENGTH_DISK_FAMILY_IN_HEADER;
			}
			// 如果解析失败,返回null
			DiskInPacketFragment fragment = null;
			try {
				fragment = new DiskInPacketFragment(buf, actLen, user);
				fragment.command = command;
				fragment.source = source;
				fragment.replyCode = QQ.QQ_REPLY_OK;
				remaining -= length;
			} catch(PacketParseException e) {
				fragment = null;
			}
			return fragment;
		} else {
			// 如果不是超长包,正常步骤解析
			try {
				switch(buf.getChar(offset + 8)) {
					case QQ.QQ_DISK_CMD_BEGIN_SESSION:
						return new BeginSessionPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_AUTHENTICATE:
						return new AuthenticateReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_GET_SERVER_LIST:
						return new GetServerListReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_GET_SHARED_DISK:
						return new GetSharedDiskReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_LIST_SHARED_DISK_DIR:
						return new ListSharedDiskDirReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_LIST_MY_DISK_DIR:
						return new ListMyDiskDirReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_PASSWORD_OP:
						return new PasswordOpReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_DOWNLOAD:
						return new DownloadReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_RENAME:
						return new RenameReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_DELETE:
						return new DeleteReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_CREATE:
						return new CreateReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_MOVE:
						return new MoveReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_UPLOAD:
						return new UploadFileReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_FINALIZE:
						return new FinalizeReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_PREPARE:
						return new PrepareReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_GET_SIZE:
						return new GetSizeReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_GET_SHARE_LIST:
						return new GetShareListReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_SET_SHARE_LIST:
						return new SetShareListReplyPacket(buf, length, user);
					case QQ.QQ_DISK_CMD_APPLY:
						return new ApplyReplyPacket(buf, length, user);
					default:
						return new UnknownDiskInPacket(buf, length, user);
				}				
			} catch(PacketParseException e) {
				buf.position(offset);
				return new UnknownDiskInPacket(buf, length, user);
			}
		}
	}

	public OutPacket parseOutcoming(ByteBuffer buf, int length, QQUser user) throws PacketParseException {
		try {
			switch(buf.getChar(offset + 8)) {
				case QQ.QQ_DISK_CMD_AUTHENTICATE:
					return new AuthenticatePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_GET_SERVER_LIST:
					return new GetServerListPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_GET_SHARED_DISK:
					return new GetSharedDiskPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_LIST_SHARED_DISK_DIR:
					return new ListSharedDiskDirPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_LIST_MY_DISK_DIR:
					return new ListMyDiskDirPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_PASSWORD_OP:
					return new PasswordOpPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_RENAME:
					return new RenamePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_DELETE:
					return new DeletePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_CREATE:
					return new CreatePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_MOVE:
					return new MovePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_UPLOAD:
					return new UploadFilePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_FINALIZE:
					return new FinalizePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_PREPARE:
					return new PreparePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_GET_SIZE:
					return new GetSizePacket(buf, length, user);
				case QQ.QQ_DISK_CMD_GET_SHARE_LIST:
					return new GetShareListPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_SET_SHARE_LIST:
					return new SetShareListPacket(buf, length, user);
				case QQ.QQ_DISK_CMD_APPLY:
					return new ApplyPacket(buf, length, user);
				default:
					return new UnknownDiskOutPacket(buf, length, user);
			}
		} catch(PacketParseException e) {
			buf.position(offset);
			return new UnknownOutPacket(buf, length, user);
		}
	}

	public boolean isDuplicatedNeedReply(InPacket in) {
		return false;
	}

	public int relocate(ByteBuffer buf) {
		if(length > QQ.QQ_MAX_PACKET_SIZE) {
			int skip = Math.min(remaining, buf.remaining());
			remaining -= skip;
			return offset + skip;
		}
		
		int offset = buf.position();
		if(buf.remaining() < 4)
			return offset;
		int len = buf.getInt(offset) + 4;
		if(len == 0 || offset + len > buf.limit())
			return offset;
		else
			return offset + len;
	}

	public PacketHistory getHistory() {
		return history;
	}

	public boolean isDuplicate(InPacket in) {
		if(in instanceof DiskInPacketFragment || in instanceof UploadFileReplyPacket)
			return false;
		else
			return history.check(in, true);
	}
}

⌨️ 快捷键说明

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