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

📄 filewatcher.java

📁 类似于MSN
💻 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.filetrans;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.util.Vector;

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

import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQClient;
import edu.tsinghua.lumaqq.qq.Utils;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.FileEvent;
import edu.tsinghua.lumaqq.qq.events.FileListener;

/**
 * 文件守望者,负责管理一次文件传输
 * 
 * @author 马若劼
 */
public abstract class FileWatcher {
	// 文件传输的一些状态常量
	public static final int FT_NONE = 0;
	public static final int FT_NEGOTIATING = 1;
	public static final int FT_SENDING = 2;
	public static final int FT_RECEIVING = 3;
	public static final int FT_SAYING_HELLO = 4;
	public static final int FT_SENDING_EOF = 5;
	public static final int FT_SENDING_BASIC = 6;
	
    // Log对象
    protected static Log log = LogFactory.getLog(FileWatcher.class);
	// 第一个监听端口
	protected int myMajorPort;
	// 第二个监听端口
	protected int myMinorPort;
	// 真实IP
	protected byte[] myLocalIp;
	// 外部IP
	protected byte[] myInternetIp;
	// 我的外部端口
	protected int myInternetPort;
	// 对方第一个监听端口
	protected int hisMajorPort;
	// 对方第二个监听端口
	protected int hisMinorPort;
	// 对方真实IP
	protected byte[] hisLocalIp;
	// 对方外部IP
	protected byte[] hisInternetIp;
	// 对方外部端口
	protected int hisInternetPort;
	// 我的文件会话密钥
	protected byte[] myFileSessionKey;
	// 对方的文件会话密钥
	protected byte[] hisFileSessionKey;
	// 文件中转服务器通讯密钥
	protected byte[] fileAgentKey;
	// 文件中转认证令牌
	protected byte[] fileAgentToken;
	// 对方的QQ号
	protected int hisQQ;
	// 我的QQ号
	protected int myQQ;
	// 我的头像号
	protected byte myFace;
	// 会话序列号,因为同时传多个文件是允许的,所以不同的会话之间序号不一样
	//     这个序号就是发送文件请求包中的那个序号,如果用户接受了,这个序号在
	//     以后的会话中将起到标识作用
	protected char sessionSequence;
	// 收发方的网络位置情况
	protected int condition;
	// 文件的大小
	protected int fileSize;
	// 发送的文件名称,或者接收的文件名称
	protected String fileName;
	// 文件的分片数
	protected int fragments;
	// 文件保存到本地的全路径名,如果我是发送者,那么这个和fileName表示的是同一个文件,
	//     如果我是接收者,那么可能不同
	protected String localFileName;
	// 随机存取文件,如果我是发送者,这个是用来读取发送文件的,如果我是接收者,这个用来
	//    保存文件
	protected RandomAccessFile localFile;
	// FileWatcher所属的QQClient
	protected QQClient client;
	// 滑窗,发送或者接收,只要一个就够了,因为要么接收,要么发送
	protected SlideWindow window;
	// 分片的最大字节数
	protected int maxFragmentSize;
	// 文件的两个md5
	protected byte[] fileMD5, fileNameMD5;
	// 文件数据信息包和文件控制信息包对象
	protected FileDataPacket fdp;
	protected FileControlPacket fcp;
	// Selector对象
	protected Selector selector;
	// 是否关闭文件守望者
	protected boolean shutdown;
	// 接收发送缓冲区
	protected ByteBuffer buffer;
	// 连接的协议是否是UDP
	protected boolean useUdp;
	// 连接的方式是否是直连
	protected boolean major;
	// 文件传输操作的当前状态
	protected int fileTransferStatus;
	// 包监视器
	protected FilePacketMonitor monitor;
	// FileListener数组
	protected Vector listeners;
		
