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.context.TorrentContext;
|
||||
import net.torrent.torrent.piece.PieceSelector;
|
||||
import net.torrent.torrent.piece.RandomPieceSelector;
|
||||
import net.torrent.torrent.piece.ScoredPieceSelector;
|
||||
|
||||
/**
|
||||
* Factory class for {@link BitTorrentClient}.
|
||||
@@ -88,7 +88,7 @@ public class BitTorrentClientFactory {
|
||||
this.datastore = new PlainTorrentDatastore(new File("store.bin"));
|
||||
this.manager = new TorrentManager(context, datastore);
|
||||
if (this.selector == null)
|
||||
this.selector = new RandomPieceSelector(manager);
|
||||
this.selector = new ScoredPieceSelector(manager);
|
||||
this.algorithm = new TorrentStdAlgorithm(manager, selector);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public class BitTorrentClientFactory {
|
||||
this.datastore = datastore;
|
||||
this.manager = new TorrentManager(context, datastore);
|
||||
if (this.selector == null)
|
||||
this.selector = new RandomPieceSelector(manager);
|
||||
this.selector = new ScoredPieceSelector(manager);
|
||||
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.peerwire.manager.TorrentManager;
|
||||
import net.torrent.torrent.piece.PieceSelector;
|
||||
import net.torrent.torrent.piece.ScoredPieceSelector;
|
||||
|
||||
/**
|
||||
* Standard torrent algorithm
|
||||
@@ -30,8 +29,6 @@ import net.torrent.torrent.piece.ScoredPieceSelector;
|
||||
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||
*/
|
||||
public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
||||
private final PieceSelector pieceSelector;
|
||||
|
||||
private final TorrentPeerAlgorithm peerAlgorithm;
|
||||
private final TorrentInterestAlgorithm interestAlgorithm;
|
||||
private final TorrentPieceDownloadAlgorithm downloadAlgorithm;
|
||||
@@ -39,8 +36,6 @@ public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
||||
|
||||
public TorrentStdAlgorithm(final TorrentManager manager,
|
||||
final PieceSelector selector) {
|
||||
pieceSelector = new ScoredPieceSelector(manager);
|
||||
|
||||
peerAlgorithm = new TorrentStdPeerAlgorithm(manager);
|
||||
interestAlgorithm = new TorrentStdInterestAlgorithm(manager, selector);
|
||||
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 {
|
||||
if (e.getMessage() instanceof HandshakeMessage) {
|
||||
if (state.hasHandshaked())
|
||||
throw new IllegalStateException("Handshake has already been sent");
|
||||
throw new IllegalStateException(
|
||||
"Handshake has already been sent");
|
||||
e.getFuture().addListener(new ChannelFutureListener() {
|
||||
@Override
|
||||
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.message.HandshakeMessage;
|
||||
import net.torrent.torrent.context.TorrentPeer;
|
||||
import net.torrent.torrent.context.TorrentPeerID;
|
||||
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
||||
import net.torrent.torrent.context.TorrentPeerID;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Set;
|
||||
import net.torrent.protocol.peerwire.PeerWirePeer;
|
||||
import net.torrent.torrent.context.TorrentContext;
|
||||
import net.torrent.torrent.context.TorrentPeer;
|
||||
import net.torrent.util.PeerCallback;
|
||||
import net.torrent.util.PeerWirePeerCallback;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
|
||||
@@ -101,7 +101,8 @@ public class HandshakeMessage implements PeerWireWritableMessage,
|
||||
|
||||
@Override
|
||||
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() {
|
||||
|
||||
@@ -20,17 +20,19 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.torrent.protocol.tracker.message.PeerListMessage.PeerInfo;
|
||||
import net.torrent.torrent.Torrent;
|
||||
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||
*/
|
||||
public class TorrentContext {
|
||||
/**
|
||||
* The torrent metadata object
|
||||
*/
|
||||
private final Torrent torrent;
|
||||
/**
|
||||
* The bitfield
|
||||
* The current torrent bitfield
|
||||
*/
|
||||
private final TorrentBitfield bitfield = new TorrentBitfield(this);
|
||||
|
||||
@@ -116,14 +118,38 @@ public class TorrentContext {
|
||||
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) {
|
||||
return swarm.getPeer(peerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the peer with the given address
|
||||
*
|
||||
* @param address
|
||||
* the address
|
||||
* @return the found peer
|
||||
*/
|
||||
public TorrentPeer getPeer(InetSocketAddress 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) {
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user