@Override public void hidFailure(HidServicesEvent event) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_FAILED, name()); } }
/** * @param client The hardware wallet client */ public HardwareWalletContext(HardwareWalletClient client) { this.client = client; // Ensure the service is subscribed to low level message events from the client MessageEvents.subscribe(this); // Verify the environment if (!client.attach()) { log.warn("Cannot start the service due to a failed environment."); throw new IllegalStateException("Cannot start the service due to a failed environment."); } }
/** * <p>Unsubscribe all subscribers from events</p> * <p>This approach ensures all subscribers will be correctly removed during a shutdown</p> */ @SuppressWarnings("unchecked") public static void unsubscribeAll() { Set allSubscribers = Sets.newHashSet(); allSubscribers.addAll(messageEventBusSubscribers); for (Object subscriber : allSubscribers) { unsubscribe(subscriber); } allSubscribers.clear(); log.info("All subscribers removed"); }
/** * <p>Stop the service</p> */ public void stopAndWait() { log.debug("Service {} stopping...", this.getClass().getSimpleName()); context.resetToStopped(); // Ensure downstream subscribers are purged HardwareWalletEvents.unsubscribeAll(); MessageEvents.unsubscribeAll(); try { clientMonitorService.awaitTermination(1, TimeUnit.SECONDS); } catch (InterruptedException e) { log.warn("Client monitor thread did not terminate within the allowed time"); } stopped = true; }
@Override public boolean connect() { if (socket != null) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_CONNECTED, name()); return true; } else { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DISCONNECTED, name()); return false; } }
/** * <p>Reset the context into a stopped state (the service will have to be stopped and a new one started)</p> */ public void resetToStopped() { log.debug("Reset to 'stopped'"); // Clear relevant information resetAllButFeatures(); // Issue a hard detach - we are done client.hardDetach(); // Unsubscribe from events MessageEvents.unsubscribe(this); // Perform the state change currentState = HardwareWalletStates.newStoppedState(); // Fire the high level event HardwareWalletEvents.fireHardwareWalletEvent(HardwareWalletEventType.SHOW_DEVICE_STOPPED, client.name()); }
@Override public boolean connect() { if (socket != null) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_CONNECTED, name()); return true; } else { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DISCONNECTED, name()); return false; } }
@Override public void hidFailure(HidServicesEvent event) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_FAILED, name()); }
@Override public void run() { while (true) { try { // Blocking read to get the client message (e.g. "Initialize") formatted as HID packets for simplicity log.debug("Waiting for server message..."); MessageEvent messageFromServer = KeepKeyMessageUtils.parseAsHIDPackets(inputFromServer); MessageEvents.fireMessageEvent(messageFromServer); } catch (HardwareWalletException | IOException e) { log.error("Failed to read back from server", e); break; } } }
@Override public void run() { while (true) { try { // Blocking read to get the client message (e.g. "Initialize") formatted as HID packets for simplicity log.debug("Waiting for server message..."); MessageEvent messageFromServer = TrezorMessageUtils.parseAsHIDPackets(inputFromServer); MessageEvents.fireMessageEvent(messageFromServer); } catch (HardwareWalletException | IOException e) { log.error("Failed to read back from server", e); break; } } }
@Override public void softDetach() { if (socket == null) { return; } // Attempt to close the socket (also closes the in/out streams) try { socket.close(); log.info("Detached from Trezor"); // Must have disconnected to be here MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DETACHED, name()); } catch (IOException e) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_FAILED, name()); } }
@Override public void hardDetach() { if (socket == null) { return; } // Attempt to close the socket (also closes the in/out streams) try { socket.close(); log.info("Hard detach from Trezor"); // Must have detached to be here MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DETACHED, name()); } catch (IOException e) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_FAILED, name()); } }
@Override protected int writeToDevice(byte[] buffer) { Preconditions.checkNotNull(buffer, "'buffer' must be present"); Preconditions.checkNotNull(out, "Socket has not been connected. Use connect() first."); try { // Apply the message to the data output stream out.write(buffer); return buffer.length; } catch (IOException e) { log.warn("I/O error during write. Closing socket.", e); // Must have disconnected to be here MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DETACHED, name()); } // Must have failed to be here return -1; }
@Override public synchronized void softDetach() { // Attempt to close the connection (also closes the in/out streams) if (locatedDevice.isPresent()) { locatedDevice.get().close(); } log.info("Disconnected from Trezor"); // Let everyone know MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DETACHED, name()); }
@Override public synchronized boolean connect() { Preconditions.checkState(socket == null, "Socket is already connected"); try { // Attempt to open a socket to the host/port socket = new Socket(host, port); // Add buffered data streams for easy data manipulation out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 1024)); in = new DataInputStream(new BufferedInputStream(socket.getInputStream(), 1024)); // Monitor the input stream //monitorDataInputStream(in); // Must have connected to be here MessageEvents.fireMessageEvent(MessageEventType.DEVICE_CONNECTED, name()); return true; } catch (IOException e) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_FAILED, name()); } // Must have failed to be here return false; }
@Override public boolean connect() { log.debug("Attempting to connect..."); isKeepKeyValid = keepKey.connect(); if (isKeepKeyValid) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_CONNECTED, name()); } return isKeepKeyValid; }
@Override public void hardDetach() { log.debug("Hard detach"); log.debug("Reset endpoints"); if (locatedDevice.isPresent()) { locatedDevice.get().close(); } locatedDevice = Optional.absent(); log.debug("Exited HID API"); HidApi.exit(); log.info("Hard detach complete"); // Let everyone know MessageEvents.fireMessageEvent(MessageEventType.DEVICE_DETACHED_HARD, name()); }
@Override public boolean connect() { log.debug("Attempting to connect..."); isTrezorValid = trezor.connect(); if (isTrezorValid) { MessageEvents.fireMessageEvent(MessageEventType.DEVICE_CONNECTED, name()); } return isTrezorValid; }
@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 hidDeviceAttached(HidServicesEvent event) { HidDevice attachedDevice = event.getHidDevice(); int attachedVendorId = (int) attachedDevice.getVendorId(); int attachedProductId = (int) attachedDevice.getProductId(); // Check if it is a device we're interested in that was attached if (vendorId.get().equals(attachedVendorId) && productId.get().equals(attachedProductId)) { // Inform others of this event MessageEvents.fireMessageEvent(MessageEventType.DEVICE_ATTACHED, name()); } }