1
0
mirror of https://github.com/Rogiel/torrent4j synced 2025-12-05 23:22:49 +00:00

Change-Id: Ia6b615902a24432719bad9ae1c3a513012c2a9cf

This commit is contained in:
rogiel
2011-05-02 00:05:05 -03:00
parent 9104b584d2
commit ffd0932df6
26 changed files with 263 additions and 31 deletions

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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);
}

View File

@@ -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;