mirror of
https://github.com/Rogiel/torrent4j
synced 2025-12-06 07:32:47 +00:00
Implements peer's client matching using PeerID
This commit is contained in:
21
pom.xml
21
pom.xml
@@ -94,6 +94,7 @@
|
|||||||
<descriptors>
|
<descriptors>
|
||||||
<descriptor>src/main/assembly/distribution-bin.xml</descriptor>
|
<descriptor>src/main/assembly/distribution-bin.xml</descriptor>
|
||||||
</descriptors>
|
</descriptors>
|
||||||
|
<attach>false</attach>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
@@ -130,6 +131,10 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-release-plugin</artifactId>
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
<version>2.2.2</version>
|
<version>2.2.2</version>
|
||||||
|
<configuration>
|
||||||
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
|
<goals>deploy site-deploy</goals><!-- we have to force site-deploy -->
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -183,7 +188,7 @@
|
|||||||
<artifactId>site-maven-plugin</artifactId>
|
<artifactId>site-maven-plugin</artifactId>
|
||||||
<version>0.4</version>
|
<version>0.4</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<message>Creating site for ${project.version}</message>
|
<message>Creating ${project.artifactId} site for ${project.version}</message>
|
||||||
<repositoryOwner>torrent4j</repositoryOwner>
|
<repositoryOwner>torrent4j</repositoryOwner>
|
||||||
<repositoryName>torrent4j.github.com</repositoryName>
|
<repositoryName>torrent4j.github.com</repositoryName>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -203,6 +208,9 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<repositoryOwner>torrent4j</repositoryOwner>
|
<repositoryOwner>torrent4j</repositoryOwner>
|
||||||
<repositoryName>torrent4j</repositoryName>
|
<repositoryName>torrent4j</repositoryName>
|
||||||
|
<includes>
|
||||||
|
<include>${project.build.directory}/${project.artifactId}-${project.version}.zip</include>
|
||||||
|
</includes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -264,6 +272,17 @@
|
|||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
<version>20041127.091804</version>
|
<version>20041127.091804</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class TestMain {
|
|||||||
new PeerWireProtocol(), new InMemoryTorrentStorage());
|
new PeerWireProtocol(), new InMemoryTorrentStorage());
|
||||||
controller.start(1234);
|
controller.start(1234);
|
||||||
|
|
||||||
final Torrent torrent = Torrent.load(Paths.get("music.torrent"));
|
final Torrent torrent = Torrent.load(Paths.get("test.torrent"));
|
||||||
System.out.println("Torrent hash is " + torrent.getHash().getString());
|
System.out.println("Torrent hash is " + torrent.getHash().getString());
|
||||||
|
|
||||||
// controller.checkExistingData(torrent);
|
// controller.checkExistingData(torrent);
|
||||||
@@ -29,7 +29,7 @@ public class TestMain {
|
|||||||
controller.registerTorrent(torrent);
|
controller.registerTorrent(torrent);
|
||||||
final TorrentPeer peer = new TorrentPeer(torrent);
|
final TorrentPeer peer = new TorrentPeer(torrent);
|
||||||
peer.setAddress(new InetSocketAddress(Inet4Address
|
peer.setAddress(new InetSocketAddress(Inet4Address
|
||||||
.getByName("192.168.1.100"), 21958));
|
.getByName("127.0.0.1"), 34096));
|
||||||
torrent.getSwarm().addPeer(peer);
|
torrent.getSwarm().addPeer(peer);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class TorrentPeer {
|
|||||||
/**
|
/**
|
||||||
* The peer ID
|
* The peer ID
|
||||||
*/
|
*/
|
||||||
private String peerID;
|
private TorrentPeerID peerID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The protocol peer used to communicate with it
|
* The protocol peer used to communicate with it
|
||||||
@@ -67,14 +67,28 @@ public class TorrentPeer {
|
|||||||
return pieces;
|
return pieces;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPeerID() {
|
public TorrentPeerID getPeerID() {
|
||||||
return peerID;
|
return peerID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPeerID(String peerID) {
|
public void setPeerID(TorrentPeerID peerID) {
|
||||||
this.peerID = peerID;
|
this.peerID = peerID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPeerID(String peerID) {
|
||||||
|
this.peerID = new TorrentPeerID(this, peerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to detect the peer's client. If unknown, {@link TorrentPeerClient#UNKNOWN} is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @return the peer torrent client
|
||||||
|
*/
|
||||||
|
public TorrentPeerClient getClient() {
|
||||||
|
return peerID.getClient();
|
||||||
|
}
|
||||||
|
|
||||||
public TorrentProtocolPeer getProtocolPeer() {
|
public TorrentProtocolPeer getProtocolPeer() {
|
||||||
return protocolPeer;
|
return protocolPeer;
|
||||||
}
|
}
|
||||||
|
|||||||
45
src/main/java/com/torrent4j/model/TorrentPeerClient.java
Normal file
45
src/main/java/com/torrent4j/model/TorrentPeerClient.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package com.torrent4j.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of known torrent clients
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*/
|
||||||
|
public enum TorrentPeerClient {
|
||||||
|
/**
|
||||||
|
* µTorrent for Mac (<strong>-UM</strong>)
|
||||||
|
*/
|
||||||
|
UTORRENT_FOR_MAC("µTorrent for Mac", "-UM"),
|
||||||
|
/**
|
||||||
|
* µTorrent (<strong>-UT</strong>)
|
||||||
|
*/
|
||||||
|
UTORRENT("µTorrent", "-UT"),
|
||||||
|
/**
|
||||||
|
* Transmission (<strong>-TR</strong>)
|
||||||
|
*/
|
||||||
|
TRANSMISSION("Transmission", "-TR"),
|
||||||
|
|
||||||
|
UNKNOWN("Unknown", "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An friendly name for the client. Can be used on an UI.
|
||||||
|
*/
|
||||||
|
public final String friendlyName;
|
||||||
|
/**
|
||||||
|
* The PeerID prefix for the client
|
||||||
|
*/
|
||||||
|
public final String prefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new enum value
|
||||||
|
*
|
||||||
|
* @param friendlyName
|
||||||
|
* an friendly name for the client
|
||||||
|
* @param prefix
|
||||||
|
* the PeerID prefix
|
||||||
|
*/
|
||||||
|
private TorrentPeerClient(String friendlyName, String prefix) {
|
||||||
|
this.friendlyName = friendlyName;
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/main/java/com/torrent4j/model/TorrentPeerID.java
Normal file
67
src/main/java/com/torrent4j/model/TorrentPeerID.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package com.torrent4j.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This ID represents an PeerID on the BitTorrent network
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*/
|
||||||
|
public class TorrentPeerID {
|
||||||
|
/**
|
||||||
|
* The torrent peer
|
||||||
|
*/
|
||||||
|
private final TorrentPeer peer;
|
||||||
|
/**
|
||||||
|
* The underlying peer ID
|
||||||
|
*/
|
||||||
|
private final String peerID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @param peerID
|
||||||
|
* the peer ID
|
||||||
|
*/
|
||||||
|
public TorrentPeerID(TorrentPeer peer, String peerID) {
|
||||||
|
this.peer = peer;
|
||||||
|
this.peerID = peerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the peerID
|
||||||
|
*/
|
||||||
|
public String getPeerID() {
|
||||||
|
return peerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to detect the peer's client. If unknown, {@link TorrentPeerClient#UNKNOWN} is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @return the peer torrent client
|
||||||
|
*/
|
||||||
|
public TorrentPeerClient getClient() {
|
||||||
|
for(TorrentPeerClient client : TorrentPeerClient.values()) {
|
||||||
|
if(client == TorrentPeerClient.UNKNOWN)
|
||||||
|
continue;
|
||||||
|
if(peerID.startsWith(client.prefix))
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
return TorrentPeerClient.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the peer
|
||||||
|
*/
|
||||||
|
public TorrentPeer getPeer() {
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the torrent
|
||||||
|
*/
|
||||||
|
public Torrent getTorrent() {
|
||||||
|
return peer.getTorrent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,14 +71,15 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
|||||||
message.peerID);
|
message.peerID);
|
||||||
if (peer == null) {
|
if (peer == null) {
|
||||||
peer = new TorrentPeer(torrent);
|
peer = new TorrentPeer(torrent);
|
||||||
peer.setPeerID(message.peerID);
|
|
||||||
peer.setAddress((InetSocketAddress) e.getChannel()
|
peer.setAddress((InetSocketAddress) e.getChannel()
|
||||||
.getRemoteAddress());
|
.getRemoteAddress());
|
||||||
}
|
}
|
||||||
|
peer.setPeerID(message.peerID);
|
||||||
|
|
||||||
this.peer = (PeerWireProtocolPeer) peer.getProtocolPeer();
|
this.peer = (PeerWireProtocolPeer) peer.getProtocolPeer();
|
||||||
|
|
||||||
e.getChannel().getPipeline().get(PeerTrafficShapingHandler.class)
|
e.getChannel().getPipeline()
|
||||||
.setPeer(peer);
|
.get(PeerTrafficShapingHandler.class).setPeer(peer);
|
||||||
e.getChannel().getPipeline()
|
e.getChannel().getPipeline()
|
||||||
.get(TorrentTrafficShapingHandler.class)
|
.get(TorrentTrafficShapingHandler.class)
|
||||||
.setTorrent(torrent);
|
.setTorrent(torrent);
|
||||||
@@ -87,6 +88,11 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
|||||||
this.peer.getStrategy().getPeerStrategy()
|
this.peer.getStrategy().getPeerStrategy()
|
||||||
.peerConnected(torrent, peer);
|
.peerConnected(torrent, peer);
|
||||||
} else if (msg instanceof HaveMessage) {
|
} else if (msg instanceof HaveMessage) {
|
||||||
|
peer.getTorrentPeer()
|
||||||
|
.getPieces()
|
||||||
|
.addPiece(
|
||||||
|
peer.getTorrent().getPiece(
|
||||||
|
((HaveMessage) msg).pieceIndex));
|
||||||
peer.getStrategy()
|
peer.getStrategy()
|
||||||
.getPeerStrategy()
|
.getPeerStrategy()
|
||||||
.havePiece(
|
.havePiece(
|
||||||
@@ -128,6 +134,11 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
|||||||
final TorrentPieceBlock block = piece.getBlock(message.begin,
|
final TorrentPieceBlock block = piece.getBlock(message.begin,
|
||||||
message.length);
|
message.length);
|
||||||
|
|
||||||
|
if(peer.getTorrentPeer().getState().hasUploadRequestedBlock()) {
|
||||||
|
peer.disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
peer.getTorrentPeer().getState().setUploadRequestedBlock(block);
|
peer.getTorrentPeer().getState().setUploadRequestedBlock(block);
|
||||||
peer.getTorrentPeer().getState()
|
peer.getTorrentPeer().getState()
|
||||||
.setUploadRequestedDate(new Date());
|
.setUploadRequestedDate(new Date());
|
||||||
@@ -233,8 +244,19 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
|||||||
peer.getTorrentPeer().getState().setLastUploadedBlock(block);
|
peer.getTorrentPeer().getState().setLastUploadedBlock(block);
|
||||||
peer.getTorrentPeer().getState()
|
peer.getTorrentPeer().getState()
|
||||||
.setLastUploadedBlockDate(new Date());
|
.setLastUploadedBlockDate(new Date());
|
||||||
peer.getTorrentPeer().getState().setUploadRequestedBlock(null);
|
|
||||||
peer.getTorrentPeer().getState().setUploadRequestedDate(null);
|
e.getFuture().addListener(new ChannelFutureListener() {
|
||||||
|
@Override
|
||||||
|
public void operationComplete(ChannelFuture future)
|
||||||
|
throws Exception {
|
||||||
|
if (!future.isSuccess())
|
||||||
|
return;
|
||||||
|
peer.getTorrentPeer().getState()
|
||||||
|
.setUploadRequestedBlock(null);
|
||||||
|
peer.getTorrentPeer().getState()
|
||||||
|
.setUploadRequestedDate(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (msg instanceof RequestMessage) {
|
} else if (msg instanceof RequestMessage) {
|
||||||
final RequestMessage message = (RequestMessage) msg;
|
final RequestMessage message = (RequestMessage) msg;
|
||||||
|
|
||||||
@@ -248,9 +270,18 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
|||||||
peer.getTorrentPeer().getState()
|
peer.getTorrentPeer().getState()
|
||||||
.setDownloadRequestedDate(new Date());
|
.setDownloadRequestedDate(new Date());
|
||||||
} else if (msg instanceof CancelMessage) {
|
} else if (msg instanceof CancelMessage) {
|
||||||
peer.getTorrentPeer().getState()
|
e.getFuture().addListener(new ChannelFutureListener() {
|
||||||
.setDownloadRequestedBlock(null);
|
@Override
|
||||||
peer.getTorrentPeer().getState().setDownloadRequestedDate(null);
|
public void operationComplete(ChannelFuture future)
|
||||||
|
throws Exception {
|
||||||
|
if (!future.isSuccess())
|
||||||
|
return;
|
||||||
|
peer.getTorrentPeer().getState()
|
||||||
|
.setDownloadRequestedBlock(null);
|
||||||
|
peer.getTorrentPeer().getState()
|
||||||
|
.setDownloadRequestedDate(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ctx.sendDownstream(e);
|
ctx.sendDownstream(e);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.torrent4j.net.peerwire;
|
|||||||
import static io.netty.channel.Channels.pipeline;
|
import static io.netty.channel.Channels.pipeline;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.ChannelPipelineFactory;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
import io.netty.logging.InternalLogLevel;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@@ -11,8 +13,8 @@ import com.torrent4j.net.peerwire.codec.PeerWireFrameDecoder;
|
|||||||
import com.torrent4j.net.peerwire.codec.PeerWireFrameEncoder;
|
import com.torrent4j.net.peerwire.codec.PeerWireFrameEncoder;
|
||||||
import com.torrent4j.net.peerwire.codec.PeerWireMessageDecoder;
|
import com.torrent4j.net.peerwire.codec.PeerWireMessageDecoder;
|
||||||
import com.torrent4j.net.peerwire.codec.PeerWireMessageEncoder;
|
import com.torrent4j.net.peerwire.codec.PeerWireMessageEncoder;
|
||||||
import com.torrent4j.net.peerwire.traffic.TorrentTrafficShapingHandler;
|
|
||||||
import com.torrent4j.net.peerwire.traffic.PeerTrafficShapingHandler;
|
import com.torrent4j.net.peerwire.traffic.PeerTrafficShapingHandler;
|
||||||
|
import com.torrent4j.net.peerwire.traffic.TorrentTrafficShapingHandler;
|
||||||
|
|
||||||
public class PeerWirePipelineFactory implements ChannelPipelineFactory {
|
public class PeerWirePipelineFactory implements ChannelPipelineFactory {
|
||||||
private final TorrentController controller;
|
private final TorrentController controller;
|
||||||
@@ -37,7 +39,7 @@ public class PeerWirePipelineFactory implements ChannelPipelineFactory {
|
|||||||
p.addLast("message-decoder", new PeerWireMessageDecoder());
|
p.addLast("message-decoder", new PeerWireMessageDecoder());
|
||||||
p.addLast("message-encoder", new PeerWireMessageEncoder());
|
p.addLast("message-encoder", new PeerWireMessageEncoder());
|
||||||
|
|
||||||
// p.addLast("logging", new LoggingHandler(InternalLogLevel.WARN));
|
p.addLast("logging", new LoggingHandler(InternalLogLevel.WARN));
|
||||||
|
|
||||||
p.addLast("handler", new PeerWireHandler(controller));
|
p.addLast("handler", new PeerWireHandler(controller));
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.torrent4j.net.peerwire.messages;
|
|||||||
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import com.torrent4j.net.peerwire.PeerWireMessage;
|
import com.torrent4j.net.peerwire.PeerWireMessage;
|
||||||
@@ -36,7 +37,7 @@ public class HandshakeMessage implements PeerWireMessage {
|
|||||||
protocolString = buffer.readBytes(protocolStringLength).toString();
|
protocolString = buffer.readBytes(protocolStringLength).toString();
|
||||||
reserved = buffer.readLong();
|
reserved = buffer.readLong();
|
||||||
torrentHash = buffer.readBytes(20).array();
|
torrentHash = buffer.readBytes(20).array();
|
||||||
peerID = buffer.readBytes(20).toString();
|
peerID = buffer.readBytes(20).toString(Charset.forName("UTF-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -42,9 +42,11 @@ public class StandardTorrentPeerStrategy implements TorrentPeerStrategy {
|
|||||||
return;
|
return;
|
||||||
if (peer.getState().hasDownloadRequestedBlock())
|
if (peer.getState().hasDownloadRequestedBlock())
|
||||||
return;
|
return;
|
||||||
if (peer.getState().isRemotellyChoked())
|
if (peer.getState().isRemotellyChoked()) {
|
||||||
return;
|
peer.declareInterest();
|
||||||
peer.requestBlock(piece.getFirstBlock());
|
} else {
|
||||||
|
peer.requestBlock(piece.getFirstBlock());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
10
src/site/site.xml
Executable file
10
src/site/site.xml
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/DECORATION/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.1.0 http://maven.apache.org/xsd/decoration-1.1.0.xsd">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<menu ref="parent" inherit="top" />
|
||||||
|
<menu ref="modules" inherit="bottom" />
|
||||||
|
<menu ref="reports" inherit="bottom" />
|
||||||
|
</body>
|
||||||
|
</project>
|
||||||
Reference in New Issue
Block a user