/** * The simple broker produces {@code SimpMessageType.CONNECT_ACK} that's not STOMP * specific and needs to be turned into a STOMP CONNECTED frame. */ private StompHeaderAccessor convertConnectAcktoStompConnected(StompHeaderAccessor connectAckHeaders) { String name = StompHeaderAccessor.CONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) connectAckHeaders.getHeader(name); if (message == null) { throw new IllegalStateException("Original STOMP CONNECT not found in " + connectAckHeaders); } StompHeaderAccessor connectHeaders = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); StompHeaderAccessor connectedHeaders = StompHeaderAccessor.create(StompCommand.CONNECTED); if (connectHeaders != null) { Set<String> acceptVersions = connectHeaders.getAcceptVersion(); connectedHeaders.setVersion( Arrays.stream(SUPPORTED_VERSIONS) .filter(acceptVersions::contains) .findAny() .orElseThrow(() -> new IllegalArgumentException( "Unsupported STOMP version '" + acceptVersions + "'"))); } long[] heartbeat = (long[]) connectAckHeaders.getHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER); if (heartbeat != null) { connectedHeaders.setHeartbeat(heartbeat[0], heartbeat[1]); } else { connectedHeaders.setHeartbeat(0, 0); } return connectedHeaders; }
@Override protected void startInternal() { if (this.tcpClient == null) { this.tcpClient = initTcpClient(); } if (logger.isInfoEnabled()) { logger.info("Starting \"system\" session, " + toString()); } StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setAcceptVersion("1.1,1.2"); accessor.setLogin(this.systemLogin); accessor.setPasscode(this.systemPasscode); accessor.setHeartbeat(this.systemHeartbeatSendInterval, this.systemHeartbeatReceiveInterval); String virtualHost = getVirtualHost(); if (virtualHost != null) { accessor.setHost(virtualHost); } accessor.setSessionId(SYSTEM_SESSION_ID); if (logger.isDebugEnabled()) { logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD)); } SystemStompConnectionHandler handler = new SystemStompConnectionHandler(accessor); this.connectionHandlers.put(handler.getSessionId(), handler); this.stats.incrementConnectCount(); this.tcpClient.connect(handler, new FixedIntervalReconnectStrategy(5000)); }
@Test public void handleMessageToClientWithHeartbeatSuppressingSockJsHeartbeat() throws IOException { SockJsSession sockJsSession = Mockito.mock(SockJsSession.class); when(sockJsSession.getId()).thenReturn("s1"); StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECTED); accessor.setHeartbeat(0, 10); Message<byte[]> message = MessageBuilder.createMessage(EMPTY_PAYLOAD, accessor.getMessageHeaders()); this.protocolHandler.handleMessageToClient(sockJsSession, message); verify(sockJsSession).getId(); verify(sockJsSession).getPrincipal(); verify(sockJsSession).disableHeartbeat(); verify(sockJsSession).sendMessage(any(WebSocketMessage.class)); verifyNoMoreInteractions(sockJsSession); sockJsSession = Mockito.mock(SockJsSession.class); when(sockJsSession.getId()).thenReturn("s1"); accessor = StompHeaderAccessor.create(StompCommand.CONNECTED); accessor.setHeartbeat(0, 0); message = MessageBuilder.createMessage(EMPTY_PAYLOAD, accessor.getMessageHeaders()); this.protocolHandler.handleMessageToClient(sockJsSession, message); verify(sockJsSession).getId(); verify(sockJsSession).getPrincipal(); verify(sockJsSession).sendMessage(any(WebSocketMessage.class)); verifyNoMoreInteractions(sockJsSession); }
@Test public void heartbeatValues() { this.session.afterConnected(this.connection); assertTrue(this.session.isConnected()); this.connectHeaders.setHeartbeat(new long[] {10000, 10000}); StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECTED); accessor.setVersion("1.2"); accessor.setHeartbeat(20000, 20000); accessor.setLeaveMutable(true); this.session.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders())); ArgumentCaptor<Long> writeInterval = ArgumentCaptor.forClass(Long.class); verify(this.connection).onWriteInactivity(any(Runnable.class), writeInterval.capture()); assertEquals(20000, (long) writeInterval.getValue()); ArgumentCaptor<Long> readInterval = ArgumentCaptor.forClass(Long.class); verify(this.connection).onReadInactivity(any(Runnable.class), readInterval.capture()); assertEquals(60000, (long) readInterval.getValue()); }
@Test public void heartbeatTasks() { this.session.afterConnected(this.connection); verify(this.connection).send(any()); this.connectHeaders.setHeartbeat(new long[] {10000, 10000}); StompHeaderAccessor connected = StompHeaderAccessor.create(StompCommand.CONNECTED); connected.setVersion("1.2"); connected.setHeartbeat(10000, 10000); connected.setLeaveMutable(true); this.session.handleMessage(MessageBuilder.createMessage(new byte[0], connected.getMessageHeaders())); ArgumentCaptor<Runnable> writeTaskCaptor = ArgumentCaptor.forClass(Runnable.class); ArgumentCaptor<Runnable> readTaskCaptor = ArgumentCaptor.forClass(Runnable.class); verify(this.connection).onWriteInactivity(writeTaskCaptor.capture(), any(Long.class)); verify(this.connection).onReadInactivity(readTaskCaptor.capture(), any(Long.class)); Runnable writeTask = writeTaskCaptor.getValue(); Runnable readTask = readTaskCaptor.getValue(); assertNotNull(writeTask); assertNotNull(readTask); writeTask.run(); StompHeaderAccessor accessor = StompHeaderAccessor.createForHeartbeat(); Message<byte[]> message = MessageBuilder.createMessage(new byte[] {'\n'}, accessor.getMessageHeaders()); verify(this.connection).send(eq(message)); verifyNoMoreInteractions(this.connection); reset(this.sessionHandler); readTask.run(); verify(this.sessionHandler).handleTransportError(same(this.session), any(IllegalStateException.class)); verifyNoMoreInteractions(this.sessionHandler); }
@Test public void heartbeatNotSupportedByServer() { this.session.afterConnected(this.connection); verify(this.connection).send(any()); this.connectHeaders.setHeartbeat(new long[] {10000, 10000}); StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECTED); accessor.setVersion("1.2"); accessor.setHeartbeat(0, 0); accessor.setLeaveMutable(true); this.session.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders())); verifyNoMoreInteractions(this.connection); }
public static MessageExchangeBuilder connect(String sessionId) { StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT); headers.setSessionId(sessionId); headers.setAcceptVersion("1.1,1.2"); headers.setHeartbeat(0, 0); Message<?> message = MessageBuilder.createMessage(new byte[0], headers.getMessageHeaders()); MessageExchangeBuilder builder = new MessageExchangeBuilder(message); builder.expected.add(new StompConnectedFrameMessageMatcher(sessionId)); return builder; }
@Test public void handleConnectedFrame() { this.session.afterConnected(this.connection); assertTrue(this.session.isConnected()); this.connectHeaders.setHeartbeat(new long[] {10000, 10000}); StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECTED); accessor.setVersion("1.2"); accessor.setHeartbeat(10000, 10000); accessor.setLeaveMutable(true); this.session.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders())); StompHeaders stompHeaders = StompHeaders.readOnlyStompHeaders(accessor.getNativeHeaders()); verify(this.sessionHandler).afterConnected(this.session, stompHeaders); verifyNoMoreInteractions(this.sessionHandler); }
@Test public void handleMessageToClientWithSimpConnectAckDefaultHeartBeat() { StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setHeartbeat(10000, 10000); accessor.setAcceptVersion("1.0"); Message<?> connectMessage = MessageBuilder.createMessage(EMPTY_PAYLOAD, accessor.getMessageHeaders()); SimpMessageHeaderAccessor ackAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT_ACK); ackAccessor.setHeader(SimpMessageHeaderAccessor.CONNECT_MESSAGE_HEADER, connectMessage); Message<byte[]> ackMessage = MessageBuilder.createMessage(EMPTY_PAYLOAD, ackAccessor.getMessageHeaders()); this.protocolHandler.handleMessageToClient(this.session, ackMessage); assertEquals(1, this.session.getSentMessages().size()); TextMessage actual = (TextMessage) this.session.getSentMessages().get(0); assertEquals("CONNECTED\n" + "version:1.0\n" + "heart-beat:0,0\n" + "user-name:joe\n" + "\n" + "\u0000", actual.getPayload()); }
@Test public void handleMessageToClientWithSimpConnectAck() { StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setHeartbeat(10000, 10000); accessor.setAcceptVersion("1.0,1.1,1.2"); Message<?> connectMessage = MessageBuilder.createMessage(EMPTY_PAYLOAD, accessor.getMessageHeaders()); SimpMessageHeaderAccessor ackAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT_ACK); ackAccessor.setHeader(SimpMessageHeaderAccessor.CONNECT_MESSAGE_HEADER, connectMessage); ackAccessor.setHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER, new long[] {15000, 15000}); Message<byte[]> ackMessage = MessageBuilder.createMessage(EMPTY_PAYLOAD, ackAccessor.getMessageHeaders()); this.protocolHandler.handleMessageToClient(this.session, ackMessage); assertEquals(1, this.session.getSentMessages().size()); TextMessage actual = (TextMessage) this.session.getSentMessages().get(0); assertEquals("CONNECTED\n" + "version:1.2\n" + "heart-beat:15000,15000\n" + "user-name:joe\n" + "\n" + "\u0000", actual.getPayload()); }
@Override protected void startInternal() { if (this.tcpClient == null) { this.tcpClient = initTcpClient(); } if (logger.isInfoEnabled()) { logger.info("Starting \"system\" session, " + toString()); } StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setAcceptVersion("1.1,1.2"); accessor.setLogin(this.systemLogin); accessor.setPasscode(this.systemPasscode); accessor.setHeartbeat(this.systemHeartbeatSendInterval, this.systemHeartbeatReceiveInterval); String virtualHost = getVirtualHost(); if (virtualHost != null) { accessor.setHost(virtualHost); } accessor.setSessionId(SYSTEM_SESSION_ID); if (logger.isDebugEnabled()) { logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD)); } SystemStompConnectionHandler handler = new SystemStompConnectionHandler(accessor); this.connectionHandlers.put(handler.getSessionId(), handler); this.stats.incrementConnectCount(); this.tcpClient.connect(handler, new FixedIntervalReconnectStrategy(5000)); }
/** * The simple broker produces {@code SimpMessageType.CONNECT_ACK} that's not STOMP * specific and needs to be turned into a STOMP CONNECTED frame. */ private StompHeaderAccessor convertConnectAcktoStompConnected(StompHeaderAccessor connectAckHeaders) { String name = StompHeaderAccessor.CONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) connectAckHeaders.getHeader(name); if (message == null) { throw new IllegalStateException("Original STOMP CONNECT not found in " + connectAckHeaders); } StompHeaderAccessor connectHeaders = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); StompHeaderAccessor connectedHeaders = StompHeaderAccessor.create(StompCommand.CONNECTED); if (connectHeaders != null) { Set<String> acceptVersions = connectHeaders.getAcceptVersion(); connectedHeaders.setVersion( Arrays.stream(SUPPORTED_VERSIONS) .filter(acceptVersions::contains) .findAny() .orElseThrow(() -> new IllegalArgumentException( "Unsupported STOMP version '" + acceptVersions + "'"))); } long[] heartbeat = (long[]) connectAckHeaders.getHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER); if (heartbeat != null) { connectedHeaders.setHeartbeat(heartbeat[0], heartbeat[1]); } else { connectedHeaders.setHeartbeat(0, 0); } return connectedHeaders; }
connectedHeaders.setHeartbeat(heartbeat[0], heartbeat[1]); connectedHeaders.setHeartbeat(0, 0);
@Override protected void startInternal() { if (this.tcpClient == null) { this.tcpClient = initTcpClient(); } if (logger.isInfoEnabled()) { logger.info("Starting \"system\" session, " + toString()); } StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setAcceptVersion("1.1,1.2"); accessor.setLogin(this.systemLogin); accessor.setPasscode(this.systemPasscode); accessor.setHeartbeat(this.systemHeartbeatSendInterval, this.systemHeartbeatReceiveInterval); String virtualHost = getVirtualHost(); if (virtualHost != null) { accessor.setHost(virtualHost); } accessor.setSessionId(SYSTEM_SESSION_ID); if (logger.isDebugEnabled()) { logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD)); } SystemStompConnectionHandler handler = new SystemStompConnectionHandler(accessor); this.connectionHandlers.put(handler.getSessionId(), handler); this.stats.incrementConnectCount(); this.tcpClient.connect(handler, new FixedIntervalReconnectStrategy(5000)); }
@Override protected void startInternal() { if (this.tcpClient == null) { this.tcpClient = initTcpClient(); } if (logger.isInfoEnabled()) { logger.info("Starting \"system\" session, " + toString()); } StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECT); accessor.setAcceptVersion("1.1,1.2"); accessor.setLogin(this.systemLogin); accessor.setPasscode(this.systemPasscode); accessor.setHeartbeat(this.systemHeartbeatSendInterval, this.systemHeartbeatReceiveInterval); String virtualHost = getVirtualHost(); if (virtualHost != null) { accessor.setHost(virtualHost); } accessor.setSessionId(SYSTEM_SESSION_ID); if (logger.isDebugEnabled()) { logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD)); } SystemStompConnectionHandler handler = new SystemStompConnectionHandler(accessor); this.connectionHandlers.put(handler.getSessionId(), handler); this.stats.incrementConnectCount(); this.tcpClient.connect(handler, new FixedIntervalReconnectStrategy(5000)); }