Class: Faye::Server

Inherits:
Object
  • Object
show all
Includes:
Extensible, Logging
Defined in:
lib/faye/protocol/server.rb

Constant Summary

Constant Summary

Constants included from Logging

Logging::DEFAULT_LOG_LEVEL, Logging::LOG_LEVELS

Instance Attribute Summary

Attributes included from Logging

#log_level

Instance Method Summary (collapse)

Methods included from Extensible

#add_extension, #pipe_through_extensions, #remove_extension

Methods included from Logging

#log

Constructor Details

- (Server) initialize(options = {})

A new instance of Server



7
8
9
10
11
12
13
14
# File 'lib/faye/protocol/server.rb', line 7

def initialize(options = {})
  @options    = options || {}
  engine_opts = @options[:engine] || {}
  engine_opts[:timeout] = @options[:timeout]
  @engine     = Faye::Engine.get(engine_opts)

  info 'Created new server: ?', @options
end

Instance Method Details

- (Object) advize(response)



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/faye/protocol/server.rb', line 100

def advize(response)
  return unless [Channel::HANDSHAKE, Channel::CONNECT].include?(response['channel'])
  
  advice = response['advice'] ||= {}
  if response['error']
    advice['reconnect'] ||= 'handshake'
  else
    advice['reconnect'] ||= 'retry'
    advice['interval']  ||= (@engine.interval * 1000).floor
    advice['timeout']   ||= (@engine.timeout * 1000).floor
  end
end

- (Object) connect(message, local = false, &callback)

MUST contain * clientId

* connectionType

MAY contain * ext

* id


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/faye/protocol/server.rb', line 150

def connect(message, local = false, &callback)
  response        = make_response(message)
  client_id       = message['clientId']
  connection_type = message['connectionType']
  
  @engine.client_exists(client_id) do |exists|
    response['error'] = Error.client_unknown(client_id) unless exists
    response['error'] = Error.parameter_missing('clientId') if client_id.nil?
    
    unless CONNECTION_TYPES.include?(connection_type)
      response['error'] = Error.conntype_mismatch(connection_type)
    end
    
    response['error'] = Error.parameter_missing('connectionType') if connection_type.nil?
    
    response['successful'] = response['error'].nil?
    
    if response['successful']
      @engine.connect(response['clientId'], message['advice']) do |events|
        callback.call([response] + events)
      end
    else
      response.delete('clientId')
      callback.call(response)
    end
  end
end

- (Object) disconnect(message, local = false, &callback)

MUST contain * clientId MAY contain * ext

* id


181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/faye/protocol/server.rb', line 181

def disconnect(message, local = false, &callback)
  response   = make_response(message)      
  client_id  = message['clientId']
  
  @engine.client_exists(client_id) do |exists|
    response['error'] = Error.client_unknown(client_id) unless exists
    response['error'] = Error.parameter_missing('clientId') if client_id.nil?
    
    response['successful'] = response['error'].nil?
    response.delete('clientId') unless response['successful']
    
    @engine.destroy_client(client_id) if response['successful']
    callback.call(response)
  end
end

- (Object) flush_connection(messages)



16
17
18
19
20
21
22
# File 'lib/faye/protocol/server.rb', line 16

def flush_connection(messages)
  [messages].flatten.each do |message|
    client_id = message["clientId"]
    info 'Flushing connection for ?', client_id
    @engine.flush(client_id) if client_id
  end
end

- (Object) handle(message, local = false, &callback)



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/faye/protocol/server.rb', line 71

def handle(message, local = false, &callback)
  return callback.call([]) if !message
  info 'Handling message: ? (local: ?)', message, local
  
  channel_name = message['channel']
  
  return handle_meta(message, local, &callback) if Channel.meta?(channel_name)
  
  @engine.publish(message) unless message['error'] or Grammar::CHANNEL_NAME !~ channel_name
  
  if message['clientId']
    response = make_response(message)
    response['successful'] = !response['error']
    callback.call([response])
  else
    callback.call([])
  end
end

- (Object) handle_meta(message, local, &callback)



90
91
92
93
94
95
96
97
98
# File 'lib/faye/protocol/server.rb', line 90

def handle_meta(message, local, &callback)
  method = Channel.parse(message['channel'])[1]
  
  __send__(method, message, local) do |responses|
    responses = [responses].flatten
    responses.each(&method(:advize))
    callback.call(responses)
  end
end

- (Object) handshake(message, local = false, &callback)

MUST contain * version

* supportedConnectionTypes

MAY contain * minimumVersion

* ext
* id


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/faye/protocol/server.rb', line 118

def handshake(message, local = false, &callback)
  response = make_response(message)
  response['version'] = BAYEUX_VERSION
  
  response['error'] = Error.parameter_missing('version') if message['version'].nil?
  
  client_conns = message['supportedConnectionTypes']
  
  unless local
    response['supportedConnectionTypes'] = CONNECTION_TYPES
    
    if client_conns
      common_conns = client_conns.select { |c| CONNECTION_TYPES.include?(c) }
      response['error'] = Error.conntype_mismatch(*client_conns) if common_conns.empty?
    else
      response['error'] = Error.parameter_missing('supportedConnectionTypes')
    end
  end
  
  response['successful'] = response['error'].nil?
  return callback.call(response) unless response['successful']
  
  @engine.create_client do |client_id|
    response['clientId'] = client_id
    callback.call(response)
  end
end

- (Object) make_response(message)



60
61
62
63
64
65
66
67
68
69
# File 'lib/faye/protocol/server.rb', line 60

def make_response(message)
  response = {}
  %w[id clientId channel error].each do |field|
    if message[field]
      response[field] = message[field]
    end
  end
  response['successful'] = !response['error']
  response
end

- (Object) process(messages, local = false, &callback)



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/faye/protocol/server.rb', line 24

def process(messages, local = false, &callback)
  messages = [messages].flatten
  info 'Processing messages: ? (local: ?)', messages, local

  return callback.call([]) if messages.size == 0
  processed, responses = 0, []
  
  gather_replies = lambda do |replies|
    responses.concat(replies)
    processed += 1
    responses.compact!
    info 'Returning replies: ?', responses
    callback.call(responses) if processed == messages.size
  end
  
  handle_reply = lambda do |replies|
    extended, expected = 0, replies.size
    gather_replies.call(replies) if expected == 0
    
    replies.each_with_index do |reply, i|
      debug 'Processing reply: ?', reply
      pipe_through_extensions(:outgoing, reply) do |message|
        replies[i] = message
        extended  += 1
        gather_replies.call(replies) if extended == expected
      end
    end
  end
  
  messages.each do |message|
    pipe_through_extensions(:incoming, message) do |piped_message|
      handle(piped_message, local, &handle_reply)
    end
  end
end

- (Object) subscribe(message, local = false, &callback)

MUST contain * clientId

* subscription

MAY contain * ext

* id


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/faye/protocol/server.rb', line 201

def subscribe(message, local = false, &callback)
  response     = make_response(message)
  client_id    = message['clientId']
  subscription = [message['subscription']].flatten
  
  @engine.client_exists(client_id) do |exists|
    response['error'] = Error.client_unknown(client_id) unless exists
    response['error'] = Error.parameter_missing('clientId') if client_id.nil?
    response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
    
    response['subscription'] = message['subscription'] || []
    
    subscription.each do |channel|
      next if response['error']
      response['error'] = Error.channel_forbidden(channel) unless local or Channel.subscribable?(channel)
      response['error'] = Error.channel_invalid(channel) unless Channel.valid?(channel)
      
      next if response['error']
      @engine.subscribe(client_id, channel)
    end
    
    response['successful'] = response['error'].nil?
    callback.call(response)
  end
end

- (Object) unsubscribe(message, local = false, &callback)

MUST contain * clientId

* subscription

MAY contain * ext

* id


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/faye/protocol/server.rb', line 231

def unsubscribe(message, local = false, &callback)
  response     = make_response(message)
  client_id    = message['clientId']
  subscription = [message['subscription']].flatten
  
  @engine.client_exists(client_id) do |exists|
    response['error'] = Error.client_unknown(client_id) unless exists
    response['error'] = Error.parameter_missing('clientId') if client_id.nil?
    response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
    
    response['subscription'] = message['subscription'] || []
    
    subscription.each do |channel|
      next if response['error']
      response['error'] = Error.channel_forbidden(channel) unless local or Channel.subscribable?(channel)
      response['error'] = Error.channel_invalid(channel) unless Channel.valid?(channel)
      
      next if response['error']
      @engine.unsubscribe(client_id, channel)
    end
    
    response['successful'] = response['error'].nil?
    callback.call(response)
  end
end