Class: Quaff::SipParser

Inherits:
Object
  • Object
show all
Defined in:
lib/sip_parser.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSipParser

Returns a new instance of SipParser.



15
16
17
18
# File 'lib/sip_parser.rb', line 15

def initialize
  @state = :blank
  @msg = SipMessage.new
end

Instance Attribute Details

#stateObject (readonly)

Returns the value of attribute state.



14
15
16
# File 'lib/sip_parser.rb', line 14

def state
  @state
end

Instance Method Details

#add_body(body) ⇒ Object



106
107
108
109
110
# File 'lib/sip_parser.rb', line 106

def add_body body
  fail "Invalid state: #{@state}" unless (@state == :waiting_for_body || @state == :done)
  @msg.body = body
  @state = :done
end

#body_lengthObject



50
51
52
53
54
55
56
# File 'lib/sip_parser.rb', line 50

def body_length
  if @msg.header("Content-Length")
    @msg.header("Content-Length").to_i
  else
    0
  end
end

#message_identifier(msg) ⇒ Object



46
47
48
# File 'lib/sip_parser.rb', line 46

def message_identifier(msg)
  msg.header("Call-ID")
end

#msgObject



112
113
114
115
# File 'lib/sip_parser.rb', line 112

def msg
  fail "Invalid state: #{@state}" unless @state == :done
  @msg
end

#parse_from_io(io, udp = false) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/sip_parser.rb', line 20

def parse_from_io(io, udp=false)
  parse_start

  parse_initial_line(io.gets.rstrip)
  while @state == :parsing_headers and not io.closed? do
    parse_header_line io.gets.rstrip
  end

  if io.closed?
    raise "Socket closed unexpectedly!"
  end

  if @state == :waiting_for_body
    body = io.read(body_length)
    add_body body
  elsif udp and msg.header("Content-Length").nil?
    add_body io.read(1500)
  end        
  @msg
end

#parse_header_line(line) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/sip_parser.rb', line 80

def parse_header_line line
  fail "Invalid state: #{@state}" unless @state == :parsing_headers
  if line == "" and (body_length == 0)
    @state = :done
  elsif line == ""
    @state = :waiting_for_body
  elsif line.start_with? " "
    process_continuation_line line
  elsif line.include? ":"
    parts = line.split ":", 2
    header_name, header_value = parts[0].rstrip, parts[1].lstrip
    @msg.headers[header_name] ||= []
    @msg.headers[header_name].push header_value

    if header_name == "Content-Length"
      # Special treatment - Content-Length defaults to 0 at
      # creation, so has to be overwritten
      @msg.headers[header_name] = [header_value]
    end

    @cur_hdr = header_name
  else
    raise line.inspect
  end
end

#parse_initial_line(line) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/sip_parser.rb', line 58

def parse_initial_line line
  fail "Invalid state: #{@state}" unless @state == :blank
  parts = line.split " ", 3
  if parts[2] == "SIP/2.0"
    # Looks like a SIP request
    @msg.method = parts[0]
    @msg.requri = parts[1]
  elsif parts[0] == "SIP/2.0"
    # Looks like a SIP response
    @msg.status_code = parts[1]
    @msg.reason = parts[2] || ""
  else
    raise parts.inspect
  end
  @state = :parsing_headers
end

#parse_startObject



41
42
43
44
# File 'lib/sip_parser.rb', line 41

def parse_start
  @msg = SipMessage.new
  @state = :blank
end

#process_continuation_line(line) ⇒ Object



75
76
77
78
# File 'lib/sip_parser.rb', line 75

def process_continuation_line line
    @msg.headers[@cur_hdr][-1] += " "
    @msg.headers[@cur_hdr][-1] += line.lstrip
end