implement tracker url parsing, begin working on application thread
running
This commit is contained in:
parent
fa7e340ad7
commit
067f10ff69
7 changed files with 172 additions and 4 deletions
|
|
@ -48,7 +48,7 @@ Server architecture 1:
|
||||||
|
|
||||||
Server architecture 2:
|
Server architecture 2:
|
||||||
There is some other entity like Application class that handles running threads, making Tracker responsible for only one thing
|
There is some other entity like Application class that handles running threads, making Tracker responsible for only one thing
|
||||||
abd that thing is tracking peers of torrents. This is preferred design choice since we can then export tracking and scraping
|
and that thing is tracking peers of torrents. This is preferred design choice since we can then export tracking and scraping
|
||||||
functionality in separate interfaces, since UDP announce protocol has scrape method, whilst HTTP doesn't. As for now, current Tracker
|
functionality in separate interfaces, since UDP announce protocol has scrape method, whilst HTTP doesn't. As for now, current Tracker
|
||||||
class implementation doesn't provide any other information for Torrent besides its InfoHash and PeerSet, which is built from local announces
|
class implementation doesn't provide any other information for Torrent besides its InfoHash and PeerSet, which is built from local announces
|
||||||
and announces to destination trackers.
|
and announces to destination trackers.
|
||||||
|
|
|
||||||
2
pom.xml
2
pom.xml
|
|
@ -124,7 +124,7 @@
|
||||||
<artifactId>exec-maven-plugin</artifactId>
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
<version>3.4.1</version>
|
<version>3.4.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>com.mykola2312.retracker.App</mainClass>
|
<mainClass>com.mykola2312.retracker.Main</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
|
||||||
19
src/main/java/com/mykola2312/retracker/Application.java
Normal file
19
src/main/java/com/mykola2312/retracker/Application.java
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.mykola2312.retracker;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.mykola2312.retracker.config.Config;
|
||||||
|
|
||||||
|
/* Class responsible for managing running server threads
|
||||||
|
* and repeating timer-based tasks
|
||||||
|
*/
|
||||||
|
public class Application {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Application.class);
|
||||||
|
|
||||||
|
private Config config;
|
||||||
|
|
||||||
|
public Application(Config config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,8 @@ import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
import ch.qos.logback.core.FileAppender;
|
import ch.qos.logback.core.FileAppender;
|
||||||
|
|
||||||
public class App {
|
public class Main {
|
||||||
private static final Logger log = LoggerFactory.getLogger(App.class);
|
private static final Logger log = LoggerFactory.getLogger(Main.class);
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
final Option configFileOpt = new Option("c", "config", true, "config.json path");
|
final Option configFileOpt = new Option("c", "config", true, "config.json path");
|
||||||
|
|
@ -84,6 +84,8 @@ public class App {
|
||||||
logbackLogger.setAdditive(false);
|
logbackLogger.setAdditive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Application app = new Application(config);
|
||||||
|
|
||||||
log.info("retracker started!");
|
log.info("retracker started!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.mykola2312.retracker.tracker;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
public class TrackerEndpoint {
|
||||||
|
private TrackerProtocol protocol;
|
||||||
|
private InetSocketAddress address;
|
||||||
|
|
||||||
|
private TrackerEndpoint(TrackerProtocol protocol, InetSocketAddress address) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackerProtocol getProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetSocketAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TrackerEndpointException extends Exception {
|
||||||
|
private static final long serialVersionUID = 284186934690560946L;
|
||||||
|
|
||||||
|
public TrackerEndpointException(String url, String message) {
|
||||||
|
super(String.format("malformed tracker url %s, error: %s", url, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrackerEndpoint parseEndpoint(String url) throws TrackerEndpointException {
|
||||||
|
int hostnameIdx = 0;
|
||||||
|
TrackerProtocol protocol;
|
||||||
|
if (url.startsWith("http://")) {
|
||||||
|
hostnameIdx = 7;
|
||||||
|
protocol = TrackerProtocol.HTTP;
|
||||||
|
} else if (url.startsWith("udp://")) {
|
||||||
|
hostnameIdx = 6;
|
||||||
|
protocol = TrackerProtocol.UDP;
|
||||||
|
} else {
|
||||||
|
throw new TrackerEndpointException(url, "unknown tracker protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
String part1 = url.substring(hostnameIdx);
|
||||||
|
if (part1.isEmpty() || part1.isBlank()) {
|
||||||
|
throw new TrackerEndpointException(url, "no hostname after protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] hostnameAndUri = part1.split("/");
|
||||||
|
String hostname = (hostnameAndUri != null && hostnameAndUri.length > 0)
|
||||||
|
? hostnameAndUri[0] : part1;
|
||||||
|
|
||||||
|
if (hostname.isEmpty() || hostname.isBlank()) {
|
||||||
|
throw new TrackerEndpointException(url, "no hostname");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] hostnameAndPort = hostname.split(":");
|
||||||
|
try {
|
||||||
|
int port;
|
||||||
|
InetSocketAddress address;
|
||||||
|
|
||||||
|
if (hostnameAndPort != null && hostnameAndPort.length > 1) {
|
||||||
|
// parse port from url
|
||||||
|
port = Integer.parseInt(hostnameAndPort[1]);
|
||||||
|
address = new InetSocketAddress(InetAddress.getByName(hostnameAndPort[0]), port);
|
||||||
|
} else {
|
||||||
|
// use default port for protocol
|
||||||
|
port = protocol.getDefaultPort();
|
||||||
|
address = new InetSocketAddress(InetAddress.getByName(hostname), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TrackerEndpoint(protocol, address);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TrackerEndpointException(url, "failed to parse port");
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new TrackerEndpointException(url, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.mykola2312.retracker.tracker;
|
||||||
|
|
||||||
|
public enum TrackerProtocol {
|
||||||
|
HTTP,
|
||||||
|
UDP;
|
||||||
|
|
||||||
|
public int getDefaultPort() {
|
||||||
|
switch (this) {
|
||||||
|
case HTTP: return 80;
|
||||||
|
case UDP: return 2710;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
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 TrackerEndpointTest {
|
||||||
|
@Test
|
||||||
|
public void parseTrackerUrlTest() {
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("http://example.com");
|
||||||
|
assertEquals(TrackerProtocol.HTTP, endpoint.getProtocol());
|
||||||
|
assertEquals("example.com", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(80, endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("http://example.com/");
|
||||||
|
assertEquals(TrackerProtocol.HTTP, endpoint.getProtocol());
|
||||||
|
assertEquals("example.com", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(80, endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("http://example.com:80");
|
||||||
|
assertEquals(TrackerProtocol.HTTP, endpoint.getProtocol());
|
||||||
|
assertEquals("example.com", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(80, endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("http://example.com:80/");
|
||||||
|
assertEquals(TrackerProtocol.HTTP, endpoint.getProtocol());
|
||||||
|
assertEquals("example.com", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(80, endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("udp://example.com");
|
||||||
|
assertEquals(TrackerProtocol.UDP, endpoint.getProtocol());
|
||||||
|
assertEquals("example.com", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(TrackerProtocol.UDP.getDefaultPort(), endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
TrackerEndpoint endpoint = TrackerEndpoint.parseEndpoint("udp://127.0.0.1:1337");
|
||||||
|
assertEquals(TrackerProtocol.UDP, endpoint.getProtocol());
|
||||||
|
assertEquals("localhost", endpoint.getAddress().getHostName());
|
||||||
|
assertEquals(1337, endpoint.getAddress().getPort());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue