fix #6 enable to set SSLContext
This commit is contained in:
@@ -3,6 +3,7 @@ package com.github.nkzawa.socketio.client;
|
|||||||
|
|
||||||
import com.github.nkzawa.socketio.parser.Parser;
|
import com.github.nkzawa.socketio.parser.Parser;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@@ -22,6 +23,9 @@ public class IO {
|
|||||||
*/
|
*/
|
||||||
public static int protocol = Parser.protocol;
|
public static int protocol = Parser.protocol;
|
||||||
|
|
||||||
|
public static void setDefaultSSLContext(SSLContext sslContext) {
|
||||||
|
Manager.defaultSSLContext = sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
private IO() {}
|
private IO() {}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.github.nkzawa.socketio.parser.Packet;
|
|||||||
import com.github.nkzawa.socketio.parser.Parser;
|
import com.github.nkzawa.socketio.parser.Parser;
|
||||||
import com.github.nkzawa.thread.EventThread;
|
import com.github.nkzawa.thread.EventThread;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -62,6 +63,8 @@ public class Manager extends Emitter {
|
|||||||
|
|
||||||
public static final String EVENT_RECONNECT_ATTEMPT = "reconnect_attempt";
|
public static final String EVENT_RECONNECT_ATTEMPT = "reconnect_attempt";
|
||||||
|
|
||||||
|
/*package*/ static SSLContext defaultSSLContext;
|
||||||
|
|
||||||
/*package*/ ReadyState readyState = null;
|
/*package*/ ReadyState readyState = null;
|
||||||
|
|
||||||
private boolean _reconnection;
|
private boolean _reconnection;
|
||||||
@@ -111,6 +114,9 @@ public class Manager extends Emitter {
|
|||||||
if (opts.path == null) {
|
if (opts.path == null) {
|
||||||
opts.path = "/socket.io";
|
opts.path = "/socket.io";
|
||||||
}
|
}
|
||||||
|
if (opts.sslContext == null) {
|
||||||
|
opts.sslContext = defaultSSLContext;
|
||||||
|
}
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
this.nsps = new ConcurrentHashMap<String, Socket>();
|
this.nsps = new ConcurrentHashMap<String, Socket>();
|
||||||
this.subs = new LinkedList<On.Handle>();
|
this.subs = new LinkedList<On.Handle>();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public abstract class Connection {
|
|||||||
|
|
||||||
private Process serverProcess;
|
private Process serverProcess;
|
||||||
private ExecutorService serverService;
|
private ExecutorService serverService;
|
||||||
private Future serverOutout;
|
private Future serverOutput;
|
||||||
private Future serverError;
|
private Future serverError;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -25,10 +25,9 @@ public abstract class Connection {
|
|||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
serverProcess = Runtime.getRuntime().exec(
|
serverProcess = Runtime.getRuntime().exec(
|
||||||
String.format("node src/test/resources/index.js %s %s", PORT, nsp()),
|
String.format("node src/test/resources/server.js %s", nsp()), createEnv());
|
||||||
new String[] {"DEBUG=socket.io:*"});
|
|
||||||
serverService = Executors.newCachedThreadPool();
|
serverService = Executors.newCachedThreadPool();
|
||||||
serverOutout = serverService.submit(new Runnable() {
|
serverOutput = serverService.submit(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
BufferedReader reader = new BufferedReader(
|
BufferedReader reader = new BufferedReader(
|
||||||
@@ -67,24 +66,36 @@ public abstract class Connection {
|
|||||||
public void stopServer() throws InterruptedException {
|
public void stopServer() throws InterruptedException {
|
||||||
System.out.println("Stopping server ...");
|
System.out.println("Stopping server ...");
|
||||||
serverProcess.destroy();
|
serverProcess.destroy();
|
||||||
serverOutout.cancel(false);
|
serverOutput.cancel(false);
|
||||||
serverError.cancel(false);
|
serverError.cancel(false);
|
||||||
serverService.shutdown();
|
serverService.shutdown();
|
||||||
serverService.awaitTermination(3000, TimeUnit.MILLISECONDS);
|
serverService.awaitTermination(3000, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Socket client() throws URISyntaxException {
|
Socket client() throws URISyntaxException {
|
||||||
IO.Options opts = new IO.Options();
|
return client(createOptions());
|
||||||
opts.forceNew = true;
|
}
|
||||||
opts.reconnection = false;
|
|
||||||
|
Socket client(IO.Options opts) throws URISyntaxException {
|
||||||
return IO.socket(uri() + nsp(), opts);
|
return IO.socket(uri() + nsp(), opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String uri() {
|
String uri() {
|
||||||
return "http://localhost:" + PORT;
|
return "http://localhost:" + PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String nsp() {
|
String nsp() {
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IO.Options createOptions() {
|
||||||
|
IO.Options opts = new IO.Options();
|
||||||
|
opts.forceNew = true;
|
||||||
|
opts.reconnection = false;
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] createEnv() {
|
||||||
|
return new String[] {"DEBUG=socket.io:*", "PORT=" + PORT};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package com.github.nkzawa.socketio.client;
|
||||||
|
|
||||||
|
import com.github.nkzawa.emitter.Emitter;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class SSLConnectionTest extends Connection {
|
||||||
|
|
||||||
|
static {
|
||||||
|
// for test on localhost
|
||||||
|
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
|
||||||
|
new javax.net.ssl.HostnameVerifier(){
|
||||||
|
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
|
||||||
|
return hostname.equals("localhost");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Socket socket;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String uri() {
|
||||||
|
return "https://localhost:" + PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
IO.Options createOptions() {
|
||||||
|
IO.Options opts = super.createOptions();
|
||||||
|
opts.secure = true;
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String[] createEnv() {
|
||||||
|
return new String[] {"DEBUG=socket.io:*", "PORT=" + PORT, "SSL=1"};
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLContext createSSLContext() throws GeneralSecurityException, IOException {
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
File file = new File("src/test/resources/keystore.jks");
|
||||||
|
ks.load(new FileInputStream(file), "password".toCharArray());
|
||||||
|
|
||||||
|
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||||
|
kmf.init(ks, "password".toCharArray());
|
||||||
|
|
||||||
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||||
|
tmf.init(ks);
|
||||||
|
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||||
|
return sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
IO.setDefaultSSLContext(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = TIMEOUT)
|
||||||
|
public void connect() throws Exception {
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
IO.Options opts = createOptions();
|
||||||
|
opts.sslContext = createSSLContext();
|
||||||
|
socket = client(opts);
|
||||||
|
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
|
||||||
|
@Override
|
||||||
|
public void call(Object... objects) {
|
||||||
|
socket.emit("echo");
|
||||||
|
socket.on("echoBack", new Emitter.Listener() {
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
socket.close();
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.connect();
|
||||||
|
latch.await();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = TIMEOUT)
|
||||||
|
public void defaultSSLContext() throws Exception {
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
IO.setDefaultSSLContext(createSSLContext());
|
||||||
|
socket = client();
|
||||||
|
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
|
||||||
|
@Override
|
||||||
|
public void call(Object... objects) {
|
||||||
|
socket.emit("echo");
|
||||||
|
socket.on("echoBack", new Emitter.Listener() {
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
socket.close();
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.connect();
|
||||||
|
latch.await();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/test/resources/cert.pem
Normal file
10
src/test/resources/cert.pem
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBfDCCASYCCQDTnGd/oOyF1DANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||||
|
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMB4XDTE0MDcwNzEzMTUzN1oXDTQxMTEyMTEzMTUzN1owRTELMAkG
|
||||||
|
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
|
||||||
|
IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC6sdeFPlqk
|
||||||
|
5Pap9woFx1RO05gLidw4MNcL+ZRSxy/sNeE4PhT/RLFcEvnXiHc92wT8YB5Z+WCM
|
||||||
|
k/jRQ0q19PNPAgMBAAEwDQYJKoZIhvcNAQEFBQADQQCnmm1N/yZiMBZw2JDfbsx3
|
||||||
|
ecc0BGQ2BwWQuGHzP07TMi1AuOyNZSczl907OphYb9iRC8shZ4O+oXjQAuGTQ1Hp
|
||||||
|
-----END CERTIFICATE-----
|
||||||
9
src/test/resources/key.pem
Normal file
9
src/test/resources/key.pem
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIBOwIBAAJBALqx14U+WqTk9qn3CgXHVE7TmAuJ3Dgw1wv5lFLHL+w14Tg+FP9E
|
||||||
|
sVwS+deIdz3bBPxgHln5YIyT+NFDSrX0808CAwEAAQJAIdwLSIEsk2drTRwe1zl1
|
||||||
|
ku5RTxZruE0zU1qqifDSQjab1StAK1tapxBVRlRlyLCfD704UClsU8sjGtq0Nh6n
|
||||||
|
kQIhAO2YJM1g0w9bWYet3zC2UdEASPzaQ7llpZmc51NRBx2NAiEAyShICAaclEuy
|
||||||
|
wwuD4hibV+b6I8CLYoyPBo32EaceN0sCIQCUed6NxfM/houlgV+Xtmfcnzv9X3yx
|
||||||
|
EDdzjpz08Q7sRQIgZFv1fBOYYSBXQppnJRFzx2pUmCvDHtrTrMh84RfIqnsCIQCf
|
||||||
|
JjNXXxOaHn1PNZpi6EHReiFQmy1Swt+AxpTsKixsfA==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
BIN
src/test/resources/keystore.jks
Normal file
BIN
src/test/resources/keystore.jks
Normal file
Binary file not shown.
@@ -1,7 +1,18 @@
|
|||||||
var server = require('http').Server()
|
var fs = require('fs');
|
||||||
, io = require('socket.io')(server)
|
|
||||||
, port = parseInt(process.argv[2], 10) || 3000
|
var server;
|
||||||
, nsp = process.argv[3] || '/';
|
if (process.env.SSL) {
|
||||||
|
server = require('https').createServer({
|
||||||
|
key: fs.readFileSync(__dirname + '/key.pem'),
|
||||||
|
cert: fs.readFileSync(__dirname + '/cert.pem')
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
server = require('http').createServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
var io = require('socket.io')(server);
|
||||||
|
var port = process.env.PORT || 3000;
|
||||||
|
var nsp = process.argv[2] || '/';
|
||||||
|
|
||||||
io.of(nsp).on('connection', function(socket) {
|
io.of(nsp).on('connection', function(socket) {
|
||||||
socket.send('hello client');
|
socket.send('hello client');
|
||||||
Reference in New Issue
Block a user