📄 btsocket.java
字号:
/*
* @(#)BTSocket.java ver 1.2 6/20/2005
*
* Copyright 2005 Weishuai Yang (wyang@cs.binghamton.edu).
* All rights reserved.
*
*/
package gps.protocol.BT;
import gps.Simulator;
import gps.event.SimEvent;
import gps.event.SimEventHandler;
import gps.event.SimEventScheduler;
import gps.gui.ProtocolPanel;
import gps.protocol.BT.param.BTPeerMessage;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.logging.Logger;
/**
* BT socket deals with lower level connection issue
*
*
* @author Weishuai Yang
* @version 1.2, 6/20/2005
*/
public class BTSocket implements SimEventHandler {
/**
* request timeout
*/
public static final int REQUEST_TIMEOUT = 5;
/**
* connection timeout
*/
public static final int CONNECTION_TIMEOUT=60;
/**
* keep alive time
*/
public static final int CONNECTION_KEEP_ALIVE=10;
/**
* singleton reference to event scheduler
*/
private static SimEventScheduler mScheduler=SimEventScheduler.getInstance();
/**
* singleton reference to debug log
*/
private static Logger mDebugLog = Logger.getLogger("Debug");
/**
* singleton reference to trace log
*/
private static Logger mTraceLog = Logger.getLogger("Trace");
//choked or not means whether this node allow the counterpart to download
/**
* I chocked the other side
*/
public boolean mAmChoking=true;
/**
* the other side chocked me
*/
public boolean mPeerChoking=true;
//interested or not means whether this node is interested in the content at counterpart's host
/**
* the other side is interested at my file
*/
public boolean mPeerInterested=false;
/**
* I'm interested in their file
*/
public boolean mAmInterested=false;
/**
* bit field of that peer
*/
public boolean mBitField[]=null;
/**
* if closed, set up the mClosed flag, and remove from hashmap
*/
public boolean mClosed=false;
/**
* reference back to the session to which this connection belongs
*/
public BTSession mSession=null;
/**
* the connection at the other side
*/
public BTSocket mCounterpart=null;
/**
* uploading or not
*/
public boolean mUploading=false;
/**
* the current uploading piece index
*/
public int mUploadingPieceIndex=-1;
//following are paramaters recorded at the downloading side
/**
* downloading or not
*/
public boolean mDownloading=false;
/**
* the piece that I'm interested, this variable is set when request is sent
*/
public int mRequestingPieceIndex=-1;
/**
* offset within a downloading piece
*/
public int mBegin=0;
/**
* length of the current downloading block
*/
public int mLength=0;
/**
* start time for this downloading bandwidth
*/
public double mStartTime=0;
/**
* bytes left within this block
*/
public int mDownloadLeft=0;
/**
* previous finished percent
*/
public float mPreviousPercent=0;
/**
* connection time out event
*/
public BTEvent mTimeout=null;
/**
* keep alive event
*/
public BTEvent mKeepAlive=null;
/**
* the keep alive message to be sent
*/
public BTEvent mKeepAliveMsg=null;
/**
* estimate finish event
*/
public BTEvent mEstimateFinish=null;
/**
* request time out event
*/
public BTEvent mRequestTimeout=null;
/**
* lower level connection
*/
public BTConnection mConnection=null;
/**
* in bandwidth history
*/
public LinkedList mInBandwidthHistory=new LinkedList();
/**
* out bandwidth history
*/
public LinkedList mOutBandwidthHistory=new LinkedList();
/**
* constructs a new bt socket object
* @param s session this socket belongs to
*/
public BTSocket(BTSession s){
mSession=s;
}
/**
* process event sent to this connection
* @param e the event object with some parameters in it
* @return true if already handled
*/
public boolean handle(SimEvent e) {
switch(e.getType()){
//all the following events come from itself
case BTEvent.CONNECTION_DOWNLOAD_BLOCK_FINISH:
handleBlockFinished((BTEvent)e);
return true;
case BTEvent.REQUEST_TIMEOUT:
handleRequestTimeout((BTEvent)e);
return true;
case BTEvent.CONNECTION_KEEP_ALIVE:
handleKeepAlive((BTEvent)e);
return true;
}
return false;
}
/**
* handles request timeout event
* @param e the event object
*/
public void handleRequestTimeout(BTEvent e){
BTPeer p=(BTPeer)e.getAddParam();
if(mSession.mRemoved) return;
if(!mSession.getConnections().containsKey(p))
return;
//mDebugLog.info(mScheduler.getCurrent()+": "+toString()+" request timeout!");
//make the next request possible, otherwise the next request will never be sent
if(mRequestingPieceIndex==-1)
mDebugLog.warning(mScheduler.getCurrent()+": "+toString()+" mRequestingPieceIndex is not supposed to be -1 when request timeout!");
if(!mSession.getDocument().inDownloadingSet(mRequestingPieceIndex))
mDebugLog.warning(mScheduler.getCurrent()+": "+toString()+" mRequestingPieceIndex should be in downloading set when request timeout!");
mSession.getDocument().removePieceDownloading(mRequestingPieceIndex);
if(mSession.getDocument().inPartialList(mRequestingPieceIndex)){
if(0==mSession.getDocument().getPieceProgress(mRequestingPieceIndex)){
mSession.getDocument().removePieceProgress(mRequestingPieceIndex);
}
}
mRequestingPieceIndex=-1;
mRequestTimeout=null;
if(!mPeerChoking){
mSession.sendRequestTo(p);
}
}
/**
* handles keep alive event
* @param e the event object
*/
public void handleKeepAlive(BTEvent e){
//send out a keep alive peer message
ArrayList morePieces=comparePieces();
if(morePieces.size()>0)
{
if(mCounterpart==null) {
mDebugLog.warning(mScheduler.getCurrent()+": "+this+" in keep alive, return since counterpart is null");
return;
}
if(mKeepAliveMsg==null){
String key=mSession.getDocument().getKey();
BTPeerMessage btpm=new BTPeerMessage(BTPeerMessage.KEEP_ALIVE);
btpm.mDocHashKey=key;
double t=mScheduler.getCurrent()+BT.getInstance().getDelayAgent(mSession.getAgent(),mCounterpart.mSession.getAgent());
BTEvent bte=new BTEvent(t, BTEvent.PEER_MESSAGE, (SimEventHandler)(mCounterpart.mSession), mSession);
bte.setAddParam(btpm);
mScheduler.enqueue(bte);
mKeepAliveMsg=bte;
}
else{
double t=mScheduler.getCurrent()+BT.getInstance().getDelayAgent(mSession.getAgent(),mCounterpart.mSession.getAgent());
mKeepAliveMsg.setTimeStamp(t);
mScheduler.enqueue(mKeepAliveMsg);
}
//enqueue next keep alive event
double t=mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE;
mKeepAlive.setTimeStamp(t);
mScheduler.enqueue(mKeepAlive);
//extend connection timeout to keep alive
if(mTimeout.getTimeStamp()<mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE){
mScheduler.cancel(mTimeout);
mTimeout.setTimeStamp(mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE);
mScheduler.enqueue(mTimeout);
//mDebugLog.info(mScheduler.getCurrent()+": "+mAgent+", received "+btpm+", connection timeout updated1 to " +(mScheduler.getCurrent()+BTSocket.CONNECTION_TIMEOUT)+" for connection to "+bts.getAgent());
}
}
}
/**
* compare piece between two peers at both end of the connection
* @return array of piece index that doesn't existing at local, but existing at remote
*/
public ArrayList comparePieces(){
BTDocument btd=mSession.getDocument();
//pieces this node already has
boolean pieces[]=btd.getPieces();
//pieces peer node has
boolean peerPieces[]=mBitField;
if(mBitField==null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -