Class: Adhearsion::Call

Inherits:
Object show all
Includes:
Celluloid, HasGuardedHandlers
Defined in:
lib/adhearsion/call.rb

Overview

Encapsulates call-related data and behavior.

Direct Known Subclasses

OutboundCall

Constant Summary collapse

Hangup =
Class.new Adhearsion::Error
CommandTimeout =
Class.new Adhearsion::Error
ExpiredError =
Class.new Celluloid::DeadActorError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Celluloid

logger

Constructor Details

#initialize(offer = nil) ⇒ Call


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/adhearsion/call.rb', line 83

def initialize(offer = nil)
  register_initial_handlers

  @offer        = nil
  @tags         = []
  @commands     = CommandRegistry.new
  @variables    = HashWithIndifferentAccess.new
  @controllers  = []
  @end_reason   = nil
  @end_code     = nil
  @end_blocker  = Celluloid::Condition.new
  @peers        = {}
  @duration     = nil
  @auto_hangup  = true
  @after_hangup_lifetime = nil

  self << offer if offer
end

Instance Attribute Details

#after_hangup_lifetimeInteger


64
65
66
# File 'lib/adhearsion/call.rb', line 64

def after_hangup_lifetime
  @after_hangup_lifetime
end

#auto_hanguptrue, false


61
62
63
# File 'lib/adhearsion/call.rb', line 61

def auto_hangup
  @auto_hangup
end

#controllersArray<Adhearsion::CallController> (readonly)


49
50
51
# File 'lib/adhearsion/call.rb', line 49

def controllers
  @controllers
end

#end_codeString (readonly)


46
47
48
# File 'lib/adhearsion/call.rb', line 46

def end_code
  @end_code
end

#end_reasonSymbol (readonly)


43
44
45
# File 'lib/adhearsion/call.rb', line 43

def end_reason
  @end_reason
end

#end_timeTime (readonly)


58
59
60
# File 'lib/adhearsion/call.rb', line 58

def end_time
  @end_time
end

#start_timeTime (readonly)


55
56
57
# File 'lib/adhearsion/call.rb', line 55

def start_time
  @start_time
end

#variablesHash<String => String> (readonly)


52
53
54
# File 'lib/adhearsion/call.rb', line 52

def variables
  @variables
end

Class Method Details

.uri(transport, id, domain) ⇒ Object


74
75
76
77
78
79
80
81
# File 'lib/adhearsion/call.rb', line 74

def self.uri(transport, id, domain)
  return nil unless id
  s = ""
  s << transport << ":" if transport
  s << id
  s << "@" << domain if domain
  s
end

Instance Method Details

#accept(headers = nil) ⇒ Object


313
314
315
316
317
# File 'lib/adhearsion/call.rb', line 313

def accept(headers = nil)
  @accept_command ||= write_and_await_response Adhearsion::Rayo::Command::Accept.new(:headers => headers)
rescue Adhearsion::ProtocolError => e
  abort e
end

#active?Boolean


309
310
311
# File 'lib/adhearsion/call.rb', line 309

def active?
  !end_reason
end

#answer(headers = nil) ⇒ Object


319
320
321
322
323
# File 'lib/adhearsion/call.rb', line 319

def answer(headers = nil)
  write_and_await_response Adhearsion::Rayo::Command::Answer.new(:headers => headers)
rescue Adhearsion::ProtocolError => e
  abort e
end

#commandsObject


206
207
208
# File 'lib/adhearsion/call.rb', line 206

def commands
  @commands.clone
end

#deliver_message(message) ⇒ Object Also known as: <<


198
199
200
201
202
203
# File 'lib/adhearsion/call.rb', line 198

def deliver_message(message)
  logger.debug "Receiving message: #{message.inspect}"
  catching_standard_errors do
    trigger_handler :event, message, broadcast: true, exception_callback: ->(e) { Adhearsion::Events.trigger :exception, [e, logger] }
  end
end

#domainString?


113
114
115
# File 'lib/adhearsion/call.rb', line 113

def domain
  offer.domain if offer
end

#durationFloat


263
264
265
266
267
268
269
270
271
# File 'lib/adhearsion/call.rb', line 263

def duration
  if @duration
    @duration
  elsif @start_time
    Time.now - @start_time
  else
    0.0
  end
end

#execute_controller(controller = nil, completion_callback = nil) { ... } ⇒ Celluloid::ThreadHandle

Execute a call controller asynchronously against this call.

To block and wait until the controller completes, call `#join` on the result of this method.

Yields:

  • execute the current block as the body of a controller by specifying no controller instance

Raises:

  • (ArgumentError)

541
542
543
544
545
546
# File 'lib/adhearsion/call.rb', line 541

def execute_controller(controller = nil, completion_callback = nil, &block)
  raise ArgumentError, "Cannot supply a controller and a block at the same time" if controller && block_given?
  controller ||= CallController.new current_actor, &block
  logger.info "Executing controller #{controller.class}"
  controller.bg_exec completion_callback
end

#fromString


72
# File 'lib/adhearsion/call.rb', line 72

delegate :from, to: :offer, allow_nil: true

#hangup(headers = nil) ⇒ Object


352
353
354
355
356
357
358
359
# File 'lib/adhearsion/call.rb', line 352

def hangup(headers = nil)
  return false unless active?
  logger.info "Hanging up"
  @end_reason = true
  write_and_await_response Adhearsion::Rayo::Command::Hangup.new(:headers => headers)
rescue Adhearsion::ProtocolError => e
  abort e
end

#idString? Also known as: to_s


105
106
107
# File 'lib/adhearsion/call.rb', line 105

def id
  offer.target_call_id if offer
end

#join(target, options = {}) ⇒ Hash

Joins this call to another call or a mixer

Options Hash (target):

  • call_uri (String)

    The call ID to join to

  • mixer_name (String)

    The mixer to join to


376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/adhearsion/call.rb', line 376

def join(target, options = {})
  logger.debug "Joining to #{target}"

  joined_condition = CountDownLatch.new(1)
  on_joined target do
    joined_condition.countdown!
  end

  unjoined_condition = CountDownLatch.new(1)
  on_unjoined target do
    unjoined_condition.countdown!
  end

  on_end do
    joined_condition.countdown!
    unjoined_condition.countdown!
  end

  command = Adhearsion::Rayo::Command::Join.new options.merge(join_options_with_target(target))
  write_and_await_response command
  {command: command, joined_condition: joined_condition, unjoined_condition: unjoined_condition}
rescue Adhearsion::ProtocolError => e
  abort e
end

#muteObject


454
455
456
457
458
# File 'lib/adhearsion/call.rb', line 454

def mute
  write_and_await_response Adhearsion::Rayo::Command::Mute.new
rescue Adhearsion::ProtocolError => e
  abort e
end

#on_end(&block) ⇒ Object


302
303
304
# File 'lib/adhearsion/call.rb', line 302

def on_end(&block)
  register_event_handler Adhearsion::Event::End, &block
end

#on_joined(target = nil, &block) ⇒ Object

Registers a callback for when this call is joined to another call or a mixer

Options Hash (target):

  • call_uri (String)

    The call ID to guard on

  • mixer_name (String)

    The mixer name to guard on


280
281
282
283
284
# File 'lib/adhearsion/call.rb', line 280

def on_joined(target = nil, &block)
  register_event_handler Adhearsion::Event::Joined, *guards_for_target(target) do |event|
    block.call event
  end
end

#on_unjoined(target = nil, &block) ⇒ Object

Registers a callback for when this call is unjoined from another call or a mixer

Options Hash (target):

  • call_uri (String)

    The call ID to guard on

  • mixer_name (String)

    The mixer name to guard on


293
294
295
# File 'lib/adhearsion/call.rb', line 293

def on_unjoined(target = nil, &block)
  register_event_handler Adhearsion::Event::Unjoined, *guards_for_target(target), &block
end

#peersHash<String => Adhearsion::Call>

Hash of joined peers


163
164
165
# File 'lib/adhearsion/call.rb', line 163

def peers
  @peers.clone
end

#redirect(to, headers = nil) ⇒ Object

Redirect the call to some other target system.

If the redirect is successful, the call will be released from the telephony engine and Adhearsion will lose control of the call.

Note that for the common case, this will result in a SIP 302 or SIP REFER, which provides the caller with a new URI to dial. As such, the redirect target cannot be any telephony-engine specific address (such as sofia/gateway, agent/101, or SIP/mypeer); instead it should be a fully-qualified external SIP URI that the caller can independently reach.


346
347
348
349
350
# File 'lib/adhearsion/call.rb', line 346

