punchblock 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # [develop](https://github.com/adhearsion/punchblock)
2
2
 
3
+ # [v1.4.1](https://github.com/adhearsion/punchblock/compare/v1.4.0...v1.4.1) - [2012-09-06](https://rubygems.org/gems/punchblock/versions/1.4.1)
4
+ * Bugfix: Cleaning up DTMF handlers for input components with a dead call should not crash on FreeSWITCH
5
+ * Bugfix: Reduced a race condition on FreeSWITCH when dispatching events from calls to dead components
6
+ * Bugfix: Events relevant to bridged channels were not being routed to the call
7
+ * Bugfix: Components using #stop_by_redirect now return an error response if stopped when they are complete
8
+ * Bugfix: Hold back ruby_ami and ruby_fs dependencies pending fixes for Celluloid 0.12.0
9
+
3
10
  # [v1.4.0](https://github.com/adhearsion/punchblock/compare/v1.3.0...v1.4.0) - [2012-08-07](https://rubygems.org/gems/punchblock/versions/1.4.0)
4
11
  * Feature: FreeSWITCH support (mostly complete, experimental, proceed with caution)
5
12
  * Bugfix: Report the correct caller ID in offers from Asterisk
@@ -2,8 +2,7 @@ module Punchblock
2
2
  module DeadActorSafety
3
3
  def safe_from_dead_actors
4
4
  yield
5
- rescue Celluloid::DeadActorError => e
6
- pb_logger.error e
5
+ rescue Celluloid::DeadActorError
7
6
  end
8
7
  end
9
8
  end
@@ -9,8 +9,12 @@ module Punchblock
9
9
  module StopByRedirect
10
10
  def execute_command(command)
11
11
  return super unless command.is_a?(Punchblock::Component::Stop)
12
- stop_by_redirect Punchblock::Event::Complete::Stop.new
13
- command.response = true
12
+ if @complete
13
+ command.response = ProtocolError.new.setup 'component-already-stopped', "Component #{id} is already stopped", call_id, id
14
+ else
15
+ stop_by_redirect Punchblock::Event::Complete::Stop.new
16
+ command.response = true
17
+ end
14
18
  end
15
19
 
16
20
  def stop_by_redirect(complete_reason)
@@ -42,7 +42,7 @@ module Punchblock
42
42
  c << recording if recording
43
43
  end
44
44
  send_event event
45
- current_actor.terminate!
45
+ terminate
46
46
  end
47
47
 
48
48
  def send_event(event)
@@ -19,6 +19,9 @@ module Punchblock
19
19
  REDIRECT_EXTENSION = '1'
20
20
  REDIRECT_PRIORITY = '1'
21
21
 
22
+ CHANNEL_NORMALIZATION_REGEXP = /^(?<prefix>Bridge\/)*(?<channel>[^<>]*)(?<suffix><.*>)*$/.freeze
23
+ EVENTS_ALLOWED_BRIDGED = %w{agiexec asyncagi}
24
+
22
25
  trap_exit :actor_died
23
26
 
24
27
  def initialize(ami_client, connection, media_engine = nil)
@@ -42,7 +45,7 @@ module Punchblock
42
45
  end
43
46
 
44
47
  def call_for_channel(channel)
45
- call_with_id @channel_to_call_id[channel]
48
+ call_with_id @channel_to_call_id[channel.match(CHANNEL_NORMALIZATION_REGEXP)[:channel]]
46
49
  end
47
50
 
48
51
  def register_component(component)
@@ -176,7 +179,13 @@ module Punchblock
176
179
  if ami_event_known_call?(event)
177
180
  channels_for_ami_event(event).each do |channel|
178
181
  call = call_for_channel channel
179
- call.process_ami_event! event if call
182
+ if call
183
+ if channel_is_bridged?(channel)
184
+ call.process_ami_event! event if EVENTS_ALLOWED_BRIDGED.include?(event.name.downcase)
185
+ else
186
+ call.process_ami_event! event
187
+ end
188
+ end
180
189
  end
181
190
  elsif event.name.downcase == "asyncagi" && event['SubEvent'] == "Start"
182
191
  handle_async_agi_start_event event
@@ -193,6 +202,11 @@ module Punchblock
193
202
  (event['Channel2'] && call_for_channel(event['Channel2']))
194
203
  end
195
204
 
