mirror of
https://github.com/Rogiel/torrent4j
synced 2025-12-06 07:32:47 +00:00
Change-Id: Ia6b615902a24432719bad9ae1c3a513012c2a9cf
This commit is contained in:
@@ -28,7 +28,7 @@ import net.torrent.protocol.peerwire.manager.TorrentManager;
|
|||||||
import net.torrent.torrent.Torrent;
|
import net.torrent.torrent.Torrent;
|
||||||
import net.torrent.torrent.context.TorrentContext;
|
import net.torrent.torrent.context.TorrentContext;
|
||||||
import net.torrent.torrent.piece.PieceSelector;
|
import net.torrent.torrent.piece.PieceSelector;
|
||||||
import net.torrent.torrent.piece.RandomPieceSelector;
|
import net.torrent.torrent.piece.ScoredPieceSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory class for {@link BitTorrentClient}.
|
* Factory class for {@link BitTorrentClient}.
|
||||||
@@ -88,7 +88,7 @@ public class BitTorrentClientFactory {
|
|||||||
this.datastore = new PlainTorrentDatastore(new File("store.bin"));
|
this.datastore = new PlainTorrentDatastore(new File("store.bin"));
|
||||||
this.manager = new TorrentManager(context, datastore);
|
this.manager = new TorrentManager(context, datastore);
|
||||||
if (this.selector == null)
|
if (this.selector == null)
|
||||||
this.selector = new RandomPieceSelector(manager);
|
this.selector = new ScoredPieceSelector(manager);
|
||||||
this.algorithm = new TorrentStdAlgorithm(manager, selector);
|
this.algorithm = new TorrentStdAlgorithm(manager, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public class BitTorrentClientFactory {
|
|||||||
this.datastore = datastore;
|
this.datastore = datastore;
|
||||||
this.manager = new TorrentManager(context, datastore);
|
this.manager = new TorrentManager(context, datastore);
|
||||||
if (this.selector == null)
|
if (this.selector == null)
|
||||||
this.selector = new RandomPieceSelector(manager);
|
this.selector = new ScoredPieceSelector(manager);
|
||||||
this.algorithm = new TorrentStdAlgorithm(manager, selector);
|
this.algorithm = new TorrentStdAlgorithm(manager, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import net.torrent.protocol.algorithm.TorrentPieceDownloadAlgorithm;
|
|||||||
import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm;
|
import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm;
|
||||||
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
||||||
import net.torrent.torrent.piece.PieceSelector;
|
import net.torrent.torrent.piece.PieceSelector;
|
||||||
import net.torrent.torrent.piece.ScoredPieceSelector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard torrent algorithm
|
* Standard torrent algorithm
|
||||||
@@ -30,8 +29,6 @@ import net.torrent.torrent.piece.ScoredPieceSelector;
|
|||||||
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
*/
|
*/
|
||||||
public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
||||||
private final PieceSelector pieceSelector;
|
|
||||||
|
|
||||||
private final TorrentPeerAlgorithm peerAlgorithm;
|
private final TorrentPeerAlgorithm peerAlgorithm;
|
||||||
private final TorrentInterestAlgorithm interestAlgorithm;
|
private final TorrentInterestAlgorithm interestAlgorithm;
|
||||||
private final TorrentPieceDownloadAlgorithm downloadAlgorithm;
|
private final TorrentPieceDownloadAlgorithm downloadAlgorithm;
|
||||||
@@ -39,8 +36,6 @@ public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
|||||||
|
|
||||||
public TorrentStdAlgorithm(final TorrentManager manager,
|
public TorrentStdAlgorithm(final TorrentManager manager,
|
||||||
final PieceSelector selector) {
|
final PieceSelector selector) {
|
||||||
pieceSelector = new ScoredPieceSelector(manager);
|
|
||||||
|
|
||||||
peerAlgorithm = new TorrentStdPeerAlgorithm(manager);
|
peerAlgorithm = new TorrentStdPeerAlgorithm(manager);
|
||||||
interestAlgorithm = new TorrentStdInterestAlgorithm(manager, selector);
|
interestAlgorithm = new TorrentStdInterestAlgorithm(manager, selector);
|
||||||
downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager,
|
downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager,
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rogiel Josias Sulzbach
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package net.torrent.protocol.peerwire.codec;
|
||||||
|
|
||||||
|
import net.torrent.protocol.peerwire.message.BitfieldMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.CancelMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.ChokeMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.HandshakeMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.HaveMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.InterestedMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.KeepAliveMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.NotInterestedMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.PieceMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.PortMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.RequestMessage;
|
||||||
|
import net.torrent.protocol.peerwire.message.UnchokeMessage;
|
||||||
|
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.channel.Channel;
|
||||||
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
import org.jboss.netty.handler.codec.frame.CorruptedFrameException;
|
||||||
|
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BitTorrent has two types of message headers:
|
||||||
|
* <p>
|
||||||
|
* <h1>Handshake message</h1> Handshake messages are composed of 1 byte, which
|
||||||
|
* indicates the size of protocol string ("BitTorrent protocol").
|
||||||
|
* <p>
|
||||||
|
* <h1>Messages</h1> All other messages are 4-byte integer containing the
|
||||||
|
* message length, followed by 1 byte opcode.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Instances of this class keep channel state content and must not be shared nor
|
||||||
|
* cached.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class PeerWireDecoder extends FrameDecoder {
|
||||||
|
private boolean handshaked = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||||
|
ChannelBuffer buffer) throws Exception {
|
||||||
|
buffer.markReaderIndex();
|
||||||
|
|
||||||
|
if (!handshaked) {
|
||||||
|
if (buffer.readableBytes() <= 47) // at least 47 bytes
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final int pstrlen = buffer.readByte();
|
||||||
|
if (buffer.readableBytes() < pstrlen + 47) {
|
||||||
|
buffer.resetReaderIndex();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
buffer.readerIndex(buffer.readerIndex() - 1);
|
||||||
|
|
||||||
|
final HandshakeMessage message = new HandshakeMessage();
|
||||||
|
message.read(buffer);
|
||||||
|
handshaked = true;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
} else {
|
||||||
|
if (buffer.readableBytes() <= 4) {
|
||||||
|
buffer.resetReaderIndex();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = buffer.readInt();
|
||||||
|
if (len == 0) {
|
||||||
|
return new KeepAliveMessage();
|
||||||
|
} else if (buffer.readableBytes() < len) {
|
||||||
|
buffer.resetReaderIndex();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte id = buffer.readByte();
|
||||||
|
final PeerWireReadableMessage message = getMessage(id);
|
||||||
|
if (message == null)
|
||||||
|
// force connection to be closed
|
||||||
|
throw new CorruptedFrameException("unknown message " + id);
|
||||||
|
message.read(buffer);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the message represented by <tt>id</tt>. Will return null if
|
||||||
|
* message id is unknown.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the id of the message
|
||||||
|
* @return the message
|
||||||
|
*/
|
||||||
|
private PeerWireReadableMessage getMessage(byte id) {
|
||||||
|
PeerWireReadableMessage message = null;
|
||||||
|
switch (id) {
|
||||||
|
case BitfieldMessage.MESSAGE_ID:
|
||||||
|
message = new BitfieldMessage();
|
||||||
|
break;
|
||||||
|
case CancelMessage.MESSAGE_ID:
|
||||||
|
message = new CancelMessage();
|
||||||
|
break;
|
||||||
|
case ChokeMessage.MESSAGE_ID:
|
||||||
|
message = new ChokeMessage();
|
||||||
|
break;
|
||||||
|
case HaveMessage.MESSAGE_ID:
|
||||||
|
message = new HaveMessage();
|
||||||
|
break;
|
||||||
|
case InterestedMessage.MESSAGE_ID:
|
||||||
|
message = new InterestedMessage();
|
||||||
|
break;
|
||||||
|
case NotInterestedMessage.MESSAGE_ID:
|
||||||
|
message = new NotInterestedMessage();
|
||||||
|
break;
|
||||||
|
case PieceMessage.MESSAGE_ID:
|
||||||
|
message = new PieceMessage();
|
||||||
|
break;
|
||||||
|
case PortMessage.MESSAGE_ID:
|
||||||
|
message = new PortMessage();
|
||||||
|
break;
|
||||||
|
case RequestMessage.MESSAGE_ID:
|
||||||
|
message = new RequestMessage();
|
||||||
|
break;
|
||||||
|
case UnchokeMessage.MESSAGE_ID:
|
||||||
|
message = new UnchokeMessage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rogiel Josias Sulzbach
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package net.torrent.protocol.peerwire.codec;
|
||||||
|
|
||||||
|
import net.torrent.protocol.peerwire.message.HandshakeMessage;
|
||||||
|
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
|
import org.jboss.netty.channel.Channel;
|
||||||
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages are encoded in {@link PeerWireWritableMessage#write(ChannelBuffer)}
|
||||||
|
* method. Message length is measured automatically by the encoder.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class PeerWireEncoder extends OneToOneEncoder {
|
||||||
|
@Override
|
||||||
|
protected Object encode(ChannelHandlerContext ctx, Channel channel,
|
||||||
|
Object msg) throws Exception {
|
||||||
|
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
|
||||||
|
if (!(msg instanceof PeerWireWritableMessage))
|
||||||
|
return msg;
|
||||||
|
|
||||||
|
if (msg instanceof HandshakeMessage) {
|
||||||
|
final HandshakeMessage message = (HandshakeMessage) msg;
|
||||||
|
message.write(buffer);
|
||||||
|
} else {
|
||||||
|
final PeerWireWritableMessage message = (PeerWireWritableMessage) msg;
|
||||||
|
buffer.writeInt(0); // allocate 4 bytes for header
|
||||||
|
message.write(buffer);
|
||||||
|
int len = buffer.readableBytes();
|
||||||
|
buffer.setInt(0, len - 4);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,7 +66,8 @@ public class PeerWireCodecHandler extends SimpleChannelHandler {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
if (e.getMessage() instanceof HandshakeMessage) {
|
if (e.getMessage() instanceof HandshakeMessage) {
|
||||||
if (state.hasHandshaked())
|
if (state.hasHandshaked())
|
||||||
throw new IllegalStateException("Handshake has already been sent");
|
throw new IllegalStateException(
|
||||||
|
"Handshake has already been sent");
|
||||||
e.getFuture().addListener(new ChannelFutureListener() {
|
e.getFuture().addListener(new ChannelFutureListener() {
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(ChannelFuture future)
|
public void operationComplete(ChannelFuture future)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import net.torrent.protocol.peerwire.PeerWirePeer;
|
|||||||
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
||||||
import net.torrent.protocol.peerwire.message.HandshakeMessage;
|
import net.torrent.protocol.peerwire.message.HandshakeMessage;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
import net.torrent.torrent.context.TorrentPeerID;
|
|
||||||
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
||||||
|
import net.torrent.torrent.context.TorrentPeerID;
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Set;
|
|||||||
import net.torrent.protocol.peerwire.PeerWirePeer;
|
import net.torrent.protocol.peerwire.PeerWirePeer;
|
||||||
import net.torrent.torrent.context.TorrentContext;
|
import net.torrent.torrent.context.TorrentContext;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
|
import net.torrent.util.PeerCallback;
|
||||||
import net.torrent.util.PeerWirePeerCallback;
|
import net.torrent.util.PeerWirePeerCallback;
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ public class HandshakeMessage implements PeerWireWritableMessage,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int length() {
|
public int length() {
|
||||||
return 1 + pstrlen + pstr.length() + 8 + infohash.length + peerId.length;
|
return 1 + pstrlen + pstr.length() + 8 + infohash.length
|
||||||
|
+ peerId.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPstrlen() {
|
public int getPstrlen() {
|
||||||
|
|||||||
@@ -20,17 +20,19 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.torrent.protocol.tracker.message.PeerListMessage.PeerInfo;
|
|
||||||
import net.torrent.torrent.Torrent;
|
import net.torrent.torrent.Torrent;
|
||||||
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
public class TorrentContext {
|
public class TorrentContext {
|
||||||
/**
|
/**
|
||||||
* The torrent metadata object
|
* The torrent metadata object
|
||||||
*/
|
*/
|
||||||
private final Torrent torrent;
|
private final Torrent torrent;
|
||||||
/**
|
/**
|
||||||
* The bitfield
|
* The current torrent bitfield
|
||||||
*/
|
*/
|
||||||
private final TorrentBitfield bitfield = new TorrentBitfield(this);
|
private final TorrentBitfield bitfield = new TorrentBitfield(this);
|
||||||
|
|
||||||
@@ -116,14 +118,38 @@ public class TorrentContext {
|
|||||||
return Collections.unmodifiableSet(unknownPeers);
|
return Collections.unmodifiableSet(unknownPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the peer with the given id
|
||||||
|
*
|
||||||
|
* @param peerId
|
||||||
|
* the peer id
|
||||||
|
* @return the found peer
|
||||||
|
*/
|
||||||
public TorrentPeer getPeer(TorrentPeerID peerId) {
|
public TorrentPeer getPeer(TorrentPeerID peerId) {
|
||||||
return swarm.getPeer(peerId);
|
return swarm.getPeer(peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the peer with the given address
|
||||||
|
*
|
||||||
|
* @param address
|
||||||
|
* the address
|
||||||
|
* @return the found peer
|
||||||
|
*/
|
||||||
public TorrentPeer getPeer(InetSocketAddress address) {
|
public TorrentPeer getPeer(InetSocketAddress address) {
|
||||||
return swarm.getPeer(address);
|
return swarm.getPeer(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to locate a peer first by its id. If no match is found, tries to
|
||||||
|
* lookup by its address.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the peer id
|
||||||
|
* @param address
|
||||||
|
* the peer address
|
||||||
|
* @return the found peer
|
||||||
|
*/
|
||||||
public TorrentPeer getPeer(TorrentPeerID id, InetSocketAddress address) {
|
public TorrentPeer getPeer(TorrentPeerID id, InetSocketAddress address) {
|
||||||
return swarm.getPeer(id, address);
|
return swarm.getPeer(id, address);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
/**
|
/*
|
||||||
|
* Copyright 2011 Rogiel Josias Sulzbach
|
||||||
*
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package net.torrent.torrent.context;
|
package net.torrent.torrent.context;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user