Merge pull request #548 from status-im/bug/ios-crash

Restarting RPC server
This commit is contained in:
Roman Volosovskyi 2016-12-13 11:12:39 +02:00 committed by GitHub
commit 28147a3730
15 changed files with 239 additions and 42 deletions

View File

@ -14,5 +14,5 @@ android {
dependencies {
compile 'com.facebook.react:react-native:+'
compile(group: 'status-im', name: 'status-go', version: 'jail-isconnected', ext: 'aar')
compile(group: 'status-im', name: 'status-go', version: 'restart-rpc', ext: 'aar')
}

View File

@ -32,6 +32,18 @@ public class StatusConnector extends ServiceConnector {
}
}
public void startRPC() {
if (checkBound()) {
sendMessage(null, StatusMessages.MSG_START_RPC, null);
}
}
public void stopRPC() {
if (checkBound()) {
sendMessage(null, StatusMessages.MSG_STOP_RPC, null);
}
}
public void login(String callbackIdentifier, String address, String password) {
if (checkBound()) {

View File

@ -59,4 +59,14 @@ public class StatusMessages {
*/
public static final int MSG_DISCARD_TRANSACTION = 11;
/**
* Start RPC server
*/
static final int MSG_START_RPC = 12;
/**
* Stop RPC server
*/
static final int MSG_STOP_RPC = 13;
}

View File

@ -144,6 +144,28 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
status.startNode(callbackIdentifier);
}
@ReactMethod
public void startNodeRPCServer() {
Log.d(TAG, "startNodeRPCServer");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
status.startRPC();
}
@ReactMethod
public void stopNodeRPCServer() {
Log.d(TAG, "stopNodeRPCServer");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
status.stopRPC();
}
@ReactMethod
public void login(String address, String password, Callback callback) {
Log.d(TAG, "login");

View File

@ -143,6 +143,14 @@ public class StatusService extends Service {
callJail(message);
break;
case StatusMessages.MSG_START_RPC:
startRPC();
break;
case StatusMessages.MSG_STOP_RPC:
stopRPC();
break;
default:
return false;
}
@ -188,6 +196,14 @@ public class StatusService extends Service {
createAndSendReply(message, StatusMessages.MSG_STOP_NODE, null);
}
private void startRPC() {
Statusgo.StartNodeRPCServer();
}
private void stopRPC() {
Statusgo.StopNodeRPCServer();
}
private void createAccount(Message message) {
Bundle data = message.getData();

View File

@ -59,6 +59,68 @@ RCT_EXPORT_METHOD(callJail:(NSString *)chatId
});
}
const int STATE_ACTIVE = 0;
const int STATE_LOCKED_WITH_ACTIVE_APP = 1;
const int STATE_BACKGROUND = 2;
const int STATE_LOCKED_WITH_INACTIVE_APP = 3;
int wozniakConstant = STATE_ACTIVE;
static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
// the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification
CFStringRef nameCFString = (CFStringRef)name;
NSString *lockState = (__bridge NSString*)nameCFString;
NSLog(@"Darwin notification NAME = %@",name);
NSString* sm = [NSString stringWithFormat:@"%i", wozniakConstant];
NSString *s1 = [NSString stringWithFormat:@"%@ %@", @"LOCK MAGIC", sm];
NSLog(s1);
if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"])
{
NSLog(@"DEVICE LOCKED");
// User locks phone when application is active
if(wozniakConstant == STATE_ACTIVE){
wozniakConstant = STATE_LOCKED_WITH_ACTIVE_APP;
StopNodeRPCServer();
}
// Here lockcomplete event comes when app is unlocked
// because it couldn't come when locking happened
// as application was not active (it could not handle callback)
if (wozniakConstant == STATE_LOCKED_WITH_INACTIVE_APP) {
wozniakConstant = STATE_ACTIVE;
StopNodeRPCServer();
StartNodeRPCServer();
}
}
else
{
NSLog(@"LOCK STATUS CHANGED");
NSString *s = [NSString stringWithFormat:@"%@ %@", @"LOCK", lockState];
NSLog(s);
// if lockstate happens before lockcomplete it means
// that phone was locked when application was not active
if(wozniakConstant == STATE_ACTIVE){
wozniakConstant = STATE_LOCKED_WITH_INACTIVE_APP;
}
if(wozniakConstant == STATE_BACKGROUND){
wozniakConstant = STATE_ACTIVE;
StartNodeRPCServer();
}
// one more lockstate event comes along with lockcomplete
// when phone is locked with active application
if(wozniakConstant == STATE_LOCKED_WITH_ACTIVE_APP){
wozniakConstant = STATE_BACKGROUND;
}
}
}
////////////////////////////////////////////////////////////////////
#pragma mark - startNode
//////////////////////////////////////////////////////////////////// startNode
@ -83,23 +145,57 @@ RCT_EXPORT_METHOD(startNode:(RCTResponseSenderBlock)onResultCallback) {
}else
NSLog(@"folderName: %@", folderName);
NSString *peer1 = @"enode://5f23bf4913dd005ce945648cb12d3ef970069818d8563a3fe054e5e1dc3898b9cb83e0af1f51b2dce75eaffc76e93f996caf538e21c5b64db5fa324958d59630@95.85.40.211:30303";
NSString *peer2 = @"enode://b9de2532421f15ac55da9d9a7cddc0dc08b0d646d631fd7ab2a170bd2163fb86b095dd8bde66b857592812f7cd9539f2919b6c64bc1a784a1d1c6ec8137681ed@188.166.229.119:30303";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(void) {
StartNode((char *) [folderName.path UTF8String]);
});
NSString *peer1 = @"enode://5f23bf4913dd005ce945648cb12d3ef970069818d8563a3fe054e5e1dc3898b9cb83e0af1f51b2dce75eaffc76e93f996caf538e21c5b64db5fa324958d59630@95.85.40.211:30303";
NSString *peer2 = @"enode://b9de2532421f15ac55da9d9a7cddc0dc08b0d646d631fd7ab2a170bd2163fb86b095dd8bde66b857592812f7cd9539f2919b6c64bc1a784a1d1c6ec8137681ed@188.166.229.119:30303";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(void) {
AddPeer((char *) [peer1 UTF8String]);
AddPeer((char *) [peer2 UTF8String]);
});
});
onResultCallback(@[[NSNull null]]);
//Screen lock notifications
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
NULL, // observer
displayStatusChanged, // callback
CFSTR("com.apple.springboard.lockcomplete"), // event name
NULL, // object
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
NULL, // observer
displayStatusChanged, // callback
CFSTR("com.apple.springboard.lockstate"), // event name
NULL, // object
CFNotificationSuspensionBehaviorDeliverImmediately);
return;
}
}
////////////////////////////////////////////////////////////////////
#pragma mark - StartNodeRPCServer method
//////////////////////////////////////////////////////////////////// createAccount
RCT_EXPORT_METHOD(startNodeRPCServer) {
#if DEBUG
NSLog(@"StartNodeRPCServer() method called");
#endif
StartNodeRPCServer();
}
////////////////////////////////////////////////////////////////////
#pragma mark - StopNodeRPCServer method
//////////////////////////////////////////////////////////////////// createAccount
RCT_EXPORT_METHOD(stopNodeRPCServer) {
#if DEBUG
NSLog(@"StopNodeRPCServer() method called");
#endif
StopNodeRPCServer();
}
RCT_EXPORT_METHOD(stopNode:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"stopNode() method called");

