diff --git a/lib/faye/websocket/client.rb b/lib/faye/websocket/client.rb index d5828e5..bee0b4c 100644 --- a/lib/faye/websocket/client.rb +++ b/lib/faye/websocket/client.rb @@ -1,4 +1,5 @@ require 'forwardable' +require 'ipaddr' module Faye class WebSocket @@ -7,8 +8,9 @@ class Client extend Forwardable include API - DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443 } - SECURE_PROTOCOLS = ['https', 'wss'] + DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443 }.freeze + SECURE_PROTOCOLS = ['https', 'wss'].freeze + IPV6_HOST_REGEX = /\[.*\]/.freeze def_delegators :@driver, :headers, :status @@ -24,7 +26,7 @@ def initialize(url, protocols = nil, options = {}) configure_proxy(proxy) - EventMachine.connect(@endpoint.host, port, Connection) do |conn| + EventMachine.connect(host(@endpoint), port, Connection) do |conn| conn.parent = self end rescue => error @@ -33,6 +35,14 @@ def initialize(url, protocols = nil, options = {}) private + def host(uri) + if IPV6_HOST_REGEX.match?(uri.host) && IPAddr.new(uri.host).ipv6? + uri.host.gsub(/\[|\]/, '') + else + uri.host + end + end + def configure_proxy(proxy) return unless proxy[:origin] @@ -53,7 +63,7 @@ def configure_proxy(proxy) def start_tls(uri, options) return unless SECURE_PROTOCOLS.include?(uri.scheme) - tls_options = { :sni_hostname => uri.host, :verify_peer => true }.merge(options) + tls_options = { :sni_hostname => host(uri), :verify_peer => true }.merge(options) @ssl_verifier = SslVerifier.new(uri.host, tls_options) @stream.start_tls(tls_options) end diff --git a/spec/faye/websocket/client_spec.rb b/spec/faye/websocket/client_spec.rb index 6a69224..29f14a9 100644 --- a/spec/faye/websocket/client_spec.rb +++ b/spec/faye/websocket/client_spec.rb @@ -125,10 +125,12 @@ def wait(seconds, &callback) let(:protocols) { ["foo", "echo"] } let(:localhost) { "localhost" } + let(:ipv6_address) { '[::1]' } let(:port) { 4180 } let(:plain_text_url) { "ws://#{ localhost }:#{ port }/" } let(:wrong_url) { "ws://#{ localhost }:9999/" } let(:secure_url) { "wss://#{ localhost }:#{ port }/" } + let(:ipv6_url) { "ws://#{ipv6_address}:#{port}/" } let :tls_options do { :root_cert_file => File.expand_path('../../../server.crt', __FILE__) } @@ -246,4 +248,10 @@ def wait(seconds, &callback) it_should_behave_like "socket server" end + + describe "with IPv6 address" do + let(:socket_url) { ipv6_url } + + it_should_behave_like "socket server" + end end