mirror of
https://github.com/anthonyraymond/joal.git
synced 2024-09-20 07:16:26 +08:00
Switch back to tomcat and fix some warnings
This commit is contained in:
parent
b5c78dd0d7
commit
78df5e9859
484
pom.xml
484
pom.xml
|
@ -1,242 +1,242 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.araymond.joal</groupId>
|
||||
<artifactId>jack-of-all-trades</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jack-of-all-trades</name>
|
||||
<description>A Java command line RatioMaster</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/anthonyraymond/joal.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:anthonyraymond/joal.git</developerConnection>
|
||||
<url>https://github.com/anthonyraymond/joal</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<!-- Project -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
|
||||
<!-- COMPILE -->
|
||||
<commons-io.version>2.6</commons-io.version>
|
||||
<commons-lang3.version>3.7</commons-lang3.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<fluent-hc.version>4.5.5</fluent-hc.version>
|
||||
<generex.version>1.0.2</generex.version>
|
||||
<google.guava.version>25.0-jre</google.guava.version>
|
||||
<ttorrent-core.version>1.5</ttorrent-core.version>
|
||||
|
||||
<!-- TESTS -->
|
||||
<org-assertj.version>3.9.1</org-assertj.version>
|
||||
|
||||
<!-- Plugins -->
|
||||
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
|
||||
<jacoco.plugin.version>0.8.1</jacoco.plugin.version>
|
||||
<coveralls.plugin.version>4.3.0</coveralls.plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.turn</groupId>
|
||||
<artifactId>ttorrent-core</artifactId>
|
||||
<version>${ttorrent-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.mifmif</groupId>
|
||||
<artifactId>generex</artifactId>
|
||||
<version>${generex.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${google.guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>fluent-hc</artifactId>
|
||||
<version>${fluent-hc.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<!-- Version inherited from spring-boot-starter-test -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<!-- Version inherited from spring-boot-starter-test -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${org-assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>bintray-cy6ergn0m-maven</id>
|
||||
<name>bintray-plugins</name>
|
||||
<url>http://dl.bintray.com/cy6ergn0m/maven</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>${jacoco.plugin.version}</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>org/araymond/joal/JackOfAllTradesApplication.class</exclude>
|
||||
<exclude>org/araymond/joal/ApplicationReadyListener.class</exclude>
|
||||
<exclude>org/araymond/joal/ApplicationClosingListener.class</exclude>
|
||||
<exclude>org/araymond/joal/web/config/BeanConfig.class</exclude>
|
||||
<exclude>org/araymond/joal/web/messages/</exclude>
|
||||
<exclude>org/araymond/joal/web/services/corelistener/</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eluder.coveralls</groupId>
|
||||
<artifactId>coveralls-maven-plugin</artifactId>
|
||||
<version>${coveralls.plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.araymond.joal</groupId>
|
||||
<artifactId>jack-of-all-trades</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jack-of-all-trades</name>
|
||||
<description>A Java command line RatioMaster</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/anthonyraymond/joal.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:anthonyraymond/joal.git</developerConnection>
|
||||
<url>https://github.com/anthonyraymond/joal</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<!-- Project -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
|
||||
<!-- COMPILE -->
|
||||
<commons-io.version>2.6</commons-io.version>
|
||||
<commons-lang3.version>3.7</commons-lang3.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<fluent-hc.version>4.5.5</fluent-hc.version>
|
||||
<generex.version>1.0.2</generex.version>
|
||||
<google.guava.version>25.1-jre</google.guava.version>
|
||||
<ttorrent-core.version>1.5</ttorrent-core.version>
|
||||
|
||||
<!-- TESTS -->
|
||||
<org-assertj.version>3.9.1</org-assertj.version>
|
||||
|
||||
<!-- Plugins -->
|
||||
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
|
||||
<jacoco.plugin.version>0.8.1</jacoco.plugin.version>
|
||||
<coveralls.plugin.version>4.3.0</coveralls.plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<!--<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>-->
|
||||
<exclusion>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.turn</groupId>
|
||||
<artifactId>ttorrent-core</artifactId>
|
||||
<version>${ttorrent-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.mifmif</groupId>
|
||||
<artifactId>generex</artifactId>
|
||||
<version>${generex.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${google.guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>fluent-hc</artifactId>
|
||||
<version>${fluent-hc.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<!-- Version inherited from spring-boot-starter-test -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<!-- Version inherited from spring-boot-starter-test -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${org-assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>bintray-cy6ergn0m-maven</id>
|
||||
<name>bintray-plugins</name>
|
||||
<url>http://dl.bintray.com/cy6ergn0m/maven</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>${jacoco.plugin.version}</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>org/araymond/joal/JackOfAllTradesApplication.class</exclude>
|
||||
<exclude>org/araymond/joal/ApplicationReadyListener.class</exclude>
|
||||
<exclude>org/araymond/joal/ApplicationClosingListener.class</exclude>
|
||||
<exclude>org/araymond/joal/web/config/BeanConfig.class</exclude>
|
||||
<exclude>org/araymond/joal/web/messages/</exclude>
|
||||
<exclude>org/araymond/joal/web/services/corelistener/</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eluder.coveralls</groupId>
|
||||
<artifactId>coveralls-maven-plugin</artifactId>
|
||||
<version>${coveralls.plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -28,7 +28,7 @@ public class CoreEventListener {
|
|||
@Async
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void handleTorrentFileAddedForSeed(final TorrentFileAddedEvent event) throws IOException {
|
||||
public void handleTorrentFileAddedForSeed(final TorrentFileAddedEvent event) throws IOException {
|
||||
logger.debug("Event TorrentFileAddedEvent caught.");
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class CoreEventListener {
|
|||
@Async
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void handleSeedSessionHasEnded(final GlobalSeedStoppedEvent event) {
|
||||
public void handleSeedSessionHasEnded(final GlobalSeedStoppedEvent event) {
|
||||
logger.debug("Event GlobalSeedStoppedEvent caught.");
|
||||
// TODO : log that the seed session is over
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.google.common.collect.Maps;
|
|||
import org.araymond.joal.core.bandwith.BandwidthDispatcher;
|
||||
import org.araymond.joal.core.bandwith.RandomSpeedProvider;
|
||||
import org.araymond.joal.core.bandwith.Speed;
|
||||
import org.araymond.joal.core.bandwith.SpeedChangedListener;
|
||||
import org.araymond.joal.core.client.emulated.BitTorrentClient;
|
||||
import org.araymond.joal.core.client.emulated.BitTorrentClientProvider;
|
||||
import org.araymond.joal.core.config.AppConfiguration;
|
||||
|
@ -93,9 +94,7 @@ public class SeedManager {
|
|||
|
||||
final RandomSpeedProvider randomSpeedProvider = new RandomSpeedProvider(appConfiguration);
|
||||
this.bandwidthDispatcher = new BandwidthDispatcher(5000, randomSpeedProvider);
|
||||
this.bandwidthDispatcher.setSpeedListener((speeds -> {
|
||||
this.publisher.publishEvent(new SeedingSpeedsHasChangedEvent(speeds));
|
||||
}));
|
||||
this.bandwidthDispatcher.setSpeedListener(new SeedManagerSpeedChangeListener(this.publisher));
|
||||
this.bandwidthDispatcher.start();
|
||||
|
||||
final AnnounceDataAccessor announceDataAccessor = new AnnounceDataAccessor(bitTorrentClient, bandwidthDispatcher, this.connectionHandler);
|
||||
|
@ -235,4 +234,17 @@ public class SeedManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class SeedManagerSpeedChangeListener implements SpeedChangedListener {
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
private SeedManagerSpeedChangeListener(final ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void speedsHasChanged(final Map<InfoHash, Speed> speeds) {
|
||||
this.publisher.publishEvent(new SeedingSpeedsHasChangedEvent(speeds));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,215 +1,217 @@
|
|||
package org.araymond.joal.core.bandwith;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.araymond.joal.core.bandwith.weight.PeersAwareWeightCalculator;
|
||||
import org.araymond.joal.core.bandwith.weight.WeightHolder;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable {
|
||||
private static final Logger logger = getLogger(BandwidthDispatcher.class);
|
||||
private final ReentrantReadWriteLock lock;
|
||||
private final WeightHolder<InfoHash> weightHolder;
|
||||
private final RandomSpeedProvider randomSpeedProvider;
|
||||
private final Map<InfoHash, TorrentSeedStats> torrentsSeedStats;
|
||||
private final Map<InfoHash, Speed> speedMap;
|
||||
private SpeedChangedListener speedChangedListener;
|
||||
private final int threadPauseInterval;
|
||||
private int threadLoopCounter = 0;
|
||||
private volatile boolean stop = false;
|
||||
private Thread thread;
|
||||
|
||||
public BandwidthDispatcher(final int threadPauseInterval, final RandomSpeedProvider randomSpeedProvider) {
|
||||
this.threadPauseInterval = threadPauseInterval;
|
||||
this.torrentsSeedStats = new HashMap<>();
|
||||
this.speedMap = new HashMap<>();
|
||||
this.lock = new ReentrantReadWriteLock();
|
||||
|
||||
|
||||
this.weightHolder = new WeightHolder<>(new PeersAwareWeightCalculator());
|
||||
this.randomSpeedProvider = randomSpeedProvider;
|
||||
}
|
||||
|
||||
public void setSpeedListener(final SpeedChangedListener speedListener) {
|
||||
this.speedChangedListener = speedListener;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method does not benefit from the lock, because the value will never be accessed in a ambiguous way.
|
||||
* And even if it happens, we returns 0 by default.
|
||||
*/
|
||||
public TorrentSeedStats getSeedStatForTorrent(final InfoHash infoHash) {
|
||||
return this.torrentsSeedStats.getOrDefault(infoHash, new TorrentSeedStats());
|
||||
}
|
||||
|
||||
public Map<InfoHash, Speed> getSpeedMap() {
|
||||
try {
|
||||
this.lock.readLock().lock();
|
||||
return speedMap;
|
||||
} finally {
|
||||
this.lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.stop = false;
|
||||
this.thread = new Thread(this);
|
||||
this.thread.setName("bandwidth-dispatcher");
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.stop = true;
|
||||
this.thread.interrupt();
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!this.stop) {
|
||||
Thread.sleep(this.threadPauseInterval);
|
||||
++this.threadLoopCounter;
|
||||
// refresh bandwidth every 1200000 milliseconds (20 minutes)
|
||||
if (this.threadLoopCounter == 1200000 / this.threadPauseInterval) {
|
||||
this.refreshCurrentBandwidth();
|
||||
this.threadLoopCounter = 0;
|
||||
}
|
||||
|
||||
// This method as to run as fast as possible to avoid blocking other ones. Because we wan't this loop
|
||||
// to be scheduled as precise as we can. Locking to much will delay the Thread.sleep and cause stats
|
||||
// to be undervalued
|
||||
this.lock.readLock().lock();
|
||||
final Set<Map.Entry<InfoHash, TorrentSeedStats>> entrySet = Sets.newHashSet(this.torrentsSeedStats.entrySet());
|
||||
this.lock.readLock().unlock();
|
||||
|
||||
for (final Map.Entry<InfoHash, TorrentSeedStats> entry : entrySet) {
|
||||
final long speedInBytesPerSecond = this.speedMap.getOrDefault(entry.getKey(), new Speed(0)).getBytesPerSeconds();
|
||||
// Divide by 1000 because of the thread pause interval being in milliseconds
|
||||
// The multiplication HAS to be done before the division, otherwise we're going to have trailing zeroes
|
||||
entry.getValue().addUploaded((speedInBytesPerSecond * this.threadPauseInterval) / 1000);
|
||||
}
|
||||
}
|
||||
} catch (final InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTorrentPeers(final InfoHash infoHash, final int seeders, final int leechers) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Updating Peers stats for {}", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.weightHolder.addOrUpdate(infoHash, new Peers(seeders, leechers));
|
||||
this.recomputeSpeeds();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerTorrent(final InfoHash infoHash) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{} has been added to bandwidth dispatcher.", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.torrentsSeedStats.put(infoHash, new TorrentSeedStats());
|
||||
this.speedMap.put(infoHash, new Speed(0));
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterTorrent(final InfoHash infoHash) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{} has been removed from bandwidth dispatcher.", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.weightHolder.remove(infoHash);
|
||||
this.torrentsSeedStats.remove(infoHash);
|
||||
this.speedMap.remove(infoHash);
|
||||
this.recomputeSpeeds();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshCurrentBandwidth() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing global bandwidth");
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.randomSpeedProvider.refresh();
|
||||
this.recomputeSpeeds();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Global bandwidth refreshed, new value is {}", FileUtils.byteCountToDisplaySize(this.randomSpeedProvider.getInBytesPerSeconds()));
|
||||
}
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void recomputeSpeeds() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing all torrents speeds");
|
||||
}
|
||||
for (final InfoHash infohash : this.torrentsSeedStats.keySet()) {
|
||||
final double percentOfSpeedAssigned = this.weightHolder.getTotalWeight() == 0.0
|
||||
? 0.0
|
||||
: this.weightHolder.getWeightFor(infohash) / this.weightHolder.getTotalWeight();
|
||||
|
||||
this.speedMap.compute(infohash, (hash, speed) -> {
|
||||
if (speed == null) {
|
||||
return new Speed(0);
|
||||
}
|
||||
speed.setBytesPerSeconds((long) (this.randomSpeedProvider.getInBytesPerSeconds() * percentOfSpeedAssigned));
|
||||
return speed;
|
||||
});
|
||||
}
|
||||
if (speedChangedListener != null) {
|
||||
this.speedChangedListener.speedsHasChanged(Maps.newHashMap(this.speedMap));
|
||||
}
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
final StringBuilder sb = new StringBuilder("All torrents speeds has been refreshed:\n");
|
||||
final double totalWeight = this.weightHolder.getTotalWeight();
|
||||
this.speedMap.forEach((infoHash, speed) -> {
|
||||
final String humanReadableSpeed = FileUtils.byteCountToDisplaySize(speed.getBytesPerSeconds());
|
||||
final double torrentWeight = this.weightHolder.getWeightFor(infoHash);
|
||||
final double weightInPercent = torrentWeight > 0.0
|
||||
? totalWeight / torrentWeight * 100
|
||||
: 0;
|
||||
sb.append(" ")
|
||||
.append(infoHash.humanReadableValue())
|
||||
.append(":")
|
||||
.append("\n ").append("current speed: ").append(humanReadableSpeed).append("/s")
|
||||
.append("\n ").append("overall upload: ").append(FileUtils.byteCountToDisplaySize(this.torrentsSeedStats.get(infoHash).getUploaded()))
|
||||
.append("\n ").append("weight: ").append(weightInPercent).append("% (").append(torrentWeight).append(" out of ").append(totalWeight).append(")")
|
||||
.append("\n");
|
||||
});
|
||||
sb.setLength(sb.length() - 1); // remove last \n
|
||||
logger.debug(sb.toString());
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.debug("Error while printing debug message for speed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package org.araymond.joal.core.bandwith;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.araymond.joal.core.bandwith.weight.PeersAwareWeightCalculator;
|
||||
import org.araymond.joal.core.bandwith.weight.WeightHolder;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable {
|
||||
private static final Logger logger = getLogger(BandwidthDispatcher.class);
|
||||
private final ReentrantReadWriteLock lock;
|
||||
private final WeightHolder<InfoHash> weightHolder;
|
||||
private final RandomSpeedProvider randomSpeedProvider;
|
||||
private final Map<InfoHash, TorrentSeedStats> torrentsSeedStats;
|
||||
private final Map<InfoHash, Speed> speedMap;
|
||||
private SpeedChangedListener speedChangedListener;
|
||||
private final int threadPauseInterval;
|
||||
private int threadLoopCounter = 0;
|
||||
private volatile boolean stop = false;
|
||||
private Thread thread;
|
||||
|
||||
public BandwidthDispatcher(final int threadPauseInterval, final RandomSpeedProvider randomSpeedProvider) {
|
||||
this.threadPauseInterval = threadPauseInterval;
|
||||
this.torrentsSeedStats = new HashMap<>();
|
||||
this.speedMap = new HashMap<>();
|
||||
this.lock = new ReentrantReadWriteLock();
|
||||
|
||||
|
||||
this.weightHolder = new WeightHolder<>(new PeersAwareWeightCalculator());
|
||||
this.randomSpeedProvider = randomSpeedProvider;
|
||||
}
|
||||
|
||||
public void setSpeedListener(final SpeedChangedListener speedListener) {
|
||||
this.speedChangedListener = speedListener;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method does not benefit from the lock, because the value will never be accessed in a ambiguous way.
|
||||
* And even if it happens, we returns 0 by default.
|
||||
*/
|
||||
public TorrentSeedStats getSeedStatForTorrent(final InfoHash infoHash) {
|
||||
final TorrentSeedStats torrentSeedStats = this.torrentsSeedStats.get(infoHash);
|
||||
return torrentSeedStats == null ? new TorrentSeedStats() : torrentSeedStats;
|
||||
}
|
||||
|
||||
public Map<InfoHash, Speed> getSpeedMap() {
|
||||
try {
|
||||
this.lock.readLock().lock();
|
||||
return Maps.newHashMap(speedMap);
|
||||
} finally {
|
||||
this.lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.stop = false;
|
||||
this.thread = new Thread(this);
|
||||
this.thread.setName("bandwidth-dispatcher");
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.stop = true;
|
||||
this.thread.interrupt();
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!this.stop) {
|
||||
Thread.sleep(this.threadPauseInterval);
|
||||
++this.threadLoopCounter;
|
||||
// refresh bandwidth every 1200000 milliseconds (20 minutes)
|
||||
if (this.threadLoopCounter == 1200000 / this.threadPauseInterval) {
|
||||
this.refreshCurrentBandwidth();
|
||||
this.threadLoopCounter = 0;
|
||||
}
|
||||
|
||||
// This method as to run as fast as possible to avoid blocking other ones. Because we wan't this loop
|
||||
// to be scheduled as precise as we can. Locking to much will delay the Thread.sleep and cause stats
|
||||
// to be undervalued
|
||||
this.lock.readLock().lock();
|
||||
final Set<Map.Entry<InfoHash, TorrentSeedStats>> entrySet = Sets.newHashSet(this.torrentsSeedStats.entrySet());
|
||||
this.lock.readLock().unlock();
|
||||
|
||||
for (final Map.Entry<InfoHash, TorrentSeedStats> entry : entrySet) {
|
||||
final Speed speed = this.speedMap.get(entry.getKey());
|
||||
final long speedInBytesPerSecond = speed == null ? 0: speed.getBytesPerSeconds(); // avoid Map#getOrDefault as it will trigger a lot of Speed object instantiation for nothing.
|
||||
// Divide by 1000 because of the thread pause interval being in milliseconds
|
||||
// The multiplication HAS to be done before the division, otherwise we're going to have trailing zeroes
|
||||
entry.getValue().addUploaded((speedInBytesPerSecond * this.threadPauseInterval) / 1000);
|
||||
}
|
||||
}
|
||||
} catch (final InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTorrentPeers(final InfoHash infoHash, final int seeders, final int leechers) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Updating Peers stats for {}", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.weightHolder.addOrUpdate(infoHash, new Peers(seeders, leechers));
|
||||
this.recomputeSpeeds();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerTorrent(final InfoHash infoHash) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{} has been added to bandwidth dispatcher.", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.torrentsSeedStats.put(infoHash, new TorrentSeedStats());
|
||||
this.speedMap.put(infoHash, new Speed(0));
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterTorrent(final InfoHash infoHash) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{} has been removed from bandwidth dispatcher.", infoHash.humanReadableValue());
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.weightHolder.remove(infoHash);
|
||||
this.torrentsSeedStats.remove(infoHash);
|
||||
this.speedMap.remove(infoHash);
|
||||
this.recomputeSpeeds();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshCurrentBandwidth() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing global bandwidth");
|
||||
}
|
||||
this.lock.writeLock().lock();
|
||||
try {
|
||||
this.randomSpeedProvider.refresh();
|
||||
this.recomputeSpeeds();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Global bandwidth refreshed, new value is {}", FileUtils.byteCountToDisplaySize(this.randomSpeedProvider.getInBytesPerSeconds()));
|
||||
}
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void recomputeSpeeds() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing all torrents speeds");
|
||||
}
|
||||
for (final InfoHash infohash : this.torrentsSeedStats.keySet()) {
|
||||
final double percentOfSpeedAssigned = this.weightHolder.getTotalWeight() == 0.0
|
||||
? 0.0
|
||||
: this.weightHolder.getWeightFor(infohash) / this.weightHolder.getTotalWeight();
|
||||
|
||||
this.speedMap.compute(infohash, (hash, speed) -> {
|
||||
if (speed == null) {
|
||||
return new Speed(0);
|
||||
}
|
||||
speed.setBytesPerSeconds((long) (this.randomSpeedProvider.getInBytesPerSeconds() * percentOfSpeedAssigned));
|
||||
return speed;
|
||||
});
|
||||
}
|
||||
if (speedChangedListener != null) {
|
||||
this.speedChangedListener.speedsHasChanged(Maps.newHashMap(this.speedMap));
|
||||
}
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
final StringBuilder sb = new StringBuilder("All torrents speeds has been refreshed:\n");
|
||||
final double totalWeight = this.weightHolder.getTotalWeight();
|
||||
this.speedMap.forEach((infoHash, speed) -> {
|
||||
final String humanReadableSpeed = FileUtils.byteCountToDisplaySize(speed.getBytesPerSeconds());
|
||||
final double torrentWeight = this.weightHolder.getWeightFor(infoHash);
|
||||
final double weightInPercent = torrentWeight > 0.0
|
||||
? totalWeight / torrentWeight * 100
|
||||
: 0;
|
||||
sb.append(" ")
|
||||
.append(infoHash.humanReadableValue())
|
||||
.append(":")
|
||||
.append("\n ").append("current speed: ").append(humanReadableSpeed).append("/s")
|
||||
.append("\n ").append("overall upload: ").append(FileUtils.byteCountToDisplaySize(this.torrentsSeedStats.get(infoHash).getUploaded()))
|
||||
.append("\n ").append("weight: ").append(weightInPercent).append("% (").append(torrentWeight).append(" out of ").append(totalWeight).append(")")
|
||||
.append("\n");
|
||||
});
|
||||
sb.setLength(sb.length() - 1); // remove last \n
|
||||
logger.debug(sb.toString());
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.debug("Error while printing debug message for speed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public class BitTorrentClient {
|
|||
public List<Map.Entry<String, String>> createRequestHeaders() {
|
||||
final List<Map.Entry<String, String>> headers = new ArrayList<>(this.headers.size() + 1);
|
||||
|
||||
this.headers.stream().forEachOrdered(header -> {
|
||||
for (final Map.Entry<String, String> header : this.headers) {
|
||||
final String name = header.getKey();
|
||||
final String value = header.getValue()
|
||||
.replaceAll("\\{java}", System.getProperty("java.version"))
|
||||
|
@ -146,7 +146,7 @@ public class BitTorrentClient {
|
|||
}
|
||||
|
||||
headers.add(new AbstractMap.SimpleImmutableEntry<>(name, value));
|
||||
});
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.araymond.joal.core.client.emulated.generator.peerid.generation;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Objects;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.araymond.joal.core.client.emulated.TorrentClientConfigIntegrityException;
|
||||
|
@ -60,7 +61,7 @@ public class RandomPoolWithChecksumPeerIdAlgorithm implements PeerIdAlgorithm {
|
|||
|
||||
@VisibleForTesting
|
||||
byte[] createSecureRandomSeed() {
|
||||
return Instant.now().toString().getBytes();
|
||||
return Instant.now().toString().getBytes(Charsets.UTF_8);
|
||||
}
|
||||
|
||||
private Integer getRandomIntBetween10And50() {
|
||||
|
|
|
@ -62,7 +62,7 @@ public class TorrentFileProvider extends FileAlterationListenerAdaptor {
|
|||
}
|
||||
|
||||
this.archiveFolder = joalFoldersPath.getTorrentArchivedPath();
|
||||
this.torrentFiles = Collections.synchronizedMap(new HashMap<File, MockedTorrent>());
|
||||
this.torrentFiles = Collections.synchronizedMap(new HashMap<>());
|
||||
this.watcher = new TorrentFileWatcher(this, torrentFolder);
|
||||
this.torrentFileChangeListener = new HashSet<>();
|
||||
}
|
||||
|
|
|
@ -1,224 +1,224 @@
|
|||
package org.araymond.joal.core.ttorrent.client;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
|
||||
import org.araymond.joal.core.config.AppConfiguration;
|
||||
import org.araymond.joal.core.events.torrent.files.TorrentFileAddedEvent;
|
||||
import org.araymond.joal.core.events.torrent.files.TorrentFileDeletedEvent;
|
||||
import org.araymond.joal.core.exception.NoMoreTorrentsFileAvailableException;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.araymond.joal.core.torrent.torrent.MockedTorrent;
|
||||
import org.araymond.joal.core.torrent.watcher.TorrentFileChangeAware;
|
||||
import org.araymond.joal.core.torrent.watcher.TorrentFileProvider;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFacade;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFactory;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnounceRequest;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnouncerExecutor;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class Client implements TorrentFileChangeAware, ClientFacade {
|
||||
private static final Logger logger = getLogger(Client.class);
|
||||
|
||||
private final AppConfiguration appConfiguration;
|
||||
private final TorrentFileProvider torrentFileProvider;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private AnnouncerExecutor announcerExecutor;
|
||||
private final List<Announcer> currentlySeedingAnnouncer;
|
||||
private final DelayQueue<AnnounceRequest> delayQueue;
|
||||
private final AnnouncerFactory announcerFactory;
|
||||
private final ReentrantReadWriteLock lock;
|
||||
private Thread thread;
|
||||
private volatile boolean stop = true;
|
||||
|
||||
Client(final AppConfiguration appConfiguration, final TorrentFileProvider torrentFileProvider, final AnnouncerExecutor announcerExecutor, final DelayQueue<AnnounceRequest> delayQueue, final AnnouncerFactory announcerFactory, final ApplicationEventPublisher eventPublisher) {
|
||||
Preconditions.checkNotNull(appConfiguration, "AppConfiguration must not be null");
|
||||
Preconditions.checkNotNull(torrentFileProvider, "TorrentFileProvider must not be null");
|
||||
Preconditions.checkNotNull(delayQueue, "DelayQueue must not be null");
|
||||
Preconditions.checkNotNull(announcerFactory, "AnnouncerFactory must not be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.appConfiguration = appConfiguration;
|
||||
this.torrentFileProvider = torrentFileProvider;
|
||||
this.announcerExecutor = announcerExecutor;
|
||||
this.delayQueue = delayQueue;
|
||||
this.announcerFactory = announcerFactory;
|
||||
this.currentlySeedingAnnouncer = new ArrayList<>();
|
||||
this.lock = new ReentrantReadWriteLock();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setAnnouncerExecutor(final AnnouncerExecutor announcerExecutor) {
|
||||
this.announcerExecutor = announcerExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.stop = false;
|
||||
|
||||
this.thread = new Thread(() -> {
|
||||
while (!this.stop) {
|
||||
final List<AnnounceRequest> availables = this.delayQueue.getAvailables();
|
||||
availables.forEach(req -> {
|
||||
this.announcerExecutor.execute(req);
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.removeIf(an -> an.equals(req.getAnnouncer())); // remove the last recorded event
|
||||
this.currentlySeedingAnnouncer.add(req.getAnnouncer());
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < this.appConfiguration.getSimultaneousSeed(); i++) {
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
break;
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
this.thread.setName("client-orchestrator-thread");
|
||||
|
||||
this.thread.start();
|
||||
this.torrentFileProvider.registerListener(this);
|
||||
}
|
||||
|
||||
private void addTorrent() throws NoMoreTorrentsFileAvailableException {
|
||||
final MockedTorrent torrent = this.torrentFileProvider.getTorrentNotIn(
|
||||
this.currentlySeedingAnnouncer.stream()
|
||||
.map(Announcer::getTorrentInfoHash)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
final Announcer announcer = this.announcerFactory.create(torrent);
|
||||
this.currentlySeedingAnnouncer.add(announcer);
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), 0, ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.stop = true;
|
||||
this.torrentFileProvider.unRegisterListener(this);
|
||||
this.thread.interrupt();
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
this.delayQueue.drainAll().stream()
|
||||
.filter(req -> req.getEvent() != RequestEvent.STARTED)
|
||||
.map(AnnounceRequest::getAnnouncer)
|
||||
.map(AnnounceRequest::createStop)
|
||||
.forEach(this.announcerExecutor::execute);
|
||||
|
||||
this.announcerExecutor.awaitForRunningTasks();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void onTooManyFailedInARaw(final Announcer announcer) {
|
||||
if (this.stop) {
|
||||
this.currentlySeedingAnnouncer.remove(announcer);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.remove(announcer); // Remove from announcers list asap, otherwise the deletion will trigger a announce stop event.
|
||||
this.torrentFileProvider.moveToArchiveFolder(announcer.getTorrentInfoHash());
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNoMorePeers(final InfoHash infoHash) {
|
||||
if (!this.appConfiguration.shouldKeepTorrentWithZeroLeechers()) {
|
||||
this.torrentFileProvider.moveToArchiveFolder(infoHash);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTorrentHasStopped(final Announcer stoppedAnnouncer) {
|
||||
if (this.stop) {
|
||||
this.currentlySeedingAnnouncer.remove(stoppedAnnouncer);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
} finally {
|
||||
this.currentlySeedingAnnouncer.remove(stoppedAnnouncer);
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorrentFileAdded(final MockedTorrent torrent) {
|
||||
this.eventPublisher.publishEvent(new TorrentFileAddedEvent(torrent));
|
||||
if (this.stop) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
if (this.currentlySeedingAnnouncer.size() >= this.appConfiguration.getSimultaneousSeed()) {
|
||||
return;
|
||||
}
|
||||
final Announcer announcer = this.announcerFactory.create(torrent);
|
||||
this.currentlySeedingAnnouncer.add(announcer);
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), 1, ChronoUnit.SECONDS);
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorrentFileRemoved(final MockedTorrent torrent) {
|
||||
this.eventPublisher.publishEvent(new TorrentFileDeletedEvent(torrent));
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.stream()
|
||||
.filter(announcer -> announcer.getTorrentInfoHash().equals(torrent.getTorrentInfoHash()))
|
||||
.findFirst()
|
||||
.ifPresent(announcer ->
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStop(announcer), 1, ChronoUnit.SECONDS)
|
||||
);
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnnouncerFacade> getCurrentlySeedingAnnouncer() {
|
||||
try {
|
||||
this.lock.readLock().lock();
|
||||
return Lists.newArrayList(this.currentlySeedingAnnouncer);
|
||||
} finally {
|
||||
this.lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.araymond.joal.core.ttorrent.client;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
|
||||
import org.araymond.joal.core.config.AppConfiguration;
|
||||
import org.araymond.joal.core.events.torrent.files.TorrentFileAddedEvent;
|
||||
import org.araymond.joal.core.events.torrent.files.TorrentFileDeletedEvent;
|
||||
import org.araymond.joal.core.exception.NoMoreTorrentsFileAvailableException;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.araymond.joal.core.torrent.torrent.MockedTorrent;
|
||||
import org.araymond.joal.core.torrent.watcher.TorrentFileChangeAware;
|
||||
import org.araymond.joal.core.torrent.watcher.TorrentFileProvider;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFacade;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFactory;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnounceRequest;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnouncerExecutor;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class Client implements TorrentFileChangeAware, ClientFacade {
|
||||
private static final Logger logger = getLogger(Client.class);
|
||||
|
||||
private final AppConfiguration appConfiguration;
|
||||
private final TorrentFileProvider torrentFileProvider;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private AnnouncerExecutor announcerExecutor;
|
||||
private final List<Announcer> currentlySeedingAnnouncer;
|
||||
private final DelayQueue<AnnounceRequest> delayQueue;
|
||||
private final AnnouncerFactory announcerFactory;
|
||||
private final ReentrantReadWriteLock lock;
|
||||
private Thread thread;
|
||||
private volatile boolean stop = true;
|
||||
|
||||
Client(final AppConfiguration appConfiguration, final TorrentFileProvider torrentFileProvider, final AnnouncerExecutor announcerExecutor, final DelayQueue<AnnounceRequest> delayQueue, final AnnouncerFactory announcerFactory, final ApplicationEventPublisher eventPublisher) {
|
||||
Preconditions.checkNotNull(appConfiguration, "AppConfiguration must not be null");
|
||||
Preconditions.checkNotNull(torrentFileProvider, "TorrentFileProvider must not be null");
|
||||
Preconditions.checkNotNull(delayQueue, "DelayQueue must not be null");
|
||||
Preconditions.checkNotNull(announcerFactory, "AnnouncerFactory must not be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.appConfiguration = appConfiguration;
|
||||
this.torrentFileProvider = torrentFileProvider;
|
||||
this.announcerExecutor = announcerExecutor;
|
||||
this.delayQueue = delayQueue;
|
||||
this.announcerFactory = announcerFactory;
|
||||
this.currentlySeedingAnnouncer = new ArrayList<>();
|
||||
this.lock = new ReentrantReadWriteLock();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setAnnouncerExecutor(final AnnouncerExecutor announcerExecutor) {
|
||||
this.announcerExecutor = announcerExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.stop = false;
|
||||
|
||||
this.thread = new Thread(() -> {
|
||||
while (!this.stop) {
|
||||
final List<AnnounceRequest> availables = this.delayQueue.getAvailables();
|
||||
for (final AnnounceRequest req : availables) {
|
||||
this.announcerExecutor.execute(req);
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.removeIf(an -> an.equals(req.getAnnouncer())); // remove the last recorded event
|
||||
this.currentlySeedingAnnouncer.add(req.getAnnouncer());
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < this.appConfiguration.getSimultaneousSeed(); i++) {
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
break;
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
this.thread.setName("client-orchestrator-thread");
|
||||
|
||||
this.thread.start();
|
||||
this.torrentFileProvider.registerListener(this);
|
||||
}
|
||||
|
||||
private void addTorrent() throws NoMoreTorrentsFileAvailableException {
|
||||
final MockedTorrent torrent = this.torrentFileProvider.getTorrentNotIn(
|
||||
this.currentlySeedingAnnouncer.stream()
|
||||
.map(Announcer::getTorrentInfoHash)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
final Announcer announcer = this.announcerFactory.create(torrent);
|
||||
this.currentlySeedingAnnouncer.add(announcer);
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), 0, ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.stop = true;
|
||||
this.torrentFileProvider.unRegisterListener(this);
|
||||
this.thread.interrupt();
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException ignored) {
|
||||
}
|
||||
this.delayQueue.drainAll().stream()
|
||||
.filter(req -> req.getEvent() != RequestEvent.STARTED)
|
||||
.map(AnnounceRequest::getAnnouncer)
|
||||
.map(AnnounceRequest::createStop)
|
||||
.forEach(this.announcerExecutor::execute);
|
||||
|
||||
this.announcerExecutor.awaitForRunningTasks();
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void onTooManyFailedInARaw(final Announcer announcer) {
|
||||
if (this.stop) {
|
||||
this.currentlySeedingAnnouncer.remove(announcer);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.remove(announcer); // Remove from announcers list asap, otherwise the deletion will trigger a announce stop event.
|
||||
this.torrentFileProvider.moveToArchiveFolder(announcer.getTorrentInfoHash());
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNoMorePeers(final InfoHash infoHash) {
|
||||
if (!this.appConfiguration.shouldKeepTorrentWithZeroLeechers()) {
|
||||
this.torrentFileProvider.moveToArchiveFolder(infoHash);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTorrentHasStopped(final Announcer stoppedAnnouncer) {
|
||||
if (this.stop) {
|
||||
this.currentlySeedingAnnouncer.remove(stoppedAnnouncer);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
|
||||
this.addTorrent();
|
||||
} catch (final NoMoreTorrentsFileAvailableException ignored) {
|
||||
} finally {
|
||||
this.currentlySeedingAnnouncer.remove(stoppedAnnouncer);
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorrentFileAdded(final MockedTorrent torrent) {
|
||||
this.eventPublisher.publishEvent(new TorrentFileAddedEvent(torrent));
|
||||
if (this.stop) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
if (this.currentlySeedingAnnouncer.size() >= this.appConfiguration.getSimultaneousSeed()) {
|
||||
return;
|
||||
}
|
||||
final Announcer announcer = this.announcerFactory.create(torrent);
|
||||
this.currentlySeedingAnnouncer.add(announcer);
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), 1, ChronoUnit.SECONDS);
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorrentFileRemoved(final MockedTorrent torrent) {
|
||||
this.eventPublisher.publishEvent(new TorrentFileDeletedEvent(torrent));
|
||||
try {
|
||||
this.lock.writeLock().lock();
|
||||
this.currentlySeedingAnnouncer.stream()
|
||||
.filter(announcer -> announcer.getTorrentInfoHash().equals(torrent.getTorrentInfoHash()))
|
||||
.findFirst()
|
||||
.ifPresent(announcer ->
|
||||
this.delayQueue.addOrReplace(AnnounceRequest.createStop(announcer), 1, ChronoUnit.SECONDS)
|
||||
);
|
||||
} finally {
|
||||
this.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnnouncerFacade> getCurrentlySeedingAnnouncer() {
|
||||
try {
|
||||
this.lock.readLock().lock();
|
||||
return Lists.newArrayList(this.currentlySeedingAnnouncer);
|
||||
} finally {
|
||||
this.lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package org.araymond.joal.core.ttorrent.client;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.*;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
|
@ -76,8 +78,13 @@ public class ConnectionHandler {
|
|||
InetAddress readIpFromProvider(final String providerUrl) throws IOException {
|
||||
final URLConnection urlConnection = new URL(providerUrl).openConnection();
|
||||
urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
|
||||
try (final BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {
|
||||
try (final BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), Charsets.UTF_8))) {
|
||||
return InetAddress.getByName(in.readLine());
|
||||
}finally {
|
||||
// Ensure all streams associated with http connection are closed
|
||||
final InputStream err = ((HttpURLConnection) urlConnection).getErrorStream();
|
||||
try { if (err != null) err.close(); }
|
||||
catch (final IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,90 +1,88 @@
|
|||
package org.araymond.joal.core.ttorrent.client.announcer.response;
|
||||
|
||||
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
|
||||
import org.araymond.joal.core.events.announce.FailedToAnnounceEvent;
|
||||
import org.araymond.joal.core.events.announce.SuccessfullyAnnounceEvent;
|
||||
import org.araymond.joal.core.events.announce.TooManyAnnouncesFailedEvent;
|
||||
import org.araymond.joal.core.events.announce.WillAnnounceEvent;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.exceptions.TooMuchAnnouncesFailedInARawException;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class AnnounceEventPublisher implements AnnounceResponseHandlerChainElement {
|
||||
private static final Logger logger = getLogger(AnnounceEventPublisher.class);
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public AnnounceEventPublisher(final ApplicationEventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnouncerWillAnnounce(final Announcer announcer, final RequestEvent event) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish WillAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new WillAnnounceEvent(announcer, event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STARTED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STARTED, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.NONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.NONE, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STOPPED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
final InfoHash infoHash = announcer.getTorrentInfoHash();
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STOPPED, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish TooManyAnnouncesFailedEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new TooManyAnnouncesFailedEvent(announcer));
|
||||
}
|
||||
|
||||
}
|
||||
package org.araymond.joal.core.ttorrent.client.announcer.response;
|
||||
|
||||
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
|
||||
import org.araymond.joal.core.events.announce.FailedToAnnounceEvent;
|
||||
import org.araymond.joal.core.events.announce.SuccessfullyAnnounceEvent;
|
||||
import org.araymond.joal.core.events.announce.TooManyAnnouncesFailedEvent;
|
||||
import org.araymond.joal.core.events.announce.WillAnnounceEvent;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.exceptions.TooMuchAnnouncesFailedInARawException;
|
||||
import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class AnnounceEventPublisher implements AnnounceResponseHandlerChainElement {
|
||||
private static final Logger logger = getLogger(AnnounceEventPublisher.class);
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public AnnounceEventPublisher(final ApplicationEventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnouncerWillAnnounce(final Announcer announcer, final RequestEvent event) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish WillAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new WillAnnounceEvent(announcer, event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STARTED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STARTED, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.NONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.NONE, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STOPPED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STOPPED, throwable.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Publish TooManyAnnouncesFailedEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new TooManyAnnouncesFailedEvent(announcer));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,7 +80,9 @@ public class TrackerClient {
|
|||
host += ":" + announceUri.getPort();
|
||||
}
|
||||
request.addHeader("Host", host);
|
||||
headers.forEach(entry -> request.addHeader(entry.getKey(), entry.getValue()));
|
||||
for (final Map.Entry<String, String> entry : headers) {
|
||||
request.addHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
final Response response;
|
||||
try {
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.springframework.messaging.Message;
|
|||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.simp.stomp.StompCommand;
|
||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
|
||||
import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.messaging.support.MessageHeaderAccessor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
@ -19,7 +19,7 @@ import javax.inject.Inject;
|
|||
*/
|
||||
@ConditionalOnWebUi
|
||||
@Component
|
||||
public class AuthChannelInterceptorAdapter extends ChannelInterceptorAdapter {
|
||||
public class AuthChannelInterceptorAdapter implements ChannelInterceptor {
|
||||
static final String USERNAME_HEADER = "X-Joal-Username";
|
||||
static final String TOKEN_HEADER = "X-Joal-Auth-Token";
|
||||
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
package org.araymond.joal.web.messages.outgoing.impl.speed;
|
||||
|
||||
import org.araymond.joal.core.events.speed.SeedingSpeedsHasChangedEvent;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.araymond.joal.web.messages.outgoing.MessagePayload;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SeedingSpeedHasChangedPayload implements MessagePayload {
|
||||
private final List<SpeedPayload> speeds;
|
||||
|
||||
public SeedingSpeedHasChangedPayload(final SeedingSpeedsHasChangedEvent event) {
|
||||
this.speeds = event.getSpeeds().entrySet().stream()
|
||||
.map(entry -> new SpeedPayload(entry.getKey(), Long.valueOf(entry.getValue().getBytesPerSeconds())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SpeedPayload> getSpeeds() {
|
||||
return speeds;
|
||||
}
|
||||
|
||||
public static final class SpeedPayload {
|
||||
private final InfoHash infoHash;
|
||||
private final Long bytesPerSeconds;
|
||||
|
||||
public SpeedPayload(final InfoHash infoHash, final Long bytesPerSeconds) {
|
||||
this.infoHash = infoHash;
|
||||
this.bytesPerSeconds = bytesPerSeconds;
|
||||
}
|
||||
|
||||
public InfoHash getInfoHash() {
|
||||
return infoHash;
|
||||
}
|
||||
|
||||
public Long getBytesPerSeconds() {
|
||||
return bytesPerSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.araymond.joal.web.messages.outgoing.impl.speed;
|
||||
|
||||
import org.araymond.joal.core.events.speed.SeedingSpeedsHasChangedEvent;
|
||||
import org.araymond.joal.core.torrent.torrent.InfoHash;
|
||||
import org.araymond.joal.web.messages.outgoing.MessagePayload;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SeedingSpeedHasChangedPayload implements MessagePayload {
|
||||
private final List<SpeedPayload> speeds;
|
||||
|
||||
public SeedingSpeedHasChangedPayload(final SeedingSpeedsHasChangedEvent event) {
|
||||
this.speeds = event.getSpeeds().entrySet().stream()
|
||||
.map(entry -> new SpeedPayload(entry.getKey(), entry.getValue().getBytesPerSeconds()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SpeedPayload> getSpeeds() {
|
||||
return speeds;
|
||||
}
|
||||
|
||||
public static final class SpeedPayload {
|
||||
private final InfoHash infoHash;
|
||||
private final Long bytesPerSeconds;
|
||||
|
||||
public SpeedPayload(final InfoHash infoHash, final Long bytesPerSeconds) {
|
||||
this.infoHash = infoHash;
|
||||
this.bytesPerSeconds = bytesPerSeconds;
|
||||
}
|
||||
|
||||
public InfoHash getInfoHash() {
|
||||
return infoHash;
|
||||
}
|
||||
|
||||
public Long getBytesPerSeconds() {
|
||||
return bytesPerSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class WebAnnounceEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void failedToAnnounce(final FailedToAnnounceEvent event) {
|
||||
public void failedToAnnounce(final FailedToAnnounceEvent event) {
|
||||
logger.debug("Send FailedToAnnouncePayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/announce", new FailedToAnnouncePayload(event));
|
||||
|
@ -42,7 +42,7 @@ public class WebAnnounceEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void successfullyAnnounce(final SuccessfullyAnnounceEvent event) {
|
||||
public void successfullyAnnounce(final SuccessfullyAnnounceEvent event) {
|
||||
logger.debug("Send SuccessfullyAnnouncePayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/announce", new SuccessfullyAnnouncePayload(event));
|
||||
|
@ -50,7 +50,7 @@ public class WebAnnounceEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void tooManyAnnouncesFailed(final TooManyAnnouncesFailedEvent event) {
|
||||
public void tooManyAnnouncesFailed(final TooManyAnnouncesFailedEvent event) {
|
||||
logger.debug("Send TooManyAnnouncesFailedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/announce", new TooManyAnnouncesFailedPayload(event));
|
||||
|
@ -58,7 +58,7 @@ public class WebAnnounceEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void willAnnounce(final WillAnnounceEvent event) {
|
||||
public void willAnnounce(final WillAnnounceEvent event) {
|
||||
logger.debug("Send WillAnnouncePayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/announce", new WillAnnouncePayload(event));
|
||||
|
|
|
@ -32,7 +32,7 @@ public class WebConfigEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void configHasBeenLoaded(final ConfigHasBeenLoadedEvent event) {
|
||||
public void configHasBeenLoaded(final ConfigHasBeenLoadedEvent event) {
|
||||
logger.debug("Send ConfigHasBeenLoadedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/config", new ConfigHasBeenLoadedPayload(event));
|
||||
|
@ -40,7 +40,7 @@ public class WebConfigEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void configIsInDirtyState(final ConfigurationIsInDirtyStateEvent event) {
|
||||
public void configIsInDirtyState(final ConfigurationIsInDirtyStateEvent event) {
|
||||
logger.debug("Send ConfigIsInDirtyStatePayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/config", new ConfigIsInDirtyStatePayload(event));
|
||||
|
@ -48,7 +48,7 @@ public class WebConfigEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void clientFilesDiscovered(final ListOfClientFilesEvent event) {
|
||||
public void clientFilesDiscovered(final ListOfClientFilesEvent event) {
|
||||
logger.debug("Send ListOfClientFilesPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/config", new ListOfClientFilesPayload(event));
|
||||
|
|
|
@ -31,7 +31,7 @@ public class WebGlobalEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void globalSeedStarted(final GlobalSeedStartedEvent event) {
|
||||
public void globalSeedStarted(final GlobalSeedStartedEvent event) {
|
||||
logger.debug("Send GlobalSeedStartedPayload to clients.");
|
||||
|
||||
final String client = event.getBitTorrentClient().getHeaders().stream()
|
||||
|
@ -45,7 +45,7 @@ public class WebGlobalEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void globalSeedStopped(@SuppressWarnings("unused") final GlobalSeedStoppedEvent event) {
|
||||
public void globalSeedStopped(@SuppressWarnings("unused") final GlobalSeedStoppedEvent event) {
|
||||
logger.debug("Send GlobalSeedStoppedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/global", new GlobalSeedStoppedPayload());
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
package org.araymond.joal.web.services.corelistener;
|
||||
|
||||
import org.araymond.joal.core.events.speed.SeedingSpeedsHasChangedEvent;
|
||||
import org.araymond.joal.web.annotations.ConditionalOnWebUi;
|
||||
import org.araymond.joal.web.messages.outgoing.impl.speed.SeedingSpeedHasChangedPayload;
|
||||
import org.araymond.joal.web.services.JoalMessageSendingTemplate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Created by raymo on 25/06/2017.
|
||||
*/
|
||||
@ConditionalOnWebUi
|
||||
@Service
|
||||
public class WebSpeedEventListener extends WebEventListener {
|
||||
private static final Logger logger = LoggerFactory.getLogger(WebSpeedEventListener.class);
|
||||
|
||||
@Inject
|
||||
public WebSpeedEventListener(final JoalMessageSendingTemplate messagingTemplate) {
|
||||
super(messagingTemplate);
|
||||
}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void failedToAnnounce(final SeedingSpeedsHasChangedEvent event) {
|
||||
logger.debug("Send SeedingSpeedHasChangedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/speed", new SeedingSpeedHasChangedPayload(event));
|
||||
}
|
||||
|
||||
}
|
||||
package org.araymond.joal.web.services.corelistener;
|
||||
|
||||
import org.araymond.joal.core.events.speed.SeedingSpeedsHasChangedEvent;
|
||||
import org.araymond.joal.web.annotations.ConditionalOnWebUi;
|
||||
import org.araymond.joal.web.messages.outgoing.impl.speed.SeedingSpeedHasChangedPayload;
|
||||
import org.araymond.joal.web.services.JoalMessageSendingTemplate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Created by raymo on 25/06/2017.
|
||||
*/
|
||||
@ConditionalOnWebUi
|
||||
@Service
|
||||
public class WebSpeedEventListener extends WebEventListener {
|
||||
private static final Logger logger = LoggerFactory.getLogger(WebSpeedEventListener.class);
|
||||
|
||||
@Inject
|
||||
public WebSpeedEventListener(final JoalMessageSendingTemplate messagingTemplate) {
|
||||
super(messagingTemplate);
|
||||
}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
public void failedToAnnounce(final SeedingSpeedsHasChangedEvent event) {
|
||||
logger.debug("Send SeedingSpeedHasChangedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/speed", new SeedingSpeedHasChangedPayload(event));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class WebTorrentFileEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void torrentFileAdded(final TorrentFileAddedEvent event) {
|
||||
public void torrentFileAdded(final TorrentFileAddedEvent event) {
|
||||
logger.debug("Send TorrentFileAddedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/torrents", new TorrentFileAddedPayload(event));
|
||||
|
@ -40,7 +40,7 @@ public class WebTorrentFileEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void torrentFileDeleted(final TorrentFileDeletedEvent event) {
|
||||
public void torrentFileDeleted(final TorrentFileDeletedEvent event) {
|
||||
logger.debug("Send TorrentFileDeletedPayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/torrents", new TorrentFileDeletedPayload(event));
|
||||
|
@ -48,7 +48,7 @@ public class WebTorrentFileEventListener extends WebEventListener {
|
|||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@EventListener
|
||||
void failedToAddTorrentFile(final FailedToAddTorrentFileEvent event) {
|
||||
public void failedToAddTorrentFile(final FailedToAddTorrentFileEvent event) {
|
||||
logger.debug("Send FailedToAddTorrentFilePayload to clients.");
|
||||
|
||||
this.messagingTemplate.convertAndSend("/torrents", new FailedToAddTorrentFilePayload(event));
|
||||
|
|
Loading…
Reference in a new issue