From 9363039a717d9d04c8641dc9bb2cb857069815af Mon Sep 17 00:00:00 2001 From: nkzawa Date: Sat, 30 Jan 2016 20:36:28 +0900 Subject: [PATCH] improve ipv6 support, add tests --- .../io/socket/engineio/client/Socket.java | 32 ++++---- .../engineio/client/transports/Polling.java | 3 +- .../engineio/client/transports/WebSocket.java | 22 +++--- .../io/socket/engineio/client/SocketTest.java | 76 ++++++++++++++++++- .../socket/engineio/client/TransportTest.java | 48 ++++++++++++ 5 files changed, 148 insertions(+), 33 deletions(-) diff --git a/src/main/java/io/socket/engineio/client/Socket.java b/src/main/java/io/socket/engineio/client/Socket.java index f8fc989..df26408 100644 --- a/src/main/java/io/socket/engineio/client/Socket.java +++ b/src/main/java/io/socket/engineio/client/Socket.java @@ -111,7 +111,7 @@ public class Socket extends Emitter { private long pingInterval; private long pingTimeout; private String id; - private String hostname; + /*package*/ String hostname; private String path; private String timestampParam; private List transports; @@ -171,29 +171,27 @@ public class Socket extends Emitter { public Socket(Options opts) { if (opts.host != null) { - boolean ipv6uri = opts.host.indexOf(']') != -1; - String[] pieces = ipv6uri ? opts.host.split("]:") : opts.host.split(":"); - boolean ipv6 = (pieces.length > 2 || opts.host.indexOf("::") == -1); + String hostname = opts.host; + boolean ipv6 = hostname.split(":").length > 2; if (ipv6) { - opts.hostname = opts.host; - } else { - opts.hostname = pieces[0]; - if (ipv6uri) { - opts.hostname = opts.hostname.substring(1); - } - if (pieces.length > 1) { - opts.port = Integer.parseInt(pieces[pieces.length - 1]); - } else if (opts.port == -1) { - // if no port is specified manually, use the protocol default - opts.port = this.secure ? 443 : 80; - } + int start = hostname.indexOf('['); + if (start != -1) hostname = hostname.substring(start + 1); + int end = hostname.lastIndexOf(']'); + if (end != -1) hostname = hostname.substring(0, end); } + opts.hostname = hostname; } this.secure = opts.secure; + + if (opts.port == -1) { + // if no port is specified manually, use the protocol default + opts.port = this.secure ? 443 : 80; + } + this.sslContext = opts.sslContext != null ? opts.sslContext : defaultSSLContext; this.hostname = opts.hostname != null ? opts.hostname : "localhost"; - this.port = opts.port != 0 ? opts.port : (this.secure ? 443 : 80); + this.port = opts.port; this.query = opts.query != null ? ParseQS.decode(opts.query) : new HashMap(); this.upgrade = opts.upgrade; diff --git a/src/main/java/io/socket/engineio/client/transports/Polling.java b/src/main/java/io/socket/engineio/client/transports/Polling.java index 2227cda..12f43a2 100644 --- a/src/main/java/io/socket/engineio/client/transports/Polling.java +++ b/src/main/java/io/socket/engineio/client/transports/Polling.java @@ -214,7 +214,8 @@ abstract public class Polling extends Transport { _query = "?" + _query; } - return schema + "://" + this.hostname + port + this.path + _query; + boolean ipv6 = this.hostname.contains(":"); + return schema + "://" + (ipv6 ? "[" + this.hostname + "]" : this.hostname) + port + this.path + _query; } abstract protected void doWrite(byte[] data, Runnable fn); diff --git a/src/main/java/io/socket/engineio/client/transports/WebSocket.java b/src/main/java/io/socket/engineio/client/transports/WebSocket.java index ef88c84..ca1abe9 100644 --- a/src/main/java/io/socket/engineio/client/transports/WebSocket.java +++ b/src/main/java/io/socket/engineio/client/transports/WebSocket.java @@ -1,15 +1,22 @@ package io.socket.engineio.client.transports; +import io.socket.engineio.client.Transport; +import io.socket.engineio.parser.Packet; +import io.socket.engineio.parser.Parser; +import io.socket.parseqs.ParseQS; +import io.socket.thread.EventThread; +import io.socket.utf8.UTF8Exception; import okhttp3.OkHttpClient; -import okhttp3.OkHttpClient.Builder; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; import okhttp3.ws.WebSocketCall; import okhttp3.ws.WebSocketListener; +import okio.Buffer; +import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.util.Date; import java.util.HashMap; @@ -19,16 +26,6 @@ import java.util.TreeMap; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; -import javax.net.ssl.SSLSocketFactory; - -import io.socket.engineio.client.Transport; -import io.socket.engineio.parser.Packet; -import io.socket.engineio.parser.Parser; -import io.socket.parseqs.ParseQS; -import io.socket.thread.EventThread; -import io.socket.utf8.UTF8Exception; -import okio.Buffer; - import static okhttp3.ws.WebSocket.BINARY; import static okhttp3.ws.WebSocket.TEXT; @@ -222,6 +219,7 @@ public class WebSocket extends Transport { _query = "?" + _query; } - return schema + "://" + this.hostname + port + this.path + _query; + boolean ipv6 = this.hostname.contains(":"); + return schema + "://" + (ipv6 ? "[" + this.hostname + "]" : this.hostname) + port + this.path + _query; } } \ No newline at end of file diff --git a/src/test/java/io/socket/engineio/client/SocketTest.java b/src/test/java/io/socket/engineio/client/SocketTest.java index 54df805..ca88911 100644 --- a/src/test/java/io/socket/engineio/client/SocketTest.java +++ b/src/test/java/io/socket/engineio/client/SocketTest.java @@ -29,23 +29,93 @@ public class SocketTest { assertThat(socket.filterUpgrades(upgrades), is(expected)); } + @Test public void properlyParseHttpUriWithoutPort() throws URISyntaxException { Socket client = new Socket("http://localhost"); + assertThat(client.hostname, is("localhost")); assertThat(client.port, is(80)); } + @Test public void properlyParseHttpsUriWithoutPort() throws URISyntaxException { - Socket client = new Socket("http://localhost"); + Socket client = new Socket("https://localhost"); + assertThat(client.hostname, is("localhost")); assertThat(client.port, is(443)); } + @Test public void properlyParseWssUriWithoutPort() throws URISyntaxException { - Socket client = new Socket("http://localhost"); + Socket client = new Socket("wss://localhost"); + assertThat(client.hostname, is("localhost")); assertThat(client.port, is(443)); } + @Test public void properlyParseWssUriWithPort() throws URISyntaxException { - Socket client = new Socket("http://localhost:2020"); + Socket client = new Socket("wss://localhost:2020"); + assertThat(client.hostname, is("localhost")); assertThat(client.port, is(2020)); } + + @Test + public void properlyParseHostWithPort() { + Socket.Options opts = new Socket.Options(); + opts.host = "localhost"; + opts.port = 8080; + Socket client = new Socket(opts); + assertThat(client.hostname, is("localhost")); + assertThat(client.port, is(8080)); + } + + @Test + public void properlyParseIPv6UriWithoutPort() throws URISyntaxException { + Socket client = new Socket("http://[::1]"); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(80)); + } + + @Test + public void properlyParseIPv6UriWithPort() throws URISyntaxException { + Socket client = new Socket("http://[::1]:8080"); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(8080)); + } + + @Test + public void properlyParseIPv6HostWithoutPort1() { + Socket.Options opts = new Socket.Options(); + opts.host = "[::1]"; + Socket client = new Socket(opts); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(80)); + } + + @Test + public void properlyParseIPv6HostWithoutPort2() { + Socket.Options opts = new Socket.Options(); + opts.secure = true; + opts.host = "[::1]"; + Socket client = new Socket(opts); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(443)); + } + + @Test + public void properlyParseIPv6HostWithPort() { + Socket.Options opts = new Socket.Options(); + opts.host = "[::1]"; + opts.port = 8080; + Socket client = new Socket(opts); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(8080)); + } + + @Test + public void properlyParseIPv6HostWithoutBrace() { + Socket.Options opts = new Socket.Options(); + opts.host = "::1"; + Socket client = new Socket(opts); + assertThat(client.hostname, is("::1")); + assertThat(client.port, is(80)); + } } diff --git a/src/test/java/io/socket/engineio/client/TransportTest.java b/src/test/java/io/socket/engineio/client/TransportTest.java index 6130530..6a6272a 100644 --- a/src/test/java/io/socket/engineio/client/TransportTest.java +++ b/src/test/java/io/socket/engineio/client/TransportTest.java @@ -87,6 +87,30 @@ public class TransportTest { assertThat(polling.uri().matches("http://localhost/engine.io\\?(j=[0-9]+&)?t=[0-9]+-[0-9]+"), is(true)); } + @Test + public void ipv6Uri() { + Transport.Options opt = new Transport.Options(); + opt.path ="/engine.io"; + opt.hostname = "::1"; + opt.secure = false; + opt.port = 80; + opt.timestampRequests = false; + Polling polling = new Polling(opt); + assertThat(polling.uri(), containsString("http://[::1]/engine.io")); + } + + @Test + public void ipv6UriWithPort() { + Transport.Options opt = new Transport.Options(); + opt.path ="/engine.io"; + opt.hostname = "::1"; + opt.secure = false; + opt.port = 8080; + opt.timestampRequests = false; + Polling polling = new Polling(opt); + assertThat(polling.uri(), containsString("http://[::1]:8080/engine.io")); + } + @Test public void wsUri() { Transport.Options opt = new Transport.Options(); @@ -123,6 +147,30 @@ public class TransportTest { assertThat(ws.uri().matches("ws://localhost/engine.io\\?woot=[0-9]+"), is(true)); } + @Test + public void wsIPv6Uri() { + Transport.Options opt = new Transport.Options(); + opt.path ="/engine.io"; + opt.hostname = "::1"; + opt.secure = false; + opt.port = 80; + opt.timestampRequests = false; + WS ws = new WS(opt); + assertThat(ws.uri(), containsString("ws://[::1]/engine.io")); + } + + @Test + public void wsIPv6UriWithPort() { + Transport.Options opt = new Transport.Options(); + opt.path ="/engine.io"; + opt.hostname = "::1"; + opt.secure = false; + opt.port = 8080; + opt.timestampRequests = false; + WS ws = new WS(opt); + assertThat(ws.uri(), containsString("ws://[::1]:8080/engine.io")); + } + class Polling extends PollingXHR { public Polling(Options opts) {