Class: PusherClient::Socket

Inherits:
Object
  • Object
show all
Defined in:
lib/pusher-client/socket.rb

Constant Summary collapse

CLIENT_ID =

Mimick the JavaScript client

'js'
VERSION =
'1.7.1'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(application_key, options = {}) ⇒ Socket

Returns a new instance of Socket.

Raises:

  • (ArgumentError)


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
# File 'lib/pusher-client/socket.rb', line 15

def initialize(application_key, options={})
  raise ArgumentError if (!application_key.is_a?(String) || application_key.size < 1)

  @path = "/app/#{application_key}?client=#{CLIENT_ID}&version=#{VERSION}"
  @key = application_key
  @secret = options[:secret]
  @socket_id = nil
  @subscriptions = Subscriptions.new
  @global_channel = Channel.new('pusher_global_channel')
  @global_channel.global = true
  @secure = false
  @connected = false
  @encrypted = options[:encrypted] || false

  bind('pusher:connection_established') do |data|
    socket = JSON.parse(data)
    @connected = true
    @socket_id = socket['socket_id']
    subscribe_all
  end

  bind('pusher:connection_disconnected') do |data|
    @subscriptions.subscriptions.each { |s| s.disconnect }
  end

  bind('pusher:error') do |data|
    PusherClient.logger.fatal("Pusher : error : #{data.inspect}")
  end
end

Instance Attribute Details

#connectedObject (readonly)

Returns the value of attribute connected.



13
14
15
# File 'lib/pusher-client/socket.rb', line 13

def connected
  @connected
end

#encryptedObject

Returns the value of attribute encrypted.



12
13
14
# File 'lib/pusher-client/socket.rb', line 12

def encrypted
  @encrypted
end

#global_channelObject (readonly)

Returns the value of attribute global_channel.



13
14
15
# File 'lib/pusher-client/socket.rb', line 13

def global_channel
  @global_channel
end

#pathObject (readonly)

Returns the value of attribute path.



13
14
15
# File 'lib/pusher-client/socket.rb', line 13

def path
  @path
end

#secureObject

Returns the value of attribute secure.



12
13
14
# File 'lib/pusher-client/socket.rb', line 12

def secure
  @secure
end

#socket_idObject (readonly)

Returns the value of attribute socket_id.



13
14
15
# File 'lib/pusher-client/socket.rb', line 13

def socket_id
  @socket_id
end

#subscriptionsObject (readonly)

Returns the value of attribute subscriptions.



13
14
15
# File 'lib/pusher-client/socket.rb', line 13

def subscriptions
  @subscriptions
end

Instance Method Details

#[](channel_name) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/pusher-client/socket.rb', line 123

def [](channel_name)
  if @subscriptions[channel_name]
    @subscriptions[channel_name]
  else
    @subscriptions << channel_name
  end
end

#authorize(subscription, callback) ⇒ Object



131
132
133
134
135
136
137
138
# File 'lib/pusher-client/socket.rb', line 131

def authorize(subscription, callback)
  if is_private_channel(subscription)
    auth_data = get_private_auth(subscription)
  elsif is_presence_channel(subscription)
    auth_data = get_presence_auth(subscription)
  end
  callback.call(subscription, auth_data)
end

#authorize_callback(subscription, auth_data) ⇒ Object



140
141
142
143
144
145
146
147
# File 'lib/pusher-client/socket.rb', line 140

def authorize_callback(subscription, auth_data)
  send_event('pusher:subscribe', {
    'channel' => subscription.channel,
    'auth' => auth_data,
    'channel_data' => subscription.user_data
  })
  subscription.acknowledge_subscription(nil)
end

#bind(event_name, &callback) ⇒ Object



118
119
120
121
# File 'lib/pusher-client/socket.rb', line 118

def bind(event_name, &callback)
  @global_channel.bind(event_name, &callback)
  return self
end

#connect(async = false) ⇒ Object



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
# File 'lib/pusher-client/socket.rb', line 45

