@Override public void onClose(final TyrusSession session, final CloseReason closeReason) { if (maxSessionsPerApp != null) { synchronized (counterLock) { counter.decrementAndGet(); } } if (maxSessionsPerRemoteAddr != null) { synchronized (remoteAddressCounters) { int remoteAddressCounter = remoteAddressCounters.get(session.getRemoteAddr()).decrementAndGet(); if (remoteAddressCounter == 0) { remoteAddressCounters.remove(session.getRemoteAddr()); } } } } };
/** * Set an interval in milliseconds between scheduled periodic Pong messages. * Setting the interval to a negative value or 0 will cancel sending of periodic Pong messages. * * @param heartbeatInterval interval between periodic Pong messages in milliseconds. */ public void setHeartbeatInterval(long heartbeatInterval) { checkConnectionState(State.CLOSED); this.heartbeatInterval = heartbeatInterval; cancelHeartBeatTask(); if (heartbeatInterval < 1) { return; } heartbeatTask = service.scheduleAtFixedRate(new HeartbeatCommand(), heartbeatInterval, heartbeatInterval, TimeUnit.MILLISECONDS); }
@Override public void close(CloseReason closeReason) throws IOException { cleanAfterClose(); checkConnectionState(State.CLOSED); changeStateToClosed(); basicRemote.close(closeReason); }
@Override public void setMaxIdleTimeout(long maxIdleTimeout) { checkConnectionState(State.CLOSED); this.maxIdleTimeout = maxIdleTimeout; restartIdleTimeoutExecutor(); if (distributedPropertyMap != null) { distributedPropertyMap.put(RemoteSession.DistributedMapKey.MAX_IDLE_TIMEOUT, maxIdleTimeout); } }
@Override public void run() { TyrusSession session = TyrusSession.this; if (session.isOpen() && session.getHeartbeatInterval() > 0) { try { session.getBasicRemote().sendPong(null); } catch (IOException e) { LOGGER.log(Level.FINE, "Pong could not have been sent " + e.getMessage()); } } else { cancelHeartBeatTask(); } } }
session.getDebugContext() .appendLogMessage(LOGGER, Level.FINEST, DebugContext.Type.MESSAGE_IN, "Received partial binary message"); session.restartIdleTimeoutExecutor(); final TyrusSession.State state = session.getState(); if (session.isPartialBinaryHandlerPresent()) { session.notifyMessageHandlers(partialBytes, last); if (state == TyrusSession.State.RECEIVING_BINARY || state == TyrusSession.State.RECEIVING_TEXT) { session.setState(TyrusSession.State.RUNNING); } else if (session.isInputStreamHandlerPresent()) { InputStreamBuffer buffer = session.getInputStreamBuffer(); switch (state) { case RUNNING: session.setInputStreamBuffer(buffer); buffer.resetBuffer(session.getMaxBinaryMessageBufferSize()); buffer.setMessageHandler((session.getMessageHandler(InputStream.class))); buffer.appendMessagePart(partialBytes, last); session.setState(TyrusSession.State.RECEIVING_BINARY); break; case RECEIVING_BINARY: buffer.appendMessagePart(partialBytes, last); if (last) { session.setState(TyrusSession.State.RUNNING); session.setState(TyrusSession.State.RUNNING);
@Override public void run() { TyrusSession session = TyrusSession.this; // condition is required because scheduled task can be (for some reason) run even when it is cancelled. if (session.getMaxIdleTimeout() > 0 && session.isOpen()) { try { session.close(new CloseReason(CloseReason.CloseCodes.CLOSED_ABNORMALLY, LocalizationMessages.SESSION_CLOSED_IDLE_TIMEOUT())); } catch (IOException e) { LOGGER.log(Level.FINE, "Session could not been closed. " + e.getMessage()); } } } }
void notifyMessageHandlers(Object message, boolean last) { boolean handled = false; for (MessageHandler handler : getMessageHandlers()) { if ((handler instanceof MessageHandler.Partial) && MessageHandlerManager.getHandlerType(handler).isAssignableFrom(message.getClass())) { if (handler instanceof AsyncMessageHandler) { checkMessageSize(message, ((AsyncMessageHandler) handler).getMaxMessageSize()); } final State currentState = state.get(); if (currentState != State.CLOSED) { //noinspection unchecked ((MessageHandler.Partial) handler).onMessage(message, last); } handled = true; break; } } if (!handled) { if (message instanceof ByteBuffer) { notifyMessageHandlers(((ByteBuffer) message).array(), last); } else { LOGGER.warning(LocalizationMessages.UNHANDLED_TEXT_MESSAGE(this)); } } }
/** * Called by the provider when the web socket connection * has an incoming ping message from the given remote endpoint. * <p> * The endpoint needs to respond as soon as possible (see the websocket RFC). * No involvement from application layer, there is no ping listener. * * @param socket {@link TyrusWebSocket} who sent the message. * @param bytes the message. */ void onPing(TyrusWebSocket socket, ByteBuffer bytes) { TyrusSession session = getSession(socket); if (session == null) { LOGGER.log(Level.FINE, "Ping received on already closed connection."); return; } session.getDebugContext() .appendLogMessage(LOGGER, Level.FINEST, DebugContext.Type.MESSAGE_IN, "Received ping message"); session.restartIdleTimeoutExecutor(); try { session.getBasicRemote().sendPong(bytes); } catch (IOException e) { // do nothing. // we might consider calling onError, but there should be better defined exception. } }
session = new TyrusSession(container, socket, this, subProtocol, extensions, upgradeRequest.isSecure(), getURI(upgradeRequest.getRequestURI().toString(), upgradeRequest.getQueryString()), session.close(new CloseReason(CloseReason.CloseCodes.TRY_AGAIN_LATER, refuseDetail)); } catch (IOException e) { debugContext.appendLogMessageWithThrowable(LOGGER, Level.WARNING, DebugContext.Type.MESSAGE_IN, e, socket.setMessageEventListener(endpointEventListener.onSessionOpened(session.getId())); sessionListener.onClose(session, CloseReasons.UNEXPECTED_CONDITION.getCloseReason()); try { session.close(CloseReasons.UNEXPECTED_CONDITION.getCloseReason()); } catch (IOException e) { debugContext.appendLogMessageWithThrowable(LOGGER, Level.FINEST, DebugContext.Type.MESSAGE_IN, e, endpointEventListener.onError(session.getId(), t);
@Override public javax.websocket.RemoteEndpoint.Basic getBasicRemote() { checkConnectionState(State.CLOSED); return basicRemote; }
@Override public void close() throws IOException { cleanAfterClose(); changeStateToClosed(); basicRemote.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, null)); }
/** * Set the state of the {@link Session}. * * @param state the newly set state. */ void setState(State state) { if (!state.equals(this.state.get())) { checkConnectionState(State.CLOSED); this.state.set(state); if (state.equals(State.CLOSED)) { cleanAfterClose(); } } }
private void cleanAfterClose() { if (readerBuffer != null) { readerBuffer.onSessionClosed(); } if (inputStreamBuffer != null) { inputStreamBuffer.onSessionClosed(); } cancelHeartBeatTask(); }
/** * Creates a Session based on the {@link TyrusWebSocket}, subprotocols and extensions. * * @param socket the other end of the connection. * @param subprotocol used. * @param extensions extensions used. * @param debugContext debug context. * @return {@link Session} representing the connection. */ public Session createSessionForRemoteEndpoint(TyrusWebSocket socket, String subprotocol, List<Extension> extensions, DebugContext debugContext) { final TyrusSession session = new TyrusSession(container, socket, this, subprotocol, extensions, false, getURI(contextPath, null), null, Collections.<String, String>emptyMap(), null, Collections.<String, List<String>>emptyMap(), null, null, null, debugContext); webSocketToSession.put(socket, session); return session; }
checkMessageSize(message, ((BasicMessageHandler) mh).getMaxMessageSize());
session.getDebugContext() .appendLogMessage(LOGGER, Level.FINEST, DebugContext.Type.MESSAGE_IN, "Received partial binary message"); session.restartIdleTimeoutExecutor(); final TyrusSession.State state = session.getState(); if (session.isPartialBinaryHandlerPresent()) { session.notifyMessageHandlers(partialBytes, last); if (state == TyrusSession.State.RECEIVING_BINARY || state == TyrusSession.State.RECEIVING_TEXT) { session.setState(TyrusSession.State.RUNNING); } else if (session.isInputStreamHandlerPresent()) { InputStreamBuffer buffer = session.getInputStreamBuffer(); switch (state) { case RUNNING: session.setInputStreamBuffer(buffer); buffer.resetBuffer(session.getMaxBinaryMessageBufferSize()); buffer.setMessageHandler((session.getMessageHandler(InputStream.class))); buffer.appendMessagePart(partialBytes, last); session.setState(TyrusSession.State.RECEIVING_BINARY); break; case RECEIVING_BINARY: buffer.appendMessagePart(partialBytes, last); if (last) { session.setState(TyrusSession.State.RUNNING); session.setState(TyrusSession.State.RUNNING);
@Override public void run() { TyrusSession session = TyrusSession.this; // condition is required because scheduled task can be (for some reason) run even when it is cancelled. if (session.getMaxIdleTimeout() > 0 && session.isOpen()) { try { session.close(new CloseReason(CloseReason.CloseCodes.CLOSED_ABNORMALLY, LocalizationMessages.SESSION_CLOSED_IDLE_TIMEOUT())); } catch (IOException e) { LOGGER.log(Level.FINE, "Session could not been closed. " + e.getMessage()); } } } }
@Override public void run() { TyrusSession session = TyrusSession.this; if (session.isOpen() && session.getHeartbeatInterval() > 0) { try { session.getBasicRemote().sendPong(null); } catch (IOException e) { LOGGER.log(Level.FINE, "Pong could not have been sent " + e.getMessage()); } } else { cancelHeartBeatTask(); } } }
void notifyMessageHandlers(Object message, boolean last) { boolean handled = false; for (MessageHandler handler : getMessageHandlers()) { if ((handler instanceof MessageHandler.Partial) && MessageHandlerManager.getHandlerType(handler).isAssignableFrom(message.getClass())) { if (handler instanceof AsyncMessageHandler) { checkMessageSize(message, ((AsyncMessageHandler) handler).getMaxMessageSize()); } final State currentState = state.get(); if (currentState != State.CLOSED) { //noinspection unchecked ((MessageHandler.Partial) handler).onMessage(message, last); } handled = true; break; } } if (!handled) { if (message instanceof ByteBuffer) { notifyMessageHandlers(((ByteBuffer) message).array(), last); } else { LOGGER.warning(LocalizationMessages.UNHANDLED_TEXT_MESSAGE(this)); } } }