quaff 0.7.1 → 0.7.2pre1

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
  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