def connect(async = false)
  if @encrypted || @secure
    url = "wss://#{HOST}:#{WSS_PORT}#{@path}"
  else
    url = "ws://#{HOST}:#{WS_PORT}#{@path}"
  end
  PusherClient.logger.debug("Pusher : connecting : #{url}")

  @connection_thread = Thread.new {
    @connection = WebSocket.new(url)
    PusherClient.logger.debug "Websocket connected"
    loop do
      msg = @connection.receive[0]
      params  = parser(msg)
      next if (params['socket_id'] && params['socket_id'] == self.socket_id)
      event_name   = params['event']
      event_data   = params['data']
      channel_name = params['channel']
      send_local_event(event_name, event_data, channel_name)
    end
  }

  @connection_thread.run
  @connection_thread.join unless async
  return self
end

#disconnectObject



72
73
74
75
76
77
78
79
80
81
# File 'lib/pusher-client/socket.rb', line 72

def disconnect
  if @connected
    PusherClient.logger.debug "Pusher : disconnecting"
    @connection.close
    @connection_thread.kill if @connection_thread
    @connected = false
  else
    PusherClient.logger.warn "Disconnect attempted... not connected"
  end
end

#get_presence_auth(subscription) ⇒ Object



163
164
165
166
167
# File 'lib/pusher-client/socket.rb', line 163

def get_presence_auth(subscription)
  string_to_sign = @socket_id + ':' + subscription.channel + ':' + subscription.user_data
  signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
  return "#{@key}:#{signature}"
end

#get_private_auth(subscription) ⇒ Object



157
158
159
160
161
# File 'lib/pusher-client/socket.rb', line 157

def get_private_auth(subscription)
  string_to_sign = @socket_id + ':' + subscription.channel + ':' + subscription.user_data
  signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
  return "#{@key}:#{signature}"
end

#is_presence_channel(subscription) ⇒ Object



153
154
155
# File 'lib/pusher-client/socket.rb', line 153

def is_presence_channel(subscription)
  subscription.channel.match(/^presence-/)
end

#is_private_channel(subscription) ⇒ Object



149
150
151
# File 'lib/pusher-client/socket.rb', line 149

def is_private_channel(subscription)
  subscription.channel.match(/^private-/)
end

#send_event(event_name, data) ⇒ Object



172
173
174
175
176
# File 'lib/pusher-client/socket.rb', line 172

def send_event(event_name, data)
  payload = {'event' => event_name, 'data' => data}.to_json
  @connection.send(payload)
  PusherClient.logger.debug("Pusher : sending event : #{payload}")
end

#subscribe(channel_name, user_id = nil, options = {}) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/pusher-client/socket.rb', line 83

def subscribe(channel_name, user_id = nil, options={})
  if user_id
    user_data = {:user_id => user_id, :user_info => options}.to_json
  else
    user_data = {:user_id => '', :user_info => ''}.to_json
  end

  subscription = @subscriptions.add(channel_name, user_data)
  if @connected
    authorize(subscription, method(:authorize_callback))
  end
  return subscription
end

#subscribe_allObject Also known as: subscribeAll



104
105
106
# File 'lib/pusher-client/socket.rb', line 104

def subscribe_all
  @subscriptions.subscriptions.each{ |s| subscribe_existing(s) }
end

#subscribe_existing(subscription) ⇒ Object



97
98
99
100
101
102
# File 'lib/pusher-client/socket.rb', line 97

def subscribe_existing(subscription)
  if @connected
    authorize(subscription, method(:authorize_callback))
  end
  return subscription
end

#unsubscribe(channel_name, user_data) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/pusher-client/socket.rb', line 108

def unsubscribe(channel_name, user_data)
  subscription = @subscriptions.remove(channel_name, user_data)
  if @connected
    send_event('pusher:unsubscribe', {
      'channel' => channel_name
    })
  end
  return subscription
end