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

📄 fileagentpacket.java

📁 LUMAQQ源代码 JAVA 地球人都知道
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
* 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.obsolete;

import java.nio.ByteBuffer;

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

import edu.tsinghua.lumaqq.qq.Crypter;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.packets.PacketParseException;

/**
 * <pre>
 * 文件中转包,这个包的格式和FilePacket的子类格式相同甚少,因此是一个独立的类,它
 * 需要使用FileDataPacket,因为它是中转包,会包含中转数据。当它不用来中转数据时,
 * 也有自己的格式。具体格式如下:
 * 
 * 文件中转请求包(从客户端发出)以0x04开头,内容如下:
 * 1. 0x04
 * 2. 客户端版本号,2字节
 * 3. 整个的包长,2字节
 * 4. 命令,2字节
 * 5. 序号,2字节
 * 6. 我的QQ号,4字节
 * 7. 未知的8字节,无规律
 * 8. 根据命令的不同,后面的内容不同:
 *    a. 如果命令是0x0001时,表示请求中转服务,格式为
 *        i.   认证令牌长度,2字节
 *        ii.  认证令牌
 *        iii. 未知2字节,0x07D0,十进制值2000 (从这个字段开始加密)
 * 		  iv.  文件传输另一方的QQ号,4字节
 * 	  b. 如果命令是0x0002,表示接收者向中转服务器报到,格式为:
 * 		  i.   文件会话ID,4字节
 *  	  ii.  认证令牌长度,2字节(从这里开始加密)
 *        iii. 认证令牌
 *    c. 如果命令是0x0003,为封装文件数据的包,格式为(均不加密)
 *        i.   文件会话ID,4字节
 *        ii.  未知的4字节
 *        iii. 被封装的数据包长度,2字节
 *        iv.  数据包,也就是FileDataPacket的格式
 *    d.  如果命令是0x0004,为中转结束包,格式为:
 *        i.   文件会话ID,4字节
 *        ii.  我的QQ号 (从这个字段开始加密)
 *        iii. 未知的两字节,一般为全0,可能表示成功
 *    e.  如果命令是0x0005,是对服务器0x0005的回复,其中7部分全0。格式为:
 *        i.   文件会话ID,4字节
 *        ii.  未知的4字节,全0 (加密)
 *    f.  如果命令是0x0006,6部分全0。格式为:
 *        i.   文件会话ID,4字节
 *        ii.  未知的2字节,全0 (加密)
 * 9. 尾部0x3
 * 
 * 文件中转回复包(从服务器端发出)以0x04开头,格式为:
 * 1. 0x04
 * 2. 中转服务器版本号
 * 3. 整个的包长,2字节
 * 4. 命令,2字节
 * 5. 序号,2字节
 * 6. 我的QQ号,4字节
 * 7. 未知的8字节,无规律
 * 8. 根据命令的不同,后面的内容不同:
 *    A.  如果命令是0x0001,表示对中转请求的回应,且6部分和请求相同。格式为(加密):
 *    	  a.   应答码,2字节,根据应答码不同,内容不同
 *            I. 如果是0x0000,表示接受中转请求,后面的格式为:
 *                 i.   中转服务器IP,little-endian格式,4字节
 *                 ii.  中转服务器端口,2字节
 *                 iii. 文件会话ID,4字节 
 *                 iv.  4字节重定向IP,全0
 *                 v.   2字节重定向端口,全0
 *                 vi.  未知的两字节,全0
 *            II. 如果是0x0001,表示重定向,格式为
 *                 i.   中转服务器IP,4字节,全0
 *                 ii.  中转服务器端口,2字节,全0
 *                 iii. 文件会话ID,4字节,全0
 *                 iv.  4字节重定向IP,little-endian格式
 *                 v.   2字节重定向端口
 *                 vi.  未知的两字节,全0
 *	  B.  如果命令是0x0002,表示中转服务器对接收者报到的应答,格式为:
 *		  a.  文件会话ID,4字节
 *		  b.  未知的4字节,全0(从这里开始加密)
 *    C.  如果命令是0x0003,表示中转的数据,格式为(均不加密):
 *        a.  文件会话ID,4字节
 *        b.  未知的4字节
 *        c.  被封装的数据包长度,2字节
 *        d.  数据包,也就是FileDataPacket的格式
 *    D.  如果命令是0x0005,则是通知客户端可以开始传送数据,格式为:
 *        a.  文件会话ID,4字节
 *        b.  已经传送完成的文件数,两字节 (从这个字段开始加密)
 *        c.  后面的消息长度,2字节
 *        d.  消息,一般是"it's time for transfering data"
 *    E.  如果命令是0x0006,则是对客户端0x0006的回复,7部分全0,格式为:
 *        a.  文件会话ID,4字节
 *        b.  未知的两字节,全0
 *        c.  未知的4字节,0x00013880,十进制值80000 
 *        d.  未知的2字节,0x003C,十进制值60
 *        e.  未知的4字节,全0
 * 9. 尾部,0x3            
 * </pre>
 * 
 * @author luma
 */
