use of org.springframework.web.socket.BinaryMessage in project spring-framework by spring-projects.
the class StompSubProtocolHandler method handleMessageFromClient.
/**
* Handle incoming WebSocket messages from clients.
*/
@Override
public void handleMessageFromClient(WebSocketSession session, WebSocketMessage<?> webSocketMessage, MessageChannel outputChannel) {
List<Message<byte[]>> messages;
try {
ByteBuffer byteBuffer;
if (webSocketMessage instanceof TextMessage) {
byteBuffer = ByteBuffer.wrap(((TextMessage) webSocketMessage).asBytes());
} else if (webSocketMessage instanceof BinaryMessage) {
byteBuffer = ((BinaryMessage) webSocketMessage).getPayload();
} else {
return;
}
BufferingStompDecoder decoder = this.decoders.get(session.getId());
if (decoder == null) {
if (!session.isOpen()) {
logger.trace("Dropped inbound WebSocket message due to closed session");
return;
}
throw new IllegalStateException("No decoder for session id '" + session.getId() + "'");
}
messages = decoder.decode(byteBuffer);
if (messages.isEmpty()) {
if (logger.isTraceEnabled()) {
logger.trace("Incomplete STOMP frame content received in session " + session + ", bufferSize=" + decoder.getBufferSize() + ", bufferSizeLimit=" + decoder.getBufferSizeLimit() + ".");
}
return;
}
} catch (Throwable ex) {
if (logger.isErrorEnabled()) {
logger.error("Failed to parse " + webSocketMessage + " in session " + session.getId() + ". Sending STOMP ERROR to client.", ex);
}
handleError(session, ex, null);
return;
}
for (Message<byte[]> message : messages) {
StompHeaderAccessor headerAccessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
Assert.state(headerAccessor != null, "No StompHeaderAccessor");
StompCommand command = headerAccessor.getCommand();
boolean isConnect = StompCommand.CONNECT.equals(command) || StompCommand.STOMP.equals(command);
boolean sent = false;
try {
headerAccessor.setSessionId(session.getId());
headerAccessor.setSessionAttributes(session.getAttributes());
headerAccessor.setUser(getUser(session));
if (isConnect) {
headerAccessor.setUserChangeCallback(user -> {
if (user != null && user != session.getPrincipal()) {
this.stompAuthentications.put(session.getId(), user);
}
});
}
headerAccessor.setHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER, headerAccessor.getHeartbeat());
if (!detectImmutableMessageInterceptor(outputChannel)) {
headerAccessor.setImmutable();
}
if (logger.isTraceEnabled()) {
logger.trace("From client: " + headerAccessor.getShortLogMessage(message.getPayload()));
}
if (isConnect) {
this.stats.incrementConnectCount();
} else if (StompCommand.DISCONNECT.equals(command)) {
this.stats.incrementDisconnectCount();
}
try {
SimpAttributesContextHolder.setAttributesFromMessage(message);
sent = outputChannel.send(message);
if (sent) {
if (this.eventPublisher != null) {
Principal user = getUser(session);
if (isConnect) {
publishEvent(this.eventPublisher, new SessionConnectEvent(this, message, user));
} else if (StompCommand.SUBSCRIBE.equals(command)) {
publishEvent(this.eventPublisher, new SessionSubscribeEvent(this, message, user));
} else if (StompCommand.UNSUBSCRIBE.equals(command)) {
publishEvent(this.eventPublisher, new SessionUnsubscribeEvent(this, message, user));
}
}
}
} finally {
SimpAttributesContextHolder.resetAttributes();
}
} catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to send message to MessageChannel in session " + session.getId(), ex);
} else if (logger.isErrorEnabled()) {
// Skip unsent CONNECT messages (likely auth issues)
if (!isConnect || sent) {
logger.error("Failed to send message to MessageChannel in session " + session.getId() + ":" + ex.getMessage());
}
}
handleError(session, ex, message);
}
}
}
use of org.springframework.web.socket.BinaryMessage in project spring-framework by spring-projects.
the class StompSubProtocolHandler method sendToClient.
private void sendToClient(WebSocketSession session, StompHeaderAccessor stompAccessor, byte[] payload) {
StompCommand command = stompAccessor.getCommand();
try {
byte[] bytes = this.stompEncoder.encode(stompAccessor.getMessageHeaders(), payload);
boolean useBinary = (payload.length > 0 && !(session instanceof SockJsSession) && MimeTypeUtils.APPLICATION_OCTET_STREAM.isCompatibleWith(stompAccessor.getContentType()));
if (useBinary) {
session.sendMessage(new BinaryMessage(bytes));
} else {
session.sendMessage(new TextMessage(bytes));
}
} catch (SessionLimitExceededException ex) {
// Bad session, just get out
throw ex;
} catch (Throwable ex) {
// Could be part of normal workflow (e.g. browser tab closed)
if (logger.isDebugEnabled()) {
logger.debug("Failed to send WebSocket message to client in session " + session.getId(), ex);
}
command = StompCommand.ERROR;
} finally {
if (StompCommand.ERROR.equals(command)) {
try {
session.close(CloseStatus.PROTOCOL_ERROR);
} catch (IOException ex) {
// Ignore
}
}
}
}
use of org.springframework.web.socket.BinaryMessage in project spring-framework by spring-projects.
the class StompSubProtocolHandlerTests method handleMessageToClientWithBinaryWebSocketMessage.
// SPR-12475
@Test
public void handleMessageToClientWithBinaryWebSocketMessage() {
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.MESSAGE);
headers.setMessageId("mess0");
headers.setSubscriptionId("sub0");
headers.setContentType(MimeTypeUtils.APPLICATION_OCTET_STREAM);
headers.setDestination("/queue/foo");
// Non-empty payload
byte[] payload = new byte[1];
Message<byte[]> message = MessageBuilder.createMessage(payload, headers.getMessageHeaders());
this.protocolHandler.handleMessageToClient(this.session, message);
assertThat(this.session.getSentMessages().size()).isEqualTo(1);
WebSocketMessage<?> webSocketMessage = this.session.getSentMessages().get(0);
assertThat(webSocketMessage instanceof BinaryMessage).isTrue();
// Empty payload
payload = EMPTY_PAYLOAD;
message = MessageBuilder.createMessage(payload, headers.getMessageHeaders());
this.protocolHandler.handleMessageToClient(this.session, message);
assertThat(this.session.getSentMessages().size()).isEqualTo(2);
webSocketMessage = this.session.getSentMessages().get(1);
assertThat(webSocketMessage instanceof TextMessage).isTrue();
}
use of org.springframework.web.socket.BinaryMessage in project spring-framework by spring-projects.
the class WebSocketStompClientTests method sendWebSocketBinary.
@Test
public void sendWebSocketBinary() throws Exception {
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.SEND);
accessor.setDestination("/b");
accessor.setContentType(MimeTypeUtils.APPLICATION_OCTET_STREAM);
byte[] payload = "payload".getBytes(StandardCharsets.UTF_8);
getTcpConnection().send(MessageBuilder.createMessage(payload, accessor.getMessageHeaders()));
ArgumentCaptor<BinaryMessage> binaryMessageCaptor = ArgumentCaptor.forClass(BinaryMessage.class);
verify(this.webSocketSession).sendMessage(binaryMessageCaptor.capture());
BinaryMessage binaryMessage = binaryMessageCaptor.getValue();
assertThat(binaryMessage).isNotNull();
assertThat(new String(binaryMessage.getPayload().array(), StandardCharsets.UTF_8)).isEqualTo("SEND\ndestination:/b\ncontent-type:application/octet-stream\ncontent-length:7\n\npayload\0");
}
use of org.springframework.web.socket.BinaryMessage in project spring-framework by spring-projects.
the class WebSocketStompClientTests method handleWebSocketMessageBinary.
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void handleWebSocketMessageBinary() throws Exception {
String text = "SEND\na:alpha\n\nMessage payload\0";
connect().handleMessage(this.webSocketSession, new BinaryMessage(text.getBytes(StandardCharsets.UTF_8)));
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(this.stompSession).handleMessage(captor.capture());
Message<byte[]> message = captor.getValue();
assertThat(message).isNotNull();
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
StompHeaders headers = StompHeaders.readOnlyStompHeaders(accessor.toNativeHeaderMap());
assertThat(accessor.getCommand()).isEqualTo(StompCommand.SEND);
assertThat(headers.getFirst("a")).isEqualTo("alpha");
assertThat(new String(message.getPayload(), StandardCharsets.UTF_8)).isEqualTo("Message payload");
}
Aggregations