signalwire 2.3.3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 617cfadba260ca55f6a9930c26eca415a3db201fdad4165a86f6c06955a98471
4
- data.tar.gz: e78dc8b25ac1cd28e0252962497ed620aa9794635b23b1fc72347b1458e79dfb
3
+ metadata.gz: 2041c5f950f029c9b9d7d6aab709868d0d6ff19eab4fe288171d145ec310b996
4
+ data.tar.gz: 7f00185024b6fbdd22d9bf21af089cc29fdecfce59ffec43ab861d8252b96ba6
5
5
  SHA512:
6
- metadata.gz: 9ca9a848b357a319f84ec836fb73a75a99e5054064fbdf59ffcb44da615b0009df676da2c8abd434062747888618016220e8f016b35682808ebf3acab2a51df4
7
- data.tar.gz: f367464b5544df04e67828765a16c5368af055eb1e24328f9e8a97d93ebac5105a8ebcd840cdee984a257825e9363c49d7f5d791b636ba7e830286962374ad54
6
+ metadata.gz: 130c9720b336190492e270d82e54b7958f44f3e0523fc41a24f6721ddc0ff22c00e0bb87317cee256fb92a233177433161c5d1536bdbe487344b8d7ae7a1263f
7
+ data.tar.gz: cdb660adf6bbced09c63d4bbd331dd35c7d7697fcf4d9675b4ac783889e8604efcd720b827998fb548cf304253f4522666e9c366a8abb1bed5cd6b7f5ffbc9ec
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ - package-ecosystem: github-actions
8
+ directory: "/"
9
+ schedule:
10
+ interval: weekly
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2']
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true
24
+ - name: Run tests
25
+ run: bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -3,7 +3,17 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
- ## [Unreleased]
6
+ ## [Unreleased]
7
+
8
+ ## [2.4.0] - 2023-
9
+ ### Added
10
+ - Add Webhook `ValidateRequest`
11
+
12
+ ## [2.3.4] - 2020-09-09
13
+ ### Fixed
14
+ - Correctly ignore non-call events and clear handlers on call end
15
+ - Async method arguments fixed
16
+ - Fix ping race condition
7
17
 
8
18
  ## [2.3.3] - 2020-03-09
9
19
  ### Fixed
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # SignalWire Ruby
2
2
 
3
3
 
