quaff 0.7.1 → 0.7.2pre1
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.
- checksums.yaml +4 -4
- data/lib/auth.rb +7 -5
- data/lib/call.rb +1 -1
- data/lib/endpoint.rb +11 -13
- data/lib/message.rb +1 -1
- data/lib/sip_parser.rb +78 -61
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9047b18e78c395218140978669aa414fc4b7b37c
|
4
|
+
data.tar.gz: 6da528c0f5bb692af431c4baa4d1ebfe578dfd27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6122a94c660e04af275f68577fa14692e3a3b07b4d89f313ff2b8ccd0ea12d26f823e6039eea444388b65055f42e816289dffd5d51b4344ee5a12d06e81624fa
|
7
|
+
data.tar.gz: 43ea4996f3fb844e64a860067d577b3910b6358664ff8ec4e17a370d64b6f99f1bb4e21363d1346f758eb82d190708d8a334ac18f993a9ba6866394c109135b3
|
data/lib/auth.rb
CHANGED
@@ -2,10 +2,12 @@ require 'base64'
|
|
2
2
|
|
3
3
|
module Quaff
|
4
4
|
module Auth #:nodoc:
|
5
|
-
def Auth.gen_nonce auth_pairs, username, passwd, method, sip_uri
|
6
|
-
|
5
|
+
def Auth.gen_nonce auth_pairs, username, passwd, method, sip_uri, ha1=""
|
6
|
+
if ha1.empty?
|
7
|
+
a1 = username + ":" + auth_pairs["realm"] + ":" + passwd
|
8
|
+
ha1 = Digest::MD5::hexdigest(a1)
|
9
|
+
end
|
7
10
|
a2 = method + ":" + sip_uri
|
8
|
-
ha1 = Digest::MD5::hexdigest(a1)
|
9
11
|
ha2 = Digest::MD5::hexdigest(a2)
|
10
12
|
digest = Digest::MD5.hexdigest(ha1 + ":" + auth_pairs["nonce"] + ":" + ha2)
|
11
13
|
return digest
|
@@ -29,14 +31,14 @@ module Quaff
|
|
29
31
|
# the SIP URI
|
30
32
|
end
|
31
33
|
|
32
|
-
def Auth.gen_auth_header auth_line, username, passwd, method, sip_uri
|
34
|
+
def Auth.gen_auth_header auth_line, username, passwd, method, sip_uri, ha1=""
|
33
35
|
# Split auth line on commas
|
34
36
|
auth_pairs = {}
|
35
37
|
auth_line.sub("Digest ", "").split(",") .each do |pair|
|
36
38
|
key, value = pair.split "="
|
37
39
|
auth_pairs[key.gsub(" ", "")] = value.gsub("\"", "").gsub(" ", "")
|
38
40
|
end
|
39
|
-
digest = gen_nonce auth_pairs, username, passwd, method, sip_uri
|
41
|
+
digest = gen_nonce auth_pairs, username, passwd, method, sip_uri, ha1
|
40
42
|
return %Q!Digest username="#{username}",realm="#{auth_pairs['realm']}",nonce="#{auth_pairs['nonce']}",uri="#{sip_uri}",response="#{digest}",algorithm="#{auth_pairs['algorithm']}",opaque="#{auth_pairs['opaque']}"!
|
41
43
|
# Return Authorization header with fields username, realm, nonce, uri, nc, cnonce, response, opaque
|
42
44
|
end
|
data/lib/call.rb
CHANGED
data/lib/endpoint.rb
CHANGED
@@ -4,14 +4,14 @@ require 'thread'
|
|
4
4
|
require 'timeout'
|
5
5
|
require 'resolv'
|
6
6
|
require 'securerandom'
|
7
|
-
#require 'milenage'
|
8
7
|
require_relative './sip_parser.rb'
|
9
8
|
require_relative './sources.rb'
|
10
9
|
require 'digest/md5'
|
10
|
+
require 'stringio'
|
11
11
|
|
12
12
|
module Quaff
|
13
13
|
class BaseEndpoint
|
14
|
-
attr_accessor :msg_trace, :uri, :sdp_port, :sdp_socket
|
14
|
+
attr_accessor :msg_trace, :uri, :sdp_port, :sdp_socket, :local_hostname
|
15
15
|
attr_reader :msg_log, :local_port, :instance_id
|
16
16
|
|
17
17
|
# Creates an SDP socket bound to an ephemeral port
|
@@ -105,6 +105,7 @@ module Quaff
|
|
105
105
|
@resolver = Resolv::DNS.new
|
106
106
|
@username = username
|
107
107
|
@password = password
|
108
|
+
@local_host = Utils::local_ip
|
108
109
|
@local_port = local_port
|
109
110
|
initialize_connection
|
110
111
|
if outbound_proxy
|
@@ -114,6 +115,7 @@ module Quaff
|
|
114
115
|
@contact_params = {}
|
115
116
|
@contact_uri_params = {"transport" => transport, "ob" => true}
|
116
117
|
@terminated = false
|
118
|
+
@local_hostname = Utils::local_ip
|
117
119
|
initialize_queues
|
118
120
|
start
|
119
121
|
end
|
@@ -121,7 +123,7 @@ module Quaff
|
|
121
123
|
def contact_header
|
122
124
|
param_str = Utils.paramhash_to_str(@contact_params)
|
123
125
|
uri_param_str = Utils.paramhash_to_str(@contact_uri_params)
|
124
|
-
"<sip:quaff@#{
|
126
|
+
"<sip:quaff@#{@local_hostname}:#{@local_port}#{uri_param_str}>#{param_str}"
|
125
127
|
end
|
126
128
|
|
127
129
|
def send_msg(data, source) # :nodoc:
|
@@ -311,12 +313,8 @@ module Quaff
|
|
311
313
|
end
|
312
314
|
|
313
315
|
def recv_msg_from_sock(sock)
|
314
|
-
@parser.
|
315
|
-
|
316
|
-
while msg.nil? and not sock.closed? do
|
317
|
-
line = sock.gets
|
318
|
-
msg = @parser.parse_partial line
|
319
|
-
end
|
316
|
+
msg = @parser.parse_from_io(sock)
|
317
|
+
|
320
318
|
queue_msg msg, TCPSourceFromSocket.new(sock)
|
321
319
|
end
|
322
320
|
end
|
@@ -352,10 +350,10 @@ module Quaff
|
|
352
350
|
end
|
353
351
|
|
354
352
|
def recv_msg
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
353
|
+
data, addrinfo = @cxn.recvfrom(65535)
|
354
|
+
@parser.parse_start
|
355
|
+
msg = @parser.parse_from_io(StringIO(data))
|
356
|
+
queue_msg msg, UDPSourceFromAddrinfo.new(addrinfo) unless msg.nil?
|
359
357
|
end
|
360
358
|
end
|
361
359
|
|
data/lib/message.rb
CHANGED
data/lib/sip_parser.rb
CHANGED
@@ -3,100 +3,117 @@ require 'digest/md5'
|
|
3
3
|
require 'abnf'
|
4
4
|
require_relative './message.rb'
|
5
5
|
|
6
|
+
# The valid states for the parser:
|
7
|
+
# :blank
|
8
|
+
# :parsing_headers
|
9
|
+
# :waiting_for_body
|
10
|
+
# :done
|
11
|
+
|
6
12
|
module Quaff
|
7
13
|
class SipParser # :nodoc:
|
8
14
|
attr_reader :state
|
9
|
-
def
|
10
|
-
@buf = ""
|
11
|
-
@msg = SipMessage.new
|
15
|
+
def initialize
|
12
16
|
@state = :blank
|
17
|
+
@msg = SipMessage.new
|
13
18
|
end
|
14
19
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
elsif @state == :parsing_body
|
22
|
-
parse_line_body line
|
23
|
-
else
|
24
|
-
parse_line_first_line_parsed line
|
25
|
-
end
|
20
|
+
def parse_from_io(io, udp=false)
|
21
|
+
parse_start
|
22
|
+
|
23
|
+
parse_initial_line(io.gets.rstrip)
|
24
|
+
while @state == :parsing_headers and not io.closed? do
|
25
|
+
parse_header_line io.gets.rstrip
|
26
26
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
return nil
|
27
|
+
|
28
|
+
if io.closed?
|
29
|
+
raise "Socket closed unexpectedly!"
|
31
30
|
end
|
31
|
+
|
32
|
+
if @state == :waiting_for_body
|
33
|
+
body = io.read(body_length)
|
34
|
+
add_body body
|
35
|
+
elsif udp and msg.header("Content-Length").nil?
|
36
|
+
add_body io.read(1500)
|
37
|
+
end
|
38
|
+
@msg
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_start
|
42
|
+
@msg = SipMessage.new
|
43
|
+
@state = :blank
|
32
44
|
end
|
33
45
|
|
34
46
|
def message_identifier(msg)
|
35
47
|
msg.header("Call-ID")
|
36
48
|
end
|
37
49
|
|
38
|
-
def
|
39
|
-
if
|
40
|
-
|
41
|
-
return
|
50
|
+
def body_length
|
51
|
+
if @msg.header("Content-Length")
|
52
|
+
@msg.header("Content-Length").to_i
|
42
53
|
else
|
43
|
-
|
44
|
-
if parts[2] == "SIP/2.0"
|
45
|
-
# Looks like a SIP request
|
46
|
-
@msg.method = parts[0]
|
47
|
-
@msg.requri = parts[1]
|
48
|
-
@state = :first_line_parsed
|
49
|
-
return
|
50
|
-
elsif parts[0] == "SIP/2.0"
|
51
|
-
# Looks like a SIP response
|
52
|
-
@msg.status_code = parts[1]
|
53
|
-
@msg.reason = parts[2] || ""
|
54
|
-
@state = :first_line_parsed
|
55
|
-
return
|
56
|
-
else
|
57
|
-
raise parts.inspect
|
58
|
-
end
|
54
|
+
0
|
59
55
|
end
|
60
|
-
# We haven't returned, so looks like a malformed line
|
61
|
-
raise line.inspect
|
62
56
|
end
|
63
57
|
|
64
|
-
def
|
65
|
-
|
58
|
+
def parse_initial_line line
|
59
|
+
fail "Invalid state: #{@state}" unless @state == :blank
|
60
|
+
parts = line.split " ", 3
|
61
|
+
if parts[2] == "SIP/2.0"
|
62
|
+
# Looks like a SIP request
|
63
|
+
@msg.method = parts[0]
|
64
|
+
@msg.requri = parts[1]
|
65
|
+
elsif parts[0] == "SIP/2.0"
|
66
|
+
# Looks like a SIP response
|
67
|
+
@msg.status_code = parts[1]
|
68
|
+
@msg.reason = parts[2] || ""
|
69
|
+
else
|
70
|
+
raise parts.inspect
|
71
|
+
end
|
72
|
+
@state = :parsing_headers
|
73
|
+
end
|
74
|
+
|
75
|
+
def process_continuation_line line
|
66
76
|
@msg.headers[@cur_hdr][-1] += " "
|
67
77
|
@msg.headers[@cur_hdr][-1] += line.lstrip
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_header_line line
|
81
|
+
fail "Invalid state: #{@state}" unless @state == :parsing_headers
|
82
|
+
if line == "" and (body_length == 0)
|
83
|
+
@state = :done
|
84
|
+
elsif line == ""
|
85
|
+
@state = :waiting_for_body
|
86
|
+
elsif line.start_with? " "
|
87
|
+
process_continuation_line line
|
68
88
|
elsif line.include? ":"
|
69
89
|
parts = line.split ":", 2
|
70
90
|
header_name, header_value = parts[0].rstrip, parts[1].lstrip
|
71
91
|
@msg.headers[header_name] ||= []
|
72
92
|
@msg.headers[header_name].push header_value
|
73
|
-
|
93
|
+
|
74
94
|
if header_name == "Content-Length"
|
75
|
-
|
95
|
+
# Special treatment - Content-Length defaults to 0 at
|
96
|
+
# creation, so has to be overwritten
|
76
97
|
@msg.headers[header_name] = [header_value]
|
77
|
-
else
|
78
|
-
if (@state != :got_content_length)
|
79
|
-
@state = :middle_of_headers
|
80
|
-
end
|
81
98
|
end
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@state = :done
|
87
|
-
end
|
88
|
-
else raise line.inspect
|
99
|
+
|
100
|
+
@cur_hdr = header_name
|
101
|
+
else
|
102
|
+
raise line.inspect
|
89
103
|
end
|
90
104
|
end
|
91
105
|
|
92
|
-
def
|
93
|
-
@
|
94
|
-
@msg.body
|
95
|
-
|
96
|
-
@state = :done
|
97
|
-
end
|
106
|
+
def add_body body
|
107
|
+
fail "Invalid state: #{@state}" unless (@state == :waiting_for_body || @state == :done)
|
108
|
+
@msg.body = body
|
109
|
+
@state = :done
|
98
110
|
end
|
99
111
|
|
112
|
+
def msg
|
113
|
+
fail "Invalid state: #{@state}" unless @state == :done
|
114
|
+
@msg
|
115
|
+
end
|
116
|
+
|
100
117
|
end
|
101
118
|
|
102
119
|
class ABNFSipParser # :nodoc:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quaff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Day
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: system-getifaddrs
|
@@ -82,9 +82,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
82
|
version: '0'
|
83
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- - '
|
85
|
+
- - '>'
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version:
|
87
|
+
version: 1.3.1
|
88
88
|
requirements: []
|
89
89
|
rubyforge_project:
|
90
90
|
rubygems_version: 2.1.11
|