205
+ def channel_is_bridged?(channel)
206
+ matches = channel.match CHANNEL_NORMALIZATION_REGEXP
207
+ matches[:prefix] || matches[:suffix]
208
+ end
209
+
196
210
  def handle_async_agi_start_event(event)
197
211
  env = RubyAMI::AsyncAGIEnvironmentParser.new(event['Env']).to_hash
198
212
 
@@ -102,7 +102,7 @@ module Punchblock
102
102
 
103
103
  register_handler :es, [:has_key?, :scope_variable_punchblock_component_id] => true do |event|
104
104
  if component = component_with_id(event[:scope_variable_punchblock_component_id])
105
- safe_from_dead_actors { component.handle_es_event event }
105
+ safe_from_dead_actors { component.handle_es_event event if component.alive? }
106
106
  end
107
107
  end
108
108
  end
@@ -21,6 +21,7 @@ module Punchblock
21
21
 
22
22
  def unregister_dtmf_event_handler
23
23
  call.unregister_handler :es, @dtmf_handler_id if instance_variable_defined?(:@dtmf_handler_id)
24
+ rescue Celluloid::DeadActorError
24
25
  end
25
26
  end
26
27
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Punchblock
4
- VERSION = "1.4.0"
4
+ VERSION = "1.4.1"
5
5
  end
data/punchblock.gemspec CHANGED
@@ -28,9 +28,9 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency %q<state_machine>, ["~> 1.0"]
29
29
  s.add_runtime_dependency %q<future-resource>, ["~> 1.0"]
30
30
  s.add_runtime_dependency %q<has-guarded-handlers>, ["~> 1.3"]
31
- s.add_runtime_dependency %q<celluloid>, [">= 0.11.0"]
32
- s.add_runtime_dependency %q<ruby_ami>, ["~> 1.2", ">= 1.2.1"]
33
- s.add_runtime_dependency %q<ruby_fs>, ["~> 1.0"]
31
+ s.add_runtime_dependency %q<celluloid>, [">= 0.11.1"]
32
+ s.add_runtime_dependency %q<ruby_ami>, ["~> 1.2", ">= 1.2.1", "< 1.2.2"]
33
+ s.add_runtime_dependency %q<ruby_fs>, ["~> 1.0", "< 1.0.1"]
34
34
  s.add_runtime_dependency %q<ruby_speech>, ["~> 1.0"]
35
35
 
36
36
  s.add_development_dependency %q<bundler>, ["~> 1.0"]
@@ -10,6 +10,9 @@ module Punchblock
10
10
 
11
11
  class MockComponent < Component
12
12
  include StopByRedirect
13
+ def set_complete
14
+ @complete = true
15
+ end
13
16
  end
14
17
 
15
18
  let(:mock_call) { mock 'Call', :id => 'foo' }
@@ -46,9 +49,13 @@ module Punchblock
46
49
  command.response(0.1).should be == true
47
50
  end
48
51
 
52
+ it "returns an error if the component is already complete" do
53
+ subject.set_complete
54
+ subject.execute_command command
55
+ command.response(0.1).should be_a ProtocolError
56
+ end
49
57
  end
50
58
  end
51
-
52
59
  end
53
60
  end
54
61
  end
@@ -583,6 +583,45 @@ module Punchblock
583
583
  end
584
584
  end
585
585
  end
