Alon Albert
7 years ago
22 changed files with 0 additions and 1088 deletions
@ -1,50 +0,0 @@ |
|||||||
package deluge; |
|
||||||
|
|
||||||
import java.io.Closeable; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.OutputStream; |
|
||||||
|
|
||||||
public class Util |
|
||||||
{ |
|
||||||
|
|
||||||
public static void close(Closeable closeable) throws IOException |
|
||||||
{ |
|
||||||
if (closeable == null) |
|
||||||
{ |
|
||||||
return; |
|
||||||
} |
|
||||||
closeable.close(); |
|
||||||
} |
|
||||||
|
|
||||||
public static long copy(InputStream from, OutputStream to) throws IOException |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
byte[] buf = new byte[4000]; |
|
||||||
long total = 0; |
|
||||||
while (true) |
|
||||||
{ |
|
||||||
int r = from.read(buf); |
|
||||||
if (r == -1) |
|
||||||
{ |
|
||||||
break; |
|
||||||
} |
|
||||||
to.write(buf, 0, r); |
|
||||||
total += r; |
|
||||||
} |
|
||||||
return total; |
|
||||||
} |
|
||||||
finally |
|
||||||
{ |
|
||||||
Util.close(to); |
|
||||||
} |
|
||||||
} |
|
||||||
finally |
|
||||||
{ |
|
||||||
Util.close(from); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,30 +0,0 @@ |
|||||||
package deluge.api; |
|
||||||
|
|
||||||
public class DelugeException extends Exception |
|
||||||
{ |
|
||||||
private static final long serialVersionUID = 1L; |
|
||||||
|
|
||||||
final public String exceptionType; |
|
||||||
final public String exceptionMsg; |
|
||||||
final public String traceback; |
|
||||||
|
|
||||||
public DelugeException(String type, String msg, String trace) |
|
||||||
{ |
|
||||||
this.exceptionType = type; |
|
||||||
this.exceptionMsg = msg; |
|
||||||
this.traceback = trace; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void printStackTrace() |
|
||||||
{ |
|
||||||
System.err.println(toString()); |
|
||||||
System.err.println(this.traceback); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
return DelugeException.class.getCanonicalName() + " " + this.exceptionType + " (" + this.exceptionMsg + ")"; |
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
package deluge.api; |
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.ExecutionException; |
|
||||||
import java.util.concurrent.Future; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
import java.util.concurrent.TimeoutException; |
|
||||||
|
|
||||||
import deluge.impl.AsyncResponse; |
|
||||||
|
|
||||||
public class DelugeFuture<V> extends AsyncResponse<V, DelugeException> implements Future<V> |
|
||||||
{ |
|
||||||
private final CountDownLatch latch = new CountDownLatch(1); |
|
||||||
private V value; |
|
||||||
|
|
||||||
public DelugeFuture() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
public boolean cancel(boolean mayInterruptIfRunning) |
|
||||||
{ |
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public V get() throws InterruptedException, ExecutionException |
|
||||||
{ |
|
||||||
this.latch.await(); |
|
||||||
return this.value; |
|
||||||
} |
|
||||||
|
|
||||||
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException |
|
||||||
{ |
|
||||||
if (!this.latch.await(timeout, unit)) |
|
||||||
{ |
|
||||||
throw new TimeoutException(); |
|
||||||
} |
|
||||||
return this.value; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isCancelled() |
|
||||||
{ |
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isDone() |
|
||||||
{ |
|
||||||
return this.value != null; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(DelugeException error) |
|
||||||
{ |
|
||||||
setValue(null); |
|
||||||
super.onError(error); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onResponse(V response) |
|
||||||
{ |
|
||||||
setValue(response); |
|
||||||
super.onResponse(response); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onServerError(Exception exception) |
|
||||||
{ |
|
||||||
setValue(null); |
|
||||||
super.onServerError(exception); |
|
||||||
} |
|
||||||
|
|
||||||
public void setValue(V val) |
|
||||||
{ |
|
||||||
this.value = val; |
|
||||||
this.latch.countDown(); |
|
||||||
} |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
package deluge.api; |
|
||||||
|
|
||||||
public abstract class ResponseCallback<R, E extends Exception> |
|
||||||
{ |
|
||||||
public void onError(E error) |
|
||||||
{ |
|
||||||
error.printStackTrace(); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract void onResponse(R response); |
|
||||||
|
|
||||||
public void onServerError(Exception exception) |
|
||||||
{ |
|
||||||
exception.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
@ -1,20 +0,0 @@ |
|||||||
package deluge.api.response; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import deluge.api.DelugeException; |
|
||||||
|
|
||||||
public class IntegerResponse extends Response |
|
||||||
{ |
|
||||||
|
|
||||||
public IntegerResponse(List<Object> data) throws IOException, DelugeException |
|
||||||
{ |
|
||||||
super(data); |
|
||||||
} |
|
||||||
|
|
||||||
public Integer getReturnValue() |
|
||||||
{ |
|
||||||
return (Integer) this.returnValue.get(2); |
|
||||||
} |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
package deluge.api.response; |
|
||||||
|
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import deluge.api.DelugeException; |
|
||||||
|
|
||||||
public abstract class Response |
|
||||||
{ |
|
||||||
protected List<Object> returnValue; |
|
||||||
|
|
||||||
protected final int RPC_RESPONSE = 1; |
|
||||||
protected final int RPC_ERROR = 2; |
|
||||||
protected final int RPC_EVENT = 3; |
|
||||||
|
|
||||||
public Response(List<Object> decodedObj) throws DelugeException |
|
||||||
{ |
|
||||||
rawData(decodedObj); |
|
||||||
} |
|
||||||
|
|
||||||
public int getMessageType() |
|
||||||
{ |
|
||||||
return (Integer) this.returnValue.get(0); |
|
||||||
} |
|
||||||
|
|
||||||
public int getRequestId() |
|
||||||
{ |
|
||||||
return (Integer) this.returnValue.get(1); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract Object getReturnValue(); |
|
||||||
|
|
||||||
private void process() throws DelugeException |
|
||||||
{ |
|
||||||
if (getMessageType() == this.RPC_ERROR) |
|
||||||
{ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
final List<String> params = (List<String>) this.returnValue.get(2); |
|
||||||
final String type = params.get(0); |
|
||||||
final String msg = params.get(1); |
|
||||||
final String trace = params.get(2); |
|
||||||
|
|
||||||
throw new DelugeException(type, msg, trace); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void rawData(List<Object> decodedObj) throws DelugeException |
|
||||||
{ |
|
||||||
this.returnValue = decodedObj; |
|
||||||
process(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
String str = "Response { "; |
|
||||||
|
|
||||||
str += this.returnValue.toString(); |
|
||||||
|
|
||||||
str += " }"; |
|
||||||
return str; |
|
||||||
} |
|
||||||
} |
|
@ -1,6 +0,0 @@ |
|||||||
package deluge.api.response; |
|
||||||
|
|
||||||
public enum ReturnType |
|
||||||
{ |
|
||||||
INTEGER, TORRENTS_STATUS |
|
||||||
} |
|
@ -1,23 +0,0 @@ |
|||||||
package deluge.api.response; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import deluge.api.DelugeException; |
|
||||||
|
|
||||||
public class TorrentsStatusResponse extends Response |
|
||||||
{ |
|
||||||
|
|
||||||
public TorrentsStatusResponse(List<Object> data) throws IOException, DelugeException |
|
||||||
{ |
|
||||||
super(data); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public Map<String, Map<String, Object>> getReturnValue() |
|
||||||
{ |
|
||||||
return (Map<String, Map<String, Object>>) this.returnValue.get(2); |
|
||||||
} |
|
||||||
} |
|
@ -1,58 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import deluge.api.ResponseCallback; |
|
||||||
|
|
||||||
public class AsyncResponse<R, E extends Exception> extends ResponseCallback<R, E> |
|
||||||
{ |
|
||||||
private final List<ResponseCallback<R, E>> callbacks; |
|
||||||
|
|
||||||
public AsyncResponse() |
|
||||||
{ |
|
||||||
this.callbacks = new ArrayList<ResponseCallback<R, E>>(); |
|
||||||
} |
|
||||||
|
|
||||||
public void addCallback(ResponseCallback<R, E> callback) |
|
||||||
{ |
|
||||||
this.callbacks.add(callback); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(E error) |
|
||||||
{ |
|
||||||
for (final ResponseCallback<R, E> cb : this.callbacks) |
|
||||||
{ |
|
||||||
cb.onError(error); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onResponse(R response) |
|
||||||
{ |
|
||||||
for (final ResponseCallback<R, E> cb : this.callbacks) |
|
||||||
{ |
|
||||||
cb.onResponse(response); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onServerError(Exception exception) |
|
||||||
{ |
|
||||||
for (final ResponseCallback<R, E> cb : this.callbacks) |
|
||||||
{ |
|
||||||
cb.onServerError(exception); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void removeCallback(ResponseCallback<R, E> callback) |
|
||||||
{ |
|
||||||
this.callbacks.remove(callback); |
|
||||||
} |
|
||||||
|
|
||||||
public void then(ResponseCallback<R, E> callback) |
|
||||||
{ |
|
||||||
addCallback(callback); |
|
||||||
} |
|
||||||
} |
|
@ -1,81 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import se.dimovski.rencode.Rencode; |
|
||||||
import deluge.api.DelugeException; |
|
||||||
import deluge.api.DelugeFuture; |
|
||||||
import deluge.api.response.IntegerResponse; |
|
||||||
import deluge.api.response.Response; |
|
||||||
import deluge.api.response.TorrentsStatusResponse; |
|
||||||
import deluge.impl.net.Session.DataCallback; |
|
||||||
|
|
||||||
public class DataHandler implements DataCallback |
|
||||||
{ |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public void dataRecived(byte[] data) |
|
||||||
{ |
|
||||||
Integer requestId = null; |
|
||||||
List<Object> decodedObj; |
|
||||||
try |
|
||||||
{ |
|
||||||
decodedObj = (List<Object>) Rencode.decode(data); |
|
||||||
requestId = (Integer) decodedObj.get(1); |
|
||||||
|
|
||||||
sendSpecificResponse(requestId, decodedObj); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private void sendSpecificResponse(Integer requestId, List<Object> decodedObj) |
|
||||||
{ |
|
||||||
|
|
||||||
final OngoingRequest req = OngoingRequests.remove(requestId); |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
switch (req.getType()) |
|
||||||
{ |
|
||||||
case INTEGER: |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> fut = (DelugeFuture<IntegerResponse>) req.getFuture(); |
|
||||||
fut.onResponse(new IntegerResponse(decodedObj)); |
|
||||||
} |
|
||||||
break; |
|
||||||
case TORRENTS_STATUS: |
|
||||||
{ |
|
||||||
final DelugeFuture<TorrentsStatusResponse> fut = (DelugeFuture<TorrentsStatusResponse>) req |
|
||||||
.getFuture(); |
|
||||||
fut.onResponse(new TorrentsStatusResponse(decodedObj)); |
|
||||||
} |
|
||||||
break; |
|
||||||
default: |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException("Unknown Request: " + req.getType()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (final DelugeException e) |
|
||||||
{ |
|
||||||
final DelugeFuture<Response> fut = (DelugeFuture<Response>) req.getFuture(); |
|
||||||
fut.onError(e); |
|
||||||
} |
|
||||||
catch (final Exception e) |
|
||||||
{ |
|
||||||
final DelugeFuture<Response> fut = (DelugeFuture<Response>) req.getFuture(); |
|
||||||
fut.onServerError(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void onError() |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
public class DelugeClient |
|
||||||
{ |
|
||||||
public static DelugeSession getSession(String host) |
|
||||||
{ |
|
||||||
final String[] parts = host.split(":"); |
|
||||||
final int port = parts.length < 2 ? DelugeClient.DEFAULT_PORT : Integer.parseInt(parts[1]); |
|
||||||
return DelugeClient.getSession(parts[0], port); |
|
||||||
} |
|
||||||
|
|
||||||
public static DelugeSession getSession(String host, int port) |
|
||||||
{ |
|
||||||
return DelugeSession.connect(host, port); |
|
||||||
} |
|
||||||
|
|
||||||
public static DelugeSession getSessionDefault() |
|
||||||
{ |
|
||||||
return DelugeClient.getSession("127.0.0.1", DelugeClient.DEFAULT_PORT); |
|
||||||
} |
|
||||||
|
|
||||||
public static final int DEFAULT_PORT = 58846; |
|
||||||
|
|
||||||
} |
|
@ -1,100 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import deluge.api.DelugeFuture; |
|
||||||
import deluge.api.response.IntegerResponse; |
|
||||||
import deluge.api.response.ReturnType; |
|
||||||
import deluge.api.response.TorrentsStatusResponse; |
|
||||||
import deluge.impl.net.Session; |
|
||||||
import deluge.impl.net.TorrentField; |
|
||||||
|
|
||||||
public class DelugeSession |
|
||||||
{ |
|
||||||
public static DelugeSession connect(String host, int port) |
|
||||||
{ |
|
||||||
final Session session = new Session(host, port); |
|
||||||
try |
|
||||||
{ |
|
||||||
session.listen(new DataHandler()); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
return new DelugeSession(session); |
|
||||||
} |
|
||||||
|
|
||||||
private final Session session; |
|
||||||
|
|
||||||
private DelugeSession(Session session) |
|
||||||
|
|
||||||
{ |
|
||||||
this.session = session; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<TorrentsStatusResponse> getTorrentsStatus(Map<Object, Object> filter, TorrentField[] fields) |
|
||||||
{ |
|
||||||
final DelugeFuture<TorrentsStatusResponse> future = new DelugeFuture<TorrentsStatusResponse>(); |
|
||||||
final Request request = RequestFactory.getTorrentsStatus(filter, fields); |
|
||||||
send(request, ReturnType.TORRENTS_STATUS, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<IntegerResponse> login(String username, String password) |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> future = new DelugeFuture<IntegerResponse>(); |
|
||||||
final Request request = new Request("daemon.login", Util.objects(username, password)); |
|
||||||
send(request, ReturnType.INTEGER, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<IntegerResponse> pauseTorrent(List<String> torrentIds) |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> future = new DelugeFuture<IntegerResponse>(); |
|
||||||
final Request request = new Request("core.pause_torrent", Util.objects(torrentIds)); |
|
||||||
send(request, ReturnType.INTEGER, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<IntegerResponse> resumeTorrent(List<String> torrentIds) |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> future = new DelugeFuture<IntegerResponse>(); |
|
||||||
final Request request = new Request("core.resume_torrent", Util.objects(torrentIds)); |
|
||||||
send(request, ReturnType.INTEGER, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<IntegerResponse> addTorrentFile(String name, String encodedContents, Map<String, Object> options) |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> future = new DelugeFuture<IntegerResponse>(); |
|
||||||
Request request = new Request("core.add_torrent_file", Util.objects(name, encodedContents, options)); |
|
||||||
send(request, ReturnType.INTEGER, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public DelugeFuture<IntegerResponse> removeTorrent(String torrentId, Boolean removeData) |
|
||||||
{ |
|
||||||
final DelugeFuture<IntegerResponse> future = new DelugeFuture<IntegerResponse>(); |
|
||||||
Request request = new Request("core.remove_torrent", Util.objects(torrentId, removeData)); |
|
||||||
send(request, ReturnType.INTEGER, future); |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
private void send(Request request, ReturnType type, Object future) |
|
||||||
{ |
|
||||||
OngoingRequests.put(request.getRequestId(), type, future); |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
this.session.send(request.toByteArray()); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,26 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import deluge.api.response.ReturnType; |
|
||||||
|
|
||||||
public class OngoingRequest |
|
||||||
{ |
|
||||||
private final ReturnType type; |
|
||||||
private final Object future; |
|
||||||
|
|
||||||
public OngoingRequest(ReturnType type, Object future) |
|
||||||
{ |
|
||||||
this.type = type; |
|
||||||
this.future = future; |
|
||||||
} |
|
||||||
|
|
||||||
public Object getFuture() |
|
||||||
{ |
|
||||||
return this.future; |
|
||||||
} |
|
||||||
|
|
||||||
public ReturnType getType() |
|
||||||
{ |
|
||||||
return this.type; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,23 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.util.Map; |
|
||||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||||
|
|
||||||
import deluge.api.response.ReturnType; |
|
||||||
|
|
||||||
public class OngoingRequests |
|
||||||
{ |
|
||||||
public static void put(int requestId, ReturnType type, Object future) |
|
||||||
{ |
|
||||||
final OngoingRequest ongoing = new OngoingRequest(type, future); |
|
||||||
OngoingRequests.mOngoingRequests.put(requestId, ongoing); |
|
||||||
} |
|
||||||
|
|
||||||
public static OngoingRequest remove(int requestId) |
|
||||||
{ |
|
||||||
return OngoingRequests.mOngoingRequests.remove(requestId); |
|
||||||
} |
|
||||||
|
|
||||||
private static Map<Integer, OngoingRequest> mOngoingRequests = new ConcurrentHashMap<Integer, OngoingRequest>(); |
|
||||||
|
|
||||||
} |
|
@ -1,56 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.concurrent.atomic.AtomicInteger; |
|
||||||
|
|
||||||
import se.dimovski.rencode.Rencode; |
|
||||||
|
|
||||||
public class Request |
|
||||||
{ |
|
||||||
private static AtomicInteger requestCounter = new AtomicInteger(); |
|
||||||
|
|
||||||
private final Integer requestId; |
|
||||||
private final String method; |
|
||||||
private final Object[] args; |
|
||||||
private final Map<Object, Object> kwargs; |
|
||||||
|
|
||||||
public Request(String method) |
|
||||||
{ |
|
||||||
this(method, new Object[0]); |
|
||||||
} |
|
||||||
|
|
||||||
public Request(String method, Object[] args) |
|
||||||
{ |
|
||||||
this(method, args, new HashMap<Object, Object>()); |
|
||||||
} |
|
||||||
|
|
||||||
public Request(String method, Object[] args, Map<Object, Object> kwargs) |
|
||||||
{ |
|
||||||
this.requestId = Request.requestCounter.getAndIncrement(); |
|
||||||
this.method = method; |
|
||||||
this.args = args; |
|
||||||
this.kwargs = kwargs; |
|
||||||
} |
|
||||||
|
|
||||||
public Integer getRequestId() |
|
||||||
{ |
|
||||||
return this.requestId; |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] toByteArray() |
|
||||||
{ |
|
||||||
final Object obj = new Object[] { new Object[] { this.requestId, this.method, this.args, this.kwargs } }; |
|
||||||
try |
|
||||||
{ |
|
||||||
return Rencode.encode(obj); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
@ -1,44 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import deluge.impl.net.TorrentField; |
|
||||||
|
|
||||||
public class RequestFactory |
|
||||||
{ |
|
||||||
|
|
||||||
public static Request getSessionState() |
|
||||||
{ |
|
||||||
return new Request("core.get_session_state"); |
|
||||||
} |
|
||||||
|
|
||||||
public static Request getTorrentsStatus() |
|
||||||
{ |
|
||||||
return RequestFactory.getTorrentsStatus(null, null); |
|
||||||
} |
|
||||||
|
|
||||||
public static Request getTorrentsStatus(Map<Object, Object> filter) |
|
||||||
{ |
|
||||||
return RequestFactory.getTorrentsStatus(filter, null); |
|
||||||
} |
|
||||||
|
|
||||||
public static Request getTorrentsStatus(Map<Object, Object> filter, TorrentField[] fields) |
|
||||||
{ |
|
||||||
Object[] fieldNames = new Object[0]; |
|
||||||
if (fields != null) |
|
||||||
{ |
|
||||||
fieldNames = new Object[fields.length]; |
|
||||||
for (int i = 0; i < fields.length; i++) |
|
||||||
{ |
|
||||||
fieldNames[i] = fields[i].toString(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return new Request("core.get_torrents_status", Util.objects(filter, fieldNames)); |
|
||||||
} |
|
||||||
|
|
||||||
public static Request getTorrentsStatus(TorrentField[] fields) |
|
||||||
{ |
|
||||||
return RequestFactory.getTorrentsStatus(null, null); |
|
||||||
} |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
package deluge.impl; |
|
||||||
|
|
||||||
import deluge.impl.net.TorrentField; |
|
||||||
|
|
||||||
public class Util |
|
||||||
{ |
|
||||||
public static TorrentField[] fields(TorrentField... fields) |
|
||||||
{ |
|
||||||
return fields; |
|
||||||
} |
|
||||||
|
|
||||||
public static Object[] objects(Object... objects) |
|
||||||
{ |
|
||||||
return objects; |
|
||||||
} |
|
||||||
} |
|
@ -1,23 +0,0 @@ |
|||||||
package deluge.impl.net; |
|
||||||
|
|
||||||
import java.security.cert.CertificateException; |
|
||||||
import java.security.cert.X509Certificate; |
|
||||||
|
|
||||||
import javax.net.ssl.X509TrustManager; |
|
||||||
|
|
||||||
public class AcceptAllTrustManager implements X509TrustManager |
|
||||||
{ |
|
||||||
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
public X509Certificate[] getAcceptedIssuers() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
@ -1,32 +0,0 @@ |
|||||||
package deluge.impl.net; |
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService; |
|
||||||
import java.util.concurrent.Executors; |
|
||||||
|
|
||||||
public class ResponseExecutor |
|
||||||
{ |
|
||||||
|
|
||||||
ExecutorService mExecutor; |
|
||||||
|
|
||||||
public ResponseExecutor() |
|
||||||
{ |
|
||||||
this.mExecutor = Executors.newFixedThreadPool(20); |
|
||||||
} |
|
||||||
|
|
||||||
public void execute(Runnable task) |
|
||||||
{ |
|
||||||
this.mExecutor.execute(task); |
|
||||||
} |
|
||||||
|
|
||||||
public void shutdown() |
|
||||||
{ |
|
||||||
if (this.mExecutor != null) |
|
||||||
{ |
|
||||||
this.mExecutor.shutdown(); |
|
||||||
while (!this.mExecutor.isTerminated()) |
|
||||||
{ |
|
||||||
} |
|
||||||
System.out.println("Finished all threads"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,41 +0,0 @@ |
|||||||
package deluge.impl.net; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.net.UnknownHostException; |
|
||||||
import java.security.KeyManagementException; |
|
||||||
import java.security.NoSuchAlgorithmException; |
|
||||||
|
|
||||||
import javax.net.ssl.HandshakeCompletedEvent; |
|
||||||
import javax.net.ssl.HandshakeCompletedListener; |
|
||||||
import javax.net.ssl.SSLContext; |
|
||||||
import javax.net.ssl.SSLSocket; |
|
||||||
import javax.net.ssl.TrustManager; |
|
||||||
|
|
||||||
public class SSL3Socket |
|
||||||
{ |
|
||||||
|
|
||||||
public static SSLSocket createSSLv3Socket(String address, int port) throws KeyManagementException, |
|
||||||
UnknownHostException, IOException, NoSuchAlgorithmException |
|
||||||
{ |
|
||||||
final TrustManager[] trustAllCerts = new TrustManager[] { new AcceptAllTrustManager() }; |
|
||||||
|
|
||||||
final SSLContext sc = SSLContext.getInstance("SSLv3"); |
|
||||||
sc.init(null, trustAllCerts, new java.security.SecureRandom()); |
|
||||||
|
|
||||||
final SSLSocket mySocket = (SSLSocket) sc.getSocketFactory().createSocket(address, port); |
|
||||||
|
|
||||||
final String[] protocols = { "SSLv3", "TLSv1" }; |
|
||||||
mySocket.setEnabledProtocols(protocols); |
|
||||||
|
|
||||||
mySocket.addHandshakeCompletedListener(new HandshakeCompletedListener() |
|
||||||
{ |
|
||||||
|
|
||||||
public void handshakeCompleted(HandshakeCompletedEvent event) |
|
||||||
{ |
|
||||||
System.out.println("Handshake complete"); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
return mySocket; |
|
||||||
} |
|
||||||
} |
|
@ -1,245 +0,0 @@ |
|||||||
package deluge.impl.net; |
|
||||||
|
|
||||||
import java.io.BufferedInputStream; |
|
||||||
import java.io.BufferedOutputStream; |
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.io.ByteArrayOutputStream; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.OutputStream; |
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.util.concurrent.ArrayBlockingQueue; |
|
||||||
import java.util.concurrent.BlockingQueue; |
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
import java.util.zip.DataFormatException; |
|
||||||
import java.util.zip.Deflater; |
|
||||||
import java.util.zip.DeflaterOutputStream; |
|
||||||
import java.util.zip.Inflater; |
|
||||||
import java.util.zip.InflaterInputStream; |
|
||||||
|
|
||||||
import javax.net.ssl.SSLSocket; |
|
||||||
|
|
||||||
import deluge.Util; |
|
||||||
|
|
||||||
public class Session |
|
||||||
{ |
|
||||||
public interface DataCallback |
|
||||||
{ |
|
||||||
public void dataRecived(byte[] data); |
|
||||||
} |
|
||||||
|
|
||||||
public static byte[] decompressByteArray(byte[] data) throws IOException |
|
||||||
{ |
|
||||||
final InputStream from = new InflaterInputStream(new ByteArrayInputStream(data)); |
|
||||||
final ByteArrayOutputStream to = new ByteArrayOutputStream(); |
|
||||||
Util.copy(from, to); |
|
||||||
byte[] output = to.toByteArray(); |
|
||||||
from.close(); |
|
||||||
to.close(); |
|
||||||
return output; |
|
||||||
} |
|
||||||
|
|
||||||
private static byte[] decompress(byte[] input) throws DataFormatException |
|
||||||
{ |
|
||||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
||||||
|
|
||||||
final Inflater decompresser = new Inflater(false); |
|
||||||
|
|
||||||
decompresser.setInput(input, 0, input.length); |
|
||||||
final byte[] result = new byte[1024]; |
|
||||||
while (!decompresser.finished()) |
|
||||||
{ |
|
||||||
final int resultLength = decompresser.inflate(result); |
|
||||||
baos.write(result, 0, resultLength); |
|
||||||
} |
|
||||||
decompresser.end(); |
|
||||||
|
|
||||||
final byte[] returnValue = baos.toByteArray(); |
|
||||||
try |
|
||||||
{ |
|
||||||
baos.close(); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
} |
|
||||||
return returnValue; |
|
||||||
} |
|
||||||
|
|
||||||
private final BlockingQueue<byte[]> queue = new ArrayBlockingQueue<byte[]>(50); |
|
||||||
private SSLSocket mySocket; |
|
||||||
String myAddress; |
|
||||||
int myPort; |
|
||||||
Thread sender = null; |
|
||||||
|
|
||||||
public final CountDownLatch latch = new CountDownLatch(1); |
|
||||||
|
|
||||||
public Session(String address, int port) |
|
||||||
{ |
|
||||||
this.myAddress = address; |
|
||||||
this.myPort = port; |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] compress(byte[] data) throws IOException |
|
||||||
{ |
|
||||||
|
|
||||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
||||||
|
|
||||||
final Deflater d = new Deflater(); |
|
||||||
final DeflaterOutputStream dout = new DeflaterOutputStream(baos, d); |
|
||||||
dout.write(data); |
|
||||||
dout.close(); |
|
||||||
|
|
||||||
final byte[] output = baos.toByteArray(); |
|
||||||
baos.close(); |
|
||||||
return output; |
|
||||||
} |
|
||||||
|
|
||||||
private void createSocket() |
|
||||||
{ |
|
||||||
if (this.mySocket == null) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
this.mySocket = SSL3Socket.createSSLv3Socket(this.myAddress, this.myPort); |
|
||||||
this.mySocket.startHandshake(); |
|
||||||
} |
|
||||||
catch (final Exception e1) |
|
||||||
{ |
|
||||||
e1.printStackTrace(); |
|
||||||
this.mySocket = null; |
|
||||||
} |
|
||||||
} |
|
||||||
this.latch.countDown(); |
|
||||||
} |
|
||||||
|
|
||||||
public void listen(final DataCallback cb) throws IOException |
|
||||||
{ |
|
||||||
new Thread(new Runnable() |
|
||||||
{ |
|
||||||
|
|
||||||
public void run() |
|
||||||
{ |
|
||||||
createSocket(); |
|
||||||
System.out.println("Listening Thread started"); |
|
||||||
try |
|
||||||
{ |
|
||||||
while (Session.this.mySocket != null) |
|
||||||
{ |
|
||||||
|
|
||||||
final InputStream inputStream = new BufferedInputStream(Session.this.mySocket.getInputStream()); |
|
||||||
|
|
||||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
||||||
|
|
||||||
int bytesRead; |
|
||||||
final byte[] buffer = new byte[1024]; |
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) |
|
||||||
{ |
|
||||||
baos.write(buffer); |
|
||||||
|
|
||||||
if (bytesRead < 1024) |
|
||||||
{ |
|
||||||
final byte[] unpacked = Session.decompressByteArray(baos.toByteArray()); |
|
||||||
baos.reset(); |
|
||||||
cb.dataRecived(unpacked); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (final UnsupportedEncodingException e) |
|
||||||
{ |
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
}).start(); |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
this.latch.await(3, TimeUnit.SECONDS); |
|
||||||
} |
|
||||||
catch (final InterruptedException e) |
|
||||||
{ |
|
||||||
} |
|
||||||
if (this.mySocket == null) |
|
||||||
{ |
|
||||||
throw new IOException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void send(byte[] request) throws IOException |
|
||||||
{ |
|
||||||
if (this.sender == null) |
|
||||||
{ |
|
||||||
sender(); |
|
||||||
} |
|
||||||
try |
|
||||||
{ |
|
||||||
this.queue.put(request); |
|
||||||
} |
|
||||||
catch (final InterruptedException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void sender() throws IOException |
|
||||||
{ |
|
||||||
this.sender = new Thread(new Runnable() |
|
||||||
{ |
|
||||||
|
|
||||||
public void run() |
|
||||||
{ |
|
||||||
createSocket(); |
|
||||||
System.out.println("Sending Thread started"); |
|
||||||
try |
|
||||||
{ |
|
||||||
while (Session.this.mySocket != null) |
|
||||||
{ |
|
||||||
byte[] packedData; |
|
||||||
try |
|
||||||
{ |
|
||||||
final byte[] x = Session.this.queue.take(); |
|
||||||
packedData = compress(x); |
|
||||||
|
|
||||||
final OutputStream out = new BufferedOutputStream(Session.this.mySocket.getOutputStream()); |
|
||||||
out.write(packedData); |
|
||||||
out.flush(); |
|
||||||
} |
|
||||||
catch (final InterruptedException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
catch (final IOException e) |
|
||||||
{ |
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
}); |
|
||||||
this.sender.start(); |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
this.latch.await(3, TimeUnit.SECONDS); |
|
||||||
} |
|
||||||
catch (final InterruptedException e) |
|
||||||
{ |
|
||||||
} |
|
||||||
if (this.mySocket == null) |
|
||||||
{ |
|
||||||
throw new IOException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package deluge.impl.net; |
|
||||||
|
|
||||||
public enum TorrentField |
|
||||||
{ |
|
||||||
ACTIVE_TIME("active_time"), ALL_TIME_DOWNLOAD("all_time_download"), COMPACT("compact"), DISTRIBUTED_COPIES( |
|
||||||
"distributed_copies"), DOWNLOAD_PAYLOAD_RATE("download_payload_rate"), FILE_PRIORITIES("file_priorities"), HASH( |
|
||||||
"hash"), IS_AUTO_MANAGED("is_auto_managed"), IS_FINISHED("is_finished"), MAX_CONNECTIONS("max_connections"), MAX_DOWNLOAD_SPEED( |
|
||||||
"max_download_speed"), MAX_UPLOAD_SLOTS("max_upload_slots"), MAX_UPLOAD_SPEED("max_upload_speed"), MESSAGE( |
|
||||||
"message"), MOVE_ON_COMPLETED_PATH("move_on_completed_path"), MOVE_ON_COMPLETED("move_on_completed"), MOVE_COMPLETED_PATH( |
|
||||||
"move_completed_path"), MOVE_COMPLETED("move_completed"), NEXT_ANNOUNCE("next_announce"), NUM_PEERS( |
|
||||||
"num_peers"), NUM_SEEDS("num_seeds"), PAUSED("paused"), PRIORITIZE_FIRST_LAST("prioritize_first_last"), PROGRESS( |
|
||||||
"progress"), REMOVE_AT_RATIO("remove_at_ratio"), SAVE_PATH("save_path"), SEEDING_TIME("seeding_time"), SEEDS_PEERS_RATIO( |
|
||||||
"seeds_peers_ratio"), SEED_RANK("seed_rank"), STATE("state"), STOP_AT_RATIO("stop_at_ratio"), STOP_RATIO( |
|
||||||
"stop_ratio"), TIME_ADDED("time_added"), TOTAL_DONE("total_done"), TOTAL_PAYLOAD_DOWNLOAD( |
|
||||||
"total_payload_download"), TOTAL_PAYLOAD_UPLOAD("total_payload_upload"), TOTAL_PEERS("total_peers"), TOTAL_SEEDS( |
|
||||||
"total_seeds"), TOTAL_UPLOADED("total_uploaded"), TOTAL_WANTED("total_wanted"), TRACKER("tracker"), TRACKERS( |
|
||||||
"trackers"), TRACKER_STATUS("tracker_status"), UPLOAD_PAYLOAD_RATE("upload_payload_rate"), COMMENT( |
|
||||||
"comment"), ETA("eta"), FILE_PROGRESS("file_progress"), FILES("files"), IS_SEED("is_seed"), NAME("name"), NUM_FILES( |
|
||||||
"num_files"), NUM_PIECES("num_pieces"), PEERS("peers"), PIECE_LENGTH("piece_length"), PRIVATE("private"), QUEUE( |
|
||||||
"queue"), RATIO("ratio"), TOTAL_SIZE("total_size"), TRACKER_HOST("tracker_host"), LABEL("label"); |
|
||||||
|
|
||||||
private final String value; |
|
||||||
|
|
||||||
TorrentField(String str) |
|
||||||
{ |
|
||||||
this.value = str; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
return this.value; |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue