quaff 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/auth.rb +1 -1
- data/lib/call.rb +109 -23
- data/lib/endpoint.rb +106 -59
- data/lib/sip_parser.rb +3 -3
- data/lib/sources.rb +5 -12
- data/lib/utils.rb +1 -1
- metadata +17 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d866d33ec2df619a80a00ee7aaaf04d70643370
|
4
|
+
data.tar.gz: f321221c8da956aef23e74104f1fd48abdd2dc02
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 761d0fc337cf7e29d4e3c10b1c83e126cb9f95e750312f08f5cd37f21205fb01dd953bb51b6c87370d9f2f10cfb565895b9e626fd9fea42fa34be71b8f700c27
|
7
|
+
data.tar.gz: edccac0984f874d1590efdf2ec8bbf6e9142d9ffdd90531fa11f2ee40f3c19887aa38cf14fd68ba7d2c30e0be64fbb78e22dfa43e35092f34fbafa6926e214f7
|
data/lib/auth.rb
CHANGED
data/lib/call.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: us-ascii -*-
|
2
2
|
require 'securerandom'
|
3
|
+
require 'timeout'
|
3
4
|
require_relative './utils.rb'
|
4
5
|
require_relative './sources.rb'
|
5
6
|
require_relative './auth.rb'
|
@@ -29,7 +30,7 @@ class Call
|
|
29
30
|
def initialize(cxn,
|
30
31
|
cid,
|
31
32
|
instance_id=nil,
|
32
|
-
uri=
|
33
|
+
uri=nil,
|
33
34
|
destination=nil,
|
34
35
|
target_uri=nil)
|
35
36
|
@cxn = cxn
|
@@ -37,14 +38,11 @@ class Call
|
|
37
38
|
@retrans = nil
|
38
39
|
@t1, @t2 = 0.5, 32
|
39
40
|
@instance_id = instance_id
|
40
|
-
set_default_headers cid, uri, target_uri
|
41
|
-
end
|
42
|
-
|
43
|
-
def change_cid cid
|
44
41
|
@cid = cid
|
45
|
-
|
42
|
+
set_default_headers cid, uri, target_uri
|
46
43
|
end
|
47
44
|
|
45
|
+
# Changes the branch parameter if the Via header, creating a new transaction
|
48
46
|
def update_branch via_hdr=nil
|
49
47
|
via_hdr ||= get_new_via_hdr
|
50
48
|
@last_Via = via_hdr
|
@@ -56,10 +54,6 @@ class Call
|
|
56
54
|
"SIP/2.0/#{@cxn.transport} #{Quaff::Utils.local_ip}:#{@cxn.local_port};rport;branch=#{Quaff::Utils::new_branch}"
|
57
55
|
end
|
58
56
|
|
59
|
-
def create_dialog msg
|
60
|
-
set_callee msg.first_header("Contact")
|
61
|
-
end
|
62
|
-
|
63
57
|
def set_callee uri
|
64
58
|
if /<(.*?)>/ =~ uri
|
65
59
|
uri = $1
|
@@ -67,7 +61,39 @@ class Call
|
|
67
61
|
|
68
62
|
@sip_destination = "#{uri}"
|
69
63
|
end
|
64
|
+
|
65
|
+
def create_dialog msg
|
66
|
+
if @in_dialog
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
@in_dialog = true
|
71
|
+
|
72
|
+
uri = msg.first_header("Contact")
|
73
|
+
|
74
|
+
if /<(.*?)>/ =~ uri
|
75
|
+
uri = $1
|
76
|
+
end
|
77
|
+
|
78
|
+
@sip_destination = uri
|
79
|
+
|
80
|
+
unless msg.all_headers("Record-Route").nil?
|
81
|
+
if msg.type == :request
|
82
|
+
@routeset = msg.all_headers("Record-Route")
|
83
|
+
else
|
84
|
+
@routeset = msg.all_headers("Record-Route").reverse
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
70
89
|
|
90
|
+
# Sets the Source where messages in this call should be sent to by
|
91
|
+
# default.
|
92
|
+
#
|
93
|
+
# Options:
|
94
|
+
# :recv_from_this - if true, also listens for any incoming
|
95
|
+
# messages over this source's connection. (This is only
|
96
|
+
# meaningful for connection-oriented transports.)
|
71
97
|
def setdest source, options={}
|
72
98
|
@src = source
|
73
99
|
if options[:recv_from_this] and source.sock
|
@@ -78,7 +104,7 @@ class Call
|
|
78
104
|
def recv_request(method, dialog_creating=true)
|
79
105
|
begin
|
80
106
|
msg = recv_something
|
81
|
-
rescue
|
107
|
+
rescue Timeout::Error
|
82
108
|
raise "#{ @uri } timed out waiting for #{ method }"
|
83
109
|
end
|
84
110
|
|
@@ -97,20 +123,85 @@ class Call
|
|
97
123
|
end
|
98
124
|
|
99
125
|
if dialog_creating
|
100
|
-
|
126
|
+
create_dialog msg
|
127
|
+
end
|
128
|
+
msg
|
129
|
+
end
|
101
130
|
|
102
|
-
|
103
|
-
|
104
|
-
|
131
|
+
# Waits until the next message comes in, and handles it if it is one
|
132
|
+
# of possible_messages.
|
133
|
+
#
|
134
|
+
# possible_messages is a list of things that can be received.
|
135
|
+
# Elements can be:
|
136
|
+
# * a string representing the SIP method, e.g. "INVITE"
|
137
|
+
# * a number representing the SIP status code, e.g. 200
|
138
|
+
# * a two-item list, containing one of the above and a boolean
|
139
|
+
# value, which indicates whether this message is dialog-creating. by
|
140
|
+
# default, requests are assumed to be dialog-creating and responses
|
141
|
+
# are not.
|
142
|
+
#
|
143
|
+
# For example, ["INVITE", 301, ["ACK", false], [200, true]] is a
|
144
|
+
# valid value for possible_messages.
|
145
|
+
def recv_any_of(possible_messages)
|
146
|
+
begin
|
147
|
+
msg = recv_something
|
148
|
+
rescue Timeout::Error
|
149
|
+
raise "#{ @uri } timed out waiting for one of these: #{possible_messages}"
|
150
|
+
end
|
151
|
+
|
152
|
+
found_match = false
|
153
|
+
dialog_creating = nil
|
154
|
+
|
155
|
+
possible_messages.each do
|
156
|
+
| what, this_dialog_creating |
|
157
|
+
type = if (what.class == String) then :request else :response end
|
158
|
+
if this_dialog_creating.nil?
|
159
|
+
this_dialog_creating = (type == :request)
|
160
|
+
end
|
161
|
+
|
162
|
+
found_match =
|
163
|
+
if type == :request
|
164
|
+
msg.type == :request and what == msg.method
|
165
|
+
else
|
166
|
+
msg.type == :response and what == msg.status_code
|
167
|
+
end
|
168
|
+
|
169
|
+
if found_match
|
170
|
+
dialog_creating = this_dialog_creating
|
171
|
+
break
|
105
172
|
end
|
106
173
|
end
|
174
|
+
|
175
|
+
unless found_match
|
176
|
+
raise((msg.to_s || "Message is nil!"))
|
177
|
+
end
|
178
|
+
|
179
|
+
if msg.type == :request
|
180
|
+
unless @has_To_tag
|
181
|
+
@has_To_tag = true
|
182
|
+
tospec = ToSpec.new
|
183
|
+
tospec.parse(msg.header("To"))
|
184
|
+
tospec.params['tag'] = generate_random_tag
|
185
|
+
@last_To = tospec.to_s
|
186
|
+
@last_From = msg.header("From")
|
187
|
+
end
|
188
|
+
else
|
189
|
+
if @in_dialog
|
190
|
+
@has_To_tag = true
|
191
|
+
@last_To = msg.header("To")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
if dialog_creating
|
196
|
+
create_dialog msg
|
197
|
+
end
|
107
198
|
msg
|
108
199
|
end
|
109
200
|
|
110
201
|
def recv_response(code, dialog_creating=false)
|
111
202
|
begin
|
112
203
|
msg = recv_something
|
113
|
-
rescue
|
204
|
+
rescue Timeout::Error
|
114
205
|
raise "#{ @uri } timed out waiting for #{ code }"
|
115
206
|
end
|
116
207
|
unless msg.type == :response \
|
@@ -119,11 +210,7 @@ class Call
|
|
119
210
|
end
|
120
211
|
|
121
212
|
if dialog_creating
|
122
|
-
|
123
|
-
set_callee msg.first_header("Contact")
|
124
|
-
unless msg.all_headers("Record-Route").nil?
|
125
|
-
@routeset = msg.all_headers("Record-Route").reverse
|
126
|
-
end
|
213
|
+
create_dialog msg
|
127
214
|
end
|
128
215
|
|
129
216
|
if @in_dialog
|
@@ -238,14 +325,13 @@ class Call
|
|
238
325
|
|
239
326
|
def set_default_headers cid, uri, target_uri
|
240
327
|
@cseq_number = 1
|
241
|
-
change_cid cid
|
242
328
|
@uri = uri
|
243
329
|
@last_From = "<#{uri}>;tag=" + generate_random_tag
|
244
330
|
@in_dialog = false
|
245
331
|
@has_To_tag = false
|
246
332
|
update_branch
|
247
333
|
@last_To = "<#{target_uri}>"
|
248
|
-
|
334
|
+
@sip_destination = target_uri
|
249
335
|
@routeset = []
|
250
336
|
end
|
251
337
|
|
data/lib/endpoint.rb
CHANGED
@@ -3,7 +3,7 @@ require 'socket'
|
|
3
3
|
require 'thread'
|
4
4
|
require 'timeout'
|
5
5
|
require 'resolv'
|
6
|
-
require '
|
6
|
+
require 'securerandom'
|
7
7
|
#require 'milenage'
|
8
8
|
require_relative './sip_parser.rb'
|
9
9
|
require_relative './sources.rb'
|
@@ -11,53 +11,75 @@ require_relative './sources.rb'
|
|
11
11
|
module Quaff
|
12
12
|
class BaseEndpoint
|
13
13
|
attr_accessor :msg_trace, :uri, :sdp_port, :sdp_socket, :instance_id
|
14
|
-
attr_reader :msg_log
|
14
|
+
attr_reader :msg_log, :local_port
|
15
15
|
|
16
|
+
# Creates an SDP socket bound to an ephemeral port
|
16
17
|
def setup_sdp
|
17
18
|
@sdp_socket = UDPSocket.new
|
18
19
|
@sdp_socket.bind('0.0.0.0', 0)
|
19
20
|
@sdp_port = @sdp_socket.addr[1]
|
20
21
|
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
|
23
|
+
# Cleans up the endpoint - designed to be overriden by
|
24
|
+
# per-transport subclasses
|
26
25
|
def terminate
|
27
26
|
end
|
28
27
|
|
28
|
+
# Adds a socket connection to another UA - designed to be
|
29
|
+
# overriden by per-transport subclasses
|
29
30
|
def add_sock sock
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
# Retrieves the next unhandled call for this endpoint and returns
|
34
|
+
# a +Call+ object representing it
|
35
|
+
def incoming_call
|
36
|
+
begin
|
37
|
+
call_id = get_new_call_id
|
38
|
+
rescue Timeout::Error
|
39
|
+
raise "#{ @uri } timed out waiting for new incoming call"
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "Call-Id for endpoint on #{@local_port} is #{call_id}" if @msg_trace
|
43
|
+
Call.new(self, call_id, @instance_id, @uri)
|
36
44
|
end
|
37
45
|
|
46
|
+
# Creates a +Call+ object representing a new outbound call
|
38
47
|
def outgoing_call to_uri
|
39
48
|
call_id = generate_call_id
|
40
|
-
puts "Call-Id for endpoint on #{@
|
49
|
+
puts "Call-Id for endpoint on #{@local_port} is #{call_id}" if @msg_trace
|
41
50
|
Call.new(self, call_id, @instance_id, @uri, @outbound_connection, to_uri)
|
42
51
|
end
|
43
52
|
|
44
|
-
|
53
|
+
# Not yet ready for use
|
54
|
+
def create_client(uri, username, password, outbound_proxy, outbound_port=5060) # :nodoc:
|
45
55
|
end
|
46
56
|
|
47
|
-
|
48
|
-
|
57
|
+
# Not yet ready for use
|
58
|
+
def create_server(uri, local_port=5060, outbound_proxy=nil, outbound_port=5060) # :nodoc:
|
49
59
|
end
|
50
60
|
|
51
|
-
|
61
|
+
# Not yet ready for use
|
62
|
+
def create_aka_client(uri, username, key, op, outbound_proxy, outbound_port=5060) # :nodoc:
|
52
63
|
end
|
53
64
|
|
65
|
+
# Constructs a new endpoint
|
66
|
+
# Params:
|
67
|
+
# +uri+:: The SIP URI of this endpoint
|
68
|
+
# +username+:: The authentication username of this endpoint
|
69
|
+
# +password+:: The authentication password of this endpoint
|
70
|
+
# +local_port+:: The port this endpoint should bind to. Use
|
71
|
+
# ':anyport' to bind to an ephemeral port.
|
72
|
+
# +outbound_proxy+:: The outbound proxy where all requests should
|
73
|
+
# be directed. Optional, but it only makes sense to omit it when
|
74
|
+
# Quaff is emulating a server rather than a client.
|
75
|
+
# +outbound_port+:: The port of the outbound proxy
|
54
76
|
def initialize(uri, username, password, local_port, outbound_proxy=nil, outbound_port=5060)
|
55
77
|
@msg_log = Array.new
|
56
78
|
@uri = uri
|
57
79
|
@resolver = Resolv::DNS.new
|
58
80
|
@username = username
|
59
81
|
@password = password
|
60
|
-
@
|
82
|
+
@local_port = local_port
|
61
83
|
initialize_connection
|
62
84
|
if outbound_proxy
|
63
85
|
@outbound_connection = new_connection(outbound_proxy, outbound_port)
|
@@ -66,40 +88,26 @@ module Quaff
|
|
66
88
|
start
|
67
89
|
end
|
68
90
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
def add_call_id cid
|
74
|
-
@messages[cid] ||= Queue.new
|
75
|
-
end
|
76
|
-
|
77
|
-
def get_new_call_id time_limit=30
|
78
|
-
Timeout::timeout(time_limit) { @call_ids.deq }
|
79
|
-
end
|
80
|
-
|
81
|
-
def get_new_message(cid, time_limit=30)
|
82
|
-
Timeout::timeout(time_limit) { @messages[cid].deq }
|
83
|
-
end
|
84
|
-
|
85
|
-
def mark_call_dead(cid)
|
86
|
-
@messages.delete cid
|
87
|
-
now = Time.now
|
88
|
-
@dead_calls[cid] = now + 30
|
89
|
-
@dead_calls = @dead_calls.keep_if {|k, v| v > now}
|
90
|
-
end
|
91
|
-
|
92
|
-
def send_msg(data, source)
|
93
|
-
@msg_log.push "Endpoint on #{@lport} sending:\n\n#{data.strip}\n\nto #{source.inspect}"
|
94
|
-
puts "Endpoint on #{@lport} sending #{data} to #{source.inspect}" if @msg_trace
|
91
|
+
def send_msg(data, source) # :nodoc:
|
92
|
+
@msg_log.push "Endpoint on #{@local_port} sending:\n\n#{data.strip}\n\nto #{source.inspect}"
|
93
|
+
puts "Endpoint on #{@local_port} sending #{data} to #{source.inspect}" if @msg_trace
|
95
94
|
source.send_msg(@cxn, data)
|
96
95
|
end
|
97
96
|
|
98
|
-
|
97
|
+
# Not yet ready for use
|
98
|
+
def set_aka_credentials key, op # :nodoc:
|
99
99
|
@kernel = Milenage.Kernel key
|
100
100
|
@kernel.op = op
|
101
101
|
end
|
102
102
|
|
103
|
+
# Utility method - handles a REGISTER/200 or
|
104
|
+
# REGISTER/401/REGISTER/200 flow to authenticate the subscriber.
|
105
|
+
# Currently only supports SIP Digest authentication. Re-REGISTERs
|
106
|
+
# are not handled; if you need long-running endpoints you should
|
107
|
+
# create a thread to re-REGISTER them yourself.
|
108
|
+
#
|
109
|
+
# Returns the +Message+ representing the 200 OK, or throws an
|
110
|
+
# exception on failure to authenticate successfully.
|
103
111
|
def register expires="3600", aka=false
|
104
112
|
@reg_call ||= outgoing_call(@uri)
|
105
113
|
auth_hdr = Quaff::Auth.gen_empty_auth_header @username
|
@@ -125,7 +133,42 @@ module Quaff
|
|
125
133
|
register 0
|
126
134
|
end
|
127
135
|
|
136
|
+
# Only designed for use by the Call class. Retrieves a new message
|
137
|
+
# on a particular call. If no new message has been received,
|
138
|
+
# blocks for up to time_limit seconds waiting for one. If nothing
|
139
|
+
# arrives, raises a TimeoutError.
|
140
|
+
def get_new_message(cid, time_limit=30) # :nodoc:
|
141
|
+
Timeout::timeout(time_limit) { @messages[cid].deq }
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
# Flags that a particular call has ended, and any more messages
|
147
|
+
# using it shold be ignored.
|
148
|
+
def mark_call_dead(cid)
|
149
|
+
@messages.delete cid
|
150
|
+
now = Time.now
|
151
|
+
@dead_calls[cid] = now + 30
|
152
|
+
@dead_calls = @dead_calls.keep_if {|k, v| v > now}
|
153
|
+
end
|
128
154
|
private
|
155
|
+
|
156
|
+
# Creates a random Call-ID
|
157
|
+
def generate_call_id
|
158
|
+
call_id = SecureRandom::hex
|
159
|
+
add_call_id call_id
|
160
|
+
return call_id
|
161
|
+
end
|
162
|
+
|
163
|
+
def get_new_call_id time_limit=30
|
164
|
+
Timeout::timeout(time_limit) { @call_ids.deq }
|
165
|
+
end
|
166
|
+
|
167
|
+
# Sets up the internal structures needed to handle calls for a new Call-ID.
|
168
|
+
def add_call_id cid
|
169
|
+
@messages[cid] ||= Queue.new
|
170
|
+
end
|
171
|
+
|
129
172
|
def initialize_queues
|
130
173
|
@messages = {}
|
131
174
|
@call_ids = Queue.new
|
@@ -142,8 +185,8 @@ module Quaff
|
|
142
185
|
end
|
143
186
|
|
144
187
|
def queue_msg(msg, source)
|
145
|
-
@msg_log.push "Endpoint on #{@
|
146
|
-
puts "Endpoint on #{@
|
188
|
+
@msg_log.push "Endpoint on #{@local_port} received:\n\n#{msg.to_s.strip}\n\nfrom #{source.inspect}"
|
189
|
+
puts "Endpoint on #{@local_port} received #{msg} from
|
147
190
|
##{source.inspect}" if @msg_trace
|
148
191
|
msg.source = source
|
149
192
|
cid = @parser.message_identifier msg
|
@@ -160,17 +203,6 @@ module Quaff
|
|
160
203
|
class TCPSIPEndpoint < BaseEndpoint
|
161
204
|
attr_accessor :sockets
|
162
205
|
|
163
|
-
def initialize_connection
|
164
|
-
if @lport != :anyport
|
165
|
-
@cxn = TCPServer.new(@lport)
|
166
|
-
else
|
167
|
-
@cxn = TCPServer.new(0)
|
168
|
-
@lport = @cxn.addr[1]
|
169
|
-
end
|
170
|
-
@parser = SipParser.new
|
171
|
-
@sockets = []
|
172
|
-
end
|
173
|
-
|
174
206
|
def transport
|
175
207
|
"TCP"
|
176
208
|
end
|
@@ -194,7 +226,21 @@ module Quaff
|
|
194
226
|
|
195
227
|
|
196
228
|
alias_method :new_connection, :new_source
|
229
|
+
|
197
230
|
private
|
231
|
+
|
232
|
+
def initialize_connection
|
233
|
+
if @local_port != :anyport
|
234
|
+
@cxn = TCPServer.new(@local_port)
|
235
|
+
else
|
236
|
+
@cxn = TCPServer.new(0)
|
237
|
+
@local_port = @cxn.addr[1]
|
238
|
+
end
|
239
|
+
@parser = SipParser.new
|
240
|
+
@sockets = []
|
241
|
+
end
|
242
|
+
|
243
|
+
|
198
244
|
def recv_msg
|
199
245
|
select_response = IO.select(@sockets, [], [], 0) || [[]]
|
200
246
|
readable = select_response[0]
|
@@ -239,13 +285,14 @@ module Quaff
|
|
239
285
|
alias_method :new_connection, :new_source
|
240
286
|
|
241
287
|
private
|
288
|
+
|
242
289
|
def initialize_connection
|
243
290
|
@cxn = UDPSocket.new
|
244
|
-
if @
|
245
|
-
@cxn.bind('0.0.0.0', @
|
291
|
+
if @local_port != :anyport
|
292
|
+
@cxn.bind('0.0.0.0', @local_port)
|
246
293
|
else
|
247
294
|
@cxn.bind('0.0.0.0', 0)
|
248
|
-
@
|
295
|
+
@local_port = @cxn.addr[1]
|
249
296
|
end
|
250
297
|
@sockets = []
|
251
298
|
@parser = SipParser.new
|
data/lib/sip_parser.rb
CHANGED
@@ -4,7 +4,7 @@ require 'abnf'
|
|
4
4
|
require_relative './message.rb'
|
5
5
|
|
6
6
|
module Quaff
|
7
|
-
class SipParser
|
7
|
+
class SipParser # :nodoc:
|
8
8
|
attr_reader :state
|
9
9
|
def parse_start
|
10
10
|
@buf = ""
|
@@ -99,7 +99,7 @@ module Quaff
|
|
99
99
|
|
100
100
|
end
|
101
101
|
|
102
|
-
class ABNFSipParser
|
102
|
+
class ABNFSipParser # :nodoc:
|
103
103
|
include ABNF
|
104
104
|
|
105
105
|
# Rules
|
@@ -227,7 +227,7 @@ module Quaff
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
|
-
class ToSpec < ABNFSipParser
|
230
|
+
class ToSpec < ABNFSipParser # :nodoc:
|
231
231
|
attr_accessor :params, :uri, :displayname, :is_nameaddr
|
232
232
|
def initialize
|
233
233
|
super
|
data/lib/sources.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
1
|
require 'socket'
|
2
2
|
module Quaff
|
3
|
+
# A Source is an abstraction representing an IP
|
4
|
+
# address/port/transport where a SIP message originates from or can
|
5
|
+
# be sent to. It allows users to abstract over TCP and UDP sockets.
|
3
6
|
class Source
|
4
|
-
|
5
|
-
@ip
|
6
|
-
end
|
7
|
-
|
8
|
-
def remote_port
|
9
|
-
@port
|
10
|
-
end
|
7
|
+
attr_reader :ip, :port, :transport, :sock
|
11
8
|
|
9
|
+
# Designed to be overriden by subclasses
|
12
10
|
def close cxn
|
13
11
|
end
|
14
12
|
|
15
|
-
def sock
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
|
19
13
|
def to_s
|
20
14
|
"#{@ip}:#{@port} (#{@transport})"
|
21
15
|
end
|
@@ -41,7 +35,6 @@ module Quaff
|
|
41
35
|
|
42
36
|
|
43
37
|
class TCPSource < Source
|
44
|
-
attr_reader :sock
|
45
38
|
|
46
39
|
def initialize ip, port
|
47
40
|
@transport = "TCP"
|
data/lib/utils.rb
CHANGED
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quaff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.6.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Rob Day
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-
|
11
|
+
date: 2014-06-22 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: facter
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 1.7.3
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 1.7.3
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: milenage
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 0.1.0
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 0.1.0
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: abnf-parsing
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: 0.2.0
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: 0.2.0
|
62
55
|
description: A Ruby library for writing SIP test scenarios
|
@@ -65,37 +58,36 @@ executables: []
|
|
65
58
|
extensions: []
|
66
59
|
extra_rdoc_files: []
|
67
60
|
files:
|
68
|
-
- lib/
|
61
|
+
- lib/call.rb
|
69
62
|
- lib/endpoint.rb
|
70
63
|
- lib/message.rb
|
71
|
-
- lib/
|
72
|
-
- lib/auth.rb
|
64
|
+
- lib/quaff.rb
|
73
65
|
- lib/sources.rb
|
66
|
+
- lib/utils.rb
|
74
67
|
- lib/sip_parser.rb
|
75
|
-
- lib/
|
68
|
+
- lib/auth.rb
|
76
69
|
homepage: http://github.com/rkday/quaff
|
77
70
|
licenses:
|
78
71
|
- GPL3
|
72
|
+
metadata: {}
|
79
73
|
post_install_message:
|
80
74
|
rdoc_options: []
|
81
75
|
require_paths:
|
82
76
|
- lib
|
83
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
-
none: false
|
85
78
|
requirements:
|
86
|
-
- -
|
79
|
+
- - '>='
|
87
80
|
- !ruby/object:Gem::Version
|
88
81
|
version: '0'
|
89
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
83
|
requirements:
|
92
|
-
- -
|
84
|
+
- - '>='
|
93
85
|
- !ruby/object:Gem::Version
|
94
86
|
version: '0'
|
95
87
|
requirements: []
|
96
88
|
rubyforge_project:
|
97
|
-
rubygems_version: 1.
|
89
|
+
rubygems_version: 2.1.11
|
98
90
|
signing_key:
|
99
|
-
specification_version:
|
91
|
+
specification_version: 4
|
100
92
|
summary: Quaff
|
101
93
|
test_files: []
|