View File

@ -25,7 +25,7 @@
<artifactItem>
<groupId>status-im</groupId>
<artifactId>status-go-ios-simulator</artifactId>
<version>jail-isconnected</version>
<version>restart-rpc2</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>./</outputDirectory>

View File

@ -122,4 +122,4 @@
;; Clipboard
(defn copy-to-clipboard [text]
(.setString (.-Clipboard react-native) text))
(.setString (.-Clipboard react-native) text))

View File

@ -62,6 +62,29 @@
(when status
(call-module #(.startNode status on-result))))
(defn stop-rpc-server []
(when status
(call-module #(.stopNodeRPCServer status))))
(defn start-rpc-server []
(when status
(call-module #(.startNodeRPCServer status))))
(defonce restarting-rpc (atom false))
(defn restart-rpc []
(when-not @restarting-rpc
(reset! restarting-rpc true)
(log/debug :restrt-rpc-on-post-error)
;; todo maybe it would be better to use something like
;; restart-rpc-server on status-go side
(stop-rpc-server)
(start-rpc-server)
(go (<! (timeout 3000))
(reset! restarting-rpc false))))
(defonce account-creation? (atom false))
(defn create-account [password on-result]

View File

@ -24,7 +24,8 @@
status-im.network.handlers
[status-im.utils.types :as t]
[status-im.constants :refer [console-chat-id]]
[status-im.utils.ethereum-network :as enet]))
[status-im.utils.ethereum-network :as enet]
[status-im.protocol.core :as protocol]))
;; -- Common --------------------------------------------------------------

View File

@ -67,7 +67,7 @@
(.addListener keyboard
"keyboardWillHide"
#(when-not (= 0 @keyboard-height)
(dispatch [:set :keyboard-height 0])))
(dispatch [:set :keyboard-height 0])))
(.hide splash-screen))
:render
(fn []

View File

@ -60,6 +60,7 @@
::d/delivery-options))
(def stop-watching-all! f/remove-all-filters!)
(def reset-all-pending-messages! d/reset-all-pending-messages!)
(defn init-whisper!
[{:keys [rpc-url identity groups callback

View File

@ -12,38 +12,42 @@
[status-im.i18n :refer [label]]
[status-im.utils.random :as random]
[taoensso.timbre :as log :refer-macros [debug]]
[status-im.constants :as c]))
[status-im.constants :as c]
[status-im.components.status :as status]))
(register-handler :initialize-protocol
(fn [db [_ current-account-id]]
(let [{:keys [public-key status updates-public-key
updates-private-key]}
(get-in db [:accounts current-account-id])]
(let [groups (chats/get-active-group-chats)
w3 (protocol/init-whisper!
{:rpc-url c/ethereum-rpc-url
:identity public-key
:groups groups
:callback #(dispatch [:incoming-message %1 %2])
:ack-not-received-s-interval 125
:default-ttl 120
:send-online-s-interval 180
:ttl {}
:max-attempts-number 3
:delivery-loop-ms-interval 500
:profile-keypair {:public updates-public-key
:private updates-private-key}
:hashtags (u/get-hashtags status)
:pending-messages (pending-messages/get-all)
:contacts (keep (fn [{:keys [whisper-identity
public-key
private-key]}]
(when (and public-key private-key)
{:identity whisper-identity
:keypair {:public public-key
:private private-key}}))
(contacts/get-all))})]
(assoc db :web3 w3)))))
(if public-key
(let [groups (chats/get-active-group-chats)
w3 (protocol/init-whisper!
{:rpc-url c/ethereum-rpc-url
:identity public-key
:groups groups
:callback #(dispatch [:incoming-message %1 %2])
:ack-not-received-s-interval 125
:default-ttl 120
:send-online-s-interval 180
:ttl {}
:max-attempts-number 3
:delivery-loop-ms-interval 500
:profile-keypair {:public updates-public-key
:private updates-private-key}
:hashtags (u/get-hashtags status)
:pending-messages (pending-messages/get-all)
:contacts (keep (fn [{:keys [whisper-identity
public-key
private-key]}]
(when (and public-key private-key)
{:identity whisper-identity
:keypair {:public public-key
:private private-key}}))
(contacts/get-all))
:post-error-callback #(dispatch [::post-error %])})]
(assoc db :web3 w3))
db))))
(register-handler :update-sync-state
(u/side-effect!
@ -175,7 +179,7 @@
(register-handler ::you-removed-from-group
(u/side-effect!
(fn [{:keys [web3]}
[_ {:keys [from]
[_ {:keys [from]
{:keys [group-id timestamp] :as payload} :payload}]]
(when (chats/new-update? timestamp group-id)
(let [message
@ -191,7 +195,7 @@
(register-handler :participant-left-group
(u/side-effect!
(fn [{:keys [current-public-key]}
[_ {:keys [from]
[_ {:keys [from]
{:keys [group-id timestamp] :as payload} :payload}]]
(when (and (not= current-public-key from)
(chats/is-active? group-id)
@ -344,3 +348,10 @@
(dispatch [:update-contact! contact])
(dispatch [:watch-contact contact]))
(dispatch [:add-chat from chat])))))))
(register-handler ::post-error
(u/side-effect!
(fn [_ [_ error]]
(.log js/console error)
(when (re-find (re-pattern "Could not connect to the server.") (.-message error))
(status/restart-rpc)))))

View File

@ -127,9 +127,12 @@
:last-attempt (u/timestamp)))))
(defn delivery-callback
[web3 {:keys [id requires-ack? to]}]
[web3 post-error-callback {:keys [id requires-ack? to]}]
(fn [error _]
(when error (log/warn :shh-post-error error))
(when error
(log/warn :shh-post-error error)
(when post-error-callback
(post-error-callback error)))
(when-not error
(debug :delivery-callback)
(message-was-sent! web3 id to)
@ -143,10 +146,12 @@
(s/def ::default-ttl ::pos-int)
(s/def ::send-online-s-interval ::pos-int)
(s/def ::online-message fn?)
(s/def ::post-error-callback fn?)
(s/def ::delivery-options
(s/keys :req-un [::delivery-loop-ms-interval ::ack-not-received-s-interval
::max-attempts-number ::default-ttl ::send-online-s-interval]
::max-attempts-number ::default-ttl ::send-online-s-interval
::post-error-callback]
:opt-un [::online-message]))
(defn should-be-retransmitted?
@ -180,7 +185,7 @@
(defn run-delivery-loop!
[web3 {:keys [delivery-loop-ms-interval default-ttl ttl-config
send-online-s-interval online-message]
send-online-s-interval online-message post-error-callback]
:as options}]
{:pre [(valid? ::delivery-options options)]}
(debug :run-delivery-loop!)
@ -201,7 +206,7 @@
(when (should-be-retransmitted? options data)
(try
(let [message' (check-ttl message type ttl-config default-ttl)
callback (delivery-callback web3 data)]
callback (delivery-callback web3 post-error-callback data)]
(t/post-message! web3 message' callback))
(catch :default err
(log/error :post-message-error err))

View File

@ -25,7 +25,7 @@
(defn handle-qr-request
[db [_ context data]]
(let [handler (get-in db [:qr-codes context])]
(when-let [handler (get-in db [:qr-codes context])]
(dispatch [handler context data])))
(defn clear-qr-request [db [_ context]]