if (isOpen()) { if (logger.isDebugEnabled()) { logger.debug("Closing SockJS session " + getId() + " with " + status); if (isActive() && !CloseStatus.SESSION_NOT_RELIABLE.equals(status)) { try { writeFrameInternal(SockJsFrame.closeFrame(status.getCode(), status.getReason())); updateLastActiveTime(); cancelHeartbeat(); disconnect(status);
/** * For internal use within a TransportHandler and the (TransportHandler-specific) * session class. */ protected void writeFrame(SockJsFrame frame) throws SockJsTransportFailureException { if (logger.isTraceEnabled()) { logger.trace("Preparing to write " + frame); } try { writeFrameInternal(frame); } catch (Throwable ex) { logWriteFrameFailure(ex); try { // Force disconnect (so we won't try to send close frame) disconnect(CloseStatus.SERVER_ERROR); } catch (Throwable disconnectFailure) { // Ignore } try { close(CloseStatus.SERVER_ERROR); } catch (Throwable closeFailure) { // Nothing of consequence, already forced disconnect } throw new SockJsTransportFailureException("Failed to write " + frame, getId(), ex); } }
@Override public void run() { synchronized (responseLock) { if (!this.expired && !isClosed()) { try { sendHeartbeat(); } catch (Throwable ex) { // Ignore: already handled in writeFrame... } finally { this.expired = true; } } } }
public final void sendMessage(WebSocketMessage<?> message) throws IOException { Assert.state(!isClosed(), "Cannot send a message when session is closed"); Assert.isInstanceOf(TextMessage.class, message, "SockJS supports text messages only"); sendMessageInternal(((TextMessage) message).getPayload()); }
protected void scheduleHeartbeat() { if (this.heartbeatDisabled) { return; } synchronized (this.responseLock) { cancelHeartbeat(); if (!isActive()) { return; } Date time = new Date(System.currentTimeMillis() + this.config.getHeartbeatTime()); this.heartbeatTask = new HeartbeatTask(); this.heartbeatFuture = this.config.getTaskScheduler().schedule(this.heartbeatTask, time); if (logger.isTraceEnabled()) { logger.trace("Scheduled heartbeat in session " + getId()); } } }
/** * Invoked when the underlying connection is closed. */ public final void delegateConnectionClosed(CloseStatus status) throws Exception { if (!isClosed()) { try { updateLastActiveTime(); // Avoid cancelHeartbeat() and responseLock within server "close" callback ScheduledFuture<?> future = this.heartbeatFuture; if (future != null) { this.heartbeatFuture = null; future.cancel(false); } } finally { this.state = State.CLOSED; this.handler.afterConnectionClosed(this, status); } } }
/** * Close due to error arising from SockJS transport handling. */ public void tryCloseWithSockJsTransportError(Throwable error, CloseStatus closeStatus) { if (logger.isDebugEnabled()) { logger.debug("Closing due to transport error for " + this); } try { delegateError(error); } catch (Throwable delegateException) { // Ignore logger.debug("Exception from error handling delegate", delegateException); } try { close(closeStatus); } catch (Throwable closeException) { logger.debug("Failure while closing " + this, closeException); } }
@Override public void disableHeartbeat() { this.heartbeatDisabled = true; cancelHeartbeat(); }
@Override public String toString() { return getClass().getSimpleName() + "[id=" + getId() + "]"; }
public void delegateMessages(String... messages) throws SockJsMessageDeliveryException { List<String> undelivered = new ArrayList<>(Arrays.asList(messages)); for (String message : messages) { try { if (isClosed()) { throw new SockJsMessageDeliveryException(this.id, undelivered, "Session closed"); } else { this.handler.handleMessage(this, new TextMessage(message)); undelivered.remove(0); } } catch (Throwable ex) { throw new SockJsMessageDeliveryException(this.id, undelivered, ex); } } }
@Override protected void updateLastActiveTime() { this.numberOfLastActiveTimeUpdates++; super.updateLastActiveTime(); }
/** * Performs cleanup and notify the {@link WebSocketHandler}. */ @Override public final void close() throws IOException { close(new CloseStatus(3000, "Go away!")); }
private void logWriteFrameFailure(Throwable ex) { if (indicatesDisconnectedClient(ex)) { if (disconnectedClientLogger.isTraceEnabled()) { disconnectedClientLogger.trace("Looks like the client has gone away", ex); } else if (disconnectedClientLogger.isDebugEnabled()) { disconnectedClientLogger.debug("Looks like the client has gone away: " + ex + " (For a full stack trace, set the log category '" + DISCONNECTED_CLIENT_LOG_CATEGORY + "' to TRACE level.)"); } } else { logger.debug("Terminating connection after failure to send message to client", ex); } }
protected void scheduleHeartbeat() { if (this.heartbeatDisabled) { return; } synchronized (this.responseLock) { cancelHeartbeat(); if (!isActive()) { return; } Date time = new Date(System.currentTimeMillis() + this.config.getHeartbeatTime()); this.heartbeatTask = new HeartbeatTask(); this.heartbeatFuture = this.config.getTaskScheduler().schedule(this.heartbeatTask, time); if (logger.isTraceEnabled()) { logger.trace("Scheduled heartbeat in session " + getId()); } } }
/** * Invoked when the underlying connection is closed. */ public final void delegateConnectionClosed(CloseStatus status) throws Exception { if (!isClosed()) { try { updateLastActiveTime(); // Avoid cancelHeartbeat() and responseLock within server "close" callback ScheduledFuture<?> future = this.heartbeatFuture; if (future != null) { this.heartbeatFuture = null; future.cancel(false); } } finally { this.state = State.CLOSED; this.handler.afterConnectionClosed(this, status); } } }
public final void sendMessage(WebSocketMessage<?> message) throws IOException { Assert.state(!isClosed(), "Cannot send a message when session is closed"); Assert.isInstanceOf(TextMessage.class, message, "SockJS supports text messages only"); sendMessageInternal(((TextMessage) message).getPayload()); }
@Override public void run() { synchronized (responseLock) { if (!this.expired && !isClosed()) { try { sendHeartbeat(); } catch (Throwable ex) { // Ignore: already handled in writeFrame... } finally { this.expired = true; } } } }