Skip to content

Commit 3427f08

Browse files
authored
Merge pull request #833 from the-thing/proxy_testing
Mina proxy handshake fix and proxy integration tests
2 parents 3faa89b + ef230f3 commit 3427f08

File tree

8 files changed

+377
-13
lines changed

8 files changed

+377
-13
lines changed

quickfixj-core/pom.xml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@
117117
<version>${slf4j.version}</version>
118118
<scope>test</scope>
119119
</dependency>
120+
<dependency>
121+
<groupId>io.netty</groupId>
122+
<artifactId>netty-example</artifactId>
123+
<version>4.1.111.Final</version>
124+
<scope>test</scope>
125+
</dependency>
120126
<dependency>
121127
<groupId>org.apache.mina</groupId>
122128
<artifactId>mina-core</artifactId>
@@ -132,11 +138,11 @@
132138
<version>18.3.12</version>
133139
<optional>true</optional>
134140
</dependency>
135-
<dependency>
136-
<groupId>com.zaxxer</groupId>
137-
<artifactId>HikariCP</artifactId>
138-
<version>4.0.3</version>
139-
</dependency>
141+
<dependency>
142+
<groupId>com.zaxxer</groupId>
143+
<artifactId>HikariCP</artifactId>
144+
<version>4.0.3</version>
145+
</dependency>
140146
</dependencies>
141147

142148

@@ -218,6 +224,15 @@
218224
</configuration>
219225
</plugin>
220226
</plugins>
227+
228+
<extensions>
229+
<!-- required by Netty cross-platform build -->
230+
<extension>
231+
<groupId>kr.motd.maven</groupId>
232+
<artifactId>os-maven-plugin</artifactId>
233+
<version>1.4.0.Final</version>
234+
</extension>
235+
</extensions>
221236
</build>
222237

223238
<reporting>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package quickfix.mina;
2+
3+
import org.apache.mina.core.filterchain.IoFilterChain;
4+
import org.apache.mina.core.session.IoSession;
5+
import org.apache.mina.filter.ssl.SslFilter;
6+
7+
import javax.net.ssl.SSLContext;
8+
9+
/**
10+
* Temporary {@link SslFilter} wrapper that prevents auto connect for initiators.
11+
*/
12+
public class CustomSslFilter extends SslFilter {
13+
14+
private static final boolean DEFAULT_AUTO_START = true;
15+
16+
private final boolean autoStart;
17+
18+
public CustomSslFilter(SSLContext sslContext) {
19+
this(sslContext, DEFAULT_AUTO_START);
20+
}
21+
22+
public CustomSslFilter(SSLContext sslContext, boolean autoStart) {
23+
super(sslContext);
24+
this.autoStart = autoStart;
25+
}
26+
27+
@Override
28+
public void onPostAdd(IoFilterChain parent, String name, NextFilter next) throws Exception {
29+
IoSession session = parent.getSession();
30+
31+
if (session.isConnected() && autoStart) {
32+
onConnected(next, session);
33+
}
34+
}
35+
}

