diff --git a/connect/build.gradle b/connect/build.gradle index d6da617b..c8b66f00 100644 --- a/connect/build.gradle +++ b/connect/build.gradle @@ -1,4 +1,3 @@ -apply plugin: 'java' apply plugin: 'kotlin' dependencies { @@ -6,7 +5,7 @@ dependencies { compile 'com.squareup.okhttp3:logging-interceptor:3.7.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' compile 'com.burgstaller:okhttp-digest:1.10' - compile 'com.github.erickok:retrofit-xmlrpc:6e2c623763' + compile 'com.github.erickok:retrofit-xmlrpc:77b5e30e43' testCompile 'junit:junit:4.12' testCompile 'com.google.truth:truth:0.31' diff --git a/connect/src/main/java/org/transdroid/connect/clients/rtorrent/LoadRawStart.kt b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/LoadRawStart.kt new file mode 100644 index 00000000..77db99de --- /dev/null +++ b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/LoadRawStart.kt @@ -0,0 +1,6 @@ +package org.transdroid.connect.clients.rtorrent + +data class LoadRawStart( + val endpoint: String, + val bytes: ByteArray +) \ No newline at end of file diff --git a/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.kt b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.kt index 11f359db..8dc604f4 100644 --- a/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.kt +++ b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.kt @@ -3,7 +3,6 @@ package org.transdroid.connect.clients.rtorrent import io.reactivex.Completable import io.reactivex.Flowable import io.reactivex.Single -import nl.nl2312.xmlrpc.Nothing import nl.nl2312.xmlrpc.XmlRpcConverterFactory import org.transdroid.connect.Configuration import org.transdroid.connect.clients.Feature @@ -13,6 +12,7 @@ import org.transdroid.connect.util.OkHttpBuilder import org.transdroid.connect.util.flatten import retrofit2.Retrofit import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import java.io.InputStream import java.util.* class Rtorrent(private val configuration: Configuration) : @@ -20,10 +20,13 @@ class Rtorrent(private val configuration: Configuration) : Feature.Listing, Feature.StartingStopping, Feature.ResumingPausing, - //Feature.AddByFile, + Feature.AddByFile, Feature.AddByUrl, Feature.AddByMagnet { + private val xmlrpcSizeMinimum = 2 * 1024 * 1024 + private val xmlrpcSizePadding = 1280 + private val service: Service = Retrofit.Builder() .baseUrl(configuration.baseUrl) .client(OkHttpBuilder.build(configuration)) @@ -61,7 +64,7 @@ class Rtorrent(private val configuration: Configuration) : .build().create(Service::class.java) override fun clientVersion(): Single { - return service.clientVersion(configuration.endpoint, Nothing.NOTHING) + return service.clientVersion(configuration.endpoint) .cache() // Cached, as it is often used but 'never' changes } @@ -139,7 +142,7 @@ class Rtorrent(private val configuration: Configuration) : override fun addByUrl(url: String): Completable { return clientVersion().asVersionInt().flatMapCompletable { integer -> - if (integer > 904) { + if (integer >= 904) { service.loadStart(configuration.endpoint, "", url) } else { service.loadStart(configuration.endpoint, url) @@ -149,7 +152,7 @@ class Rtorrent(private val configuration: Configuration) : override fun addByMagnet(magnet: String): Completable { return clientVersion().asVersionInt().flatMapCompletable { integer -> - if (integer > 904) { + if (integer >= 904) { service.loadStart(configuration.endpoint, "", magnet) } else { service.loadStart(configuration.endpoint, magnet) @@ -157,6 +160,20 @@ class Rtorrent(private val configuration: Configuration) : } } + override fun addByFile(file: InputStream): Completable { + return clientVersion().asVersionInt().flatMapCompletable { integer -> + val bytes = file.readBytes() + val size = Math.max(bytes.size, xmlrpcSizeMinimum) + xmlrpcSizePadding + if (integer >= 904) { + service.networkSizeLimitSet(configuration.endpoint, "", size) + .flatMapCompletable { service.loadRawStart(configuration.endpoint, "", bytes) } + } else { + service.networkSizeLimitSet(configuration.endpoint, size) + .flatMapCompletable { service.loadRawStart(configuration.endpoint, bytes) } + } + } + } + private fun torrentStatus(state: Long, complete: Long, active: Long, checking: Long): TorrentStatus { if (state == 0L) { return TorrentStatus.QUEUED diff --git a/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Service.kt b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Service.kt index c7197480..8dc67d72 100644 --- a/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Service.kt +++ b/connect/src/main/java/org/transdroid/connect/clients/rtorrent/Service.kt @@ -13,7 +13,7 @@ internal interface Service { @XmlRpc("system.client_version") @POST("{endpoint}") - fun clientVersion(@Path("endpoint") endpoint: String?, @Body nothing: Nothing): Single + fun clientVersion(@Path("endpoint") endpoint: String?, @Body nothing: Nothing = Nothing.NOTHING): Single @XmlRpc("d.multicall2") @POST("{endpoint}") @@ -31,4 +31,12 @@ internal interface Service { @POST("{endpoint}") fun loadStart(@Path("endpoint") endpoint: String?, @Body vararg args: String): Completable + @XmlRpc("load.raw_start") + @POST("{endpoint}") + fun loadRawStart(@Path("endpoint") endpoint: String?, @Body vararg args: Any): Completable + + @XmlRpc("network.xmlrpc.size_limit.set") + @POST("{endpoint}") + fun networkSizeLimitSet(@Path("endpoint") endpoint: String?, @Body vararg args: Any): Single + } diff --git a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentLiveTest.kt b/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentLiveTest.kt index bcf001ac..21799148 100644 --- a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentLiveTest.kt +++ b/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentLiveTest.kt @@ -8,6 +8,7 @@ import org.transdroid.connect.clients.Client import org.transdroid.connect.clients.ClientSpec import org.transdroid.connect.clients.Feature import org.transdroid.connect.clients.UnsupportedFeatureException +import org.transdroid.connect.mock.MockTorrent import org.transdroid.connect.model.Torrent class RtorrentLiveTest { @@ -17,8 +18,7 @@ class RtorrentLiveTest { @Before fun setUp() { rtorrent = Configuration(Client.RTORRENT, - "http://localhost:8008/", - "RPC2", + "http://localhost:8008/", "RPC2", loggingEnabled = true) .createClient() } @@ -64,6 +64,13 @@ class RtorrentLiveTest { .assertNoErrors() } + @Test + fun addByFile() { + rtorrent.addByFile(MockTorrent.torrentFile) + .test() + .assertNoErrors() + } + @Test fun start() { rtorrent.start(firstLiveTorrent()) diff --git a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentMockTest.kt b/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentMockTest.kt index 326833f6..33a0111d 100644 --- a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentMockTest.kt +++ b/connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentMockTest.kt @@ -6,6 +6,8 @@ import org.junit.Before import org.junit.Test import org.transdroid.connect.Configuration import org.transdroid.connect.clients.Client +import org.transdroid.connect.mock.MockTorrent +import java.io.File class RtorrentMockTest { @@ -20,7 +22,7 @@ class RtorrentMockTest { @Test fun clientVersion() { - server.enqueue(mock("0.9.6")) + server.enqueue(mock("0.9.6")) rtorrent.clientVersion() .test() .assertValue("0.9.6") @@ -29,7 +31,7 @@ class RtorrentMockTest { @Test fun torrents() { - server.enqueue(mock("59066769B9AD42DA2E508611C33D7C4480B3857Bubuntu-17.04-desktop-amd64.iso000000016090398721609039872149207715900000")) + server.enqueue(mock("59066769B9AD42DA2E508611C33D7C4480B3857Bubuntu-17.04-desktop-amd64.iso000000016090398721609039872149207715900000")) rtorrent.torrents() .test() .assertValue { it.hash == "59066769B9AD42DA2E508611C33D7C4480B3857B" } @@ -38,9 +40,9 @@ class RtorrentMockTest { @Test fun addByUrl() { - server.enqueue(mock("0.9.6")) - server.enqueue(mock("0")) - rtorrent.addByUrl("http://releases.ubuntu.com/17.04/ubuntu-17.04-desktop-amd64.iso.torrent") + server.enqueue(mock("0.9.6")) + server.enqueue(mock("0")) + rtorrent.addByUrl(MockTorrent.torrentUrl) .test() .assertNoErrors() server.takeRequest() @@ -49,9 +51,20 @@ class RtorrentMockTest { @Test fun addByMagnet() { - server.enqueue(mock("0.9.6")) - server.enqueue(mock("0")) - rtorrent.addByMagnet("http://torrent.ubuntu.com:6969/file?info_hash=%04%03%FBG%28%BDx%8F%BC%B6%7E%87%D6%FE%B2A%EF8%C7Z") + server.enqueue(mock("0.9.6")) + server.enqueue(mock("0")) + rtorrent.addByMagnet(MockTorrent.magnetUrl) + .test() + .assertNoErrors() + server.takeRequest() + server.takeRequest() + } + + @Test + fun addByFile() { + server.enqueue(mock("0.9.6")) + server.enqueue(mock("0")) + rtorrent.addByFile(MockTorrent.torrentFile) .test() .assertNoErrors() server.takeRequest() @@ -60,7 +73,7 @@ class RtorrentMockTest { @Test fun start() { - server.enqueue(mock("0")) + server.enqueue(mock("0")) rtorrent.start(MockTorrent.downloading) .test() .assertValue { it.canStop } @@ -69,7 +82,7 @@ class RtorrentMockTest { @Test fun stop() { - server.enqueue(mock("0")) + server.enqueue(mock("0")) rtorrent.stop(MockTorrent.seeding) .test() .assertValue { it.canStart } @@ -82,7 +95,7 @@ class RtorrentMockTest { .setBody("\n" + "\n" + " \n" + - " {$params}\n" + + " {$params}\n" + " \n" + "") } diff --git a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/MockTorrent.kt b/connect/src/test/java/org/transdroid/connect/mock/MockTorrent.kt similarity index 86% rename from connect/src/test/java/org/transdroid/connect/clients/rtorrent/MockTorrent.kt rename to connect/src/test/java/org/transdroid/connect/mock/MockTorrent.kt index 6bfb7385..f5ec22f2 100644 --- a/connect/src/test/java/org/transdroid/connect/clients/rtorrent/MockTorrent.kt +++ b/connect/src/test/java/org/transdroid/connect/mock/MockTorrent.kt @@ -1,13 +1,15 @@ -package org.transdroid.connect.clients.rtorrent +package org.transdroid.connect.mock import org.transdroid.connect.model.Torrent import org.transdroid.connect.model.TorrentStatus +import java.io.File import java.util.* object MockTorrent { val torrentUrl = "http://releases.ubuntu.com/17.04/ubuntu-17.04-desktop-amd64.iso.torrent" val magnetUrl = "http://torrent.ubuntu.com:6969/file?info_hash=%04%03%FBG%28%BDx%8F%BC%B6%7E%87%D6%FE%B2A%EF8%C7Z" + val torrentFile = File("connect/src/test/resources/test/ubuntu.torrent").inputStream() val downloading = Torrent(0, "59066769B9AD42DA2E508611C33D7C4480B3857B", "ubuntu-17.04-desktop-amd64.iso", TorrentStatus.DOWNLOADING, "/downloads/", 1000000, 200000, 20, 20, 2, 50, null, 804519936, 160903987, 1609039872, 0.5F, 0.8F, "distros", Date(1492681983), null, null) diff --git a/connect/src/test/resources/test/ubuntu.torrent b/connect/src/test/resources/test/ubuntu.torrent new file mode 100644 index 00000000..cfad566d Binary files /dev/null and b/connect/src/test/resources/test/ubuntu.torrent differ