@SuppressWarnings("unused")
public class FileAgentPacket {
    // Log对象
    protected static Log log = LogFactory.getLog(FilePacket.class);
    // 文件守望者
    private FileWatcher watcher;
	// 命令
	protected char command;
	// 序号
	protected char sequence;
    // 加密解密类
    protected static Crypter crypter = new Crypter();
    // 被封装的FileDataPacket
    protected FileDataPacket fdp;
    // 加密部分缓冲区
    protected static ByteBuffer buffer = ByteBuffer.allocate(50);

    // 所有的包都会有的字段
    private char sessionId;
    
    // 请求中转服务回复包字段,如果是重定向,则ip为重定向ip;如果是接受,ip为中转服务器ip
    //     这里的IP已经被转换成big-endian格式
    private char replyCode;
    private byte[] agentIp;
    private int agentPort;
    
    /**
     * 构造函数
     * @param watcher 文件守望者对象
     */
    public FileAgentPacket(FileWatcher watcher) {
        this.watcher = watcher;
        this.fdp = new FileDataPacket(watcher);
    }
    
    /**
     * 填充包内容到out中,out中原来的内容将被清空,填充完毕后,out的
     * position等于包长
     * @param out ByteBuffer对象
     */
    public void fill(ByteBuffer out) {
        out.clear();
        // 填充头部
        putHead(out);
        // 填充包体
        putBody(out);
        // 填充包尾
        putTail(out);
    }
    
    /**
     * 填充包内容到out中,out中原来的内容
     * @param out
     * @param from
     */
    public void fill(ByteBuffer out, int from) {
        out.position(from);
        // 填充头部
        putHead(out);
        // 填充包体
        putBody(out);
        // 填充包尾
        putTail(out);
    }
    
    /**
     * 从in的当前位置开始解析文件中转包,解析后的position将位于这个包之后
     * @param in
     * @throws PacketParseException
     */
    public void parse(ByteBuffer in) throws PacketParseException {
        // 解析头部
        parseHead(in);
        // 解析包体
        parseBody(in);
    }

    /**
     * 从in的当前未知开始解析包体
     * @param in
     * @throws PacketParseException
     */
    private void parseBody(ByteBuffer in) throws PacketParseException {
        switch(command) {
    	case QQ.QQ_FILE_CMD_REQUEST_AGENT:
    	    /* 0x0001 */
    	    parseRequestAgent(in);
    	    break;
    	case QQ.QQ_FILE_CMD_CHECK_IN:
    	    /* 0x0002 */
    	    parseCheckIn(in);
    		break;
    	case QQ.QQ_FILE_CMD_FORWARD:
    	    /* 0x0003 */
    	    parseForward(in);
    	    break;
    	case QQ.QQ_FILE_CMD_IT_IS_TIME:
    	    /* 0x0005 */
    	    parseItIsTime(in);
    	    break;
    	case QQ.QQ_FILE_CMD_I_AM_READY:
    	    /* 0x0006 */
    	    parseIAmReady(in);
    	    break;
    	default:
    	    log.error("不支持的命令类型");
    	    break;
        }
    }

    /**
     * 从in的当前未知开始解析报到的回复包
     * @param in
     */
    private void parseCheckIn(ByteBuffer in) {
        // 会话ID
        sessionId = (char)in.getInt();
    }

    /**
     * 从in的当前未知开始解析I Am Ready回复包
     * @param in
     */
    private void parseIAmReady(ByteBuffer in) {
        // 会话ID
        sessionId = (char)in.getInt();
        // TODO 后面的目前看来没有什么用处,先忽略
    }

    /**
     * 从in的当前未知开始解析ItIsTime通知包
     * @param in
     */
    private void parseItIsTime(ByteBuffer in) {
        // 会话ID
        sessionId = (char)in.getInt();
        // TODO 后面的目前看来没有什么用处,先忽略
    }

    /**
     * 从in的当前未知开始解析数据转发包

⌨️ 快捷键说明

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