4
- [![Build Status](https://ci.signalwire.com/api/badges/signalwire/signalwire-ruby/status.svg)](https://ci.signalwire.com/signalwire/signalwire-ruby) [![Gem Version](https://badge.fury.io/rb/signalwire.svg)](https://badge.fury.io/rb/signalwire)
4
+ [![CI](https://github.com/signalwire/signalwire-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/signalwire/signalwire-ruby/actions/workflows/ci.yml)
5
+ [![Gem Version](https://badge.fury.io/rb/signalwire.svg)](https://badge.fury.io/rb/signalwire)
5
6
 
6
7
  The Relay SDK for Ruby enables Ruby developers to connect and use SignalWire's Relay APIs within their own Ruby code. Our Relay SDK allows developers to build or add robust and innovative communication services to their applications.
7
8
 
@@ -34,5 +35,5 @@ Relay SDK forRuby follows Semantic Versioning 2.0 as defined at <http://semver.o
34
35
 
35
36
  ## License
36
37
 
37
- Relay SDK for Ruby is copyright © 2018-2019
38
- [SignalWire](http://signalwire.com). It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](https://github.com//signalwire/signalwire-ruby/blob/master/LICENSE) file.
38
+ Relay SDK for Ruby is copyright © 2018-2023
39
+ [SignalWire](http://signalwire.com). It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](https://github.com//signalwire/signalwire-ruby/blob/master/LICENSE) file.
@@ -4,6 +4,7 @@ require 'has_guarded_handlers'
4
4
  require 'eventmachine'
5
5
  require 'faye/websocket'
6
6
  require 'json'
7
+ require 'concurrent-ruby'
7
8
 
8
9
  module Signalwire::Blade
9
10
  class Connection
@@ -22,10 +23,14 @@ module Signalwire::Blade
22
23
  @log_traffic = options.fetch(:log_traffic, true)
23
24
  @authentication = options.fetch(:authentication, nil)
24
25
 
26
+
27
+
25
28
  @inbound_queue = EM::Queue.new
26
29
  @outbound_queue = EM::Queue.new
27
30
 
31
+ @pong = Concurrent::AtomicBoolean.new
28
32
  @keep_alive_timer = nil
33
+ @ping_is_sent = Concurrent::AtomicBoolean.new
29
34
 
30
35
  @shutdown_list = []
31
36
  end
@@ -48,6 +53,7 @@ module Signalwire::Blade
48
53
 
49
54
  def main_loop!
50
55
  EM.run do
56
+ logger.info "CREATING SOCKET"
51
57
  @ws = Faye::WebSocket::Client.new(@url)
52
58
 
53
59
  @ws.on(:open) { |event| broadcast :started, event }
@@ -71,7 +77,7 @@ module Signalwire::Blade
71
77
  begin
72
78
  @connected = true
73
79
  myreq = connect_request
74
- @pong = nil
80
+ @pong.make_false
75
81
 
76
82
  write_command(myreq) do |event|
77
83
  @session_id = event.dig(:result, :sessionid) unless @session_id
@@ -131,7 +137,9 @@ module Signalwire::Blade
131
137
  end
132
138
 
133
139
  def ping(&block)
134
- block_given? ? write_command(Ping.new, &block) : write_command(Ping.new)
140
+ ping_cmd = Ping.new
141
+ block_given? ? write_command(ping_cmd, &block) : write_command(ping_cmd)
142
+ ping_cmd
135
143
  end
136
144
 
137
145
  def subscribe(params, &block)
@@ -150,7 +158,6 @@ module Signalwire::Blade
150
158
  end
151
159
 
152
160
  def disconnect!
153
- # logger.info 'Stopping Blade event loop'
154
161
  clear_connections
155
162
  EM.stop
156
163
  end
@@ -183,19 +190,21 @@ module Signalwire::Blade
183
190
  end
184
191
 
185
192
  def keep_alive
186
- @pong = false
187
-
188
- ping do
189
- @pong = true
193
+ if @ping_is_sent.false?
194
+ ping do
195
+ @pong.make_true
196
+ end
197
+ @ping_is_sent.make_true
198
+ else
199
+ if @pong.false?
200
+ logger.error "KEEPALIVE: Ping failed"
201
+ reconnect! if connected?
202
+ end
203
+ @ping_is_sent.make_false
190
204
  end
191
205
 
192
206
  @keep_alive_timer = EventMachine::Timer.new(Signalwire::Relay::PING_TIMEOUT) do
193
- if @pong === false
194
- logger.error "Ping failed"
195
- reconnect! if connected?
196
- else
197
- keep_alive
198
- end
207
+ keep_alive
199
208
  end
200
209
  end
201
210
 
@@ -10,7 +10,8 @@ module Signalwire::Blade
10
10
  major: 2,
11
11
  minor: 1,
12
12
  revision: 0
13
- }
13
+ },
14
+ agent: "Ruby SDK/#{Signalwire::VERSION}"
14
15
  }
15
16
  }
16
17
  end
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class ConnectAction < Action
7
7
  def result
8
- ConnectResult.new(@component)
8
+ ConnectResult.new(component: @component)
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class DetectAction < Action
7
7
  def result
8
- DetectResult.new(@component)
8
+ DetectResult.new(component: @component)
9
9
  end
10
10
 
11
11
  def stop
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class FaxAction < Action
7
7
  def result
8
- FaxResult.new(@component)
8
+ FaxResult.new(component: @component)
9
9
  end
10
10
 
11
11
  def stop
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class PlayAction < Action
7
7
  def result
8
- PlayResult.new(@component)
8
+ PlayResult.new(component: @component)
9
9
  end
10
10
 
11
11
  def stop
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class PromptAction < Action
7
7
  def result
8
- PromptResult.new(@component)
8
+ PromptResult.new(component: @component)
9
9
  end
10
10
 
11
11
  def stop
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class RecordAction < Action
7
7
  def result
8
- RecordResult.new(@component)
8
+ RecordResult.new(component: @component)
9
9
  end
10
10
 
11
11
  def stop
@@ -5,7 +5,7 @@ require 'forwardable'
5
5
  module Signalwire::Relay::Calling
6
6
  class SendDigitsAction < Action
7
7
  def result
8
- SendDigitsResult.new(@component)
8
+ SendDigitsResult.new(component: @component)
9
9
  end
10
10
  end
11
11
  end
@@ -7,7 +7,7 @@ module Signalwire::Relay::Calling
7
7
  def_delegators :@component, :source_device
8
8
 
9
9
  def result
10
- TapResult.new(@component)
10
+ TapResult.new(component: @component)
11
11
  end
12
12
 
13
13
  def stop
@@ -45,7 +45,7 @@ module Signalwire::Relay::Calling
45
45
  end
46
46
 
47
47
  def setup_call_event_handlers
48
- @client.on(:event, proc { |evt| call_match_event(evt) }) do |event|
48
+ @call_event_handler = @client.on(:event, proc { |evt| call_match_event(evt) }) do |event|
49
49
  case event.event_type
50
50
  when 'calling.call.connect'
51
51
  change_connect_state(event.call_params[:connect_state])
@@ -81,7 +81,8 @@ module Signalwire::Relay::Calling
81
81
  end
82
82
 
83
83
  def call_match_event(event)
84
- event.event_type.match(/calling\.call/) &&
84
+ event.event_type &&
85
+ event.event_type.match(/calling\.call/) &&
85
86
  !event.event_type.match(/receive/) &&
86
87
  (event.call_id == id || event.call_params[:tag] == tag)
87
88
  end
@@ -316,6 +317,7 @@ module Signalwire::Relay::Calling
316
317
  end
317
318
 
318
319
  def finish_call(params)
320
+ @client.unregister_handler(:event, @call_event_handler)
319
321
  terminate_components(params)
320
322
  client.calling.end_call(id)
321
323
  @busy = true if params[:reason] == Relay::DisconnectReason::BUSY
@@ -51,7 +51,7 @@ module Signalwire::Relay::Calling
51
51
  end
52
52
 
53
53
  def after_execute(execute_event)
54
- @url = execute_event.dig(:params, :params, :params, :url)
54
+ @url = execute_event.dig(:params, :params, :params, :url) if execute_event
55
55
  end
56
56
  end
57
57
  end
@@ -10,6 +10,7 @@ require 'signalwire/sdk/voice_response'
10
10
  require 'signalwire/sdk/fax_response'
11
11
  require 'signalwire/sdk/messaging_response'
12
12
  require 'signalwire/rest/client'
13
+ require 'signalwire/webhook/validate_request'
13
14
 
14
15
  module Signalwire
15
16
  module Sdk
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signalwire
4
- VERSION = '2.3.3'
4
+ VERSION = '2.4.0'
5
5
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Signalwire::Webhook
6
+ class ValidateRequest
7
+ attr_reader :private_key
8
+
9
+ def initialize(private_key)
10
+ @private_key = private_key
11
+ raise ArgumentError, 'Private key is required' if @private_key.nil?
12
+ end
13
+
14
+ def validate(url, raw_body, header)
15
+ return false if header.nil? || url.nil?
16
+
17
+ # compatibility validation for POST parameters of x-www-form-urlencoded requests
18
+ if raw_body.is_a?(Hash)
19
+ return validate_with_compatibility_api(url, raw_body, header)
20
+ end
21
+
22
+ # relay json validation
23
+ payload = url + raw_body
24
+ expected_signature = compute_signature(payload)
25
+ valid = secure_compare(expected_signature, header)
26
+
27
+ return true if valid
28
+
29
+ # fallback compatibilty json validation
30
+ validate_with_compatibility_api(url, raw_body, header)
31
+ end
32
+
33
+ private
34
+
35
+ def validate_with_compatibility_api(url, params, signature)
36
+ validator = Twilio::Security::RequestValidator.new(private_key)
37
+ validator.validate(url, params, signature)
38
+ end
39
+
40
+ def compute_signature(payload)
41
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), private_key, payload)
42
+ end
43
+
44
+ # Constant time string comparison, from ActiveSupport
45
+ def secure_compare(a, b)
46
+ return false if a.nil? || b.nil?
47
+ return false unless a.bytesize == b.bytesize
48
+
49
+ l = a.unpack "C#{a.bytesize}"
50
+
51
+ res = 0
52
+ b.each_byte { |byte| res |= byte ^ l.shift }
53
+ res == 0
54
+ end
55
+ end
56
+ end
data/lib/signalwire.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  module Signalwire
4
4
  end
5
5
 
6
+ require 'signalwire/version'
6
7
  require 'signalwire/sdk'
7
8
  require 'signalwire/logger'
8
9
  require 'signalwire/common'
data/signalwire.gemspec CHANGED
@@ -27,17 +27,17 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'bundler', '~> 2.1'
28
28
  spec.add_development_dependency 'bundler-audit', '~> 0.6'
29
29
  spec.add_development_dependency 'guard-rspec', '~> 4.7'
30
- spec.add_development_dependency 'rake', '~> 12.3'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
31
  spec.add_development_dependency 'rdoc', '~> 6.1'
32
32
  spec.add_development_dependency 'rspec', '~> 3.0'
33
33
  spec.add_development_dependency 'rubocop', '~> 0.67'
34
34
  spec.add_development_dependency 'ruby-prof', '~> 0.17'
35
35
  spec.add_development_dependency 'simplecov', '~> 0.16'
36
- spec.add_development_dependency 'vcr', '~> 4.0'
36
+ spec.add_development_dependency 'vcr', '~> 5.0'
37
37
  spec.add_development_dependency 'webmock', '~> 3.5'
38
38
 
39
39
  spec.add_dependency 'twilio-ruby', '~> 5.0'
40
- spec.add_dependency 'faye-websocket', '~> 0.10'
40
+ spec.add_dependency 'faye-websocket', '~> 0.11'
41
41
  spec.add_dependency 'concurrent-ruby', '~> 1.1'
42
42
  spec.add_dependency 'has-guarded-handlers', '~> 1.6.3'
43
43
  spec.add_dependency 'logger', '~> 1.3'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signalwire
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.3
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SignalWire Team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-09 00:00:00.000000000 Z
11
+ date: 2023-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '12.3'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '12.3'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rdoc
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '4.0'
145
+ version: '5.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '4.0'
152
+ version: '5.0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: webmock
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: '0.10'
187
+ version: '0.11'
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: '0.10'
194
+ version: '0.11'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: concurrent-ruby
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -234,7 +234,7 @@ dependencies:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
236
  version: '1.3'
237
- description:
237
+ description:
238
238
  email:
239
239
  - open.source@signalwire.com
240
240
  executables: []
@@ -242,7 +242,8 @@ extensions: []
242
242
  extra_rdoc_files: []
243
243
  files:
244
244
  - ".document"
245
- - ".drone.yml"
245
+ - ".github/dependabot.yml"
246
+ - ".github/workflows/ci.yml"
246
247
  - ".gitignore"
247
248
  - ".rspec"
248
249
  - ".rubocop.yml"
@@ -350,12 +351,13 @@ files:
350
351
  - lib/signalwire/sdk/twilio_set_host.rb
351
352
  - lib/signalwire/sdk/voice_response.rb
352
353
  - lib/signalwire/version.rb
354
+ - lib/signalwire/webhook/validate_request.rb
353
355
  - signalwire.gemspec
354
356
  homepage: https://github.com/signalwire/signalwire-ruby
355
357
  licenses:
356
358
  - MIT
357
359
  metadata: {}
358
- post_install_message:
360
+ post_install_message:
359
361
  rdoc_options: []
360
362
  require_paths:
361
363
  - lib
@@ -370,8 +372,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
370
372
  - !ruby/object:Gem::Version
371
373
  version: '0'
372
374
  requirements: []
373
- rubygems_version: 3.0.6
374
- signing_key:
375
+ rubygems_version: 3.4.7
376
+ signing_key:
375
377
  specification_version: 4
376
378
  summary: Ruby client for Signalwire
377
379
  test_files: []
data/.drone.yml DELETED
@@ -1,14 +0,0 @@
1
- kind: pipeline
2
- name: default
3
-
4
- steps:
5
- - name: test
6
- image: ruby:2.6
7
- commands:
8
- - gem install bundler
9
- - bundle install --jobs=3 --retry=3
10
- - bundle exec rspec
11
-
12
- trigger:
13
- event: push
14
-