oversip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/AUTHORS.txt +11 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +16 -0
  4. data/Rakefile +55 -0
  5. data/bin/oversip +182 -0
  6. data/ext/common/c_util.h +74 -0
  7. data/ext/common/ruby_c_util.h +88 -0
  8. data/ext/sip_parser/common_headers.h +209 -0
  9. data/ext/sip_parser/ext_help.h +18 -0
  10. data/ext/sip_parser/extconf.rb +3 -0
  11. data/ext/sip_parser/sip_parser.c +29649 -0
  12. data/ext/sip_parser/sip_parser.h +227 -0
  13. data/ext/sip_parser/sip_parser_ruby.c +1292 -0
  14. data/ext/stud/extconf.rb +27 -0
  15. data/ext/stud/stud.tar.gz +0 -0
  16. data/ext/stun/ext_help.h +16 -0
  17. data/ext/stun/extconf.rb +3 -0
  18. data/ext/stun/stun_ruby.c +391 -0
  19. data/ext/utils/ext_help.h +14 -0
  20. data/ext/utils/extconf.rb +3 -0
  21. data/ext/utils/haproxy_protocol.c +6163 -0
  22. data/ext/utils/haproxy_protocol.h +27 -0
  23. data/ext/utils/ip_utils.c +5952 -0
  24. data/ext/utils/ip_utils.h +61 -0
  25. data/ext/utils/outbound_utils.c +3227 -0
  26. data/ext/utils/outbound_utils.h +27 -0
  27. data/ext/utils/utils_ruby.c +384 -0
  28. data/ext/utils/utils_ruby.h +75 -0
  29. data/ext/websocket_framing_utils/ext_help.h +18 -0
  30. data/ext/websocket_framing_utils/extconf.rb +3 -0
  31. data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
  32. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  33. data/ext/websocket_http_parser/ext_help.h +18 -0
  34. data/ext/websocket_http_parser/extconf.rb +3 -0
  35. data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
  36. data/ext/websocket_http_parser/ws_http_parser.h +86 -0
  37. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  38. data/lib/oversip/config.rb +541 -0
  39. data/lib/oversip/config_validators.rb +126 -0
  40. data/lib/oversip/errors.rb +7 -0
  41. data/lib/oversip/fiber_pool.rb +56 -0
  42. data/lib/oversip/launcher.rb +507 -0
  43. data/lib/oversip/logger.rb +170 -0
  44. data/lib/oversip/master_process.rb +67 -0
  45. data/lib/oversip/posix_mq.rb +121 -0
  46. data/lib/oversip/proxies_config.rb +169 -0
  47. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  48. data/lib/oversip/sip/client_transaction.rb +587 -0
  49. data/lib/oversip/sip/constants.rb +87 -0
  50. data/lib/oversip/sip/grammar/name_addr.rb +27 -0
  51. data/lib/oversip/sip/grammar/uri.rb +116 -0
  52. data/lib/oversip/sip/launcher.rb +180 -0
  53. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  54. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
  55. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  56. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
  57. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
  58. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
  59. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  60. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
  61. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  62. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
  63. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
  64. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
  65. data/lib/oversip/sip/listeners/reactor.rb +39 -0
  66. data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
  67. data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
  68. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  69. data/lib/oversip/sip/listeners/tls_client.rb +117 -0
  70. data/lib/oversip/sip/listeners/tls_server.rb +70 -0
  71. data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
  72. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  73. data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
  74. data/lib/oversip/sip/listeners.rb +28 -0
  75. data/lib/oversip/sip/logic.rb +14 -0
  76. data/lib/oversip/sip/message.rb +168 -0
  77. data/lib/oversip/sip/message_processor.rb +202 -0
  78. data/lib/oversip/sip/modules/core.rb +200 -0
  79. data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
  80. data/lib/oversip/sip/modules/user_assertion.rb +123 -0
  81. data/lib/oversip/sip/proxy.rb +460 -0
  82. data/lib/oversip/sip/request.rb +128 -0
  83. data/lib/oversip/sip/response.rb +30 -0
  84. data/lib/oversip/sip/rfc3263.rb +646 -0
  85. data/lib/oversip/sip/server_transaction.rb +295 -0
  86. data/lib/oversip/sip/sip.rb +74 -0
  87. data/lib/oversip/sip/tags.rb +39 -0
  88. data/lib/oversip/sip/timers.rb +55 -0
  89. data/lib/oversip/sip/transport_manager.rb +129 -0
  90. data/lib/oversip/syslogger_process.rb +119 -0
  91. data/lib/oversip/tls.rb +179 -0
  92. data/lib/oversip/utils.rb +25 -0
  93. data/lib/oversip/version.rb +23 -0
  94. data/lib/oversip/websocket/constants.rb +56 -0
  95. data/lib/oversip/websocket/default_policy.rb +19 -0
  96. data/lib/oversip/websocket/http_request.rb +63 -0
  97. data/lib/oversip/websocket/launcher.rb +207 -0
  98. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
  99. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
  100. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
  101. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
  102. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
  103. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
  104. data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
  105. data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
  106. data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
  107. data/lib/oversip/websocket/listeners.rb +12 -0
  108. data/lib/oversip/websocket/ws_app.rb +75 -0
  109. data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
  110. data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
  111. data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
  112. data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
  113. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
  114. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
  115. data/lib/oversip/websocket/ws_apps.rb +9 -0
  116. data/lib/oversip/websocket/ws_framing.rb +597 -0
  117. data/lib/oversip.rb +59 -0
  118. data/test/oversip_test_helper.rb +20 -0
  119. data/test/test_http_parser.rb +73 -0
  120. data/test/test_sip_parser.rb +139 -0
  121. metadata +256 -0
