@Override public void onFailure(Throwable t) { log.error("Failed to complete 'message' event: {}", event.getEventType().name(), t); } });
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { // TODO Implement default: handleUnexpectedMessageEvent(context, event); } } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { // TODO Implement default: handleUnexpectedMessageEvent(context, event); } } }
@Override public void onSuccess(Boolean result) { log.debug("Completed 'message' event: {}", event.getEventType().name()); }
@Override public Boolean call() { log.debug("Firing 'message' event: {} for {}", event.getEventType().name(), event.getSource()); messageEventBus.post(event); // Must be OK to be here return true; } });
@Subscribe public void onHardwareWalletProtocolEvent(MessageEvent event) { // Decode into a message type for use with a switch MessageEventType eventType = event.getEventType(); // Protocol message log.debug("Received event: {}", eventType.name()); log.debug("{}", event.getMessage().toString()); // Add the event to the queue for blocking purposes messageEvents.add(event); }
@Subscribe public void onHardwareWalletProtocolEvent(MessageEvent event) { // Decode into a message type for use with a switch MessageEventType eventType = event.getEventType(); // Protocol message log.debug("Received event: {}", eventType.name()); log.debug("{}", event.getMessage().toString()); // Add the event to the queue for blocking purposes messageEvents.add(event); }
@Override public void run() { while (!(monitorHidExecutorService.isShutdown() || monitorHidExecutorService.isTerminated())) { // Wait for 10 seconds for a response (this is so that the monitorExecutorService can shut down cleanly) Optional<MessageEvent> messageEvent = readMessage(10, TimeUnit.SECONDS); if (messageEvent.isPresent()) { if (MessageEventType.DEVICE_FAILED.equals(messageEvent.get().getEventType())) { // Stop reading messages on this thread for a short while to allow recovery time Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); } else { // Fire the event MessageEvents.fireMessageEvent(messageEvent.get()); } } } } });
@Override public void run() { while (!(monitorHidExecutorService.isShutdown() || monitorHidExecutorService.isTerminated())) { // Wait for 10 seconds for a response (this is so that the monitorExecutorService can shut down cleanly) Optional<MessageEvent> messageEvent = readMessage(10, TimeUnit.SECONDS); if (messageEvent.isPresent()) { if (MessageEventType.DEVICE_FAILED.equals(messageEvent.get().getEventType())) { // Stop reading messages on this thread for a short while to allow recovery time Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); } else { // Fire the event MessageEvents.fireMessageEvent(messageEvent.get()); } } } } });
@Override public void run() { while (true) { log.debug("Waiting for hardware wallet message..."); Optional<MessageEvent> messageEvent = hardwareWallet.readMessage(1, TimeUnit.MINUTES); if (messageEvent.isPresent()) { if (MessageEventType.DEVICE_FAILED.equals(messageEvent.get().getEventType())) { // Stop reading messages on this thread for a short while to allow recovery time Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); } else { // Send the Message back to the client log.debug("Sending raw message to client"); writeMessage(messageEvent.get().getRawMessage().get(), outputToClient); } } } }
@Override public void run() { while (true) { log.debug("Waiting for hardware wallet message..."); Optional<MessageEvent> messageEvent = hardwareWallet.readMessage(1, TimeUnit.MINUTES); if (messageEvent.isPresent()) { if (MessageEventType.DEVICE_FAILED.equals(messageEvent.get().getEventType())) { // Stop reading messages on this thread for a short while to allow recovery time Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); } else { // Send the Message back to the client log.debug("Sending raw message to client"); writeMessage(messageEvent.get().getRawMessage().get(), outputToClient); } } } }
/** * @param event The low level message event */ @Subscribe public void onMessageEvent(MessageEvent event) { // Filter messages not associated with this context if (!getClient().name().equalsIgnoreCase(event.getSource())) { log.debug("Discarded message event: '{}' (different device)", event.getEventType().name()); return; } log.debug("Received message event: '{}'", event.getEventType().name()); // Perform a state transition as a result of this event try { currentState.transition(client, this, event); } catch (Exception e) { e.printStackTrace(); } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { case DEVICE_FAILED: context.resetToFailed(); break; case DEVICE_DETACHED: // Do nothing break; case DEVICE_ATTACHED: context.resetToAttached(); break; default: handleUnexpectedMessageEvent(context, event); } } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { // We don't expect any messages switch (event.getEventType()) { case SUCCESS: // Possible Ping HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_SUCCEEDED, event.getMessage().get(), client.name()); // Ensure the Features are updated context.resetToConnected(); break; default: handleUnexpectedMessageEvent(context, event); } }
/** * <p>Provide standard handling for an unexpected message so the downstream consumer can react appropriately</p> * * @param context The current context providing parameters for decisions * @param event The event driving the transition */ protected void handleUnexpectedMessageEvent(HardwareWalletContext context, MessageEvent event) { log.warn("Unexpected message event '{}'", event.getEventType().name()); if (event.getMessage().isPresent()) { HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, event.getMessage().get(), context.getClient().name()); } else { HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, context.getClient().name()); } context.resetToConnected(); } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { case BUTTON_REQUEST: // Device is asking for the user to acknowledge a word display HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_BUTTON_PRESS, event.getMessage().get(), client.name()); client.buttonAck(); break; case SUCCESS: // Device has completed the create wallet operation HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_SUCCEEDED, event.getMessage().get(), client.name()); // Ensure the Features are updated context.resetToConnected(); break; case FAILURE: // User has cancelled or operation failed HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, event.getMessage().get(), client.name()); context.resetToInitialised(); break; default: handleUnexpectedMessageEvent(context, event); } } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { case PIN_MATRIX_REQUEST: // Device is asking for a PIN matrix to be displayed (user must read the screen carefully) HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_PIN_ENTRY, event.getMessage().get(), client.name()); // Further state transitions will occur after the user has provided the PIN via the service break; case PASSPHRASE_REQUEST: // Device is asking for a passphrase screen to be displayed HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_PASSPHRASE_ENTRY, client.name()); // Further state transitions will occur after the user has provided the passphrase via the service break; case PUBLIC_KEY: // Device has completed the operation and provided a public key HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.PUBLIC_KEY, event.getMessage().get(), client.name()); break; case FAILURE: // User has cancelled or operation failed HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, event.getMessage().get(), client.name()); context.resetToInitialised(); break; default: handleUnexpectedMessageEvent(context, event); } } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { case FEATURES: Features features = (Features) event.getMessage().get(); context.setFeatures(features); // Verify the Features through the client if (!client.verifyFeatures(features)) { features.setSupported(false); context.resetToFailed(); } else { features.setSupported(true); context.resetToInitialised(); } break; case FAILURE: HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, event.getMessage().get(), client.name()); context.resetToInitialised(); break; default: handleUnexpectedMessageEvent(context, event); } } }
@Override protected void internalTransition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { switch (event.getEventType()) { case PIN_MATRIX_REQUEST: // Device is asking for a PIN matrix to be displayed (user must read the screen carefully) HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_PIN_ENTRY, event.getMessage().get(), client.name()); // Further state transitions will occur after the user has provided the PIN via the service break; case PASSPHRASE_REQUEST: // Device is asking for a passphrase screen to be displayed HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_PASSPHRASE_ENTRY, client.name()); // Further state transitions will occur after the user has provided the passphrase via the service break; case ENTROPY_REQUEST: // Device is asking for additional entropy from the user HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.PROVIDE_ENTROPY, client.name()); // Further state transitions will occur after the user has provided the entropy via the service break; case FAILURE: // User has cancelled or operation failed HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_OPERATION_FAILED, event.getMessage().get(), client.name()); context.resetToInitialised(); break; default: handleUnexpectedMessageEvent(context, event); } } }
@Override public void transition(HardwareWalletClient client, HardwareWalletContext context, MessageEvent event) { // Handle low level message events for the device switch (event.getEventType()) { case DEVICE_ATTACHED: context.resetToAttached(); return; case DEVICE_DETACHED: client.softDetach(); context.resetToDetached(); return; case DEVICE_CONNECTED: context.resetToConnected(); return; case DEVICE_DISCONNECTED: context.resetToDisconnected(); return; case DEVICE_FAILED: context.resetToFailed(); return; } // Must be unhandled to be here so rely on internal handler // provided by implementation internalTransition(client, context, event); }