diff --git a/.classpath b/.classpath index ad81989..5776e5f 100644 --- a/.classpath +++ b/.classpath @@ -4,8 +4,8 @@ - - + + diff --git a/.gitignore b/.gitignore index e351214..f709ad4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /target /store.bin /target +/logging.properties diff --git a/.project b/.project index f9ad6f7..4650023 100644 --- a/.project +++ b/.project @@ -11,12 +11,13 @@ - org.maven.ide.eclipse.maven2Builder + org.eclipse.m2e.core.maven2Builder + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature org.maven.ide.eclipse.maven2Nature diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 3940f5a..aba7c47 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,3 +1,6 @@ -#Thu Apr 28 01:49:42 BRT 2011 +#Wed Sep 14 13:05:56 BRT 2011 eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..a5162ba --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,5 @@ +#Wed Sep 14 13:04:25 BRT 2011 +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/pom.xml b/pom.xml index 8570a1c..1746279 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ libtorrent jar libtorrent - 1.0.0-alpha2 + 1.0.0-alpha2.1 Java library used for downloading and uploading torrent files http://code.google.com/p/libtorrent-java @@ -35,6 +35,11 @@ 3.2.4.Final compile + + org.slf4j + slf4j-api + 1.6.2 + @@ -47,12 +52,18 @@ junit 4.8.2 jar - compile + test + + + org.slf4j + slf4j-jdk14 + 1.6.2 + runtime - package + assembly @@ -68,6 +79,15 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + org.apache.maven.plugins @@ -97,30 +117,34 @@ + + + + + + + + + + + + + + org.apache.maven.plugins - maven-pdf-plugin - 1.1 + maven-assembly-plugin + + + src/assembly/distribution-bin.xml + + - pdf + jar package - pdf - - - - - - org.apache.maven.plugins - maven-clean-plugin - 2.4.1 - - - clean - package - - clean + assembly diff --git a/src/assembly/distribution-bin.xml b/src/assembly/distribution-bin.xml new file mode 100644 index 0000000..51bbd69 --- /dev/null +++ b/src/assembly/distribution-bin.xml @@ -0,0 +1,33 @@ + + bin + + tar.gz + tar.bz2 + zip + + + + + ${project.build.directory} + / + + ${project.artifactId}-${project.version}.jar + ${project.artifactId}-${project.version}-javadoc.jar + + + + + + /libs + true + false + runtime + + net.bittorrent:libtorrent + + + + \ No newline at end of file diff --git a/src/main/java/net/torrent/BitTorrentClient.java b/src/main/java/net/torrent/BitTorrentClient.java index 7c77786..d1c3acd 100644 --- a/src/main/java/net/torrent/BitTorrentClient.java +++ b/src/main/java/net/torrent/BitTorrentClient.java @@ -15,16 +15,24 @@ */ package net.torrent; +import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; +import java.net.MalformedURLException; import java.util.Timer; import java.util.TimerTask; import net.torrent.protocol.algorithm.TorrentAlgorithm; import net.torrent.protocol.peerwire.PeerWireManager; import net.torrent.protocol.peerwire.manager.TorrentManager; +import net.torrent.protocol.tracker.HttpTorrentTrackerAnnouncer; import net.torrent.torrent.context.TorrentContext; import net.torrent.torrent.context.TorrentPeer; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This is the main class used to controll your torrent transfer. It is not * recommended to directly instantiate this class, instead use @@ -33,6 +41,11 @@ import net.torrent.torrent.context.TorrentPeer; * @author Rogiel Josias Sulzbach */ public class BitTorrentClient implements Runnable { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * Configuration of an BitTorrentClient. */ @@ -100,8 +113,21 @@ public class BitTorrentClient implements Runnable { if (config.getListenPort() > 0) peerWire.listen(config.getListenPort()); + final HttpTorrentTrackerAnnouncer announcer = new HttpTorrentTrackerAnnouncer( + context.getSwarm()); + try { + announcer.announce(context.getTorrent().getTrackers().iterator() + .next()); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // run every 10 seconds - only 1 connection per turn - connectorTimer.schedule(new ConnectorTimerTask(), 0, 10 * 1000); + connectorTimer.schedule(new ConnectorTimerTask(), 0 * 1000, 2 * 1000); if (addrs != null) for (final InetSocketAddress addr : addrs) { @@ -121,8 +147,17 @@ public class BitTorrentClient implements Runnable { public void run() { TorrentPeer peer = null; while ((peer = algorithm.getPeerAlgorithm().connect()) != null) { - peerWire.connect(peer.getSocketAddress()); + log.debug("Connecting to {}", peer); + try { + if (!peerWire.connect(peer.getSocketAddress()).await() + .isSuccess()) { + peer.setAccessible(false); + } + } catch (InterruptedException e) { + } + return; } + log.debug("No new peers to connect"); } } diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdAlgorithm.java index 4738f5b..e1b4d06 100644 --- a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdAlgorithm.java +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdAlgorithm.java @@ -36,11 +36,18 @@ public class TorrentStdAlgorithm implements TorrentAlgorithm { public TorrentStdAlgorithm(final TorrentManager manager, final PieceSelector selector) { - peerAlgorithm = new TorrentStdPeerAlgorithm(manager); - interestAlgorithm = new TorrentStdInterestAlgorithm(manager, selector); - downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager, + final TorrentStdAlgorithmContext ctx = new TorrentStdAlgorithmContext(); + + peerAlgorithm = new TorrentStdPeerAlgorithm(manager, ctx); + interestAlgorithm = new TorrentStdInterestAlgorithm(manager, ctx, selector); + downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager, ctx, selector); - uploadAlgorithm = new TorrentStdPieceUploadAlgorithm(manager); + uploadAlgorithm = new TorrentStdPieceUploadAlgorithm(manager, ctx); + } + + protected class TorrentStdAlgorithmContext { + public int downloadingPieces = 0; + public int activeConnections = 0; } @Override diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdInterestAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdInterestAlgorithm.java index 1b86b46..8c5fdac 100644 --- a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdInterestAlgorithm.java +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdInterestAlgorithm.java @@ -16,23 +16,36 @@ package net.torrent.protocol.algorithm.impl; import net.torrent.protocol.algorithm.TorrentInterestAlgorithm; +import net.torrent.protocol.algorithm.impl.TorrentStdAlgorithm.TorrentStdAlgorithmContext; import net.torrent.protocol.peerwire.manager.TorrentManager; import net.torrent.torrent.context.TorrentPeer; import net.torrent.torrent.context.TorrentPeer.ChokingState; import net.torrent.torrent.context.TorrentPeer.InterestState; import net.torrent.torrent.piece.PieceSelector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Standard torrent interest algorithm * * @author Rogiel Josias Sulzbach */ public class TorrentStdInterestAlgorithm implements TorrentInterestAlgorithm { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * The torrent manager */ @SuppressWarnings("unused") private final TorrentManager manager; + /** + * The algorithm context + */ + private final TorrentStdAlgorithmContext context; /** * This selector is used to find the next piece to be downloaded. Parts are @@ -49,21 +62,32 @@ public class TorrentStdInterestAlgorithm implements TorrentInterestAlgorithm { * the piece selector */ public TorrentStdInterestAlgorithm(TorrentManager manager, - PieceSelector selector) { + TorrentStdAlgorithmContext context, PieceSelector selector) { this.manager = manager; + this.context = context; this.selector = selector; } @Override public InterestState interested(TorrentPeer peer) { + log.debug("Checking interest in peer {}", peer); + if (context.downloadingPieces >= 10) { + log.debug("Already downloading 10 or more pieces, no interest in {}", peer); + return InterestState.UNINTERESTED; + } + int pieces = selector.countPieces(peer); - if (pieces >= 5) + if (pieces >= 5) { + log.debug("Peer {} has {} interesting pieces", peer, pieces); return InterestState.INTERESTED; + } + log.debug("Peer {} does not have 5 or more pieces we dont have", peer); return InterestState.INTERESTED; } @Override public ChokingState choke(TorrentPeer peer) { + log.debug("Never choke peer {}", peer); return ChokingState.UNCHOKED; } } diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPeerAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPeerAlgorithm.java index a132cd0..544f093 100644 --- a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPeerAlgorithm.java +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPeerAlgorithm.java @@ -16,6 +16,7 @@ package net.torrent.protocol.algorithm.impl; import net.torrent.protocol.algorithm.TorrentPeerAlgorithm; +import net.torrent.protocol.algorithm.impl.TorrentStdAlgorithm.TorrentStdAlgorithmContext; import net.torrent.protocol.peerwire.manager.TorrentManager; import net.torrent.torrent.context.TorrentPeer; import net.torrent.torrent.context.TorrentPeer.ChokingState; @@ -27,16 +28,23 @@ import net.torrent.torrent.context.TorrentPeer.InterestState; * @author Rogiel Josias Sulzbach */ public class TorrentStdPeerAlgorithm implements TorrentPeerAlgorithm { - @SuppressWarnings("unused") private final TorrentManager manager; + /** + * The algorithm context + */ + private final TorrentStdAlgorithmContext context; - public TorrentStdPeerAlgorithm(TorrentManager manager) { + public TorrentStdPeerAlgorithm(TorrentManager manager, + TorrentStdAlgorithmContext context) { this.manager = manager; + this.context = context; } @Override public TorrentPeer connect() { - return null; + if (context.activeConnections >= 30) + return null; + return manager.getContext().getSwarm().getRandomPeer(); } @Override diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceDownloadAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceDownloadAlgorithm.java index 138d60e..dd69362 100644 --- a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceDownloadAlgorithm.java +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceDownloadAlgorithm.java @@ -19,6 +19,7 @@ import java.util.HashSet; import java.util.Set; import net.torrent.protocol.algorithm.TorrentPieceDownloadAlgorithm; +import net.torrent.protocol.algorithm.impl.TorrentStdAlgorithm.TorrentStdAlgorithmContext; import net.torrent.protocol.peerwire.manager.TorrentManager; import net.torrent.torrent.TorrentPart; import net.torrent.torrent.TorrentPiece; @@ -39,6 +40,10 @@ public class TorrentStdPieceDownloadAlgorithm implements * The torrent manager */ private final TorrentManager manager; + /** + * The algorithm context + */ + private final TorrentStdAlgorithmContext context; /** * This selector is used to find the next piece to be downloaded. Parts are @@ -64,9 +69,10 @@ public class TorrentStdPieceDownloadAlgorithm implements * @param selector * the piece selector */ - public TorrentStdPieceDownloadAlgorithm(TorrentManager manager, + public TorrentStdPieceDownloadAlgorithm(TorrentManager manager,TorrentStdAlgorithmContext context, PieceSelector selector) { this.manager = manager; + this.context = context; this.selector = selector; } diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceUploadAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceUploadAlgorithm.java index f01a4b0..17f439f 100644 --- a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceUploadAlgorithm.java +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentStdPieceUploadAlgorithm.java @@ -16,6 +16,7 @@ package net.torrent.protocol.algorithm.impl; import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm; +import net.torrent.protocol.algorithm.impl.TorrentStdAlgorithm.TorrentStdAlgorithmContext; import net.torrent.protocol.peerwire.manager.TorrentManager; import net.torrent.torrent.TorrentPart; import net.torrent.torrent.context.TorrentPeer; @@ -29,9 +30,15 @@ public class TorrentStdPieceUploadAlgorithm implements TorrentPieceUploadAlgorithm { @SuppressWarnings("unused") private final TorrentManager manager; + /** + * The algorithm context + */ + private final TorrentStdAlgorithmContext context; - public TorrentStdPieceUploadAlgorithm(TorrentManager manager) { + public TorrentStdPieceUploadAlgorithm(TorrentManager manager, + TorrentStdAlgorithmContext context) { this.manager = manager; + this.context = context; } @Override diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestAlgorithm.java new file mode 100644 index 0000000..0e0445b --- /dev/null +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestAlgorithm.java @@ -0,0 +1,65 @@ +/* + * 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.algorithm.impl; + +import net.torrent.protocol.algorithm.TorrentAlgorithm; +import net.torrent.protocol.algorithm.TorrentInterestAlgorithm; +import net.torrent.protocol.algorithm.TorrentPeerAlgorithm; +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; + +/** + * Standard torrent algorithm + * + * @author Rogiel Josias Sulzbach + */ +public class TorrentTestAlgorithm implements TorrentAlgorithm { + private final TorrentPeerAlgorithm peerAlgorithm; + private final TorrentInterestAlgorithm interestAlgorithm; + private final TorrentPieceDownloadAlgorithm downloadAlgorithm; + private final TorrentPieceUploadAlgorithm uploadAlgorithm; + + public TorrentTestAlgorithm(final TorrentManager manager, + final PieceSelector selector) { + peerAlgorithm = new TorrentTestPeerAlgorithm(manager); + interestAlgorithm = new TorrentTestInterestAlgorithm(manager, selector); + downloadAlgorithm = new TorrentTestPieceDownloadAlgorithm(manager, + selector); + uploadAlgorithm = new TorrentTestPieceUploadAlgorithm(manager); + } + + @Override + public TorrentPeerAlgorithm getPeerAlgorithm() { + return peerAlgorithm; + } + + @Override + public TorrentInterestAlgorithm getInterestAlgorithm() { + return interestAlgorithm; + } + + @Override + public TorrentPieceDownloadAlgorithm getDownloadAlgorithm() { + return downloadAlgorithm; + } + + @Override + public TorrentPieceUploadAlgorithm getUploadAlgorithm() { + return uploadAlgorithm; + } +} diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestInterestAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestInterestAlgorithm.java new file mode 100644 index 0000000..ef681a2 --- /dev/null +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestInterestAlgorithm.java @@ -0,0 +1,69 @@ +/* + * 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.algorithm.impl; + +import net.torrent.protocol.algorithm.TorrentInterestAlgorithm; +import net.torrent.protocol.peerwire.manager.TorrentManager; +import net.torrent.torrent.context.TorrentPeer; +import net.torrent.torrent.context.TorrentPeer.ChokingState; +import net.torrent.torrent.context.TorrentPeer.InterestState; +import net.torrent.torrent.piece.PieceSelector; + +/** + * Standard torrent interest algorithm + * + * @author Rogiel Josias Sulzbach + */ +public class TorrentTestInterestAlgorithm implements TorrentInterestAlgorithm { + /** + * The torrent manager + */ + @SuppressWarnings("unused") + private final TorrentManager manager; + + /** + * This selector is used to find the next piece to be downloaded. Parts are + * managed inside this algorithm. + */ + private final PieceSelector selector; + + /** + * Creates a new instance + * + * @param manager + * the manager + * @param selector + * the piece selector + */ + public TorrentTestInterestAlgorithm(TorrentManager manager, + PieceSelector selector) { + this.manager = manager; + this.selector = selector; + } + + @Override + public InterestState interested(TorrentPeer peer) { + int pieces = selector.countPieces(peer); + if (pieces >= 5) + return InterestState.INTERESTED; + return InterestState.INTERESTED; + } + + @Override + public ChokingState choke(TorrentPeer peer) { + return ChokingState.UNCHOKED; + } +} diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPeerAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPeerAlgorithm.java new file mode 100644 index 0000000..76a589e --- /dev/null +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPeerAlgorithm.java @@ -0,0 +1,73 @@ +/* + * 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.algorithm.impl; + +import net.torrent.protocol.algorithm.TorrentPeerAlgorithm; +import net.torrent.protocol.peerwire.manager.TorrentManager; +import net.torrent.torrent.context.TorrentPeer; +import net.torrent.torrent.context.TorrentPeer.ChokingState; +import net.torrent.torrent.context.TorrentPeer.InterestState; + +/** + * Standard torrent peer algorithm + * + * @author Rogiel Josias Sulzbach + */ +public class TorrentTestPeerAlgorithm implements TorrentPeerAlgorithm { + @SuppressWarnings("unused") + private final TorrentManager manager; + + public TorrentTestPeerAlgorithm(TorrentManager manager) { + this.manager = manager; + } + + @Override + public TorrentPeer connect() { + return null; + } + + @Override + public PeerDiscoveredAction discovered(TorrentPeer peer) { + return PeerDiscoveredAction.CONNECT; + } + + @Override + public KeepAliveAction keepAlive(TorrentPeer peer) { + return KeepAliveAction.KEEP_ALIVE; + } + + @Override + public ChokingState interested(TorrentPeer peer, InterestState interest) { + switch (interest) { + case INTERESTED: + return ChokingState.UNCHOKED; + case UNINTERESTED: + return ChokingState.CHOKED; + } + return null; + } + + @Override + public PeerChokedAction choked(TorrentPeer peer, ChokingState state) { + switch (state) { + case CHOKED: + return PeerChokedAction.NONE; + case UNCHOKED: + return PeerChokedAction.DOWNLOAD; + } + return null; + } +} diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceDownloadAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceDownloadAlgorithm.java new file mode 100644 index 0000000..19e5b90 --- /dev/null +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceDownloadAlgorithm.java @@ -0,0 +1,118 @@ +/* + * 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.algorithm.impl; + +import java.util.HashSet; +import java.util.Set; + +import net.torrent.protocol.algorithm.TorrentPieceDownloadAlgorithm; +import net.torrent.protocol.peerwire.manager.TorrentManager; +import net.torrent.torrent.TorrentPart; +import net.torrent.torrent.TorrentPiece; +import net.torrent.torrent.context.TorrentPeer; +import net.torrent.torrent.piece.PieceSelector; + +/** + * This standard implementation of {@link TorrentPieceDownloadAlgorithm} chooses + * a random missing piece and tries to download all the parts from the same + * peer, following the standard behavior of most of torrent clients. + * + * @author Rogiel Josias Sulzbach + */ +// TODO separate standard algorithm from extension ones +public class TorrentTestPieceDownloadAlgorithm implements + TorrentPieceDownloadAlgorithm { + /** + * The torrent manager + */ + private final TorrentManager manager; + + /** + * This selector is used to find the next piece to be downloaded. Parts are + * managed inside this algorithm. + */ + private final PieceSelector selector; + /** + * Maps all unchecked completed pieces. The piece is removed from the list + * once + * {@link TorrentPieceDownloadAlgorithm#isComplete(TorrentPeer, TorrentPiece)} + * is called. + */ + private Set completedPieces = new HashSet(); + + /** + * Creates a new instance of this algorithm. + * + * @param manager + * the torrent manager instance. With this object is possible to + * retrieve current downloads/uploads and connections. + * @param pieceSelector + * the piece selector + * @param selector + * the piece selector + */ + public TorrentTestPieceDownloadAlgorithm(TorrentManager manager, + PieceSelector selector) { + this.manager = manager; + this.selector = selector; + } + + @Override + public TorrentPart getNextPart(TorrentPeer peer, TorrentPart part) { + if (part != null) { + if (part.isLast()) { + completedPieces.add(part.getPiece()); + } else { + return part.getNextPart(); + } + } + TorrentPiece piece = selector.select(peer); + if (piece == null) + // no piece, return null. The default handler will check, again, the + // interest on this peer. + return null; + return piece.getFirstPart(); + } + + @Override + public TorrentPart sugested(TorrentPeer peer, TorrentPiece piece) { + return piece.getFirstPart(); + } + + @Override + public TorrentPart allowedFast(TorrentPeer peer, TorrentPiece piece) { + return piece.getFirstPart(); + } + + @Override + public RejectAction rejected(TorrentPeer peer, TorrentPart part) { + return RejectAction.TRY_ANOTHER_PIECE; + } + + @Override + public boolean isComplete(TorrentPeer peer, TorrentPiece piece) { + if (manager.getContext().getBitfield().hasPiece(piece)) + return true; + // minimum overhead possible, will return true if was on list + return completedPieces.remove(piece); + } + + @Override + public CorruptedAction corrupted(TorrentPeer peer, TorrentPiece piece) { + // TODO ban peer sending many corrupted pieces + return CorruptedAction.CANCEL; + } +} diff --git a/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceUploadAlgorithm.java b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceUploadAlgorithm.java new file mode 100644 index 0000000..1e846a4 --- /dev/null +++ b/src/main/java/net/torrent/protocol/algorithm/impl/TorrentTestPieceUploadAlgorithm.java @@ -0,0 +1,47 @@ +/* + * 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.algorithm.impl; + +import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm; +import net.torrent.protocol.peerwire.manager.TorrentManager; +import net.torrent.torrent.TorrentPart; +import net.torrent.torrent.context.TorrentPeer; + +/** + * Standard torrent upload algorithm + * + * @author Rogiel Josias Sulzbach + */ +public class TorrentTestPieceUploadAlgorithm implements + TorrentPieceUploadAlgorithm { + @SuppressWarnings("unused") + private final TorrentManager manager; + + public TorrentTestPieceUploadAlgorithm(TorrentManager manager) { + this.manager = manager; + } + + @Override + public RequestAction request(TorrentPeer peer, TorrentPart part) { + return RequestAction.NONE; + } + + @Override + public boolean cancel(TorrentPeer peer, TorrentPart part) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/net/torrent/protocol/peerwire/PeerWirePeer.java b/src/main/java/net/torrent/protocol/peerwire/PeerWirePeer.java index 9b1fdb9..a0474e6 100644 --- a/src/main/java/net/torrent/protocol/peerwire/PeerWirePeer.java +++ b/src/main/java/net/torrent/protocol/peerwire/PeerWirePeer.java @@ -44,6 +44,8 @@ import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * An PeerWire Peer manages the {@link Channel channel} (the current peer @@ -54,6 +56,11 @@ import org.jboss.netty.channel.ChannelFutureListener; * @author Rogiel Josias Sulzbach */ public class PeerWirePeer { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * The active {@link Channel} */ @@ -109,11 +116,14 @@ public class PeerWirePeer { public void choke() { if (peer.getChokingState() == ChokingState.CHOKED) return; + log.debug("Chocking peer {}", this); + write(new ChokeMessage()).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { + log.debug("Chocked peer {}", this); peer.setChokingState(ChokingState.CHOKED); } } @@ -126,11 +136,14 @@ public class PeerWirePeer { public void unchoke() { if (peer.getChokingState() == ChokingState.UNCHOKED) return; + log.debug("Unchocking peer {}", this); + write(new UnchokeMessage()).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { + log.debug("Unchocked peer {}", this); peer.setChokingState(ChokingState.UNCHOKED); } } @@ -143,11 +156,14 @@ public class PeerWirePeer { public void interested() { if (peer.getInterestState() == InterestState.INTERESTED) return; + log.debug("Informing interest in peer {}", this); + write(new InterestedMessage()).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { + log.debug("Interest informed to peer {}", this); peer.setInterestState(InterestState.INTERESTED); } } @@ -160,12 +176,15 @@ public class PeerWirePeer { public void uninterested() { if (peer.getInterestState() == InterestState.UNINTERESTED) return; + log.debug("Informing no interest to peer {}", this); + write(new NotInterestedMessage()).addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { + log.debug("No interest informed to peer {}", this); peer.setInterestState(InterestState.UNINTERESTED); } } @@ -184,6 +203,8 @@ public class PeerWirePeer { * @return the {@link ChannelFuture} for this message */ public ChannelFuture request(int index, int start, int length) { + log.debug("Requesting piece {} part {} with {} length to peer {}", + new Object[] { index, start, length, peer }); return write(new RequestMessage(index, start, length)); } @@ -201,6 +222,8 @@ public class PeerWirePeer { */ public void upload(int index, int start, int length, ByteBuffer data) { this.unchoke(); + log.debug("Sending piece {} part {} with {} length to {}, buffer: {}", + new Object[] { index, start, length, this, data }); write(new PieceMessage(index, start, length, data)); } @@ -211,6 +234,7 @@ public class PeerWirePeer { * the piece index */ public void have(int index) { + log.debug("Notifying have piece {} to peer {}", index, this); write(new HaveMessage(index)); } @@ -225,6 +249,9 @@ public class PeerWirePeer { * the length */ public void cancel(int index, int start, int length) { + log.debug( + "Cancelling piece {} reuquest, part {} with {} length from peer {}", + new Object[] { index, start, length, this }); write(new CancelMessage(index, start, length)); } @@ -232,6 +259,7 @@ public class PeerWirePeer { * Send an keep alive message */ public void keepAlive() { + log.debug("Keeping alive peer {}", this); write(new KeepAliveMessage()); } @@ -246,6 +274,7 @@ public class PeerWirePeer { * the port number */ public void port(short port) { + log.debug("Sending DHT port {} to peer {}", port, this); write(new PortMessage(port)); } @@ -256,6 +285,7 @@ public class PeerWirePeer { * Send an have none message. */ public void haveNone() { + log.debug("Sendind NO-PIECES message to peer {}", this); write(new HaveNoneMessage()); } @@ -266,6 +296,7 @@ public class PeerWirePeer { * Send an have all message. */ public void haveAll() { + log.debug("Sending HAVE-ALL message to peer {}", this); write(new HaveAllMessage()); } @@ -284,6 +315,9 @@ public class PeerWirePeer { */ public void reject(int index, int start, int length) { this.choke(); + log.debug( + "Rejecting part {}, starting at {} with {] length from peer {}", + new Object[] { index, start, length, this }); write(new RejectMessage(index, start, length)); } @@ -297,6 +331,7 @@ public class PeerWirePeer { * the piece index */ public void suggest(int index) { + log.debug("Suggesting piece {} to peer {}", index, this); write(new SuggestPieceMessage(index)); } @@ -311,6 +346,7 @@ public class PeerWirePeer { * the piece indexes */ public void allowedFast(int... indexes) { + log.debug("Allowing {} fast pieces to peer {}", indexes.length, this); write(new AllowedFastMessage(indexes)); } @@ -355,6 +391,16 @@ public class PeerWirePeer { return channel; } + /** + * @return + * @see org.jboss.netty.channel.Channel#isOpen() + */ + public boolean isConnected() { + if (channel == null) + return false; + return channel.isOpen(); + } + /** * Get the active {@link TorrentPeer} * diff --git a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java index df0305c..5097aa9 100644 --- a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java +++ b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java @@ -55,6 +55,8 @@ import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; import org.jboss.netty.handler.timeout.IdleStateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Standard handler responsible for forwarding calls to {@link TorrentAlgorithm} @@ -69,6 +71,11 @@ import org.jboss.netty.handler.timeout.IdleStateEvent; */ // TODO separate extensions handler from algorithm handler public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * The torrent manager */ @@ -223,9 +230,11 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { private void testInterest(PeerWirePeer peer) { switch (interestAlgorithm.interested(peer.getTorrentPeer())) { case INTERESTED: + log.debug("Algorithm is interested in peer {}", peer); peer.interested(); return; case UNINTERESTED: + log.debug("Algorithm is not interested in peer {}", peer); peer.uninterested(); return; } @@ -240,9 +249,11 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { private void testChoke(PeerWirePeer peer) { switch (interestAlgorithm.choke(peer.getTorrentPeer())) { case CHOKED: + log.debug("Algorithm wants to choke peer {}", peer); peer.choke(); return; case UNCHOKED: + log.debug("Algorithm wants to unchoke peer {}", peer); peer.unchoke(); return; } @@ -257,12 +268,14 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { * the new interest state */ private void peerIntrestUpdate(PeerWirePeer peer, InterestState state) { + log.debug("Peer {} has updated interest state to {}", peer, state); switch (peerAlgorithm.interested(peer.getTorrentPeer(), state)) { case CHOKED: + log.debug("Algorithm wants to choke peer {}", peer); peer.choke(); return; - case UNCHOKED: + log.debug("Algorithm wants to unchoke peer {}", peer); peer.unchoke(); return; } @@ -277,17 +290,22 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { * the choke state */ private void peerChokeUpdate(PeerWirePeer peer, ChokingState state) { + log.debug("Peer {} has updated choke state to {}", peer, state); switch (peerAlgorithm.choked(peer.getTorrentPeer(), state)) { case DISCONNECT: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); break; case CONNECT_NEW_PEER: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); + log.debug("Algorithm wants connect to a new peer"); connect(peerAlgorithm.connect()); return; case DOWNLOAD: + log.debug("Algorithm wants to download a piece from peer {}", peer); download(peer, downloadAlgorithm.getNextPart(peer.getTorrentPeer(), null)); return; @@ -305,25 +323,34 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { */ private void processRequest(PeerWirePeer peer, TorrentPart part) throws IOException { + log.debug("Peer {} has requested {}", peer, part); switch (uploadAlgorithm.request(peer.getTorrentPeer(), part)) { case DISCONNECT: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); break; case REJECT: + log.debug("Algorithm wants to reject part {} from peer {}", part, peer); if (!peer.getTorrentPeer().getCapabilities() - .supports(TorrentPeerCapability.FAST_PEERS)) + .supports(TorrentPeerCapability.FAST_PEERS)) { + log.debug("Peer {} do not support rejecting part {}, ignoring request", peer, part); return; + } peer.reject(part.getPiece().getIndex(), part.getStart(), part.getLength()); break; case CONNECT_NEW_PEER: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); + log.debug("Algorithm wants connect to a new peer"); connect(peerAlgorithm.connect()); break; case CHOKE: + log.debug("Algorithm wants to choke peer {}", peer); peer.choke(); break; case UPLOAD: + log.debug("Algorithm wants to upload part {} to peer {}", part, peer); upload(peer, part); break; } @@ -342,8 +369,11 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { */ private void processDownload(final PeerWirePeer peer, final TorrentPart part, ByteBuffer data) throws IOException { + log.debug("Received part {} from peer {}", part, peer); + final TorrentPart nextPart = downloadAlgorithm.getNextPart( peer.getTorrentPeer(), part); + log.debug("Next part from peer {} is {}", peer, nextPart); boolean complete = downloadAlgorithm.isComplete(peer.getTorrentPeer(), part.getPiece()); final ChannelFuture future = download(peer, nextPart); @@ -353,36 +383,47 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { return; if (!complete) return; + log.debug("Piece {} is complete, calculating check sum", part.getPiece()); if (datastore.checksum(part.getPiece())) { manager.getContext().getBitfield().setPiece(part.getPiece(), true); manager.getPeerManager().executeActive(new PeerWirePeerCallback() { @Override public void callback(PeerWirePeer peer) { + log.debug("Broadcasting HAVE {} message to all peers", part.getPiece()); peer.have(part.getPiece().getIndex()); } }); } else { - System.exit(0); + log.debug("Checksum for piece {} is not valid", part.getPiece()); manager.getContext().getBitfield().setPiece(part.getPiece(), false); switch (downloadAlgorithm.corrupted(peer.getTorrentPeer(), part.getPiece())) { case CHOKE: - if (future != null && !future.cancel()) + log.debug("Algorithm wants to choke peer {}", peer); + if (future != null && !future.cancel()) { + log.debug("Canceling part {} request from peer {}", nextPart, peer); peer.cancel(nextPart.getPiece().getIndex(), nextPart.getStart(), nextPart.getLength()); + } peer.choke(); break; case DISCONNECT: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); break; + case CONNECT_NEW_PEER: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); + log.debug("Algorithm wants connect to a new peer"); connect(peerAlgorithm.connect()); - break; + return; case CONTINUE: + log.debug("Algorithm wants to continue downloads from peer {}", peer); break; case CANCEL: + log.debug("Algorithms wants to cancel part {} request from peer {}", nextPart, peer); if (future != null && !future.cancel()) peer.cancel(nextPart.getPiece().getIndex(), nextPart.getStart(), nextPart.getLength()); @@ -398,15 +439,21 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { * the peer */ private void keepAlive(PeerWirePeer peer) { + log.debug("Peer {} is keeping alive", peer); switch (peerAlgorithm.keepAlive(peer.getTorrentPeer())) { case DISCONNECT: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); break; + case CONNECT_NEW_PEER: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); + log.debug("Algorithm wants connect to a new peer"); connect(peerAlgorithm.connect()); - break; + return; case KEEP_ALIVE: + log.debug("Algorithm wants to keep alive peer {}", peer); peer.keepAlive(); break; } @@ -493,23 +540,31 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler { } private void rejected(PeerWirePeer peer, TorrentPart part) { + log.debug("Peer {} rejected part request {}", peer, part); switch (downloadAlgorithm.rejected(peer.getTorrentPeer(), part)) { case DISCONNECT: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); break; + case CONNECT_NEW_PEER: + log.debug("Algorithm wants to diconnect peer {}", peer); peer.disconnect(); + log.debug("Algorithm wants connect to a new peer"); connect(peerAlgorithm.connect()); - break; + return; case NOT_INTERESTED: + log.debug("Algorithm has no interest in peer {}", peer); peer.uninterested(); break; case RETRY: + log.debug("Algorithm wants to retry request for part {} from peer {}", part, peer); download(peer, part); break; case TRY_ANOTHER_PIECE: final TorrentPart nextPart = downloadAlgorithm.getNextPart( peer.getTorrentPeer(), part); + log.debug("Algorithm wants to try another part request {} from peer {}", nextPart, peer); download(peer, nextPart); break; } diff --git a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerHeadHandler.java b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerHeadHandler.java index 960c4e0..d6d5436 100644 --- a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerHeadHandler.java +++ b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerHeadHandler.java @@ -21,7 +21,6 @@ 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.TorrentPeerCapabilities.TorrentPeerCapability; import net.torrent.torrent.context.TorrentPeerID; import org.jboss.netty.channel.Channel; @@ -29,6 +28,8 @@ import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handles pre-algoritihm handler stuff. @@ -38,6 +39,11 @@ import org.jboss.netty.channel.SimpleChannelHandler; * @author Rogiel Josias Sulzbach */ public class PeerWireManagerHeadHandler extends SimpleChannelHandler { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * The torrent manager */ @@ -88,14 +94,16 @@ public class PeerWireManagerHeadHandler extends SimpleChannelHandler { peer.setSocketAddress((InetSocketAddress) channel .getRemoteAddress()); peer.getCapabilities().setCapabilities(handshake.getReserved()); + + log.debug("Handshaked with peer {}", pwpeer); // TODO send bitfield - if (peer.getCapabilities().supports( - TorrentPeerCapability.FAST_PEERS)) { - pwpeer.haveAll(); - } else { - // pwpeer.bitfield(manager.getContext().getBitfield().getBits()); - } + // if (peer.getCapabilities().supports( + // TorrentPeerCapability.FAST_PEERS)) { + // //pwpeer.haveAll(); + // } else { + pwpeer.bitfield(manager.getContext().getBitfield().getBits()); + // } } super.messageReceived(ctx, e); } diff --git a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerTailHandler.java b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerTailHandler.java index dfa4e2d..e825e3b 100644 --- a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerTailHandler.java +++ b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireManagerTailHandler.java @@ -30,6 +30,8 @@ import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handles post-algorithm handler stuff. @@ -39,6 +41,11 @@ import org.jboss.netty.channel.SimpleChannelHandler; * @author Rogiel Josias Sulzbach */ public class PeerWireManagerTailHandler extends SimpleChannelHandler { + /** + * The logger instance + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + /** * The torrent manager */ @@ -64,12 +71,18 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { final Torrent torrent = manager.getTorrent(); final TorrentPart part = torrent.getPart(pieceMsg.getIndex(), pieceMsg.getStart(), pieceMsg.getLength()); + + log.debug("Removing {} from download queue", part); + manager.getDownloadManager().remove(part); } else if (msg instanceof RejectMessage) { final RejectMessage reject = (RejectMessage) msg; final Torrent torrent = manager.getTorrent(); final TorrentPart part = torrent.getPart(reject.getIndex(), reject.getStart(), reject.getLength()); + + log.debug("Removing {} from download queue", part); + manager.getDownloadManager().remove(part); } super.messageReceived(ctx, e); @@ -87,11 +100,15 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { final Torrent torrent = manager.getContext().getTorrent(); final TorrentPart part = torrent.getPart(message.getIndex(), message.getStart(), message.getLength()); + + log.debug("Adding {} to upload queue", part); + manager.getUploadManager().add(part, peer.getTorrentPeer()); e.getFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { + log.debug("Removing {} from upload queue", part); manager.getUploadManager().remove(part); } }); @@ -100,6 +117,9 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { final Torrent torrent = manager.getContext().getTorrent(); final TorrentPart part = torrent.getPart(message.getIndex(), message.getStart(), message.getLength()); + + log.debug("Adding {} to download queue", part); + manager.getDownloadManager().add(part, peer.getTorrentPeer()); } else if (msg instanceof CancelMessage) { final CancelMessage message = (CancelMessage) msg; @@ -110,6 +130,7 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { @Override public void operationComplete(ChannelFuture future) throws Exception { + log.debug("Removing {} from download queue", part); manager.getDownloadManager().remove(part); } }); @@ -124,7 +145,9 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { final PeerWirePeer peer = manager.getPeerManager().update( e.getChannel()); if (peer.getTorrentPeer() != null) { + log.debug("Removing all peer {} pieces from download queue", peer); manager.getDownloadManager().remove(peer.getTorrentPeer()); + log.debug("Removing all peer {} pieces from upload queue", peer); manager.getUploadManager().remove(peer.getTorrentPeer()); } super.channelDisconnected(ctx, e); @@ -137,7 +160,9 @@ public class PeerWireManagerTailHandler extends SimpleChannelHandler { final PeerWirePeer peer = manager.getPeerManager().remove( e.getChannel()); if (peer.getTorrentPeer() != null) { + log.debug("Removing all peer {} pieces from download queue", peer); manager.getDownloadManager().remove(peer.getTorrentPeer()); + log.debug("Removing all peer {} pieces from upload queue", peer); manager.getUploadManager().remove(peer.getTorrentPeer()); } super.channelClosed(ctx, e); diff --git a/src/main/java/net/torrent/protocol/peerwire/message/BitfieldMessage.java b/src/main/java/net/torrent/protocol/peerwire/message/BitfieldMessage.java index 6bbc4b0..bb74ffb 100644 --- a/src/main/java/net/torrent/protocol/peerwire/message/BitfieldMessage.java +++ b/src/main/java/net/torrent/protocol/peerwire/message/BitfieldMessage.java @@ -65,19 +65,15 @@ public class BitfieldMessage implements PeerWireWritableMessage, @Override public void read(ChannelBuffer buffer) throws IOException { - buffer.readerIndex(buffer.readerIndex() - 5); - int len = buffer.readInt() - 2; buffer.readByte(); // unk - bitfield = new BitSet(len * 8); + bitfield = new BitSet(8); int i = 0; - int read = 0; - while (read <= len) { + while (buffer.readable()) { byte b = buffer.readByte(); for (int j = 128; j > 0; j >>= 1) { bitfield.set(i++, (b & j) != 0); } - read++; } } diff --git a/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerAnnouncer.java b/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerAnnouncer.java index 90b59ab..61ef16e 100644 --- a/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerAnnouncer.java +++ b/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerAnnouncer.java @@ -25,6 +25,7 @@ import net.torrent.protocol.tracker.message.AnnounceMessage; import net.torrent.protocol.tracker.message.AnnounceMessage.Event; import net.torrent.torrent.Torrent; import net.torrent.torrent.TorrentTracker; +import net.torrent.torrent.context.TorrentSwarm; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.ChannelFuture; @@ -35,16 +36,21 @@ public class HttpTorrentTrackerAnnouncer { new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); - public HttpTorrentTrackerAnnouncer() { - client.setPipelineFactory(new HttpTorrentTrackerPipelineFactory()); + private final TorrentSwarm swarm; +private final Torrent torrent; + + public HttpTorrentTrackerAnnouncer(TorrentSwarm swarm) { + this.swarm = swarm; + this.torrent = swarm.getContext().getTorrent(); + client.setPipelineFactory(new HttpTorrentTrackerPipelineFactory(swarm)); } - public boolean announce(Torrent torrent, TorrentTracker tracker) + public boolean announce(TorrentTracker tracker) throws UnsupportedEncodingException, MalformedURLException { final AnnounceMessage announceMessage = new AnnounceMessage(tracker .getURL().toString(), torrent.getInfoHash().toByteArray(), - torrent.getInfoHash().toByteArray(), 10, 0, 0, 0, true, false, - Event.STARTED); + torrent.getInfoHash().toByteArray(), 10254, 0, 0, 0, true, + false, Event.STARTED); int port = (tracker.getURL().getPort() > 0 ? tracker.getURL().getPort() : tracker.getURL().getDefaultPort()); final ChannelFuture chFuture = client.connect(new InetSocketAddress( diff --git a/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerPipelineFactory.java b/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerPipelineFactory.java index 68875ee..86b846e 100644 --- a/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerPipelineFactory.java +++ b/src/main/java/net/torrent/protocol/tracker/HttpTorrentTrackerPipelineFactory.java @@ -16,38 +16,49 @@ package net.torrent.protocol.tracker; import static org.jboss.netty.channel.Channels.pipeline; -import net.torrent.protocol.tracker.codec.ISO8859HttpRequestEncoder; import net.torrent.protocol.tracker.codec.TorrentTrackerBDecoder; import net.torrent.protocol.tracker.codec.TorrentTrackerDecoder; import net.torrent.protocol.tracker.codec.TorrentTrackerEncoder; +import net.torrent.torrent.context.TorrentSwarm; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.http.HttpRequestEncoder; import org.jboss.netty.handler.codec.http.HttpResponseDecoder; import org.jboss.netty.handler.logging.LoggingHandler; import org.jboss.netty.logging.InternalLogLevel; public class HttpTorrentTrackerPipelineFactory implements ChannelPipelineFactory { + private final TorrentSwarm swarm; + + /** + * @param torrent + */ + public HttpTorrentTrackerPipelineFactory(TorrentSwarm swarm) { + this.swarm = swarm; + } + @Override public ChannelPipeline getPipeline() throws Exception { final ChannelPipeline pipeline = pipeline(); // log binary data input and object output - // pipeline.addFirst("logging", new LoggingHandler()); + pipeline.addFirst("logging-start", new LoggingHandler( + InternalLogLevel.INFO)); pipeline.addLast("tracker.encoder", new TorrentTrackerEncoder()); - pipeline.addLast("encoder", new ISO8859HttpRequestEncoder()); + pipeline.addLast("http.encoder", new HttpRequestEncoder()); pipeline.addLast("interceptor", new Interceptor()); - pipeline.addLast("decoder", new HttpResponseDecoder()); + pipeline.addLast("http.decoder", new HttpResponseDecoder()); pipeline.addLast("bdecoder", new TorrentTrackerBDecoder()); pipeline.addLast("tracker.decoder", new TorrentTrackerDecoder()); - pipeline.addLast("handler", new TrackerHandler()); + pipeline.addLast("handler", new TrackerHandler(swarm)); - pipeline.addLast("logging", new LoggingHandler(InternalLogLevel.WARN)); + pipeline.addLast("logging", new LoggingHandler(InternalLogLevel.INFO)); return pipeline; } diff --git a/src/main/java/net/torrent/protocol/tracker/TrackerHandler.java b/src/main/java/net/torrent/protocol/tracker/TrackerHandler.java index 519660c..f0a5a50 100644 --- a/src/main/java/net/torrent/protocol/tracker/TrackerHandler.java +++ b/src/main/java/net/torrent/protocol/tracker/TrackerHandler.java @@ -15,15 +15,43 @@ */ package net.torrent.protocol.tracker; +import java.net.Inet4Address; +import java.net.InetSocketAddress; + +import net.torrent.protocol.tracker.message.PeerListMessage; +import net.torrent.protocol.tracker.message.PeerListMessage.PeerInfo; +import net.torrent.torrent.context.TorrentPeer; +import net.torrent.torrent.context.TorrentPeerID; +import net.torrent.torrent.context.TorrentSwarm; + import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelUpstreamHandler; +import org.jboss.netty.channel.SimpleChannelHandler; + +public class TrackerHandler extends SimpleChannelHandler { + private final TorrentSwarm swarm; + + /** + * @param torrent + */ + public TrackerHandler(TorrentSwarm swarm) { + this.swarm = swarm; + } -public class TrackerHandler extends SimpleChannelUpstreamHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - System.out.println(e.getMessage()); + if (e.getMessage() instanceof PeerListMessage) { + final PeerListMessage message = (PeerListMessage) e.getMessage(); + + for (final PeerInfo peerInfo : message.getPeerList()) { + final TorrentPeer peer = new TorrentPeer(swarm.getContext(), + TorrentPeerID.create(peerInfo.getPeerId()), + new InetSocketAddress(Inet4Address.getByName(peerInfo + .getIp()), peerInfo.getPort())); + swarm.add(peer); + } + } super.messageReceived(ctx, e); } } diff --git a/src/main/java/net/torrent/protocol/tracker/codec/ISO8859HttpRequestEncoder.java b/src/main/java/net/torrent/protocol/tracker/codec/ISO8859HttpRequestEncoder.java deleted file mode 100644 index 6170586..0000000 --- a/src/main/java/net/torrent/protocol/tracker/codec/ISO8859HttpRequestEncoder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.tracker.codec; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.handler.codec.http.HttpMessage; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpRequestEncoder; - -public class ISO8859HttpRequestEncoder extends HttpRequestEncoder { - static final byte SP = 32; - static final byte CR = 13; - static final byte LF = 10; - - @Override - protected void encodeInitialLine(ChannelBuffer buf, HttpMessage message) - throws Exception { - HttpRequest request = (HttpRequest) message; - buf.writeBytes(request.getMethod().toString().getBytes()); - buf.writeByte(SP); - buf.writeBytes(request.getUri().getBytes()); - buf.writeByte(SP); - buf.writeBytes(request.getProtocolVersion().toString().getBytes()); - buf.writeByte(CR); - buf.writeByte(LF); - } -} diff --git a/src/main/java/net/torrent/protocol/tracker/codec/TorrentTrackerBDecoder.java b/src/main/java/net/torrent/protocol/tracker/codec/TorrentTrackerBDecoder.java index 0a2d7cf..4e682a7 100644 --- a/src/main/java/net/torrent/protocol/tracker/codec/TorrentTrackerBDecoder.java +++ b/src/main/java/net/torrent/protocol/tracker/codec/TorrentTrackerBDecoder.java @@ -22,18 +22,17 @@ import net.torrent.util.bencoding.BMap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.http.HttpChunk; +import org.jboss.netty.handler.codec.http.DefaultHttpResponse; import org.jboss.netty.handler.codec.oneone.OneToOneDecoder; public class TorrentTrackerBDecoder extends OneToOneDecoder { @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { - if (!(msg instanceof HttpChunk)) + if (!(msg instanceof DefaultHttpResponse)) return msg; - final HttpChunk message = (HttpChunk) msg; + final DefaultHttpResponse message = (DefaultHttpResponse) msg; - System.out.println(new String(message.getContent().array())); if (message.getContent().readableBytes() <= 0) return null; diff --git a/src/main/java/net/torrent/protocol/tracker/message/AnnounceMessage.java b/src/main/java/net/torrent/protocol/tracker/message/AnnounceMessage.java index 30d8aab..88883f2 100644 --- a/src/main/java/net/torrent/protocol/tracker/message/AnnounceMessage.java +++ b/src/main/java/net/torrent/protocol/tracker/message/AnnounceMessage.java @@ -57,7 +57,7 @@ public class AnnounceMessage implements TorrentTrackerRequestMessage { } private String ip; - private Integer numWant = 10; + private Integer numWant = 100; private String key = "avtbyit8"; private String trackerId; @@ -114,19 +114,20 @@ public class AnnounceMessage implements TorrentTrackerRequestMessage { add(builder, "downloaded", Long.toString(downloaded)); add(builder, "left", Long.toString(left)); - add(builder, "compact", compact); - add(builder, "no_peer_id", noPeerId); + //add(builder, "compact", compact); + //add(builder, "no_peer_id", noPeerId); if (event != Event.UPDATE) add(builder, "event", event.urlArg()); add(builder, "ip", ip); add(builder, "numwant", numWant); - add(builder, "key", key); - add(builder, "trackerid", trackerId); + //add(builder, "key", key); + //add(builder, "trackerid", trackerId); builder.setLength(builder.length() - 1);// trim last character it is an // unnecessary &. final URL url = new URL(builder.toString()); + System.out.println(builder.toString()); return new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, url.getPath() + "?" + url.getQuery()); @@ -136,25 +137,21 @@ public class AnnounceMessage implements TorrentTrackerRequestMessage { throws UnsupportedEncodingException { if (value == null) return; - builder.append(key + "=" + value).append("&"); + builder.append(key + "=" + URLEncoder.encode(value, "ISO-8859-1").replace("*", "%2a")).append("&"); } private void add(StringBuilder builder, String key, byte[] value) throws UnsupportedEncodingException { if (value == null) return; - add(builder, key, URLEncoder.encode(new String(value), "ISO-8859-1") - .replaceAll("\\+", "%20")); + add(builder, key, new String(value, "ISO-8859-1")); } private void addLowerCase(StringBuilder builder, String key, byte[] value) throws UnsupportedEncodingException { if (value == null) return; - add(builder, key, - URLEncoder - .encode(new String(value, "ISO-8859-1"), "ISO-8859-1") - .replaceAll("\\+", "%20").toLowerCase()); + add(builder, key, new String(value, "ISO-8859-1")); } private void add(StringBuilder builder, String key, Number value) diff --git a/src/main/java/net/torrent/protocol/tracker/message/PeerListMessage.java b/src/main/java/net/torrent/protocol/tracker/message/PeerListMessage.java index df524be..22f07d3 100644 --- a/src/main/java/net/torrent/protocol/tracker/message/PeerListMessage.java +++ b/src/main/java/net/torrent/protocol/tracker/message/PeerListMessage.java @@ -159,7 +159,7 @@ public class PeerListMessage implements TorrentTrackerResponseMessage { public static PeerInfo fromBMap(BMap map) throws BTypeException { return new PeerInfo((byte[]) map.get("peer id"), - map.getString("peer ip"), map.getInteger("port")); + map.getString("ip"), map.getInteger("port")); } public static PeerInfo fromRawIP(byte[] list, int i, int j) { diff --git a/src/main/java/net/torrent/torrent/Torrent.java b/src/main/java/net/torrent/torrent/Torrent.java index 4edbd3f..32e18dd 100644 --- a/src/main/java/net/torrent/torrent/Torrent.java +++ b/src/main/java/net/torrent/torrent/Torrent.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.security.InvalidParameterException; import java.util.Arrays; import java.util.Collections; @@ -340,8 +341,12 @@ public class Torrent { if (in == null) throw new InvalidParameterException("InputStream cannot be null"); - final BMap map = (BMap) new BEncodedInputStream(in).readElement(); - return new Torrent(map); + try { + final BMap map = (BMap) new BEncodedInputStream(in).readElement(); + return new Torrent(map); + } finally { + in.close(); + } } /** @@ -359,4 +364,19 @@ public class Torrent { throw new InvalidParameterException("File cannot be null"); return load(new FileInputStream(file)); } + + /** + * Load an torrent from an {@link File} + * + * @param url + * the {@link URL} + * @return the loaded {@link Torrent} instance + * @throws IOException + * @throws URISyntaxException + */ + public static Torrent load(URL url) throws IOException, URISyntaxException { + if (url == null) + throw new InvalidParameterException("File cannot be null"); + return load(url.openStream()); + } } diff --git a/src/main/java/net/torrent/torrent/context/TorrentPeer.java b/src/main/java/net/torrent/torrent/context/TorrentPeer.java index bbb482b..4101439 100644 --- a/src/main/java/net/torrent/torrent/context/TorrentPeer.java +++ b/src/main/java/net/torrent/torrent/context/TorrentPeer.java @@ -18,6 +18,8 @@ package net.torrent.torrent.context; import java.net.InetSocketAddress; import java.util.Date; +import net.torrent.protocol.peerwire.PeerWirePeer; + /** * Object representing a peer in the swarm. * @@ -118,6 +120,8 @@ public class TorrentPeer { */ private boolean accessible = true; + private PeerWirePeer peerWirePeer; + /** * Creates a new peer * @@ -313,6 +317,28 @@ public class TorrentPeer { this.accessible = accessible; } + + + /** + * @return the peerWirePeer + */ + public PeerWirePeer getPeerWirePeer() { + return peerWirePeer; + } + + /** + * @param peerWirePeer the peerWirePeer to set + */ + public void setPeerWirePeer(PeerWirePeer peerWirePeer) { + this.peerWirePeer = peerWirePeer; + } + + public boolean isConnected() { + if(this.peerWirePeer == null) + return false; + return true; + } + /** * Get the torrent context * diff --git a/src/main/java/net/torrent/torrent/context/TorrentSwarm.java b/src/main/java/net/torrent/torrent/context/TorrentSwarm.java index 476b09b..d5c3317 100644 --- a/src/main/java/net/torrent/torrent/context/TorrentSwarm.java +++ b/src/main/java/net/torrent/torrent/context/TorrentSwarm.java @@ -61,6 +61,17 @@ public class TorrentSwarm implements Iterable { return this.peers.add(peer); } + /** + * Add an given peers to the swarm + * + * @param peers + * the peers + * @return true if was not present in swarm + */ + public boolean add(List peers) { + return this.peers.addAll(peers); + } + /** * Removes an given peer from the swarm * @@ -131,6 +142,44 @@ public class TorrentSwarm implements Iterable { return null; } + /** + * Get an peer by its address + * + * @return an random peer + */ + public TorrentPeer getRandomPeer() { + if (peers.size() == 0) + return null; + return peers.get((int) (Math.random() * (peers.size() - 1))); + } + + /** + * Get an peer by its address + * + * @return an random peer + */ + public TorrentPeer getRandomOfflinePeer() { + List accessiblePeers = new ArrayList(); + List nonAccessiblePeers = new ArrayList(); + for (final TorrentPeer peer : peers) { + if (peer.isConnected()) { + if (peer.isAccessible()) { + accessiblePeers.add(peer); + } else { + nonAccessiblePeers.add(peer); + } + } + } + + List peerList = accessiblePeers; + + if (peerList.size() == 0) + peerList = nonAccessiblePeers; + if (peerList.size() == 0) + return null; + return peerList.get((int) (Math.random() * (peerList.size() - 1))); + } + /** * Lookup for a peer first by its id, then by address, if still not found, * creates a new entry. diff --git a/src/main/java/net/torrent/torrent/piece/ScoredPieceSelector.java b/src/main/java/net/torrent/torrent/piece/ScoredPieceSelector.java index 1de2aba..9553d44 100644 --- a/src/main/java/net/torrent/torrent/piece/ScoredPieceSelector.java +++ b/src/main/java/net/torrent/torrent/piece/ScoredPieceSelector.java @@ -65,7 +65,6 @@ public class ScoredPieceSelector extends SortedListPieceSelector { protected void sort(List pieces) { if (comparator != null) Collections.sort(pieces, comparator); - System.out.println(pieces); } @Override diff --git a/src/test/java/net/bittorrent/protocol/tracker/HttpTorrentTrackerAnnouncerTest.java b/src/test/java/net/bittorrent/protocol/tracker/HttpTorrentTrackerAnnouncerTest.java deleted file mode 100644 index e57a4a2..0000000 --- a/src/test/java/net/bittorrent/protocol/tracker/HttpTorrentTrackerAnnouncerTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.bittorrent.protocol.tracker; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; - -import net.torrent.protocol.tracker.HttpTorrentTrackerAnnouncer; -import net.torrent.torrent.Torrent; - -import org.junit.Test; - -public class HttpTorrentTrackerAnnouncerTest { - @Test - public void testAnnounce() throws IOException, URISyntaxException, - InterruptedException { - final Torrent torrent = Torrent - .load(new File( - "src/test/resources/Tim Besamusca - Running Away EP Urban Sickness Audio USA1008.torrent")); - final HttpTorrentTrackerAnnouncer announcer = new HttpTorrentTrackerAnnouncer(); - System.out.println(announcer.announce(torrent, torrent.getTrackers() - .iterator().next())); - - //Thread.sleep(10 * 60 * 1000); - } -} diff --git a/src/test/java/net/torrent/protocol/peerwire/PeerWireManagerTest.java b/src/test/java/net/torrent/protocol/peerwire/PeerWireManagerTest.java index 37c2574..4d15f5b 100644 --- a/src/test/java/net/torrent/protocol/peerwire/PeerWireManagerTest.java +++ b/src/test/java/net/torrent/protocol/peerwire/PeerWireManagerTest.java @@ -15,27 +15,42 @@ */ package net.torrent.protocol.peerwire; -import java.io.File; import java.io.IOException; -import java.net.InetSocketAddress; import java.net.URISyntaxException; +import java.net.URL; +import java.util.logging.LogManager; import net.torrent.BitTorrentClient; import net.torrent.BitTorrentClientFactory; import net.torrent.torrent.Torrent; +import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.logging.JdkLoggerFactory; +import org.junit.Test; + public class PeerWireManagerTest { - // @Test + //@Test public void testPeerWire() throws IOException, InterruptedException, URISyntaxException { - final Torrent torrent = Torrent.load(new File( - "src/test/resources/oth.s01e13.avi.torrent")); + LogManager.getLogManager().readConfiguration( + this.getClass().getResourceAsStream("/logging.properties")); + InternalLoggerFactory.setDefaultFactory(new JdkLoggerFactory()); + + + //GET /announce?info_hash=9uKh%e8%2a%81%a47%5b%95%24%d7%84kD-%af%a7%93&peer_id=-TR2130-0kr8c2gx1d39&port=51413&uploaded=0&downloaded=0&left=124928000&numwant=0&key=c3gvpc8w&compact=1&supportcrypto=1&event=stopped HTTP/1.1\r\n + //GET /announce?info_hash=9uKh%E8%2a%81%A47%5B%95%24%D7%84kD-%AF%A7%93&peer_id=-TR2130-g4mvcv2iyehf&port=10254&uploaded=0&downloaded=0&left=0&compact=1&event=started HTTP/1.1 + + + final Torrent torrent = Torrent + .load(new URL( + "http://build.eclipse.org/technology/phoenix/torrents/indigo/eclipse-java-indigo-linux-gtk-x86_64.tar.gz.torrent")); System.out.println(torrent.getInfoHash()); final BitTorrentClient client = new BitTorrentClientFactory(torrent) .newBitTorrentClient(); - client.start(new InetSocketAddress("192.168.1.100", 25944)); + // client.start(new InetSocketAddress("192.168.1.100", 25944)); // client.start(new InetSocketAddress("192.168.1.110", 51413)); + client.start(); Thread.sleep(60 * 1000 * 30); } diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties new file mode 100644 index 0000000..e192994 --- /dev/null +++ b/src/test/resources/logging.properties @@ -0,0 +1,3 @@ +handlers = java.util.logging.ConsoleHandler +.level=FINE +java.util.logging.ConsoleHandler.level = FINE \ No newline at end of file