586
+
587
+ describe 'with an event for a channel with Bridge and special statuses appended' do
588
+ let :ami_event do
589
+ RubyAMI::Event.new('AGIExec').tap do |e|
590
+ e['SubEvent'] = "End"
591
+ e['Channel'] = "Bridge/SIP/1234-00000000<ZOMBIE>"
592
+ end
593
+ end
594
+
595
+ let :ami_event2 do
596
+ RubyAMI::Event.new('Hangup').tap do |e|
597
+ e['Uniqueid'] = "1320842458.8"
598
+ e['Calleridnum'] = "5678"
599
+ e['Calleridname'] = "Jane Smith"
600
+ e['Cause'] = "0"
601
+ e['Cause-txt'] = "Unknown"
602
+ e['Channel'] = "Bridge/SIP/1234-00000000<ZOMBIE>"
603
+ end
604
+ end
605
+
606
+ let(:call) do
607
+ Asterisk::Call.new "SIP/1234-00000000", subject, "agi_request%3A%20async%0Aagi_channel%3A%20SIP%2F1234-00000000%0Aagi_language%3A%20en%0Aagi_type%3A%20SIP%0Aagi_uniqueid%3A%201320835995.0%0Aagi_version%3A%201.8.4.1%0Aagi_callerid%3A%205678%0Aagi_calleridname%3A%20Jane%20Smith%0Aagi_callingpres%3A%200%0Aagi_callingani2%3A%200%0Aagi_callington%3A%200%0Aagi_callingtns%3A%200%0Aagi_dnid%3A%201000%0Aagi_rdnis%3A%20unknown%0Aagi_context%3A%20default%0Aagi_extension%3A%201000%0Aagi_priority%3A%201%0Aagi_enhanced%3A%200.0%0Aagi_accountcode%3A%20%0Aagi_threadid%3A%204366221312%0A%0A"
608
+ end
609
+
610
+ before do
611
+ subject.register_call call
612
+ end
613
+
614
+ it 'sends the AMI event to the call and to the connection as a PB event if it is an allowed event' do
615
+ call.expects(:process_ami_event!).once.with ami_event
616
+ subject.handle_ami_event ami_event
617
+ end
618
+
619
+ it 'does not send the AMI event to a bridged channel if it is not allowed' do
620
+ call.expects(:process_ami_event!).never.with ami_event2
621
+ subject.handle_ami_event ami_event2
622
+ end
623
+
624
+ end
586
625
  end#handle_ami_event
587
626
 
588
627
  describe '#send_ami_action' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: punchblock
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-08-07 00:00:00.000000000 Z
14
+ date: 2012-09-06 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: niceogiri
@@ -116,7 +116,7 @@ dependencies:
116
116
  requirements:
117
117
  - - ! '>='
118
118
  - !ruby/object:Gem::Version
119
- version: 0.11.0
119
+ version: 0.11.1
120
120
  type: :runtime
121
121
  prerelease: false
122
122
  version_requirements: !ruby/object:Gem::Requirement
@@ -124,7 +124,7 @@ dependencies:
124
124
  requirements:
125
125
  - - ! '>='
126
126
  - !ruby/object:Gem::Version
127
- version: 0.11.0
127
+ version: 0.11.1
128
128
  - !ruby/object:Gem::Dependency
129
129
  name: ruby_ami
130
130
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,9 @@ dependencies:
136
136
  - - ! '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: 1.2.1
139
+ - - <
140
+ - !ruby/object:Gem::Version
141
+ version: 1.2.2
139
142
  type: :runtime
140
143
  prerelease: false
141
144
  version_requirements: !ruby/object:Gem::Requirement
@@ -147,6 +150,9 @@ dependencies:
147
150
  - - ! '>='
148
151
  - !ruby/object:Gem::Version
149
152
  version: 1.2.1
153
+ - - <
154
+ - !ruby/object:Gem::Version
155
+ version: 1.2.2
150
156
  - !ruby/object:Gem::Dependency
151
157
  name: ruby_fs
152
158
  requirement: !ruby/object:Gem::Requirement
@@ -155,6 +161,9 @@ dependencies:
155
161
  - - ~>
156
162
  - !ruby/object:Gem::Version
157
163
  version: '1.0'
164
+ - - <
165
+ - !ruby/object:Gem::Version
166
+ version: 1.0.1
158
167
  type: :runtime
159
168
  prerelease: false
160
169
  version_requirements: !ruby/object:Gem::Requirement
@@ -163,6 +172,9 @@ dependencies:
163
172
  - - ~>
164
173
  - !ruby/object:Gem::Version
165
174
  version: '1.0'
175
+ - - <
176
+ - !ruby/object:Gem::Version
177
+ version: 1.0.1
166
178
  - !ruby/object:Gem::Dependency
167
179
  name: ruby_speech
168
180
  requirement: !ruby/object:Gem::Requirement
@@ -511,7 +523,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
511
523
  version: '0'
512
524
  segments:
513
525
  - 0
514
- hash: 2536698351368430325
526
+ hash: 1778552231483051908
515
527
  required_rubygems_version: !ruby/object:Gem::Requirement
516
528
  none: false
517
529
  requirements:
@@ -520,7 +532,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
520
532
  version: 1.3.7
521
533
  requirements: []
522
534
  rubyforge_project: punchblock
523
- rubygems_version: 1.8.24
535
+ rubygems_version: 1.8.23
524
536
  signing_key:
525
537
  specification_version: 3
526
538
  summary: Punchblock is a telephony middleware library