?? filereceiverpacketprocessor.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.filetrans;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.Util;
/**
* <pre>
* 文件接收者的包處理類
* </pre>
*
* @author 馬若劼
*/
public class FileReceiverPacketProcessor {
// Log對象
static Log log = LogFactory.getLog(FileReceiverPacketProcessor.class);
// FileReceiverPacketProcessor從屬的FileReceiver對象
private FileReceiver receiver;
/**
* @param fr
*/
public FileReceiverPacketProcessor(FileReceiver fr) {
receiver = fr;
}
/**
* 處理網絡事件
* @throws IOException
*/
public void processSelectedKeys(ByteBuffer buffer) throws Exception {
// 讀取頭部標志,判斷包類型
buffer.flip();
if(buffer.get() == QQ.QQ_HEADER_03_FAMILY) {
buffer.rewind();
receiver.fdp.parse(buffer);
processFileDataPacket(receiver.fdp);
} else {
buffer.rewind();
receiver.fcp.parse(buffer);
processFileControlPacket(receiver.fcp);
}
}
// 處理文件控制信息包
private void processFileControlPacket(FileControlPacket fcp) throws IOException {
switch(fcp.getCommand()) {
case QQ.QQ_FILE_CMD_PING:
log.debug("收到Init Connection包");
processInitConnection(fcp);
break;
case QQ.QQ_FILE_CMD_SENDER_SAY_HELLO:
log.debug("收到Sender Hello, HelloByte: " + fcp.getHelloByte());
processSenderSayHello(fcp);
break;
case QQ.QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
log.debug("收到Sender Hello Ack, HelloByte: " + fcp.getHelloByte());
break;
case QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO:
log.debug("收到Receiver Hello, HelloByte: " + fcp.getHelloByte());
break;
case QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
log.debug("收到Reciver Hello Ack, HelloByte: " + fcp.getHelloByte());
break;
}
}
/**
* @param packet
* @throws IOException
*/
private void processSenderSayHello(FileControlPacket packet) throws IOException {
packet.setCommand(QQ.QQ_FILE_CMD_SENDER_SAY_HELLO_ACK);
packet.setHelloByte(packet.getHelloByte());
packet.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
log.debug("Sender Hello Ack 已發送");
packet.setCommand(QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO);
packet.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
log.debug("Receiver Hello 已發送");
// 設置提示信息
if(!receiver.monitor.checkDuplicate(packet)) {
receiver.setFileTransferStatus(FileWatcher.FT_RECEIVING);
receiver.fireFileConnectedEvent();
}
}
// 處理003D命令
private void processInitConnection(FileControlPacket packet) throws IOException {
packet.setCommand(QQ.QQ_FILE_CMD_PONG);
packet.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
log.debug("Init Connection Ack 已發送");
}
// 處理文件數據信息包
private void processFileDataPacket(FileDataPacket fdp) throws Exception {
switch(fdp.getCommand()) {
case QQ.QQ_FILE_CMD_HEART_BEAT:
log.debug("收到Heart Beat 序號: " + (int)fdp.getHeartBeatSequence());
// 返回heart beat的確認包
fdp.setCommand(QQ.QQ_FILE_CMD_HEART_BEAT_ACK);
fdp.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
break;
case QQ.QQ_FILE_CMD_HEART_BEAT_ACK:
log.debug("收到Heart Beat回復,序號: " + (int)fdp.getHeartBeatSequence());
break;
case QQ.QQ_FILE_CMD_TRANSFER_FINISHED:
// 返回回復包
fdp.setCommand(QQ.QQ_FILE_CMD_TRANSFER_FINISHED);
fdp.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
if(!receiver.monitor.checkDuplicate(fdp)) {
// 檢查是否已經收到了全部分片,如果不是,表明對方取消了文件傳送
if(receiver.window.isFinished()) {
log.debug("文件傳輸正常結束");
receiver.finish();
} else {
log.debug("文件傳輸取消");
receiver.abort();
}
}
break;
case QQ.QQ_FILE_CMD_FILE_OP:
processFileOp(fdp);
break;
case QQ.QQ_FILE_CMD_FILE_OP_ACK:
break;
}
}
// 處理文件命令,文件命令又包含三種子命令
private void processFileOp(FileDataPacket fdp) throws IOException {
switch(fdp.getInfoType()) {
case QQ.QQ_FILE_BASIC_INFO:
log.debug("收到文件基本信息,文件名: " + fdp.getFileName() + " 大小:" + fdp.getFileSize() + " 分片數: " + fdp.getFragments());
processFileBasicInfo(fdp);
break;
case QQ.QQ_FILE_DATA_INFO:
processFileDataInfo(fdp);
break;
case QQ.QQ_FILE_EOF:
log.debug("收到文件EOF信息包");
processFileEOF(fdp);
break;
}
}
// 處理收到文件結尾信息事件
private void processFileEOF(FileDataPacket packet) throws IOException {
// 檢查是否已經收到了最后一個分片,如果不是,不回復這個EOF包
if(receiver.window.isFinished()) {
packet.setCommand(QQ.QQ_FILE_CMD_FILE_OP_ACK);
packet.setInfoType(QQ.QQ_FILE_EOF);
packet.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
log.debug("File EOF 確認已發送");
if(!receiver.monitor.checkDuplicate(packet))
receiver.fireFileInProgressEvent();
}
}
// 處理收到文件數據信息事件
private void processFileDataInfo(FileDataPacket packet) throws IOException {
// 寫入分片數據到文件
// 推入分片,如果返回false,說明這個分片不在期望接收范圍內,不處理
if(receiver.window.put(packet.getFragmentIndex())) {
log.debug("得到分片數據,偏移: " + packet.getFragmentOffset() + " 分片號: " + packet.getFragmentIndex());
receiver.saveFragment(packet.getFragmentData(), packet.getFragmentOffset());
// 觸發事件,以便GUI能更新進度條
receiver.fireFileInProgressEvent();
// 不管是否已經收到了這個分片,都發送回復包
packet.setCommand(QQ.QQ_FILE_CMD_FILE_OP_ACK);
packet.setInfoType(QQ.QQ_FILE_DATA_INFO);
packet.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
log.debug("分片" + packet.getFragmentIndex() + "的確認已發送");
}
}
// 處理收到文件基本信息事件
private void processFileBasicInfo(FileDataPacket fdp) throws IOException {
// 檢查文件名MD5信息是否正確,不正確則不回復
// TODO 可能實際的QQ處理不同,也許是返回一個錯誤碼,這個還有待研究
String fn = fdp.getFileName();
byte[] fnByte = Util.getBytes(fn);
if(Util.compareMD5(fdp.getFileNameMD5(), Util.doMD5(fnByte))) {
log.debug("文件名MD5正確,開始傳送文件數據");
// 保存得到的文件基本信息
receiver.setFileName(fn);
receiver.setFileSize(fdp.getFileSize());
receiver.setFragments(fdp.getFragments() - 1);
receiver.setMaxFragmentSize(fdp.getFragmentMaxSize());
receiver.setFileMD5(fdp.getFileMD5());
receiver.setFileNameMD5(fdp.getFileNameMD5());
receiver.initSlideWindow(1, 0, receiver.fragments);
// 發送回復包
fdp.setCommand(QQ.QQ_FILE_CMD_FILE_OP_ACK);
fdp.setInfoType(QQ.QQ_FILE_BASIC_INFO);
fdp.fill(receiver.buffer);
receiver.buffer.flip();
receiver.send();
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -