Class: Wampproto::Dealer

Inherits:
Object
  • Object
show all
Defined in:
lib/wampproto/dealer.rb

Overview

Wamprpoto Dealer handler

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id_gen = IdGenerator.new) ⇒ Dealer

Returns a new instance of Dealer.



9
10
11
12
13
14
15
16
# File 'lib/wampproto/dealer.rb', line 9

def initialize(id_gen = IdGenerator.new)
  @registrations_by_session = {}
  @registrations_by_procedure = Hash.new { |h, k| h[k] = {} }
  @pending_calls = {}
  @pending_invocations = {}
  @id_gen = id_gen
  @sessions = {}
end

Instance Attribute Details

#id_genObject (readonly)

Returns the value of attribute id_gen.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def id_gen
  @id_gen
end

#pending_callsObject (readonly)

Returns the value of attribute pending_calls.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def pending_calls
  @pending_calls
end

#pending_invocationsObject (readonly)

Returns the value of attribute pending_invocations.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def pending_invocations
  @pending_invocations
end

#registrations_by_procedureObject (readonly)

Returns the value of attribute registrations_by_procedure.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def registrations_by_procedure
  @registrations_by_procedure
end

#registrations_by_sessionObject (readonly)

Returns the value of attribute registrations_by_session.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def registrations_by_session
  @registrations_by_session
end

#sessionsObject (readonly)

Returns the value of attribute sessions.



6
7
8
# File 'lib/wampproto/dealer.rb', line 6

def sessions
  @sessions
end

Instance Method Details

#add_session(details) ⇒ Object

Raises:

  • (KeyError)


18
19
20
21
22
23
24
25
26
# File 'lib/wampproto/dealer.rb', line 18

def add_session(details)
  session_id = details.session_id

  error_message = "cannot add session twice"
  raise KeyError, error_message if registrations_by_session.include?(session_id)

  registrations_by_session[session_id] = {}
  sessions[session_id] = details
end

#handle_call(session_id, message) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/wampproto/dealer.rb', line 57

def handle_call(session_id, message) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  registrations = registrations_by_procedure.fetch(message.procedure, {})
  if registrations.empty?
    error = Message::Error.new(Message::Type::CALL, message.request_id, {}, "wamp.error.no_such_procedure")
    return MessageWithRecipient.new(error, session_id)
  end

  registration_id, callee_id = registrations.first

  pending_calls[callee_id] = {} unless pending_calls.include?(callee_id)
  pending_invocations[callee_id] = {} unless pending_invocations.include?(callee_id)

  # we received call from the "caller" lets call that request_id "1"
  # we need to send invocation message to "callee" let call that request_id "10"
  # we need "caller" id after we have received yield so that request_id will be "10"
  # we need to send request to "caller" to the original request_id 1
  request_id = id_gen.next

  pending_invocations[callee_id][request_id] = session_id

  pending_calls[callee_id][session_id] = message.request_id

  invocation = Message::Invocation.new(
    request_id,
    registration_id,
    invocation_details_for(session_id, message),
    *message.args,
    **message.kwargs
  )

  MessageWithRecipient.new(invocation, callee_id)
end

#handle_register(session_id, message) ⇒ Object

Raises:



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/wampproto/dealer.rb', line 111

def handle_register(session_id, message)
  error_message = "cannot register, session #{session_id} doesn't exist"
  raise ValueError, error_message unless registrations_by_session.include?(session_id)

  registration_id = id_gen.next
  registrations_by_procedure[message.procedure][registration_id] = session_id
  registrations_by_session[session_id][registration_id] = message.procedure

  registered = Message::Registered.new(message.request_id, registration_id)
  MessageWithRecipient.new(registered, session_id)
end

#handle_unregister(session_id, message) ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/MethodLength)

Raises:



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/wampproto/dealer.rb', line 123

def handle_unregister(session_id, message) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength)
  error_message = "cannot unregister, session #{session_id} doesn't exist"
  raise ValueError, error_message unless registrations_by_session.include?(session_id)

  registrations = registrations_by_session.fetch(session_id)

  unless registrations.include?(message.registration_id)
    error = Message::Error.new(Message::Type::UNREGISTER, message.request_id, {}, "wamp.error.no_such_registration")
    return MessageWithRecipient.new(error, session_id)
  end

  procedure = registrations.fetch(message.registration_id)

  registrations_by_procedure[procedure].delete(message.registration_id)
  registrations_by_session[session_id].delete(message.registration_id)

  unregistered = Message::Unregistered.new(message.request_id)
  MessageWithRecipient.new(unregistered, session_id)
end

#handle_yield(session_id, message) ⇒ Object

Raises:



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/wampproto/dealer.rb', line 97

def handle_yield(session_id, message)
  calls = pending_calls.fetch(session_id, {})
  error_message = "no pending calls for session #{session_id}"
  raise ValueError, error_message if calls.empty?

  invocations = pending_invocations[session_id]
  caller_id = invocations.delete(message.request_id).to_i # make steep happy

  request_id = calls.delete(caller_id)

  result = Message::Result.new(request_id, {}, *message.args, **message.kwargs)
  MessageWithRecipient.new(result, caller_id)
end

#invocation_details_for(session_id, message) ⇒ Object



90
91
92
93
94
95
# File 'lib/wampproto/dealer.rb', line 90

def invocation_details_for(session_id, message)
  return {} unless message.options.include?(:disclose_me)

  session = sessions[session_id]
  { caller: session_id, caller_authid: session.authid, caller_authrole: session.authrole }
end

#receive_message(session_id, message) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/wampproto/dealer.rb', line 46

def receive_message(session_id, message)
  case message
  when Wampproto::Message::Call then handle_call(session_id, message)
  when Message::Yield then handle_yield(session_id, message)
  when Message::Register then handle_register(session_id, message)
  when Message::Unregister then handle_unregister(session_id, message)
  else
    raise ValueError, "message type not supported"
  end
end

#registration?(procedure) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
42
43
44
# File 'lib/wampproto/dealer.rb', line 39

def registration?(procedure)
  registrations = registrations_by_procedure[procedure]
  return false unless registrations

  registrations.any?
end

#remove_session(session_id) ⇒ Object

Raises:

  • (KeyError)


28
29
30
31
32
33
34
35
36
37
# File 'lib/wampproto/dealer.rb', line 28

def remove_session(session_id)
  error_message = "cannot remove non-existing session"
  raise KeyError, error_message unless registrations_by_session.include?(session_id)

  registrations = registrations_by_session.delete(session_id) || {}
  registrations.each do |registration_id, procedure|
    registrations_by_procedure[procedure].delete(registration_id)
  end
  sessions.delete(session_id)
end