implement InfoHash torrent data type
This commit is contained in:
parent
b7b772af86
commit
670b11b49a
5 changed files with 146 additions and 1 deletions
|
|
@ -17,5 +17,8 @@ When there is need to expose local tracker a tracker endpoint should be declare
|
|||
is HTTP or UDP server responsing to BitTorrent announces just like if it was any other regular torrent tracker.
|
||||
|
||||
|
||||
Announce request coming from local peer contains local (peer) data: ID, uploaded, downloaded, and so on.
|
||||
Announce response contains peer set.
|
||||
|
||||
Maven exec with args:
|
||||
mvn exec:java -Dexec.args=''
|
||||
5
pom.xml
5
pom.xml
|
|
@ -70,6 +70,11 @@
|
|||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.18.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.17.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ public class App {
|
|||
private static final Logger log = LoggerFactory.getLogger(App.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
final Option logDirOpt = new Option("l", "log", true, "log dir path");
|
||||
final Option configFileOpt = new Option("c", "config", true, "config.json path");
|
||||
final Option logDirOpt = new Option("l", "log", true, "log dir path");
|
||||
final Options options = new Options()
|
||||
.addOption(configFileOpt)
|
||||
.addOption(logDirOpt);
|
||||
|
|
|
|||
70
src/main/java/com/mykola2312/retracker/tracker/InfoHash.java
Normal file
70
src/main/java/com/mykola2312/retracker/tracker/InfoHash.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package com.mykola2312.retracker.tracker;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.net.URLCodec;
|
||||
|
||||
public class InfoHash {
|
||||
public static final int HASH_LENGTH = 20;
|
||||
|
||||
private byte[] hash = null;
|
||||
|
||||
public InfoHash() {
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
public InfoHash(byte[] hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public byte[] bytes() {
|
||||
return this.hash;
|
||||
}
|
||||
|
||||
public void fromURLEncoded(String urlParam) throws DecoderException {
|
||||
this.hash = URLCodec.decodeUrl(urlParam.getBytes());
|
||||
}
|
||||
|
||||
public String toURLEncoded() {
|
||||
return new String(URLCodec.encodeUrl(new BitSet(), this.hash), StandardCharsets.US_ASCII);
|
||||
}
|
||||
|
||||
public void fromString(String hashString) throws Exception {
|
||||
if (hashString.length() != InfoHash.HASH_LENGTH * 2) {
|
||||
throw new Exception(String.format("hash is not 40 characters length: %s, %d", hashString, hashString.length()));
|
||||
}
|
||||
|
||||
char[] bytePair = new char[2];
|
||||
hash = new byte[InfoHash.HASH_LENGTH];
|
||||
for (int i = 0; i < InfoHash.HASH_LENGTH; i++) {
|
||||
hashString.getChars(i*2, i*2 + 2, bytePair, 0);
|
||||
hash[i] = (byte)Short.parseShort(new String(bytePair), 16);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (int i = 0; i < InfoHash.HASH_LENGTH; i++) {
|
||||
out.append(String.format("%02x", hash[i]));
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof InfoHash)) return false;
|
||||
InfoHash other = (InfoHash)o;
|
||||
return Arrays.equals(this.hash, other.hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.hash != null ? Arrays.hashCode(this.hash) : 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.mykola2312.retracker.tracker;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class InfoHashTest {
|
||||
@Test
|
||||
public void testHashString() {
|
||||
final String hashString = "360775c6629eb06e60d90201aed1b7bc49a1ce16";
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
InfoHash hash = new InfoHash();
|
||||
|
||||
hash.fromString(hashString);
|
||||
assertEquals(hashString, hash.toString());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashEquals() {
|
||||
final String hashString = "360775c6629eb06e60d90201aed1b7bc49a1ce16";
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
InfoHash hashOne = new InfoHash();
|
||||
InfoHash hashTwo = new InfoHash();
|
||||
|
||||
hashOne.fromString(hashString);
|
||||
hashTwo.fromString(hashString);
|
||||
|
||||
assertEquals(true, hashOne.equals(hashTwo));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
final String hashString = "360775c6629eb06e60d90201aed1b7bc49a1ce16";
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
InfoHash hashOne = new InfoHash();
|
||||
InfoHash hashTwo = new InfoHash();
|
||||
|
||||
hashOne.fromString(hashString);
|
||||
hashTwo.fromString(hashString);
|
||||
|
||||
assertEquals(true, hashOne.hashCode() == hashTwo.hashCode());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLEncode() {
|
||||
final String hashString = "360775c6629eb06e60d90201aed1b7bc49a1ce16";
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
InfoHash first = new InfoHash();
|
||||
first.fromString(hashString);
|
||||
|
||||
InfoHash second = new InfoHash();
|
||||
second.fromURLEncoded(first.toURLEncoded());
|
||||
|
||||
System.out.printf("url encoded hash: %s\n", first.toURLEncoded());
|
||||
|
||||
assertEquals(first, second);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue