lib/pusher-client/socket.rb in pusher-client-0.3.1 vs lib/pusher-client/socket.rb in pusher-client-0.4.0

- old
+ new

@@ -1,35 +1,38 @@ require 'json' -require 'hmac-sha2' +require 'openssl' require 'digest/md5' module PusherClient class Socket CLIENT_ID = 'pusher-ruby-client' - VERSION = '0.3.0' PROTOCOL = '5' - attr_accessor :encrypted, :secure attr_reader :path, :connected, :channels, :global_channel, :socket_id - def initialize(application_key, options={}) - raise ArgumentError if (!application_key.is_a?(String) || application_key.size < 1) + def initialize(app_key, options={}) + raise "Missing app_key" unless app_key && !app_key.empty? - @path = "/app/#{application_key}?client=#{CLIENT_ID}&version=#{VERSION}&protocol=#{PROTOCOL}" - @key = application_key + @path = "#{options[:ws_path]}/app/#{app_key}?client=#{CLIENT_ID}&version=#{PusherClient::VERSION}&protocol=#{PROTOCOL}" + @key = app_key @secret = options[:secret] @socket_id = nil @channels = Channels.new @global_channel = Channel.new('pusher_global_channel') @global_channel.global = true - @secure = false @connected = false @encrypted = options[:encrypted] || false + @private_auth_method = options[:private_auth_method] + @cert_file = options[:cert_file] + @ws_host = options[:ws_host] || HOST + @ws_port = options[:ws_port] || WS_PORT + @wss_port = options[:wss_port] || WSS_PORT + @ssl_verify = options.fetch(:ssl_verify) { true } bind('pusher:connection_established') do |data| - socket = JSON.parse(data) + socket = parser(data) @connected = true @socket_id = socket['socket_id'] subscribe_all end @@ -47,19 +50,19 @@ send_event('pusher:pong', nil) end end def connect(async = false) - if @encrypted || @secure - url = "wss://#{HOST}:#{WSS_PORT}#{@path}" + if @encrypted + url = "wss://#{@ws_host}:#{@wss_port}#{@path}" else - url = "ws://#{HOST}:#{WS_PORT}#{@path}" + url = "ws://#{@ws_host}:#{@ws_port}#{@path}" end PusherClient.logger.debug("Pusher : connecting : #{url}") @connection_thread = Thread.new { - options = {:ssl => @encrypted || @secure} + options = {:ssl => @encrypted, :cert_file => @cert_file, :ssl_verify => @ssl_verify} @connection = PusherWebSocket.new(url, options) PusherClient.logger.debug "Websocket connected" loop do msg = @connection.receive[0] @@ -85,12 +88,16 @@ else PusherClient.logger.warn "Disconnect attempted... not connected" end end - def subscribe(channel_name, user_id = nil) - @user_data = {:user_id => user_id}.to_json unless user_id.nil? + def subscribe(channel_name, user_data = nil) + if user_data.is_a? Hash + @user_data = user_data.to_json + elsif not user_data.nil? + @user_data = {:user_id => user_data}.to_json + end channel = @channels << channel_name if @connected authorize(channel, method(:authorize_callback)) end @@ -154,18 +161,22 @@ def is_presence_channel(channel_name) channel_name.match(/^presence-/) end def get_private_auth(channel) - string_to_sign = @socket_id + ':' + channel.name - signature = HMAC::SHA256.hexdigest(@secret, string_to_sign) - return "#{@key}:#{signature}" + if (@private_auth_method.nil?) + string_to_sign = @socket_id + ':' + channel.name + signature = hmac(@secret, string_to_sign) + return "#{@key}:#{signature}" + else + return @private_auth_method.call(@socket_id, channel) + end end def get_presence_auth(channel) string_to_sign = @socket_id + ':' + channel.name + ':' + @user_data - signature = HMAC::SHA256.hexdigest(@secret, string_to_sign) + signature = hmac(@secret, string_to_sign) return "#{@key}:#{signature}" end # For compatibility with JavaScript client API @@ -190,16 +201,20 @@ @global_channel.dispatch_with_all(event_name, event_data) PusherClient.logger.debug("Pusher : event received : channel: #{channel_name}; event: #{event_name}") end def parser(data) - begin - return JSON.parse(data) - rescue => err - PusherClient.logger.warn(err) - PusherClient.logger.warn("Pusher : data attribute not valid JSON - you may wish to implement your own Pusher::Client.parser") - return data - end + return data if data.is_a? Hash + return JSON.parse(data) + rescue => err + PusherClient.logger.warn(err) + PusherClient.logger.warn("Pusher : data attribute not valid JSON - you may wish to implement your own Pusher::Client.parser") + return data + end + + def hmac(secret, string_to_sign) + digest = OpenSSL::Digest::SHA256.new + signature = OpenSSL::HMAC.hexdigest(digest, secret, string_to_sign) end end end