def redirect(to, headers = nil)
  write_and_await_response Adhearsion::Rayo::Command::Redirect.new(to: to, headers: headers)
rescue Adhearsion::ProtocolError => e
  abort e
end

#register_event_handler(*guards) {|Object| ... } ⇒ String

Register a handler for events on this call. Note that Adhearsion::Call implements the has-guarded-handlers API, and all of its methods are available. Specifically, all Adhearsion events are available on the `:event` channel.

Yields:

  • (Object)

    trigger_object the incoming event

See Also:


194
195
196
# File 'lib/adhearsion/call.rb', line 194

def register_event_handler(*guards, &block)
  register_handler :event, *guards, &block
end

#reject(reason = :busy, headers = nil) ⇒ Object


325
326
327
328
329
330
# File 'lib/adhearsion/call.rb', line 325

def reject(reason = :busy, headers = nil)
  write_and_await_response Adhearsion::Rayo::Command::Reject.new(:reason => reason, :headers => headers)
  Adhearsion::Events.trigger_immediately :call_rejected, call: current_actor, reason: reason
rescue Adhearsion::ProtocolError => e
  abort e
end

#remove_tag(label) ⇒ Object

Remove a label


146
147
148
# File 'lib/adhearsion/call.rb', line 146

def remove_tag(label)
  @tags.reject! { |tag| tag == label }
end

#send_message(body, options = {}) ⇒ Object

Sends a message to the caller

Options Hash (options):

  • subject (String)

    The message subject.


511
512
513
514
# File 'lib/adhearsion/call.rb', line 511

def send_message(body, options = {})
  logger.debug "Sending message: #{body}"
  client.send_message id, domain, body, options
end

#tag(label) ⇒ Object

Tag a call with an arbitrary label


136
137
138
139
# File 'lib/adhearsion/call.rb', line 136

def tag(label)
  abort ArgumentError.new "Tag must be a String or Symbol" unless [String, Symbol].include?(label.class)
  @tags << label
end

#tagged_with?(label) ⇒ Boolean

Establish if the call is tagged with the provided label


155
156
157
# File 'lib/adhearsion/call.rb', line 155

def tagged_with?(label)
  @tags.include? label
end

#tagsArray


127
128
129
# File 'lib/adhearsion/call.rb', line 127

def tags
  @tags.clone
end

#toString


69
# File 'lib/adhearsion/call.rb', line 69

delegate :to, to: :offer, allow_nil: true

#unjoin(target = nil) ⇒ Object

Unjoins this call from another call or a mixer

Options Hash (target):

  • call_uri (String)

    The call ID to unjoin from

  • mixer_name (String)

    The mixer to unjoin from


408
409
410
411
412
413
414
# File 'lib/adhearsion/call.rb', line 408

def unjoin(target = nil)
  logger.info "Unjoining from #{target}"
  command = Adhearsion::Rayo::Command::Unjoin.new join_options_with_target(target)
  write_and_await_response command
rescue Adhearsion::ProtocolError => e
  abort e
end

#unmuteObject


460
461
462
463
464
# File 'lib/adhearsion/call.rb', line 460

def unmute
  write_and_await_response Adhearsion::Rayo::Command::Unmute.new
rescue Adhearsion::ProtocolError => e
  abort e
end

#uriString?


120
121
122
# File 'lib/adhearsion/call.rb', line 120

def uri
  self.class.uri(transport, id, domain)
end

#wait_for_end(timeout = nil) ⇒ Symbol

Wait for the call to end. Returns immediately if the call has already ended, else blocks until it does so.


173
174
175
176
177
178
179
180
181
# File 'lib/adhearsion/call.rb', line 173

def wait_for_end(timeout = nil)
  if end_reason
    end_reason
  else
    @end_blocker.wait(timeout)
  end
rescue Celluloid::ConditionError => e
  abort e
end

#wait_for_joined(expected_target) ⇒ Object


440
441
442
443
444
445
# File 'lib/adhearsion/call.rb', line 440

def wait_for_joined(expected_target)
  target = nil
  until target == expected_target do
    target = wait :joined
  end
end

#wait_for_unjoined(expected_target) ⇒ Object


447
448
449
450
451
452
# File 'lib/adhearsion/call.rb', line 447

def wait_for_unjoined(expected_target)
  target = nil
  until target == expected_target do
    target = wait :unjoined
  end
end