mirror of
https://github.com/Rogiel/torrent4j
synced 2025-12-05 23:22:49 +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>
|
||||
<descriptor>src/main/assembly/distribution-bin.xml</descriptor>
|
||||
</descriptors>
|
||||
<attach>false</attach>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -130,6 +131,10 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<goals>deploy site-deploy</goals><!-- we have to force site-deploy -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
@@ -183,7 +188,7 @@
|
||||
<artifactId>site-maven-plugin</artifactId>
|
||||
<version>0.4</version>
|
||||
<configuration>
|
||||
<message>Creating site for ${project.version}</message>
|
||||
<message>Creating ${project.artifactId} site for ${project.version}</message>
|
||||
<repositoryOwner>torrent4j</repositoryOwner>
|
||||
<repositoryName>torrent4j.github.com</repositoryName>
|
||||
</configuration>
|
||||
@@ -203,6 +208,9 @@
|
||||
<configuration>
|
||||
<repositoryOwner>torrent4j</repositoryOwner>
|
||||
<repositoryName>torrent4j</repositoryName>
|
||||
<includes>
|
||||
<include>${project.build.directory}/${project.artifactId}-${project.version}.zip</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -264,6 +272,17 @@
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>20041127.091804</version>
|
||||
</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>
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class TestMain {
|
||||
new PeerWireProtocol(), new InMemoryTorrentStorage());
|
||||
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());
|
||||
|
||||
// controller.checkExistingData(torrent);
|
||||
@@ -29,7 +29,7 @@ public class TestMain {
|
||||
controller.registerTorrent(torrent);
|
||||
final TorrentPeer peer = new TorrentPeer(torrent);
|
||||
peer.setAddress(new InetSocketAddress(Inet4Address
|
||||
.getByName("192.168.1.100"), 21958));
|
||||
.getByName("127.0.0.1"), 34096));
|
||||
torrent.getSwarm().addPeer(peer);
|
||||
|
||||
while(true) {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class TorrentPeer {
|
||||
/**
|
||||
* The peer ID
|
||||
*/
|
||||
private String peerID;
|
||||
private TorrentPeerID peerID;
|
||||
|
||||
/**
|
||||
* The protocol peer used to communicate with it
|
||||
@@ -67,13 +67,27 @@ public class TorrentPeer {
|
||||
return pieces;
|
||||
}
|
||||
|
||||
public String getPeerID() {
|
||||
public TorrentPeerID getPeerID() {
|
||||
return peerID;
|
||||
}
|
||||
|
||||
public void setPeerID(String peerID) {
|
||||
public void setPeerID(TorrentPeerID 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() {
|
||||
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);
|
||||
if (peer == null) {
|
||||
peer = new TorrentPeer(torrent);
|
||||
peer.setPeerID(message.peerID);
|
||||
peer.setAddress((InetSocketAddress) e.getChannel()
|
||||
.getRemoteAddress());
|
||||
}
|
||||
peer.setPeerID(message.peerID);
|
||||
|
||||
this.peer = (PeerWireProtocolPeer) peer.getProtocolPeer();
|
||||
|
||||
e.getChannel().getPipeline().get(PeerTrafficShapingHandler.class)
|
||||
.setPeer(peer);
|
||||
e.getChannel().getPipeline()
|
||||
.get(PeerTrafficShapingHandler.class).setPeer(peer);
|
||||
e.getChannel().getPipeline()
|
||||
.get(TorrentTrafficShapingHandler.class)
|
||||
.setTorrent(torrent);
|
||||
@@ -87,6 +88,11 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
||||
this.peer.getStrategy().getPeerStrategy()
|
||||
.peerConnected(torrent, peer);
|
||||
} else if (msg instanceof HaveMessage) {
|
||||
peer.getTorrentPeer()
|
||||
.getPieces()
|
||||
.addPiece(
|
||||
peer.getTorrent().getPiece(
|
||||
((HaveMessage) msg).pieceIndex));
|
||||
peer.getStrategy()
|
||||
.getPeerStrategy()
|
||||
.havePiece(
|
||||
@@ -127,6 +133,11 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
||||
message.pieceIndex);
|
||||
final TorrentPieceBlock block = piece.getBlock(message.begin,
|
||||
message.length);
|
||||
|
||||
if(peer.getTorrentPeer().getState().hasUploadRequestedBlock()) {
|
||||
peer.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
peer.getTorrentPeer().getState().setUploadRequestedBlock(block);
|
||||
peer.getTorrentPeer().getState()
|
||||
@@ -233,8 +244,19 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
||||
peer.getTorrentPeer().getState().setLastUploadedBlock(block);
|
||||
peer.getTorrentPeer().getState()
|
||||
.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) {
|
||||
final RequestMessage message = (RequestMessage) msg;
|
||||
|
||||
@@ -248,9 +270,18 @@ public class PeerWireHandler extends SimpleChannelHandler {
|
||||
peer.getTorrentPeer().getState()
|
||||
.setDownloadRequestedDate(new Date());
|
||||
} else if (msg instanceof CancelMessage) {
|
||||
peer.getTorrentPeer().getState()
|
||||
.setDownloadRequestedBlock(null);
|
||||
peer.getTorrentPeer().getState().setDownloadRequestedDate(null);
|
||||
e.getFuture().addListener(new ChannelFutureListener() {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future)
|
||||
throws Exception {
|
||||
if (!future.isSuccess())
|
||||
return;
|
||||
peer.getTorrentPeer().getState()
|
||||
.setDownloadRequestedBlock(null);
|
||||
peer.getTorrentPeer().getState()
|
||||
.setDownloadRequestedDate(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
ctx.sendDownstream(e);
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.torrent4j.net.peerwire;
|
||||
import static io.netty.channel.Channels.pipeline;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPipelineFactory;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import io.netty.logging.InternalLogLevel;
|
||||
|
||||
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.PeerWireMessageDecoder;
|
||||
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.TorrentTrafficShapingHandler;
|
||||
|
||||
public class PeerWirePipelineFactory implements ChannelPipelineFactory {
|
||||
private final TorrentController controller;
|
||||
@@ -37,7 +39,7 @@ public class PeerWirePipelineFactory implements ChannelPipelineFactory {
|
||||
p.addLast("message-decoder", new PeerWireMessageDecoder());
|
||||
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));
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.torrent4j.net.peerwire.messages;
|
||||
|
||||
import io.netty.buffer.ChannelBuffer;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.torrent4j.net.peerwire.PeerWireMessage;
|
||||
@@ -36,7 +37,7 @@ public class HandshakeMessage implements PeerWireMessage {
|
||||
protocolString = buffer.readBytes(protocolStringLength).toString();
|
||||
reserved = buffer.readLong();
|
||||
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;
|
||||
if (peer.getState().hasDownloadRequestedBlock())
|
||||
return;
|
||||
if (peer.getState().isRemotellyChoked())
|
||||
return;
|
||||
peer.requestBlock(piece.getFirstBlock());
|
||||
if (peer.getState().isRemotellyChoked()) {
|
||||
peer.declareInterest();
|
||||
} else {
|
||||
peer.requestBlock(piece.getFirstBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@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