Skip to content

Commit 8eae452

Browse files
committed
Add support for creating server from existing Channel
See #1440 The main motivation for this feature is the ability to integrate with on-demand socket activation.
1 parent 3b29042 commit 8eae452

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/main/java/org/java_websocket/server/WebSocketServer.java

+33-2
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,30 @@ public WebSocketServer(InetSocketAddress address, int decodercount, List<Draft>
181181
this(address, decodercount, drafts, new HashSet<WebSocket>());
182182
}
183183

184+
// Small internal helper function to get around limitations of Java constructors.
185+
private static InetSocketAddress checkAddressOfExistingChannel(ServerSocketChannel existingChannel) {
186+
assert existingChannel.isOpen();
187+
SocketAddress addr;
188+
try {
189+
addr = existingChannel.getLocalAddress();
190+
} catch (IOException e) {
191+
throw new IllegalArgumentException("Could not get address of channel passed to WebSocketServer, make sure it is bound", e);
192+
}
193+
if (addr == null) {
194+
throw new IllegalArgumentException("Could not get address of channel passed to WebSocketServer, make sure it is bound");
195+
}
196+
return (InetSocketAddress)addr;
197+
}
198+
199+
/**
200+
* @param existingChannel An already open and bound server socket channel, which this server will use.
201+
* For example, it can be System.inheritedChannel() to implement socket activation.
202+
*/
203+
public WebSocketServer(ServerSocketChannel existingChannel) {
204+
this(checkAddressOfExistingChannel(existingChannel));
205+
this.server = existingChannel;
206+
}
207+
184208
/**
185209
* Creates a WebSocketServer that will attempt to bind/listen on the given <var>address</var>, and
186210
* comply with <code>Draft</code> version <var>draft</var>.
@@ -575,15 +599,22 @@ private void doWrite(SelectionKey key) throws WrappedIOException {
575599
private boolean doSetupSelectorAndServerThread() {
576600
selectorthread.setName("WebSocketSelector-" + selectorthread.getId());
577601
try {
578-
server = ServerSocketChannel.open();
602+
if (server == null) {
603+
server = ServerSocketChannel.open();
604+
// If 'server' is not null, that means WebSocketServer was created from existing channel.
605+
}
579606
server.configureBlocking(false);
580607
ServerSocket socket = server.socket();
581608
int receiveBufferSize = getReceiveBufferSize();
582609
if (receiveBufferSize > 0) {
583610
socket.setReceiveBufferSize(receiveBufferSize);
584611
}
585612
socket.setReuseAddress(isReuseAddr());
586-
socket.bind(address, getMaxPendingConnections());
613+
// Socket may be already bound, if an existing channel was passed to constructor.
614+
// In this case we cannot modify backlog size from pure Java code, so leave it as is.
615+
if (!socket.isBound()) {
616+
socket.bind(address, getMaxPendingConnections());
617+
}
587618
selector = Selector.open();
588619
server.register(selector, server.validOps());
589620
startConnectionLostTimer();

0 commit comments

Comments
 (0)