-
-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2479 from deltachat/link2xt/jsonrpc
Add DcJsonrpcInstance class
- Loading branch information
Showing
23 changed files
with
281 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.b44t.messenger; | ||
|
||
public class DcJsonrpcInstance { | ||
|
||
public DcJsonrpcInstance(long jsonrpcInstanceCPtr) { | ||
this.jsonrpcInstanceCPtr = jsonrpcInstanceCPtr; | ||
} | ||
|
||
@Override protected void finalize() throws Throwable { | ||
super.finalize(); | ||
unrefJsonrpcInstanceCPtr(); | ||
jsonrpcInstanceCPtr = 0; | ||
} | ||
|
||
public native void request(String request); | ||
public native String getNextResponse(); | ||
|
||
// working with raw c-data | ||
private long jsonrpcInstanceCPtr; // CAVE: the name is referenced in the JNI | ||
private native void unrefJsonrpcInstanceCPtr(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.b44t.messenger.rpc; | ||
|
||
import android.util.Base64; | ||
|
||
public class HttpResponse { | ||
// base64-encoded response body. | ||
private String blob; | ||
// MIME type, e.g. "text/plain" or "text/html". | ||
private String mimetype; | ||
// Encoding, e.g. "utf-8". | ||
private String encoding; | ||
|
||
public HttpResponse(String blob, String mimetype, String encoding) { | ||
this.blob = blob; | ||
this.mimetype = mimetype; | ||
this.encoding = encoding; | ||
} | ||
|
||
public byte[] getBlob() { | ||
if (blob == null) { | ||
return null; | ||
} | ||
return Base64.decode(blob, Base64.NO_WRAP | Base64.NO_PADDING); | ||
} | ||
|
||
public String getMimetype() { | ||
return mimetype; | ||
} | ||
|
||
public String getEncoding() { | ||
return encoding; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package com.b44t.messenger.rpc; | ||
|
||
import com.b44t.messenger.DcJsonrpcInstance; | ||
import com.b44t.messenger.util.concurrent.SettableFuture; | ||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonSyntaxException; | ||
import com.google.gson.reflect.TypeToken; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
public class Rpc { | ||
private final Map<Integer, SettableFuture<JsonElement>> requestFutures = new ConcurrentHashMap<>(); | ||
private final DcJsonrpcInstance dcJsonrpcInstance; | ||
private int requestId = 0; | ||
private final Gson gson = new GsonBuilder().serializeNulls().create(); | ||
|
||
public Rpc(DcJsonrpcInstance dcJsonrpcInstance) { | ||
this.dcJsonrpcInstance = dcJsonrpcInstance; | ||
} | ||
|
||
private void processResponse() throws JsonSyntaxException { | ||
String jsonResponse = dcJsonrpcInstance.getNextResponse(); | ||
Response response = gson.fromJson(jsonResponse, Response.class); | ||
|
||
if (response.id == 0) { // Got JSON-RPC notification/event, ignore | ||
return; | ||
} | ||
|
||
SettableFuture<JsonElement> future = requestFutures.remove(response.id); | ||
if (future == null) { // Got a response with unknown ID, ignore | ||
return; | ||
} | ||
|
||
if (response.error != null) { | ||
future.setException(new RpcException(response.error.toString())); | ||
} else if (response.result != null) { | ||
future.set(response.result); | ||
} else { | ||
future.setException(new RpcException("Got JSON-RPC response witout result or error: " + jsonResponse)); | ||
} | ||
} | ||
|
||
public void start() { | ||
new Thread(() -> { | ||
while (true) { | ||
try { | ||
processResponse(); | ||
} catch (JsonSyntaxException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
}, "jsonrpcThread").start(); | ||
} | ||
|
||
public SettableFuture<JsonElement> call(String method, Object... params) { | ||
int id; | ||
synchronized (this) { | ||
id = ++requestId; | ||
} | ||
String jsonRequest = gson.toJson(new Request(method, params, id)); | ||
SettableFuture<JsonElement> future = new SettableFuture<>(); | ||
requestFutures.put(id, future); | ||
dcJsonrpcInstance.request(jsonRequest); | ||
return future; | ||
} | ||
|
||
public JsonElement getResult(String method, Object... params) throws RpcException { | ||
try { | ||
return call(method, params).get(); | ||
} catch (ExecutionException e) { | ||
throw (RpcException)e.getCause(); | ||
} catch (InterruptedException e) { | ||
throw new RpcException(e.getMessage()); | ||
} | ||
} | ||
|
||
public int addAccount() throws RpcException { | ||
return gson.fromJson(getResult("add_account"), int.class); | ||
} | ||
|
||
public void startIO() throws RpcException { | ||
getResult("start_io_for_all_accounts"); | ||
} | ||
|
||
public void stopIO() throws RpcException { | ||
getResult("stop_io_for_all_accounts"); | ||
} | ||
|
||
public Map<String, String> getSystemInfo() throws RpcException { | ||
TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){}; | ||
return gson.fromJson(getResult("get_system_info"), mapType); | ||
} | ||
|
||
public HttpResponse getHttpResponse(int accountId, String url) throws RpcException { | ||
return gson.fromJson(getResult("get_http_response", accountId, url), HttpResponse.class); | ||
} | ||
|
||
|
||
private static class Request { | ||
public String jsonrpc = "2.0"; | ||
public String method; | ||
public Object[] params; | ||
public int id; | ||
|
||
public Request(String method, Object[] params, int id) { | ||
this.method = method; | ||
this.params = params; | ||
this.id = id; | ||
} | ||
} | ||
|
||
private static class Response { | ||
public int id = 0; | ||
public JsonElement result; | ||
public JsonElement error; | ||
|
||
public Response(int id, JsonElement result, JsonElement error) { | ||
this.id = id; | ||
this.result = result; | ||
this.error = error; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.b44t.messenger.rpc; | ||
|
||
/** | ||
* An exception occurred while processing a request in Delta Chat core. | ||
**/ | ||
public class RpcException extends Exception { | ||
|
||
public RpcException(String message) { | ||
super(message); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...sms/util/concurrent/ListenableFuture.java → ...ger/util/concurrent/ListenableFuture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...resms/util/concurrent/SettableFuture.java → ...enger/util/concurrent/SettableFuture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.