Browse Source

Merge pull request #506 from dampcake/deluge-rpc-v2

Add support for Deluge V2 RPC.
pull/509/head
Eric Kok 5 years ago committed by GitHub
parent
commit
e6f7e6e4da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 47
      app/src/main/java/org/transdroid/daemon/Daemon.java
  2. 16
      app/src/main/java/org/transdroid/daemon/Deluge/DelugeRpcAdapter.java
  3. 48
      app/src/main/java/org/transdroid/daemon/Deluge/DelugeRpcClient.java
  4. 2
      app/src/main/res/values/strings.xml

47
app/src/main/java/org/transdroid/daemon/Daemon.java

@ -69,7 +69,12 @@ public enum Daemon { @@ -69,7 +69,12 @@ public enum Daemon {
},
DelugeRpc {
public IDaemonAdapter createAdapter(DaemonSettings settings) {
return new DelugeRpcAdapter(settings);
return new DelugeRpcAdapter(settings, false);
}
},
Deluge2Rpc {
public IDaemonAdapter createAdapter(DaemonSettings settings) {
return new DelugeRpcAdapter(settings, true);
}
},
Dummy {
@ -155,8 +160,10 @@ public enum Daemon { @@ -155,8 +160,10 @@ public enum Daemon {
return "daemon_buffalonas";
case Deluge:
return "daemon_deluge";
case DelugeRpc:
case DelugeRpc:
return "daemon_deluge_rpc";
case Deluge2Rpc:
return "daemon_deluge2_rpc";
case DLinkRouterBT:
return "daemon_dlinkrouterbt";
case Dummy:
@ -214,6 +221,9 @@ public enum Daemon { @@ -214,6 +221,9 @@ public enum Daemon {
if (daemonCode.equals("daemon_deluge_rpc")) {
return DelugeRpc;
}
if (daemonCode.equals("daemon_deluge2_rpc")) {
return Deluge2Rpc;
}
if (daemonCode.equals("daemon_dlinkrouterbt")) {
return DLinkRouterBT;
}
@ -275,6 +285,7 @@ public enum Daemon { @@ -275,6 +285,7 @@ public enum Daemon {
return 8112;
case DelugeRpc:
case Deluge2Rpc:
return DelugeRpcAdapter.DEFAULT_PORT;
case Synology:
@ -308,13 +319,13 @@ public enum Daemon { @@ -308,13 +319,13 @@ public enum Daemon {
public static boolean supportsFileListing(Daemon type) {
return type == Synology || type == Transmission || type == uTorrent || type == BitTorrent || type == KTorrent || type == Deluge
|| type == DelugeRpc || type == rTorrent || type == Vuze || type == DLinkRouterBT || type == Bitflu || type == qBittorrent
|| type == BuffaloNas || type == BitComet || type == Aria2 || type == tTorrent || type == Dummy;
|| type == DelugeRpc || type == Deluge2Rpc || type == rTorrent || type == Vuze || type == DLinkRouterBT || type == Bitflu
|| type == qBittorrent || type == BuffaloNas || type == BitComet || type == Aria2 || type == tTorrent || type == Dummy;
}
public static boolean supportsFineDetails(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Daemon.Transmission || type == Deluge || type == DelugeRpc
|| type == rTorrent || type == qBittorrent || type == Aria2 || type == Dummy;
|| type == Deluge2Rpc || type == rTorrent || type == qBittorrent || type == Aria2 || type == Dummy;
}
public static boolean needsManualPathSpecified(Daemon type) {
@ -322,7 +333,7 @@ public enum Daemon { @@ -322,7 +333,7 @@ public enum Daemon {
}
public static boolean supportsFilePaths(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Vuze || type == Deluge || type == DelugeRpc
return type == uTorrent || type == BitTorrent || type == Vuze || type == Deluge || type == DelugeRpc || type == Deluge2Rpc
|| type == Transmission || type == rTorrent || type == KTorrent || type == BuffaloNas || type == Aria2 || type == Dummy;
}
@ -335,12 +346,12 @@ public enum Daemon { @@ -335,12 +346,12 @@ public enum Daemon {
}
public static boolean supportsCustomFolder(Daemon type) {
return type == rTorrent || type == Tfb4rt || type == Bitflu || type == Deluge || type == DelugeRpc || type == Aria2
return type == rTorrent || type == Tfb4rt || type == Bitflu || type == Deluge || type == DelugeRpc || type == Deluge2Rpc || type == Aria2
|| type == Transmission || type == BitTorrent || type == uTorrent || type == qBittorrent || type == Dummy;
}
public static boolean supportsSetTransferRates(Daemon type) {
return type == Deluge || type == DelugeRpc
return type == Deluge || type == DelugeRpc || type == Deluge2Rpc
|| type == Transmission || type == uTorrent || type == BitTorrent || type == rTorrent || type == Vuze || type == BuffaloNas
|| type == BitComet || type == Aria2 || type == qBittorrent || type == Dummy;
}
@ -364,28 +375,28 @@ public enum Daemon { @@ -364,28 +375,28 @@ public enum Daemon {
public static boolean supportsFilePrioritySetting(Daemon type) {
return type == BitTorrent || type == uTorrent || type == Transmission || type == KTorrent || type == rTorrent || type == Vuze
|| type == Deluge || type == DelugeRpc
|| type == Deluge || type == DelugeRpc || type == Deluge2Rpc
|| type == qBittorrent || type == tTorrent || type == Dummy;
}
public static boolean supportsDateAdded(Daemon type) {
return type == Vuze || type == Transmission || type == rTorrent || type == Bitflu || type == BitComet || type == uTorrent
|| type == BitTorrent || type == Deluge || type == DelugeRpc
|| type == BitTorrent || type == Deluge || type == DelugeRpc || type == Deluge2Rpc
|| type == qBittorrent || type == Dummy;
}
public static boolean supportsLabels(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == BitComet || type == rTorrent
|| type == qBittorrent || type == Dummy;
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == Deluge2Rpc || type == BitComet
|| type == rTorrent || type == qBittorrent || type == Dummy;
}
public static boolean supportsSetLabel(Daemon type) {
return type == uTorrent || type == BitTorrent || type == rTorrent || type == Deluge || type == DelugeRpc
return type == uTorrent || type == BitTorrent || type == rTorrent || type == Deluge || type == DelugeRpc || type == Deluge2Rpc
|| type == qBittorrent || type == Dummy;
}
public static boolean supportsSetDownloadLocation(Daemon type) {
return type == Transmission || type == Deluge || type == DelugeRpc || type == qBittorrent || type == Dummy;
return type == Transmission || type == Deluge || type == DelugeRpc || type == Deluge2Rpc|| type == qBittorrent || type == Dummy;
}
public static boolean supportsSetAlternativeMode(Daemon type) {
@ -393,12 +404,12 @@ public enum Daemon { @@ -393,12 +404,12 @@ public enum Daemon {
}
public static boolean supportsSetTrackers(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == Dummy;
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == Deluge2Rpc|| type == Dummy;
}
public static boolean supportsForceRecheck(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == rTorrent || type == Transmission
|| type == Dummy || type == qBittorrent;
return type == uTorrent || type == BitTorrent || type == Deluge || type == DelugeRpc || type == Deluge2Rpc || type == rTorrent
|| type == Transmission || type == Dummy || type == qBittorrent;
}
public static boolean supportsExtraPassword(Daemon type) {
@ -406,7 +417,7 @@ public enum Daemon { @@ -406,7 +417,7 @@ public enum Daemon {
}
public static boolean supportsRemoteRssManagement(Daemon type) {
return type == uTorrent || type == DelugeRpc;
return type == uTorrent || type == DelugeRpc || type == Deluge2Rpc;
}
}

16
app/src/main/java/org/transdroid/daemon/Deluge/DelugeRpcAdapter.java

@ -49,16 +49,18 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { @@ -49,16 +49,18 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier {
public static final int DEFAULT_PORT = 58846;
private final DaemonSettings settings;
private final boolean isVersion2;
private int version = -1;
public DelugeRpcAdapter(DaemonSettings settings) {
public DelugeRpcAdapter(DaemonSettings settings, boolean isVersion2) {
this.settings = settings;
this.isVersion2 = isVersion2;
}
@Override
public DaemonTaskResult executeTask(Log log, DaemonTask task) {
final DelugeRpcClient client = new DelugeRpcClient();
final DelugeRpcClient client = new DelugeRpcClient(isVersion2);
try {
client.connect(settings);
switch (task.getMethod()) {
@ -109,7 +111,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { @@ -109,7 +111,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier {
@Override
public Daemon getType() {
return Daemon.DelugeRpc;
return isVersion2 ? Daemon.Deluge2Rpc : Daemon.DelugeRpc;
}
@Override
@ -120,7 +122,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { @@ -120,7 +122,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier {
@Override
public ArrayList<RemoteRssChannel> getRemoteRssChannels(Log log) throws DaemonException {
final long now = System.currentTimeMillis();
final DelugeRpcClient client = new DelugeRpcClient();
final DelugeRpcClient client = new DelugeRpcClient(isVersion2);
try {
client.connect(settings);
@ -197,7 +199,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { @@ -197,7 +199,7 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier {
} else {
label = null;
}
final DelugeRpcClient client = new DelugeRpcClient();
final DelugeRpcClient client = new DelugeRpcClient(isVersion2);
try {
client.connect(settings);
@ -369,10 +371,10 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { @@ -369,10 +371,10 @@ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier {
final List<Torrent> torrents = new ArrayList<>();
int id = 0;
for (Map<String, Object> torrentMap : torrentMaps) {
final Object timeAdded = torrentMap.get(RPC_TIMEADDED);
final Number timeAdded = (Number) torrentMap.get(RPC_TIMEADDED);
final Date timeAddedDate;
if (timeAdded != null) {
final long seconds = (long) (float) timeAdded;
final long seconds = timeAdded.longValue();
timeAddedDate = new Date(seconds * 1000L);
} else {
timeAddedDate = null;

48
app/src/main/java/org/transdroid/daemon/Deluge/DelugeRpcClient.java

@ -27,8 +27,10 @@ import se.dimovski.rencode.Rencode; @@ -27,8 +27,10 @@ import se.dimovski.rencode.Rencode;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@ -36,6 +38,7 @@ import java.util.zip.DeflaterOutputStream; @@ -36,6 +38,7 @@ import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import static org.transdroid.daemon.Deluge.DelugeCommon.RPC_METHOD_DAEMON_LOGIN;
import static org.transdroid.daemon.Deluge.DelugeCommon.RPC_METHOD_INFO;
/**
* A Deluge RPC API Client.
@ -45,13 +48,23 @@ class DelugeRpcClient implements Closeable { @@ -45,13 +48,23 @@ class DelugeRpcClient implements Closeable {
private static final int RESPONSE_TYPE_INDEX = 0;
private static final int RESPONSE_RETURN_VALUE_INDEX = 2;
private static final int RPC_ERROR = 2;
private static final byte V2_PROTOCOL_VERSION = 1;
private static final int V2_HEADER_SIZE = 5;
private Socket socket;
private final boolean isVersion2;
private static AtomicInteger requestId = new AtomicInteger();
DelugeRpcClient(boolean isVersion2) {
this.isVersion2 = isVersion2;
}
void connect(DaemonSettings settings) throws DaemonException {
try {
socket = openSocket(settings);
if (isVersion2) {
sendRequest(RPC_METHOD_INFO);
}
if (settings.shouldUseAuthentication()) {
sendRequest(RPC_METHOD_DAEMON_LOGIN, settings.getUsername(), settings.getPassword());
}
@ -75,12 +88,26 @@ class DelugeRpcClient implements Closeable { @@ -75,12 +88,26 @@ class DelugeRpcClient implements Closeable {
Object sendRequest(String method, Object... args) throws DaemonException {
final byte[] requestBytes;
try {
requestBytes = compress(Rencode.encode(new Object[]{new Object[]{requestId.getAndIncrement(), method, args, new HashMap<>()}}));
HashMap<Object, Object> kwargs = new HashMap<>();
if (isVersion2 && RPC_METHOD_DAEMON_LOGIN.equals(method)) {
kwargs.put("client_version", "" + V2_PROTOCOL_VERSION);
}
requestBytes = compress(Rencode.encode(new Object[]{new Object[]{requestId.getAndIncrement(), method, args, kwargs}}));
} catch (IOException e) {
throw new DaemonException(ExceptionType.ConnectionError, "Failed to encode request: " + e.getMessage());
}
try {
socket.getOutputStream().write(requestBytes);
if (isVersion2) {
socket.getOutputStream().write(
ByteBuffer.allocate(V2_HEADER_SIZE + requestBytes.length)
.put(V2_PROTOCOL_VERSION)
.putInt(requestBytes.length)
.put(requestBytes)
.array()
);
} else {
socket.getOutputStream().write(requestBytes);
}
return readResponse();
} catch (IOException e) {
throw new DaemonException(ExceptionType.ConnectionError, e.getMessage());
@ -106,9 +133,22 @@ class DelugeRpcClient implements Closeable { @@ -106,9 +133,22 @@ class DelugeRpcClient implements Closeable {
@NonNull
private Object readResponse() throws DaemonException, IOException {
final InflaterInputStream inflater = new InflaterInputStream(socket.getInputStream());
final InputStream in = socket.getInputStream();
final InflaterInputStream inflater = new InflaterInputStream(in);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final byte[] buffer = new byte[1024];
final byte[] buffer;
if (isVersion2) {
final byte[] header = new byte[V2_HEADER_SIZE];
in.read(header, 0, V2_HEADER_SIZE);
if (header[0] != V2_PROTOCOL_VERSION) {
throw new DaemonException(ExceptionType.ConnectionError, "Unexpected protocol version: " + header[0]);
}
buffer = new byte[ByteBuffer.wrap(header).getInt(1)];
} else {
buffer = new byte[1024];
}
while (inflater.available() > 0) {
final int n = inflater.read(buffer);
if (n > 0) {

2
app/src/main/res/values/strings.xml

@ -389,6 +389,7 @@ @@ -389,6 +389,7 @@
<item>Buffalo NAS -1.31</item>
<item>Deluge 1.2+</item>
<item>Deluge RPC</item>
<item>Deluge 2 RPC</item>
<item>DLink Router BT</item>
<item>Ktorrent</item>
<item>qBittorrent</item>
@ -408,6 +409,7 @@ @@ -408,6 +409,7 @@
<item>daemon_buffalonas</item>
<item>daemon_deluge</item>
<item>daemon_deluge_rpc</item>
<item>daemon_deluge2_rpc</item>
<item>daemon_dlinkrouterbt</item>
<item>daemon_ktorrent</item>
<item>daemon_qbittorrent</item>

Loading…
Cancel
Save