implement InfoHash torrent data type

This commit is contained in:
mykola2312 2024-10-20 05:34:32 +03:00
parent b7b772af86
commit 670b11b49a
5 changed files with 146 additions and 1 deletions

View file

@ -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=''

View file

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

View file

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

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

View file

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