punchblock 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
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