Skip to content

Commit

Permalink
Add the ability to define binding address for client socket. (#687)
Browse files Browse the repository at this point in the history
* Add the ability to define binding address for client socket.
The goal of this functionality is to decide which network interface will be used by WebSockets

Signed-off-by: olivierayache <[email protected]
  • Loading branch information
olivierayache authored and jansupol committed Jan 14, 2020
1 parent 825e872 commit ad1a075
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -17,6 +17,7 @@
package org.glassfish.tyrus.client;


import java.net.InetAddress;
import java.net.URI;

import org.glassfish.tyrus.client.auth.AuthConfig;
Expand Down Expand Up @@ -284,4 +285,15 @@ public final class ClientProperties {
* of masking keys.
*/
public static final String MASKING_KEY_GENERATOR = "org.glassfish.tyrus.client.maskingKeyGenerator";
}

/**
* Property name for defining local binding address for all socket created by the client. The expected value is an instance
* of {@link java.net.InetAddress}.
* <p>
* Sample below demonstrates how to use this property:
* <pre>
* client.getProperties().put(ClientProperties.SOCKET_BINDING, InetAddress.getByName("127.0.0.1"));
* </pre>
*/
public static final String SOCKET_BINDING = "org.glassfish.tyrus.client.socketBinding";
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -17,6 +17,7 @@
package org.glassfish.tyrus.container.grizzly.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
Expand Down Expand Up @@ -359,7 +360,13 @@ public void handleTimeout() {
sharedTransportTimeout, proxyHeaders, grizzlyConnector, sslHandshakeFuture,
upgradeRequest));

connectionGrizzlyFuture = connectorHandler.connect(connectAddress);
InetAddress bindingAddress = Utils.getProperty(properties, ClientProperties.SOCKET_BINDING, InetAddress.class);

if (bindingAddress == null) {
connectionGrizzlyFuture = connectorHandler.connect(connectAddress);
} else {
connectionGrizzlyFuture = connectorHandler.connect(socketAddress, new InetSocketAddress(bindingAddress, 0));
}

try {
final Connection connection = connectionGrizzlyFuture.get(timeoutMs, TimeUnit.MILLISECONDS);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -17,6 +17,7 @@
package org.glassfish.tyrus.container.jdk.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
Expand Down Expand Up @@ -99,6 +100,9 @@ public void openClientSocket(final ClientEndpointConfig cec, final Map<String, O
final Integer containerIdleTimeout =
Utils.getProperty(properties, ClientProperties.SHARED_CONTAINER_IDLE_TIMEOUT, Integer.class);

final InetAddress bindingAddress =
Utils.getProperty(properties, ClientProperties.SOCKET_BINDING, InetAddress.class);

final ThreadPoolConfig finalThreadPoolConfig = threadPoolConfig;
final Callable<Void> jdkConnector = new Callable<Void>() {

Expand All @@ -118,13 +122,19 @@ public Void call() throws DeploymentException {

if (secure) {
TransportFilter transportFilter =
createTransportFilter(SSL_INPUT_BUFFER_SIZE, finalThreadPoolConfig, containerIdleTimeout);
createTransportFilter(SSL_INPUT_BUFFER_SIZE,
finalThreadPoolConfig,
containerIdleTimeout,
bindingAddress);
SslFilter sslFilter = createSslFilter(cec, properties, transportFilter, uri);
writeQueue = createTaskQueueFilter(sslFilter);

} else {
TransportFilter transportFilter =
createTransportFilter(INPUT_BUFFER_SIZE, finalThreadPoolConfig, containerIdleTimeout);
createTransportFilter(INPUT_BUFFER_SIZE,
finalThreadPoolConfig,
containerIdleTimeout,
bindingAddress);
writeQueue = createTaskQueueFilter(transportFilter);
}

Expand Down Expand Up @@ -276,9 +286,11 @@ private SslFilter createSslFilter(ClientEndpointConfig cec, Map<String, Object>
return sslFilter;
}

private TransportFilter createTransportFilter(int sslInputBufferSize, ThreadPoolConfig threadPoolConfig,
Integer containerIdleTimeout) {
return new TransportFilter(sslInputBufferSize, threadPoolConfig, containerIdleTimeout);
private TransportFilter createTransportFilter(int sslInputBufferSize,
ThreadPoolConfig threadPoolConfig,
Integer containerIdleTimeout,
InetAddress bindingAddress) {
return new TransportFilter(sslInputBufferSize, threadPoolConfig, containerIdleTimeout, bindingAddress);
}

private TaskQueueFilter createTaskQueueFilter(Filter downstreamFilter) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -17,6 +17,8 @@
package org.glassfish.tyrus.container.jdk.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
Expand Down Expand Up @@ -85,6 +87,7 @@ public Thread newThread(Runnable r) {
private final int inputBufferSize;
private final ThreadPoolConfig threadPoolConfig;
private final Integer containerIdleTimeout;
private final InetAddress bindingAddress;

private volatile AsynchronousSocketChannel socketChannel;

Expand All @@ -99,12 +102,18 @@ public Thread newThread(Runnable r) {
* @param threadPoolConfig thread pool configuration used for creating thread pool.
* @param containerIdleTimeout idle time after which the shared thread pool will be destroyed. If {@code null}
* default value will be used. The default value is 30 seconds.
* @param bindingAddress local address to bind sockets ({@link #socketChannel}) when they are created.
* Binding is done only if not {@code null}.
*/
TransportFilter(int inputBufferSize, ThreadPoolConfig threadPoolConfig, Integer containerIdleTimeout) {
TransportFilter(int inputBufferSize,
ThreadPoolConfig threadPoolConfig,
Integer containerIdleTimeout,
InetAddress bindingAddress) {
super(null);
this.inputBufferSize = inputBufferSize;
this.threadPoolConfig = threadPoolConfig;
this.containerIdleTimeout = containerIdleTimeout;
this.bindingAddress = bindingAddress;
}

@Override
Expand Down Expand Up @@ -161,6 +170,9 @@ public void handleConnect(SocketAddress serverAddress, Filter upstreamFilter) {
updateThreadPoolConfig();
initializeChannelGroup();
socketChannel = AsynchronousSocketChannel.open(channelGroup);
if (bindingAddress != null) {
socketChannel.bind(new InetSocketAddress(bindingAddress, 0));
}
openedConnections.incrementAndGet();
}
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -381,7 +381,7 @@ private Filter openClientSocket(String host, final ByteBuffer readBuffer, final
SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator(sslConfig.createSSLContext());
sslEngineConfigurator.setHostnameVerifier(customHostnameVerifier);

final TransportFilter transportFilter = new TransportFilter(17_000, ThreadPoolConfig.defaultConfig(), null);
final TransportFilter transportFilter = new TransportFilter(17_000, ThreadPoolConfig.defaultConfig(), null, null);
final SslFilter sslFilter = new SslFilter(transportFilter, sslEngineConfigurator, host);

// exceptions errors that occur before SSL handshake has finished are thrown from this method
Expand Down

0 comments on commit ad1a075

Please sign in to comment.