-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathMultiThreadedSSLClient.java
More file actions
262 lines (210 loc) · 9.03 KB
/
Copy pathMultiThreadedSSLClient.java
File metadata and controls
262 lines (210 loc) · 9.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/* MultiThreadedSSLClient.java
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/**
* Multi threaded SSLSocket example that connects a specified number of
* client threads to a server. Intended to test multi-threading with wolfJSSE.
*
* This example creates a specified number of client threads to a server
* located at 127.0.0.1:11118. This example is set up to use the SSLSocket
* class. It makes one connection (handshake), sends/receives data, and shuts
* down.
*
* A random amount of time is injected into each client thread before:
* 1) The SSL/TLS handshake
* 2) Doing I/O operations after the handshake
*
* The maximum amount of sleep time for each of those is "maxSleep", or
* 3 seconds by default. This is intended to add some randomness into the
* the client thread operations.
*
* Example usage:
*
* $ ant examples
* $ ./examples/provider/MultiThreadedSSLClient.sh
*
* This example is designed to connect against the MultiThreadedSSLServer
* example:
*
* $ ./examples/provider/MultiThreadedSSLServer.sh
*
* This example also prints out average SSL/TLS handshake time, which is
* measured in milliseconds on the "startHandshake()" API call.
*/
import java.util.*;
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.security.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import com.wolfssl.provider.jsse.WolfSSLProvider;
public class MultiThreadedSSLClient
{
String tmfType = "SunX509"; /* TrustManagerFactory type */
String tmfProv = "wolfJSSE"; /* TrustManagerFactory provider */
String kmfType = "SunX509"; /* KeyManagerFactory type */
String kmfProv = "wolfJSSE"; /* KeyManagerFactory provider */
String ctxProv = "wolfJSSE"; /* SSLContext provider */
String srvHost = "127.0.0.1"; /* server host */
int srvPort = 11118; /* server port */
int numClientConnections = 10; /* number of client connection threads */
int startedClientConnections = 0; /* active clients connected to server */
int successClientConnections = 0; /* successful client connections */
int failedClientConnections = 0; /* failed client connections */
/* Sleep 10 seconds before and after execution of main example,
* to allow profilers like VisualVM to be attached. */
boolean profileSleep = false;
long totalConnectionTimeMs = 0; /* total handshake time, across clients */
final Object timeLock = new Object();
class ClientThread implements Runnable
{
private KeyManagerFactory km = null;
private TrustManagerFactory tm = null;
private CountDownLatch latch;
public ClientThread(KeyManagerFactory km, TrustManagerFactory tm,
CountDownLatch latch) {
this.km = km;
this.tm = tm;
this.latch = latch;
}
public void run() {
byte[] back = new byte[80];
String msg = "Too legit to quit";
/* max sleep is 3 seconds */
int maxSleep = 3000;
/* get random sleep value before calling connect() */
int randConnectSleep =
ThreadLocalRandom.current().nextInt(0, maxSleep + 1);
/* get random sleep value before doing I/O after handshake */
int randIOSleep =
ThreadLocalRandom.current().nextInt(0, maxSleep +1);
try {
SSLContext ctx = SSLContext.getInstance("TLS", ctxProv);
ctx.init(km.getKeyManagers(), tm.getTrustManagers(), null);
SSLSocket sock = (SSLSocket)ctx.getSocketFactory()
.createSocket();
Thread.sleep(randConnectSleep);
sock.connect(new InetSocketAddress(srvHost, srvPort));
final long startTime = System.currentTimeMillis();
sock.startHandshake();
final long endTime = System.currentTimeMillis();
synchronized (timeLock) {
totalConnectionTimeMs += (endTime - startTime);
}
Thread.sleep(randIOSleep);
sock.getOutputStream().write(msg.getBytes());
sock.getInputStream().read(back);
System.out.println("Server message : " + new String(back));
sock.close();
successClientConnections++;
} catch (Exception e) {
e.printStackTrace();
failedClientConnections++;
}
this.latch.countDown();
}
}
public MultiThreadedSSLClient(String[] args) {
Security.addProvider(new WolfSSLProvider());
String clientKS = "./examples/provider/client.jks";
String clientTS = "./examples/provider/ca-server.jks";
String jkspass = "wolfSSL test";
char[] passArr = jkspass.toCharArray();
/* pull in command line options from user */
for (int i = 0; i < args.length; i++)
{
String arg = args[i];
if (arg.equals("-n")) {
if (args.length < i+2)
printUsage();
numClientConnections = Integer.parseInt(args[++i]);
} else if (arg.equals("-profile")) {
profileSleep = true;
} else {
printUsage();
}
}
try {
if (profileSleep) {
System.out.println(
"Sleeping 10 seconds to allow profiler to attach");
Thread.sleep(10000);
}
List<ClientThread> clientList = new ArrayList<ClientThread>();
CountDownLatch latch = new CountDownLatch(numClientConnections);
/* set up client KeyStore */
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(new FileInputStream(clientKS), passArr);
KeyManagerFactory clientKMF =
KeyManagerFactory.getInstance(kmfType, kmfProv);
clientKMF.init(clientKeyStore, passArr);
/* set up CA TrustManagerFactory */
KeyStore caKeyStore = KeyStore.getInstance("JKS");
caKeyStore.load(new FileInputStream(clientTS), passArr);
TrustManagerFactory tm = TrustManagerFactory
.getInstance(tmfType, tmfProv);
tm.init(caKeyStore);
for (int i = 0; i < numClientConnections; i++) {
clientList.add(new ClientThread(clientKMF, tm, latch));
}
ExecutorService executor = Executors.newFixedThreadPool(
clientList.size());
for (final ClientThread c : clientList) {
executor.execute(c);
}
latch.await();
executor.shutdown();
Security.removeProvider("wolfJSSE");
if (profileSleep) {
/* Try and kick start garbage collector before profiling
* heap dump */
System.gc();
System.out.println(
"Sleeping 10 seconds to allow profiler to dump heap");
Thread.sleep(10000);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("================================================");
System.out.println("All Client Connections Finished");
System.out.println("Successful = " + successClientConnections);
System.out.println("Failed = " + failedClientConnections);
if (successClientConnections > 0) {
System.out.println("Avg handshake time = " +
totalConnectionTimeMs / successClientConnections + " ms");
}
System.out.println("================================================");
}
public static void main(String[] args) {
new MultiThreadedSSLClient(args);
}
private void printUsage() {
System.out.println("Java wolfJSSE example threaded client usage:");
System.out.println("-n <num>\tNumber of client connections");
System.out.println("-profile\tSleep for 10 sec before/after running " +
"to allow profilers to attach");
System.exit(1);
}
}