@@ -0,0 +1,213 @@
1
+ module OverSIP::SIP
2
+
3
+ class UdpReactor < Reactor
4
+
5
+ def receive_data data
6
+ @buffer << data
7
+
8
+ while (case @state
9
+ when :init
10
+ @parser.reset
11
+ @parser_nbytes = 0
12
+ @state = :message
13
+
14
+ when :message
15
+ parse_message
16
+
17
+ when :finished
18
+ # Invoke the custom logic for requests.
19
+ if @msg.request?
20
+ process_request
21
+ else
22
+ process_response
23
+ end
24
+ @state = :init
25
+ false
26
+ end)
27
+ end # while
28
+ end
29
+
30
+ def parse_message
31
+ return false if @buffer.empty?
32
+
33
+ buffer_str = @buffer.to_str
34
+
35
+ # Quikly ignore single CRLF (widely used by SIP UDP clients as keep-alive.
36
+ if buffer_str == CRLF
37
+ @buffer.clear
38
+ @state = :init
39
+ return false
40
+ end
41
+
42
+ begin
43
+ source_port, source_ip = ::Socket.unpack_sockaddr_in(get_peername)
44
+ rescue => e
45
+ log_system_crit "error obtaining remote IP/port (#{e.class}: #{e.message})"
46
+ @buffer.clear
47
+ @state = :init
48
+ return false
49
+ end
50
+
51
+ case stun_res = ::OverSIP::Stun.parse_request(buffer_str, source_ip, source_port)
52
+ # Not a STUN request so continue with SIP parsing.
53
+ when nil
54
+ # An invalid STUN request, log it and drop it.
55
+ when false
56
+ log_system_debug "invalid STUN message received (not a valid STUN Binding Request)" if $oversip_debug
57
+ @buffer.clear
58
+ @state = :init
59
+ return false
60
+ # A valid STUN Binding Request so we get a response to be sent.
61
+ when String
62
+ log_system_debug "STUN Binding Request received, replying to it" if $oversip_debug
63
+ send_data stun_res
64
+ @buffer.clear
65
+ @state = :init
66
+ return false
67
+ end
68
+
69
+ # Parse the currently buffered data. If parsing fails @parser_nbytes gets nil value.
70
+ unless @parser_nbytes = @parser.execute(buffer_str, @parser_nbytes)
71
+ # The parsed data is invalid, however some data could be parsed so @parsed.parsed
72
+ # can be:
73
+ # - SIP::Request
74
+ # - SIP::Response
75
+ # - nil (the message is so wrong that cannot be neither a request or response).
76
+ if wrong_message = @parser.parsed
77
+ log_system_warn "parsing error for #{MSG_TYPE[wrong_message.class]}: \"#{@parser.error}\""
78
+ else
79
+ log_system_warn "parsing error: \"#{@parser.error}\""
80
+ end
81
+
82
+ @buffer.clear
83
+ @state = :init
84
+ return false
85
+ end
86
+
87
+ unless @parser.finished?
88
+ # The parsing has not finished.
89
+ # If UDP it's invalid as per RFC 3261 a UDP datagram MUST contain an entire
90
+ # SIP request or response. Note we also allow double CRLF in UDP. If just a
91
+ # single CRLF arrives ignore it and clear the buffer.
92
+ # Maybe the parser has gone enought data to determine if the unfinished
93
+ # message is a SIP request or response, log it if so.
94
+ # If not, then @parser.parsed returns nil and nothing is logged.
95
+ unfinished_msg = @parser.parsed
96
+ log_system_warn "ignoring not finished #{MSG_TYPE[unfinished_msg.class]} via UDP" if
97
+ unfinished_msg.is_a? ::OverSIP::SIP::Request or unfinished_msg.is_a? ::OverSIP::SIP::Response
98
+ # Clear the buffer, set :init state and wait for new messages.
99
+ @buffer.clear
100
+ @state = :init
101
+ return false
102
+ end
103
+
104
+ # At this point we've got a SIP::Request, SIP::Response or :outbound_keepalive symbol.
105
+ @msg = @parser.parsed
106
+
107
+ # Clear parsed data from the buffer.
108
+ @buffer.read(@parser_nbytes)
109
+
110
+ # Received data is a Outbound keealive (also allowed in UDP however). Reply single CRLF.
111
+ if @msg == :outbound_keepalive
112
+ log_system_debug "Outbound keepalive received, replying single CRLF" if $oversip_debug
113
+ # Reply a single CRLF over the same connection.
114
+ send_data CRLF
115
+ # If UDP there could be invalid data after double CRLF CRLF, just ignore it
116
+ # and clear the buffer. Set :init state and return false so we leave receive_data()
117
+ # method.
118
+ @buffer.clear
119
+ @state = :init
120
+ return false
121
+ end
122
+
123
+ @parser.post_parsing
124
+
125
+ # Here we have received the entire headers of a SIP request or response. Fill some
126
+ # attributes.
127
+ @msg.connection = self
128
+ @msg.transport = :udp
129
+ @msg.source_ip = source_ip
130
+ @msg.source_port = source_port
131
+ @msg.source_ip_type = self.class.ip_type
132
+
133
+ unless valid_message?
134
+ @buffer.clear
135
+ @state = :init
136
+ return false
137
+ end
138
+
139
+ add_via_received_rport if @msg.request?
140
+
141
+ unless check_via_branch
142
+ @buffer.clear
143
+ @state = :init
144
+ return false
145
+ end
146
+
147
+ # Examine Content-Length header.
148
+ # There is Content-Length header.
149
+ if cl = @msg.content_length and cl > 0
150
+ # Body size is correct. Read it and clear the buffer.
151
+ # Set :finished state and return true so message will be processed.
152
+ if cl == @buffer.size
153
+ @msg.body = @buffer.read.force_encoding(::Encoding::UTF_8)
154
+ @buffer.clear
155
+ @state = :finished
156
+ return true
157
+ # In UDP the remaining data after headers must be the entire body
158
+ # and fill exactly Content-Length bytes. If not it's invalid. Reply
159
+ # 400 and clear the buffer.
160
+ else
161
+ if @msg.request?
162
+ unless @msg.sip_method == :ACK
163
+ log_system_warn "request body size doesn't match Content-Length => 400"
164
+ @msg.reply 400, "Body size doesn't match Content-Length"
165
+ else
166
+ log_system_warn "ACK body size doesn't match Content-Length, ignoring it"
167
+ end
168
+ else
169
+ log_system_warn "response body size doesn't match Content-Length, ignoring it"
170
+ end
171
+ @buffer.clear
172
+ @state = :init
173
+ return false
174
+ end
175
+ # No Content-Length header or 0 value. However it could occur that the datagram
176
+ # contains remaining unuseful data, in this case reply 400. If not
177
+ # set :finished state and return true so message will be processed.
178
+ else
179
+ # Ensure there is no more data in the buffer. If it's ok set :finished
180
+ # state and return true so message will be processed.
181
+ if @buffer.size.zero?
182
+ @state = :finished
183
+ return true
184
+ # Non valid remaining data in the UDP datagram. Reply 400.
185
+ else
186
+ if @msg.request?
187
+ log_system_warn "request contains body but Content-Length is zero or not present => 400"
188
+ @msg.reply 400, "request contains body but Content-Length is zero or not present"
189
+ else
190
+ log_system_warn "response contains body but Content-Length is zero or not present, ignoring it"
191
+ end
192
+ @buffer.clear
193
+ @state = :init
194
+ return false
195
+ end
196
+ end
197
+
198
+ end # parse_headers
199
+
200
+ def send_sip_msg msg, ip, port
201
+ send_datagram msg, ip, port
202
+ true
203
+ end
204
+
205
+
206
+ def unbind cause=nil
207
+ log_system_crit "UDP socket closed!!! cause: #{cause.inspect}"
208
+ end
209
+
210
+ end # class UdpReactor
211
+
212
+ end
213
+
@@ -0,0 +1,28 @@
1
+ # OverSIP files
2
+
3
+ require "oversip/sip/listeners/reactor"
4
+
5
+ require "oversip/sip/listeners/udp_reactor"
6
+ require "oversip/sip/listeners/tcp_reactor"
7
+ require "oversip/sip/listeners/tls_tunnel_reactor"
8
+
9
+ require "oversip/sip/listeners/tcp_server"
10
+ require "oversip/sip/listeners/tls_server"
11
+ require "oversip/sip/listeners/tls_tunnel_server"
12
+
13
+ require "oversip/sip/listeners/ipv4_udp_server"
14
+ require "oversip/sip/listeners/ipv6_udp_server"
15
+ require "oversip/sip/listeners/ipv4_tcp_server"
16
+ require "oversip/sip/listeners/ipv6_tcp_server"
17
+ require "oversip/sip/listeners/ipv4_tls_server"
18
+ require "oversip/sip/listeners/ipv6_tls_server"
19
+ require "oversip/sip/listeners/ipv4_tls_tunnel_server"
20
+ require "oversip/sip/listeners/ipv6_tls_tunnel_server"
21
+
22
+ require "oversip/sip/listeners/tcp_client"
23
+ require "oversip/sip/listeners/tls_client"
24
+
25
+ require "oversip/sip/listeners/ipv4_tcp_client"
26
+ require "oversip/sip/listeners/ipv6_tcp_client"
27
+ require "oversip/sip/listeners/ipv4_tls_client"
28
+ require "oversip/sip/listeners/ipv6_tls_client"
@@ -0,0 +1,14 @@
1
+ module OverSIP::SIP
2
+
3
+ class Logic
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ def initialize request
8
+ @log_id = "Logic " << request.via_branch_id
9
+ @request = request
10
+ end
11
+
12
+ end # class Logic
13
+
14
+ end
@@ -0,0 +1,168 @@
1
+ module OverSIP::SIP
2
+
3
+ class Message
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ DIALOG_FORMING_METHODS = { :INVITE=>true, :SUBSCRIBE=>true, :REFER=>true }
8
+ LOOSE_RECORD_AWARE_METHODS = { :INVITE=>true, :REGISTER=>true, :SUBSCRIBE=>true, :REFER=>true }
9
+ OUTBOUND_AWARE_METHODS = { :INVITE=>true, :REGISTER=>true, :SUBSCRIBE=>true, :REFER=>true }
10
+ EMPTY_ARRAY = [].freeze
11
+
12
+ # SIP related attributes.
13
+ attr_accessor :transport
14
+ attr_accessor :source_ip
15
+ attr_accessor :source_ip_type
16
+ attr_accessor :source_port
17
+ attr_accessor :connection
18
+
19
+ # SIP message attributes.
20
+ attr_reader :sip_method
21
+ attr_reader :sip_version
22
+ attr_reader :headers
23
+
24
+ attr_reader :via_sent_by_host
25
+ attr_reader :via_sent_by_port
26
+ attr_reader :via_branch
27
+ attr_accessor :via_branch_id # It's the branch value without "z9hG4bK".
28
+ attr_reader :via_branch_rfc3261
29
+ attr_reader :via_received
30
+ attr_reader :via_has_rport
31
+ attr_accessor :via_rport # Value not parsed.
32
+ attr_reader :via_has_alias
33
+ attr_reader :via_core_value
34
+ attr_reader :via_params
35
+ attr_reader :num_vias
36
+
37
+ attr_reader :call_id
38
+ attr_reader :cseq
39
+ attr_reader :max_forwards
40
+ attr_reader :content_length
41
+ attr_reader :routes
42
+ attr_reader :require
43
+ attr_reader :supported
44
+ attr_reader :proxy_require
45
+
46
+ attr_accessor :body
47
+
48
+ attr_accessor :from # NameAddr instance.
49
+ attr_reader :from_tag
50
+ attr_accessor :to # NameAddr instance.
51
+ attr_reader :to_tag
52
+ attr_reader :contact # NameAddr instance (when it has a single value).
53
+ attr_reader :contact_params
54
+
55
+ attr_reader :hdr_via # Array
56
+ attr_reader :hdr_from # String
57
+ attr_reader :hdr_to # String
58
+ attr_reader :hdr_route # Array
59
+
60
+ # Other attributes.
61
+ attr_accessor :tvars # Transaction variables (a hash).
62
+
63
+
64
+ def udp? ; @transport == :udp end
65
+ def tcp? ; @transport == :tcp end
66
+ def tls? ; @transport == :tls end
67
+ def ws? ; @transport == :ws end
68
+ def tls? ; @transport == :wss end
69
+
70
+ def websocket? ; @transport == :ws || @transport == :wss end
71
+
72
+ def unknown_method? ; @is_unknown_method end
73
+
74
+ def via_rport? ; @via_has_rport end
75
+
76
+ def via_alias? ; @via_has_alias end
77
+
78
+ def dialog_forming?
79
+ DIALOG_FORMING_METHODS[@sip_method]
80
+ end
81
+
82
+ def loose_record_aware?
83
+ LOOSE_RECORD_AWARE_METHODS[@sip_method]
84
+ end
85
+
86
+ def outbound_aware?
87
+ OUTBOUND_AWARE_METHODS[@sip_method]
88
+ end
89
+
90
+ # Returns true if a header with the given header _name_ exists, false otherwise.
91
+ def has_header? name
92
+ @headers[MessageParser.headerize(name)] && true
93
+ end
94
+
95
+ # Returns the first value of the given header _name_, nil if it doesn't exist.
96
+ def header_top name
97
+ ( hdr = @headers[MessageParser.headerize(name)] ) ? hdr[0] : nil
98
+ end
99
+ alias :header :header_top
100
+
101
+ # Returns an array with all the values of the given header _name_, an empty array
102
+ # if it doesn't exist.
103
+ def header_all name
104
+ ( hdr = @headers[MessageParser.headerize(name)] ) ? hdr : EMPTY_ARRAY
105
+ end
106
+
107
+ # Replaces the header of given _name_ with a the given _value_.
108
+ # _value_ can be a single value or an array.
109
+ def set_header name, value
110
+ @headers[MessageParser.headerize(name)] =
111
+ case value
112
+ when Array
113
+ value
114
+ else
115
+ [ value.to_s ]
116
+ end
117
+ end
118
+
119
+ # Completely deletes the header with given _name_.
120
+ # Returns an array containing all the header values, nil otherwise.
121
+ def delete_header name
122
+ @headers.delete MessageParser.headerize(name)
123
+ end
124
+
125
+ # Removes the first value of a given header _name_.
126
+ # Returns the extracted value, nil otherwise.
127
+ def delete_header_top name
128
+ if hdr = @headers[k=MessageParser.headerize(name)]
129
+ hdr.size > 1 ? hdr.shift : @headers.delete(k)[0]
130
+ end
131
+ end
132
+
133
+ # Inserts the given _value_ in the first position of header _name_.
134
+ # _value_ must be a string.
135
+ def insert_header name, value
136
+ if hdr = @headers[k=MessageParser.headerize(name)]
137
+ hdr.insert 0, value.to_s
138
+ else
139
+ #@headers[k] = [ value.to_s ]
140
+ # NOTE: If the header name doesn't already exist in the mesage, insert
141
+ # the new header in the first position of the Hash.
142
+ @headers = { k => [ value.to_s ] }.merge! @headers
143
+ end
144
+ end
145
+
146
+ # Append the given _value_ in the last position of header _name_.
147
+ # _value_ must be a string.
148
+ def append_header name, value
149
+ if hdr = @headers[k=MessageParser.headerize(name)]
150
+ hdr.push value.to_s
151
+ else
152
+ @headers[k] = [ value.to_s ]
153
+ end
154
+ end
155
+
156
+ # Replaces the top value of the given header _name_ with the
157
+ # string given as argument _value_.
158
+ def replace_header_top name, value
159
+ if hdr = @headers[k=MessageParser.headerize(name)]
160
+ hdr[0] = value.to_s
161
+ else
162
+ @headers[k] = [ value.to_s ]
163
+ end
164
+ end
165
+
166
+ end # class Message
167
+
168
+ end
@@ -0,0 +1,202 @@
1
+ module OverSIP::SIP
2
+
3
+ module MessageProcessor
4
+
5
+ # Constants for efficiency.
6
+ MSG_TYPE = {
7
+ ::OverSIP::SIP::Request => "SIP request",
8
+ ::OverSIP::SIP::Response => "SIP response",
9
+ :outbound_keepalive => "Outbound keepalive"
10
+ }
11
+
12
+
13
+ def valid_message?
14
+ if header = @parser.missing_core_header?
15
+ log_system_notice "ignoring #{MSG_TYPE[@msg.class]} missing #{header} header"
16
+ return false
17
+ elsif header = @parser.duplicated_core_header?
18
+ log_system_notice "ignoring #{MSG_TYPE[@msg.class]} with duplicated #{header} header"
19
+ return false
20
+ end
21
+ return true
22
+ end
23
+ private :valid_message?
24
+
25
+
26
+ # Via ;received and ;rport stuff.
27
+ def add_via_received_rport
28
+ # - If ;rport is present ;received MUST also be set (RFC 3581).
29
+ # - If not add ;received according to RFC 3261 rules.
30
+ if @msg.via_rport?
31
+ via_received = @msg.source_ip
32
+ @msg.via_rport = @msg.source_port
33
+ else
34
+ via_received = (::OverSIP::Utils.compare_ips(@msg.via_sent_by_host, @msg.source_ip) ? nil : @msg.source_ip)
35
+ end
36
+
37
+ if via_received
38
+ via_params = ";branch=" << @msg.via_branch if @msg.via_branch
39
+ via_params << ";received=" << via_received if via_received
40
+ via_params << ";rport=" << @msg.via_rport.to_s if @msg.via_rport
41
+ via_params << ";alias" if @msg.via_alias?
42
+
43
+ if @msg.via_params
44
+ @msg.via_params.each { |k,v| via_params << ( v ? ";#{k}=#{v}" : ";#{k}" ) }
45
+ end
46
+
47
+ @msg.hdr_via[0] = "#{@msg.via_core_value}#{via_params}"
48
+ end
49
+ end
50
+ private :add_via_received_rport
51
+
52
+
53
+ # Reject the message in case it doesn't contain a Via branch compliant with RFC 3261
54
+ def check_via_branch
55
+ if @msg.via_branch_rfc3261
56
+ @msg.via_branch_id = @msg.via_branch[7..-1] # The branch without "z9hG4bK".
57
+ return true
58
+ end
59
+
60
+ if @msg.is_a? Request
61
+ unless @msg.sip_method == :ACK
62
+ log_system_notice "request doesn't contain a RFC 3261 Via branch => 400"
63
+ @msg.reply 400, "Via branch non RFC 3261 compliant"
64
+ else
65
+ log_system_notice "ACK doesn't contain a RFC 3261 Via branch, ignoring it"
66
+ end
67
+ else
68
+ log_system_notice "response doesn't contain a RFC 3261 Via branch, ignoring it"
69
+ end
70
+ false
71
+ end
72
+ private :check_via_branch
73
+
74
+
75
+ def process_request
76
+ # Create a new Logic instance for this request (unless it's a retransmission of the request,
77
+ # a CANCEL or an ACK for a final non-2XX response).
78
+ unless check_transaction
79
+ begin
80
+ # Create the antiloop identifier for this request.
81
+ @msg.antiloop_id = ::OverSIP::SIP::Tags.create_antiloop_id(@msg)
82
+
83
+ # Check loops.
84
+ if @msg.antiloop_id == @msg.via_branch_id[-32..-1]
85
+ @msg.reply 482, "Loop Detected"
86
+ return
87
+ end
88
+
89
+ # Initialize some attributes for the request (for received responses
90
+ # it's set in Proxy#receive_response).
91
+ @msg.tvars = {}
92
+
93
+ # Create the Logic instance and run it!
94
+ OverSIP::SIP::Logic.new(@msg).run
95
+ rescue => e
96
+ log_system_error e
97
+ @msg.reply 503, "Internal Error", ["Content-Type: text/plain"], "#{e.class }: #{e.message}"
98
+ end
99
+ end
100
+ end
101
+ private :process_request
102
+
103
+
104
+ # Process a received response.
105
+ def process_response
106
+ case @msg.sip_method
107
+ when :INVITE
108
+ ### TODO: Esto va a petar cuando tenga una clase que hereda de, p.ej, IPv4TcpServer que se llame xxxClient,
109
+ # ya que en ella no existirá @invite_client_transactions. Tengo que hacer que su @invite_client_transactions
110
+ # se rellene al de la clase padre al hacer el load de las clases.
111
+ if client_transaction = self.class.invite_client_transactions[@msg.via_branch_id]
112
+ client_transaction.receive_response(@msg)
113
+ return
114
+ end
115
+ when :ACK
116
+ when :CANCEL
117
+ if client_transaction = self.class.invite_client_transactions[@msg.via_branch_id]
118
+ client_transaction.receive_response_to_cancel(@msg)
119
+ return
120
+ end
121
+ else
122
+ if client_transaction = self.class.non_invite_client_transactions[@msg.via_branch_id]
123
+ client_transaction.receive_response(@msg)
124
+ return
125
+ end
126
+ end
127
+ log_system_debug "ignoring a response non matching a client transaction (#{@msg.sip_method} #{@msg.status_code})" if $oversip_debug
128
+ end
129
+ private :process_response
130
+
131
+
132
+ # Check transaction.
133
+ def check_transaction
134
+ case @msg.sip_method
135
+
136
+ when :INVITE
137
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
138
+ # If the retranmission arrives via a different connection (for TCP/TLS) then use
139
+ # the new one.
140
+ if @msg.connection == server_transaction.request.connection
141
+ log_system_debug "INVITE retransmission received" if $oversip_debug
142
+ else
143
+ log_system_debug "INVITE retransmission received via other connection, updating server transaction" if $oversip_debug
144
+ server_transaction.request.connection = @msg.connection
145
+ end
146
+ server_transaction.retransmit_last_response
147
+ return true
148
+ end
149
+
150
+ when :ACK
151
+ # If there is associated INVITE transaction (so it has been rejected)
152
+ # pass ACK to the transaction.
153
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
154
+ server_transaction.receive_ack
155
+ return true
156
+ # Absorb ACK for statelessly generated final responses by us.
157
+ elsif OverSIP::SIP::Tags.check_totag_for_sl_reply(@msg.to_tag)
158
+ log_system_debug "absorving ACK for a stateless final response" if $oversip_debug
159
+ return true
160
+ else
161
+ log_system_debug "passing ACK to the core" if $oversip_debug
162
+ return false
163
+ end
164
+
165
+ when :CANCEL
166
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
167
+ case state = server_transaction.state
168
+ when :proceeding
169
+ log_system_debug "CANCEL matches an INVITE server transaction in proceeding state => 200" if $oversip_debug
170
+ @msg.reply 200, "Cancelled"
171
+ server_transaction.receive_cancel(@msg)
172
+ else
173
+ log_system_debug "CANCEL matches an INVITE server transaction in #{state} state => 200" if $oversip_debug
174
+ @msg.reply 200, "Cancelled"
175
+ end
176
+ else
177
+ log_system_debug "CANCEL does not match an INVITE server transaction => 481" if $oversip_debug
178
+ @msg.reply 481
179
+ end
180
+ return true
181
+
182
+ else
183
+ if server_transaction = @msg.connection.class.non_invite_server_transactions[@msg.via_branch_id]
184
+ # If the retranmission arrives via a different connection (for TCP/TLS) then use
185
+ # the new one.
186
+ if @msg.connection == server_transaction.request.connection
187
+ log_system_debug "#{server_transaction.request.sip_method} retransmission received" if $oversip_debug
188
+ else
189
+ log_system_debug "#{server_transaction.request.sip_method} retransmission received via other connection, updating server transaction" if $oversip_debug
190
+ server_transaction.request.connection = @msg.connection
191
+ end
192
+ server_transaction.retransmit_last_response
193
+ return true
194
+ end
195
+
196
+ end
197
+ end # def check_transaction
198
+ private :check_transaction
199
+
200
+ end
201
+
202
+ end