public void closeEndpoints(int waitMillis) throws Exception { final Collection<E> endpoints = new HashSet<>(this.endpoints); for (E endpoint : endpoints) { endpoint.close(); } for (E endpoint : endpoints) { endpoint.awaitClose(waitMillis); } } }
@Override public String toString() { return XEndpoint.defaultToString(this); } }
/** * Asynchronously sends a text frame. * * @param payload The payload. */ default void send(String payload) { send(payload, null); }
@Override public void run() { while (running) { try { final long now = System.currentTimeMillis(); for (E endpoint : endpoints) { if (! endpoint.isOpen()) { log.debug("Terminating defunct endpoint {}", endpoint); endpoint.terminate(); } else if (pingIntervalMillis != 0) { final long lastActivity = endpoint.getLastActivityTime(); if (now - lastActivity > pingIntervalMillis) { log.trace("Pinging {}", endpoint); endpoint.sendPing(); } } } } catch (Exception e) { log.error("Unexpected error", e); } try { Thread.sleep(scanIntervalMillis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); continue; } } }
/** * The default {@code toString()} implementation. * * @param endpoint The endpoint. * @return The default {@code toString()}} representation. */ static String defaultToString(XEndpoint endpoint) { return endpoint.getClass().getSimpleName() + " [remote=" + endpoint.getRemoteAddress() + ", lastActivity=" + endpoint.getLastActivityZoned() + "]"; } }
/** * Obtains the last activity time as a {@link ZonedDateTime}. * * @return The last activity time. */ default ZonedDateTime getLastActivityZoned() { return ZonedDateTime.ofInstant(Instant.ofEpochMilli(getLastActivityTime()), ZoneOffset.systemDefault()); }
/** * Awaits the closure of the underlying channel, which implies that the close frame handshake * would have been performed. * * @param waitMillis The number of milliseconds to wait. * @return True if the endpoint was closed. * @throws InterruptedException If the thread was interrupted. */ default boolean awaitClose(int waitMillis) throws InterruptedException { return Await.bounded(waitMillis, () -> ! isOpen()); }
/** * Asynchronously sends a binary frame. * * @param payload The payload. */ default void send(ByteBuffer payload) { send(payload, null); }