quickfixj-core/src/main/java/quickfix/mina/ProtocolFactory.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,21 @@ public class ProtocolFactory {
5252

5353
public final static int SOCKET = 0;
5454
public final static int VM_PIPE = 1;
55-
public final static int PROXY = 2;
5655

5756
public static String getTypeString(int type) {
5857
switch (type) {
5958
case SOCKET:
6059
return "SOCKET";
6160
case VM_PIPE:
6261
return "VM_PIPE";
63-
case PROXY:
64-
return "PROXY";
6562
default:
6663
return "unknown";
6764
}
6865
}
6966

7067
public static SocketAddress createSocketAddress(int transportType, String host,
7168
int port) throws ConfigError {
72-
if (transportType == SOCKET || transportType == PROXY) {
69+
if (transportType == SOCKET) {
7370
return host != null ? new InetSocketAddress(host, port) : new InetSocketAddress(port);
7471
} else if (transportType == VM_PIPE) {
7572
return new VmPipeAddress(port);
@@ -94,8 +91,6 @@ public static int getTransportType(String string) {
9491
return SOCKET;
9592
} else if (string.equalsIgnoreCase("VM_PIPE")) {
9693
return VM_PIPE;
97-
} else if (string.equalsIgnoreCase("PROXY")) {
98-
return PROXY;
9994
} else {
10095
throw new RuntimeError("Unknown Transport Type type: " + string);
10196
}

quickfixj-core/src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import quickfix.SessionID;
4141
import quickfix.SessionSettings;
4242
import quickfix.mina.CompositeIoFilterChainBuilder;
43+
import quickfix.mina.CustomSslFilter;
4344
import quickfix.mina.EventHandlingStrategy;
4445
import quickfix.mina.NetworkingOptions;
4546
import quickfix.mina.ProtocolFactory;
@@ -134,7 +135,7 @@ private void installSSL(AcceptorSocketDescriptor descriptor,
134135
log.info("Installing SSL filter for {}", descriptor.getAddress());
135136
SSLConfig sslConfig = descriptor.getSslConfig();
136137
SSLContext sslContext = SSLContextFactory.getInstance(sslConfig);
137-
SslFilter sslFilter = new SslFilter(sslContext);
138+
SslFilter sslFilter = new CustomSslFilter(sslContext);
138139
sslFilter.setNeedClientAuth(sslConfig.isNeedClientAuth());
139140
sslFilter.setEnabledCipherSuites(sslConfig.getEnabledCipherSuites() != null ? sslConfig.getEnabledCipherSuites()
140141
: SSLSupport.getDefaultCipherSuites(sslContext));

quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import quickfix.SessionSettings;
3535
import quickfix.SystemTime;
3636
import quickfix.mina.CompositeIoFilterChainBuilder;
37+
import quickfix.mina.CustomSslFilter;
3738
import quickfix.mina.EventHandlingStrategy;
3839
import quickfix.mina.NetworkingOptions;
3940
import quickfix.mina.ProtocolFactory;
@@ -189,7 +190,7 @@ private void setupIoConnector() throws ConfigError, GeneralSecurityException {
189190
private SslFilter installSslFilter(CompositeIoFilterChainBuilder ioFilterChainBuilder)
190191
throws GeneralSecurityException {
191192
final SSLContext sslContext = SSLContextFactory.getInstance(sslConfig);
192-
final SslFilter sslFilter = new SslFilter(sslContext);
193+
final SslFilter sslFilter = new CustomSslFilter(sslContext, false);
193194
sslFilter.setEnabledCipherSuites(sslConfig.getEnabledCipherSuites() != null ? sslConfig.getEnabledCipherSuites()
194195
: SSLSupport.getDefaultCipherSuites(sslContext));
195196
sslFilter.setEnabledProtocols(sslConfig.getEnabledProtocols() != null ? sslConfig.getEnabledProtocols()
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package quickfix.mina;
2+
3+
import io.netty.bootstrap.ServerBootstrap;
4+
import io.netty.channel.Channel;
5+
import io.netty.channel.nio.NioEventLoopGroup;
6+
import io.netty.channel.socket.nio.NioServerSocketChannel;
7+
import io.netty.example.socksproxy.SocksServerInitializer;
8+
import io.netty.handler.logging.LogLevel;
9+
import io.netty.handler.logging.LoggingHandler;
10+
import org.apache.mina.util.DaemonThreadFactory;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
import java.util.concurrent.ThreadFactory;
15+
16+
/**
17+
* Simple SOCKS proxy server based on Netty examples. Only SOCKS protocols are currently supported.
18+
* The implementation performs the proxy handshake, but it doesn't perform any user authentication.
19+
*/
20+
public class SocksProxyServer {
21+
22+
private static final Logger LOGGER = LoggerFactory.getLogger(SocksProxyServer.class);
23+
private static final ThreadFactory THREAD_FACTORY = new DaemonThreadFactory();
24+
25+
private final ServerBootstrap bootstrap;
26+
private final int port;
27+
private Channel channel;
28+
29+
public SocksProxyServer(int port) {
30+
this.bootstrap = new ServerBootstrap();
31+
this.bootstrap.group(new NioEventLoopGroup(THREAD_FACTORY), new NioEventLoopGroup(THREAD_FACTORY))
32+
.channel(NioServerSocketChannel.class)
33+
.handler(new LoggingHandler(LogLevel.DEBUG))
34+
.childHandler(new SocksServerInitializer());
35+
this.port = port;
36+
}
37+
38+
public synchronized void start() {
39+
if (channel != null) {
40+
throw new IllegalStateException("SOCKS proxy server is running already");
41+
}
42+
43+
try {
44+
channel = bootstrap.bind(port)
45+
.sync()
46+
.channel();
47+
} catch (InterruptedException e) {
48+
Thread.currentThread().interrupt();
49+
throw new RuntimeException(e);
50+
}
51+
52+
LOGGER.info("SOCKS proxy server started at port: {}", port);
53+
}
54+
55+
public synchronized void stop() {
56+
if (channel == null) {
57+
throw new IllegalStateException("SOCKS proxy server is not running");
58+
}
59+
60+
try {
61+
channel.close().sync();
62+
channel = null;
63+
} catch (InterruptedException e) {
64+
Thread.currentThread().interrupt();
65+
throw new RuntimeException("Failed to close SOCKS proxy server");
66+
}
67+
68+
LOGGER.info("SOCKS proxy server stopped at port {}", port);
69+
}
70+
71+
public int getPort() {
72+
return port;
73+
}
74+
}

0 commit comments

Comments
 (0)