	/**
	 * @param udp 是否是udp方式
	 * @param parent FileWatcher所属的发送消息窗口
	 * @param me QQUser对象
	 */
	public FileWatcher(QQClient client) {
		this.client = client;
		QQUser me = client.getUser();
		myQQ = me.getQQ();
		myFileSessionKey = me.getFileSessionKey();
		myInternetIp = me.getIp();
		myInternetPort = me.getPort();
        try {
            myLocalIp = Utils.getIpByteArrayFromString(InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException e) {
            log.error(e.getMessage());
        }
		myFace = Utils.getByte(me.getContactInfo().infos[me.getContactInfo().face], 0);
		fdp = new FileDataPacket(this);
		fcp = new FileControlPacket(this);
		monitor = new FilePacketMonitor();
		shutdown = false;
		fileTransferStatus = FT_NONE;
		listeners = new Vector();
        buffer = ByteBuffer.allocateDirect(QQ.MAX_PACKET_SIZE);
	}
	
	/**
	 * 初始化滑窗
	 * @param size 窗口大小
	 * @param l 窗口初始下限
	 * @param m 窗口最大值
	 */
	public void initSlideWindow(int size, int l, int m) {
	    if(window == null)
	        window = new SlideWindow(size, l, m);
	}  
	
	/**
	 * 添加文件传输事件监听器
	 * @param listener
	 */
	public void addFileListener(FileListener listener) {
	    listeners.add(listener);
	}
	
	/**
	 * 移除文件传输事件监听器
	 * @param listener
	 */
	public void removeFileListener(FileListener listener) {
	    listeners.remove(listener);
	}
	
	/**
	 * 触发文件传输被取消事件
	 */
	protected void fireFileAbortedEvent() {
	    FileEvent e = new FileEvent(this);
	    int size = listeners.size();
	    for(int i = 0; i < size; i++)
	        ((FileListener)listeners.get(i)).fileAborted(e);
	}
	
	/**
	 * 触发文件传输完成事件
	 */
	protected void fireFileFinishedEvent() {
	    FileEvent e = new FileEvent(this);
	    int size = listeners.size();
	    for(int i = 0; i < size; i++)
	        ((FileListener)listeners.get(i)).fileFinished(e);
	}	
	
	/**
	 * 触发文件传送中事件
	 */
	protected void fireFileInProgressEvent() {
	    FileEvent e = new FileEvent(this);
	    int size = listeners.size();
	    for(int i = 0; i < size; i++)
	        ((FileListener)listeners.get(i)).fileInProgress(e);
	}	
	
	/**
	 * 触发连接建立事件
	 */
	protected void fireFileConnectedEvent() {
	    FileEvent e = new FileEvent(this);
	    int size = listeners.size();
	    for(int i = 0; i < size; i++)
	        ((FileListener)listeners.get(i)).fileConnected(e);
	}	
	
	/**
	 * 根据各方的IP情况,得到双方在网络上的处境
	 */
	protected void checkCondition() {
	    if(Utils.isIpEquals(myInternetIp, hisInternetIp)) {
	        setCondition(QQ.QQ_SAME_LAN);
	    } else {
	        boolean amIBehindFirewall = !Utils.isIpEquals(myInternetIp, myLocalIp);
	        boolean isHeBehindFirewall = !Utils.isIpEquals(hisInternetIp, hisLocalIp);
	        if(amIBehindFirewall && isHeBehindFirewall)
	            setCondition(QQ.QQ_ALL_BEHIND_FIREWALL);
	        else if(amIBehindFirewall)
	            setCondition(QQ.QQ_I_AM_BEHIND_FIREWALL);
	        else if(isHeBehindFirewall)
	            setCondition(QQ.QQ_HE_IS_BEHIND_FIREWALL);
	        else
	            setCondition(QQ.QQ_NONE_BEHIND_FIREWALL);
	    }
	}
	
	/**
	 * 关闭守望者
	 */
	public abstract void shutdown();
	
	/**
	 * 取消文件传输
	 */
	public abstract void abort();
	
	/**
	 * 结束文件传输,处理一些善后事宜
	 */
	public abstract void finish();
	
	/**
	 * 打开本地文件准备读和写
	 */
	public abstract boolean openLocalFile();
	
	/**
	 * <pre>
	 * 启动守望者,对于接收者,他将选择一条链路进行连接准备传输
	 * 对于发送者,他将启动两个端口等待对方应答
	 * </pre>
	 */
	public abstract void start();     
	
    /**
     * @return Returns the hisFirstPort.
     */
    public int getHisMajorPort() {
        return hisMajorPort;
    }
    
    /**
     * @param hisFirstPort The hisFirstPort to set.
     */
    public void setHisMajorPort(int hisFirstPort) {
        this.hisMajorPort = hisFirstPort;
    }
    
    /**
     * @return Returns the hisSecondPort.
     */
    public int getHisMinorPort() {
        return hisMinorPort;
    }
    
    /**
     * @param hisSecondPort The hisSecondPort to set.
     */
    public void setHisMinorPort(int hisSecondPort) {
        this.hisMinorPort = hisSecondPort;
    }
    
    /**
     * @return Returns the myFirstPort.
     */
    public int getMyMajorPort() {
        return myMajorPort;
    }
    
    /**
     * @param myFirstPort The myFirstPort to set.
     */
    public void setMyMajorPort(int myFirstPort) {
        this.myMajorPort = myFirstPort;
    }
    
    /**
     * @return Returns the mySecondPort.
     */
    public int getMyMinorPort() {
        return myMinorPort;
    }
    
    /**
     * @param mySecondPort The mySecondPort to set.
     */
    public void setMyMinorPort(int mySecondPort) {
        this.myMinorPort = mySecondPort;
    }
    
    /**
     * @return Returns the myExternalPort.
     */
    public int getMyInternetPort() {
        return myInternetPort;
    }

⌨️ 快捷键说明

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