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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a8712d73990e1e8deda860a69f809f469df1d3c
4
- data.tar.gz: 26bc29589ac1c2617e87e69e84a64452e3b07f8a
3
+ metadata.gz: 9047b18e78c395218140978669aa414fc4b7b37c
4
+ data.tar.gz: 6da528c0f5bb692af431c4baa4d1ebfe578dfd27
5
5
  SHA512:
6
- metadata.gz: 1283c0cc9af8d4b41560a6f5ea1aeb28cabe90f329f64a49858c28d55f4bbf77af1895c4ea50cdc6189419612dd4dabfcc2c2ebc6a9c2c58895c9d8ae46d916e
7
- data.tar.gz: f3e9ff6fb9a817144032e1d9c579f036b0ad5712d682d6675b95464b03dcfc6f406625099089eccb2f37dfa5acf68c5e1dc3c3c3a9aba8d380067b14152df234
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
- a1 = username + ":" + auth_pairs["realm"] + ":" + passwd
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
@@ -25,7 +25,7 @@ module Quaff
25
25
  end
26
26
 
27
27
  class Call
28
- attr_reader :cid
28
+ attr_reader :cid, :last_To, :last_From, :sip_destination
29
29
 
30
30
  def initialize(cxn,
31
31
  cid,
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@#{Utils::local_ip}:#{@local_port}#{uri_param_str}>#{param_str}"
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.parse_start
315
- msg = nil
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
- data, addrinfo = @cxn.recvfrom(65535)
356
- @parser.parse_start
357
- msg = @parser.parse_partial(data)
358
- queue_msg msg, UDPSourceFromAddrinfo.new(addrinfo) unless msg.nil?
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
@@ -8,7 +8,7 @@ class SipMessage
8
8
  @headers = headers
9
9
  @method, @status_code, @reason, @requri = method, status_code, reason, req_uri
10
10
  @body = body
11
- @headers['Content-Length'] = [body.length]
11
+ @headers['Content-Length'] = [body.length.to_s]
12
12
  end
13
13
 
14
14
  def [] key
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 parse_start
10
- @buf = ""
11
- @msg = SipMessage.new
15
+ def initialize
12
16
  @state = :blank
17
+ @msg = SipMessage.new
13
18
  end
14
19
 
15
- def parse_partial(data)
16
- return nil if data.nil?
17
- data.lines.each do |line|
18
- line.rstrip!
19
- if @state == :blank
20
- parse_line_blank line
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
- if @state == :done
28
- return @msg
29
- else
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 parse_line_blank line
39
- if line == ""
40
- # skip empty lines
41
- return
50
+ def body_length
51
+ if @msg.header("Content-Length")
52
+ @msg.header("Content-Length").to_i
42
53
  else
43
- parts = line.split " ", 3
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 parse_line_first_line_parsed line
65
- if line.start_with? " "
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
- @cur_hdr = header_name
93
+
74
94
  if header_name == "Content-Length"
75
- @state = :got_content_length
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
- elsif line == ""
83
- if (@state == :got_content_length) and (@msg.header("Content-Length").to_i > 0)
84
- @state = :parsing_body
85
- else
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 parse_line_body line
93
- @msg.body << line
94
- @msg.body << "\r\n"
95
- if line == "" or @msg.body.length >= @msg.header("Content-Length").to_i
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.1
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-10 00:00:00.000000000 Z
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: '0'
87
+ version: 1.3.1
88
88
  requirements: []
89
89
  rubyforge_project:
90
90
  rubygems_version: 2.1.11