|
|
|
@ -16,13 +16,14 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.web.reactive.socket.adapter; |
|
|
|
package org.springframework.web.reactive.socket.adapter; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
|
|
|
import java.net.URISyntaxException; |
|
|
|
import java.net.URISyntaxException; |
|
|
|
import java.nio.ByteBuffer; |
|
|
|
import java.nio.ByteBuffer; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
|
|
|
|
|
|
|
import org.reactivestreams.Subscriber; |
|
|
|
import org.reactivestreams.Subscriber; |
|
|
|
import org.reactivestreams.Subscription; |
|
|
|
import org.reactivestreams.Subscription; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.core.io.buffer.DataBuffer; |
|
|
|
import org.springframework.core.io.buffer.DataBufferFactory; |
|
|
|
import org.springframework.core.io.buffer.DataBufferFactory; |
|
|
|
import org.springframework.core.io.buffer.DefaultDataBufferFactory; |
|
|
|
import org.springframework.core.io.buffer.DefaultDataBufferFactory; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
@ -50,78 +51,78 @@ public class UndertowWebSocketHandlerAdapter implements WebSocketConnectionCallb |
|
|
|
|
|
|
|
|
|
|
|
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory(false); |
|
|
|
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory(false); |
|
|
|
|
|
|
|
|
|
|
|
private final WebSocketHandler handler; |
|
|
|
private final WebSocketHandler delegate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private UndertowWebSocketSession session; |
|
|
|
|
|
|
|
|
|
|
|
private UndertowWebSocketSession wsSession; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public UndertowWebSocketHandlerAdapter(WebSocketHandler handler) { |
|
|
|
public UndertowWebSocketHandlerAdapter(WebSocketHandler delegate) { |
|
|
|
Assert.notNull("'handler' is required"); |
|
|
|
Assert.notNull("WebSocketHandler is required"); |
|
|
|
this.handler = handler; |
|
|
|
this.delegate = delegate; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) { |
|
|
|
public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
this.wsSession = new UndertowWebSocketSession(channel); |
|
|
|
this.session = new UndertowWebSocketSession(channel); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (URISyntaxException e) { |
|
|
|
catch (URISyntaxException e) { |
|
|
|
// TODO Auto-generated catch block
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
e.printStackTrace(); |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
channel.getReceiveSetter().set(new ReceiveListener()); |
|
|
|
channel.getReceiveSetter().set(new UndertowReceiveListener()); |
|
|
|
channel.resumeReceives(); |
|
|
|
channel.resumeReceives(); |
|
|
|
|
|
|
|
|
|
|
|
HandlerResultSubscriber resultSubscriber = new HandlerResultSubscriber(); |
|
|
|
HandlerResultSubscriber resultSubscriber = new HandlerResultSubscriber(); |
|
|
|
this.handler.handle(this.wsSession).subscribe(resultSubscriber); |
|
|
|
this.delegate.handle(this.session).subscribe(resultSubscriber); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private final class ReceiveListener extends AbstractReceiveListener { |
|
|
|
|
|
|
|
|
|
|
|
private final class UndertowReceiveListener extends AbstractReceiveListener { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) { |
|
|
|
protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) { |
|
|
|
wsSession.handleMessage(Type.TEXT, toMessage(Type.TEXT, message.getData())); |
|
|
|
session.handleMessage(Type.TEXT, toMessage(Type.TEXT, message.getData())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onFullBinaryMessage(WebSocketChannel channel, |
|
|
|
protected void onFullBinaryMessage(WebSocketChannel channel, BufferedBinaryMessage message) { |
|
|
|
BufferedBinaryMessage message) throws IOException { |
|
|
|
session.handleMessage(Type.BINARY, toMessage(Type.BINARY, message.getData().getResource())); |
|
|
|
wsSession.handleMessage(Type.BINARY, toMessage(Type.BINARY, message.getData().getResource())); |
|
|
|
|
|
|
|
message.getData().free(); |
|
|
|
message.getData().free(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onFullPongMessage(WebSocketChannel channel, |
|
|
|
protected void onFullPongMessage(WebSocketChannel channel, BufferedBinaryMessage message) { |
|
|
|
BufferedBinaryMessage message) throws IOException { |
|
|
|
session.handleMessage(Type.PONG, toMessage(Type.PONG, message.getData().getResource())); |
|
|
|
wsSession.handleMessage(Type.PONG, toMessage(Type.PONG, message.getData().getResource())); |
|
|
|
|
|
|
|
message.getData().free(); |
|
|
|
message.getData().free(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onFullCloseMessage(WebSocketChannel channel, |
|
|
|
protected void onFullCloseMessage(WebSocketChannel channel, BufferedBinaryMessage message) { |
|
|
|
BufferedBinaryMessage message) throws IOException { |
|
|
|
|
|
|
|
CloseMessage closeMessage = new CloseMessage(message.getData().getResource()); |
|
|
|
CloseMessage closeMessage = new CloseMessage(message.getData().getResource()); |
|
|
|
wsSession.handleClose(new CloseStatus(closeMessage.getCode(), closeMessage.getReason())); |
|
|
|
session.handleClose(new CloseStatus(closeMessage.getCode(), closeMessage.getReason())); |
|
|
|
message.getData().free(); |
|
|
|
message.getData().free(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onError(WebSocketChannel channel, Throwable error) { |
|
|
|
protected void onError(WebSocketChannel channel, Throwable error) { |
|
|
|
wsSession.handleError(error); |
|
|
|
session.handleError(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private <T> WebSocketMessage toMessage(Type type, T message) { |
|
|
|
private <T> WebSocketMessage toMessage(Type type, T message) { |
|
|
|
if (Type.TEXT.equals(type)) { |
|
|
|
if (Type.TEXT.equals(type)) { |
|
|
|
return WebSocketMessage.create(Type.TEXT, |
|
|
|
byte[] bytes = ((String) message).getBytes(StandardCharsets.UTF_8); |
|
|
|
bufferFactory.wrap(((String) message).getBytes(StandardCharsets.UTF_8))); |
|
|
|
return WebSocketMessage.create(Type.TEXT, bufferFactory.wrap(bytes)); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (Type.BINARY.equals(type)) { |
|
|
|
else if (Type.BINARY.equals(type)) { |
|
|
|
return WebSocketMessage.create(Type.BINARY, |
|
|
|
DataBuffer buffer = bufferFactory.allocateBuffer().write((ByteBuffer[]) message); |
|
|
|
bufferFactory.allocateBuffer().write((ByteBuffer[]) message)); |
|
|
|
return WebSocketMessage.create(Type.BINARY, buffer); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (Type.PONG.equals(type)) { |
|
|
|
else if (Type.PONG.equals(type)) { |
|
|
|
return WebSocketMessage.create(Type.PONG, |
|
|
|
DataBuffer buffer = bufferFactory.allocateBuffer().write((ByteBuffer[]) message); |
|
|
|
bufferFactory.allocateBuffer().write((ByteBuffer[]) message)); |
|
|
|
return WebSocketMessage.create(Type.PONG, buffer); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
throw new IllegalArgumentException("Unexpected message type: " + message); |
|
|
|
throw new IllegalArgumentException("Unexpected message type: " + message); |
|
|
|
@ -144,12 +145,12 @@ public class UndertowWebSocketHandlerAdapter implements WebSocketConnectionCallb |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onError(Throwable ex) { |
|
|
|
public void onError(Throwable ex) { |
|
|
|
wsSession.close(new CloseStatus(CloseStatus.SERVER_ERROR.getCode(), ex.getMessage())); |
|
|
|
session.close(new CloseStatus(CloseStatus.SERVER_ERROR.getCode(), ex.getMessage())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onComplete() { |
|
|
|
public void onComplete() { |
|
|
|
wsSession.close(); |
|
|
|
session.close(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|