Merge branch 'develop' of github.com:Agorise/graphenej into develop
This commit is contained in:
commit
c76548cbee
2 changed files with 115 additions and 58 deletions
|
@ -80,9 +80,10 @@ public class NetworkService extends Service {
|
|||
private final String TAG = this.getClass().getName();
|
||||
|
||||
public static final int NORMAL_CLOSURE_STATUS = 1000;
|
||||
private static final int NO_HISTORY_CLOSURE_STATUS = 1001;
|
||||
|
||||
// Time to wait before retrying a connection attempt
|
||||
private final int DEFAULT_RETRY_DELAY = 500;
|
||||
private static final int DEFAULT_RETRY_DELAY = 500;
|
||||
|
||||
// Default connection delay when using the node latency verification strategy. This initial
|
||||
// delay is required in order ot make sure we have a fair selection of node latencies from
|
||||
|
@ -285,7 +286,17 @@ public class NetworkService extends Service {
|
|||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
Bundle extras = intent.getExtras();
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize information and try to connect to a node accordingly. This methods were moved
|
||||
* from onBind to avoid crashes due to components other than {@link NetworkServiceManager}
|
||||
* binding to the service without submitting the proper information.
|
||||
*
|
||||
* @param extras Bundle that contains all required information for a proper initialization
|
||||
*/
|
||||
public void bootstrapService(Bundle extras) {
|
||||
// Retrieving credentials and requested API data from the shared preferences
|
||||
mUsername = extras.getString(NetworkService.KEY_USERNAME, "");
|
||||
mPassword = extras.getString(NetworkService.KEY_PASSWORD, "");
|
||||
|
@ -328,7 +339,6 @@ public class NetworkService extends Service {
|
|||
mHandler.postDelayed(mConnectAttempt, DEFAULT_INITIAL_DELAY);
|
||||
}
|
||||
}
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -556,6 +566,9 @@ public class NetworkService extends Service {
|
|||
} else if (requestClass == GetFullAccounts.class) {
|
||||
Type GetFullAccountsResponse = new TypeToken<JsonRpcResponse<List<FullAccountDetails>>>(){}.getType();
|
||||
parsedResponse = gson.fromJson(text, GetFullAccountsResponse);
|
||||
|
||||
if(parsedResponse != null)
|
||||
verifyNodeHasHistoryApi(parsedResponse);
|
||||
} else if(requestClass == GetKeyReferences.class){
|
||||
Type GetKeyReferencesResponse = new TypeToken<JsonRpcResponse<List<List<UserAccount>>>>(){}.getType();
|
||||
parsedResponse = gson.fromJson(text, GetKeyReferencesResponse);
|
||||
|
@ -578,6 +591,30 @@ public class NetworkService extends Service {
|
|||
RxBus.getBusInstance().send(parsedResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method inspects the node response to find out if the totalOps is equal to zero,
|
||||
* in that case the current connected node may not have the history plugin so we would need
|
||||
* to close the connection and choose a different node.
|
||||
*
|
||||
* @param parsedResponse A JSONRpcResponse from a GetFullAccounts API call
|
||||
*/
|
||||
private void verifyNodeHasHistoryApi(JsonRpcResponse parsedResponse) {
|
||||
if(parsedResponse.result instanceof List &&
|
||||
((List) parsedResponse.result).size() > 0 &&
|
||||
((List) parsedResponse.result).get(0) instanceof FullAccountDetails) {
|
||||
|
||||
FullAccountDetails fullAccountDetails = (FullAccountDetails) ((List) parsedResponse.result).get(0);
|
||||
long totalOps = fullAccountDetails.getStatistics().total_ops;
|
||||
|
||||
if (totalOps == 0) {
|
||||
Log.d(TAG, "The node returned 0 total_ops for current account and may not have installed the history plugin. " +
|
||||
"Trying to connect to a different node.");
|
||||
|
||||
mWebSocket.close(NO_HISTORY_CLOSURE_STATUS, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private method that will just broadcast a de-serialized notification to all interested parties
|
||||
* @param notification De-serialized notification
|
||||
|
@ -636,6 +673,37 @@ public class NetworkService extends Service {
|
|||
public void onClosed(WebSocket webSocket, int code, String reason) {
|
||||
super.onClosed(webSocket, code, reason);
|
||||
Log.d(TAG,"onClosed");
|
||||
|
||||
if (code == NO_HISTORY_CLOSURE_STATUS)
|
||||
handleWebSocketDisconnection(true);
|
||||
else
|
||||
handleWebSocketDisconnection(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
Log.e(TAG,"onFailure. Exception: "+t.getClass().getName()+", Msg: "+t.getMessage());
|
||||
// Logging error stack trace
|
||||
for(StackTraceElement element : t.getStackTrace()){
|
||||
Log.v(TAG,String.format("%s#%s:%s", element.getClassName(), element.getMethodName(), element.getLineNumber()));
|
||||
}
|
||||
|
||||
// If there is a response, we print it
|
||||
if(response != null){
|
||||
Log.e(TAG,"Response: "+response.message());
|
||||
}
|
||||
|
||||
handleWebSocketDisconnection(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that encapsulates the behavior of handling a disconnection to the current node, and
|
||||
* potentially tries to reconnect to another one.
|
||||
*
|
||||
* @param tryReconnection Variable that states if a reconnection to other node should be tried.
|
||||
*/
|
||||
private void handleWebSocketDisconnection(boolean tryReconnection) {
|
||||
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED, ApiAccess.API_NONE));
|
||||
|
||||
isLoggedIn = false;
|
||||
|
@ -647,29 +715,11 @@ public class NetworkService extends Service {
|
|||
if(nodeLatencyVerifier != null)
|
||||
nodeLatencyVerifier.updateActiveNodeInformation(mSelectedNode);
|
||||
|
||||
|
||||
// We have currently no selected node
|
||||
mSelectedNode = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
Log.e(TAG,"onFailure. Exception: "+t.getClass().getName()+", Msg: "+t.getMessage());
|
||||
// Logging error stack trace
|
||||
for(StackTraceElement element : t.getStackTrace()){
|
||||
Log.v(TAG,String.format("%s#%s:%s", element.getClassName(), element.getMethodName(), element.getLineNumber()));
|
||||
}
|
||||
if(tryReconnection) {
|
||||
// Registering current status
|
||||
isLoggedIn = false;
|
||||
mCurrentId = 0;
|
||||
mApiIds.clear();
|
||||
|
||||
// If there is a response, we print it
|
||||
if(response != null){
|
||||
Log.e(TAG,"Response: "+response.message());
|
||||
}
|
||||
|
||||
// Adding a very high latency value to this node in order to prevent
|
||||
// us from getting it again
|
||||
mSelectedNode.addLatencyValue(Long.MAX_VALUE);
|
||||
|
@ -690,12 +740,7 @@ public class NetworkService extends Service {
|
|||
}
|
||||
}, DEFAULT_RETRY_DELAY);
|
||||
}
|
||||
// Marking the selected node as not connected
|
||||
mSelectedNode.setConnected(false);
|
||||
|
||||
// Updating the selected node's 'connected' status on the NodeLatencyVerifier instance
|
||||
if(nodeLatencyVerifier != null)
|
||||
nodeLatencyVerifier.updateActiveNodeInformation(mSelectedNode);
|
||||
}
|
||||
|
||||
// We have currently no selected node
|
||||
mSelectedNode = null;
|
||||
|
|
|
@ -25,14 +25,14 @@ import cy.agorise.graphenej.stats.ExponentialMovingAverage;
|
|||
*/
|
||||
|
||||
public class NetworkServiceManager implements Application.ActivityLifecycleCallbacks {
|
||||
private final static String TAG = "NetworkServiceManager";
|
||||
private final String TAG = this.getClass().getName();
|
||||
/**
|
||||
* Constant used to specify how long will the app wait for another activity to go through its starting life
|
||||
* cycle events before running the teardownConnectionTask task.
|
||||
*
|
||||
* This is used as a means to detect whether or not the user has left the app.
|
||||
*/
|
||||
private final int DISCONNECT_DELAY = 1500;
|
||||
private static final int DISCONNECT_DELAY = 1500;
|
||||
|
||||
/**
|
||||
* Handler instance used to schedule tasks back to the main thread
|
||||
|
@ -72,8 +72,8 @@ public class NetworkServiceManager implements Application.ActivityLifecycleCallb
|
|||
}
|
||||
};
|
||||
|
||||
public NetworkServiceManager(Context context){
|
||||
mContextReference = new WeakReference<Context>(context);
|
||||
private NetworkServiceManager(Context context){
|
||||
mContextReference = new WeakReference<>(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,7 +89,15 @@ public class NetworkServiceManager implements Application.ActivityLifecycleCallb
|
|||
// Creating a new Intent that will be used to start the NetworkService
|
||||
Context context = mContextReference.get();
|
||||
Intent intent = new Intent(context, NetworkService.class);
|
||||
context.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method passes all the required information to the NetworkService to properly
|
||||
* initialize itself
|
||||
*/
|
||||
private void passRequiredInfoToConfigureService() {
|
||||
// Adding user-provided node URLs
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Iterator<String> it = mCustomNodeUrls.iterator();
|
||||
|
@ -99,15 +107,17 @@ public class NetworkServiceManager implements Application.ActivityLifecycleCallb
|
|||
}
|
||||
String customNodes = stringBuilder.toString();
|
||||
|
||||
Bundle b = new Bundle();
|
||||
|
||||
// Adding all
|
||||
intent.putExtra(NetworkService.KEY_USERNAME, mUserName)
|
||||
.putExtra(NetworkService.KEY_PASSWORD, mPassword)
|
||||
.putExtra(NetworkService.KEY_REQUESTED_APIS, mRequestedApis)
|
||||
.putExtra(NetworkService.KEY_NODE_URLS, customNodes)
|
||||
.putExtra(NetworkService.KEY_AUTO_CONNECT, mAutoConnect)
|
||||
.putExtra(NetworkService.KEY_ENABLE_LATENCY_VERIFIER, mVerifyLatency);
|
||||
context.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
b.putString(NetworkService.KEY_USERNAME, mUserName);
|
||||
b.putString(NetworkService.KEY_PASSWORD, mPassword);
|
||||
b.putInt(NetworkService.KEY_REQUESTED_APIS, mRequestedApis);
|
||||
b.putString(NetworkService.KEY_NODE_URLS, customNodes);
|
||||
b.putBoolean(NetworkService.KEY_AUTO_CONNECT, mAutoConnect);
|
||||
b.putBoolean(NetworkService.KEY_ENABLE_LATENCY_VERIFIER, mVerifyLatency);
|
||||
|
||||
mService.bootstrapService(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -133,6 +143,8 @@ public class NetworkServiceManager implements Application.ActivityLifecycleCallb
|
|||
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
||||
NetworkService.LocalBinder binder = (NetworkService.LocalBinder) service;
|
||||
mService = binder.getService();
|
||||
|
||||
passRequiredInfoToConfigureService();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue