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,200 @@
1
+ module OverSIP::SIP
2
+
3
+ module Modules
4
+ module Core
5
+
6
+ # Create a server transaction for the incoming request.
7
+ def create_transaction
8
+ case @sip_method
9
+ when :INVITE
10
+ ::OverSIP::SIP::InviteServerTransaction.new self
11
+ when :ACK
12
+ when :CANCEL
13
+ else
14
+ ::OverSIP::SIP::NonInviteServerTransaction.new self
15
+ end
16
+ end
17
+
18
+
19
+ def check_max_forwards max_forwards
20
+ if @max_forwards
21
+ unless @max_forwards.zero?
22
+ @new_max_forwards = ( @max_forwards > max_forwards ? max_forwards : @max_forwards - 1 )
23
+ return true
24
+ else
25
+ log_system_notice "Max-Forwards is 0 => 483"
26
+ reply 483
27
+ return false
28
+ end
29
+ else
30
+ @new_max_forwards = max_forwards
31
+ return true
32
+ end
33
+ end
34
+
35
+
36
+ # Returns a Proxy instance. The user MUST call route() and optionally set the callbacks
37
+ # before calling route().
38
+ def proxy proxy_name=:default_proxy
39
+ if (proxy_conf = ::OverSIP.proxies[proxy_name.to_sym])
40
+ ::OverSIP::SIP::Proxy.new self, proxy_conf
41
+ else
42
+ raise ::OverSIP::LogicError, "proxy '#{proxy_name}' is not defined"
43
+ end
44
+ end
45
+
46
+
47
+ def loose_route
48
+ num_removes = 0
49
+ has_preloaded_route_with_ob_param = false
50
+
51
+ # Remove all the Route's pointing to the proxy until a Route not pointing to us is found.
52
+ if @routes
53
+ @routes.each do |route|
54
+ if ::OverSIP::SIP::Tags.check_value_for_route_ovid(route.ovid_param)
55
+ num_removes += 1
56
+ else
57
+ if local_uri? route
58
+ log_system_debug "removing pre-loaded Route pointing to this server" if $oversip_debug
59
+ has_preloaded_route_with_ob_param = true if route.ob_param?
60
+ num_removes += 1
61
+ else
62
+ break
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ ### Outbound stuf. RFC 5626 section 5.3.
69
+
70
+ # Outgoing initial request asking for Outbound. Just valid when:
71
+ # - It's an initial request.
72
+ # - Single Via (so there is no a proxy in front of us).
73
+ # - It's an INVITE, REGISTER, SUBSCRIBE or REFER request.
74
+ # - Has a preloaded top Route with ;ob param pointing to us, or has Contact with ;ob, or
75
+ # it's a REGISTER with ;+sip.instance.
76
+ #
77
+ # TODO: and (has_preloaded_route_with_ob_param or @request.contact.ob_param?).
78
+ # TODO: For REGISTER check also ;+sip.instance Contact param.
79
+ if (
80
+ @force_outgoing_outbound or (
81
+ initial? and
82
+ @num_vias == 1 and
83
+ outbound_aware? and
84
+ has_preloaded_route_with_ob_param
85
+ )
86
+ )
87
+ @outgoing_outbound_requested = true
88
+ log_system_debug "applying outgoing Outbound support" if $oversip_debug
89
+ end
90
+
91
+ # Incoming initial request or in-dialog incoming/outgoing request. Must only perform
92
+ # Outbound for the incoming case and just when:
93
+ # - There are 2 Route headers.
94
+ # - All the Route headers point to us.
95
+ # - The latest Route has a flow token and a valid ;ovid param (so has been generated
96
+ # previously by us).
97
+ # NOTE: But don't check its value so it still would work in case of server reboot.
98
+ # - It's an incoming Outbound request (so flow token in the Route does not match the
99
+ # flow token of the incoming connection).
100
+ if (
101
+ num_removes == 2 and
102
+ @routes.size == 2 and
103
+ (outbound_route = @routes.last) and
104
+ outbound_route.ovid_param and
105
+ (@route_outbound_flow_token = outbound_route.user) != @connection_outbound_flow_token
106
+ )
107
+ @incoming_outbound_requested = true
108
+ log_system_debug "destination is an incoming Outbound connection" if $oversip_debug
109
+ end
110
+
111
+ # If there are not Route headers return false.
112
+ return false unless @routes
113
+
114
+ # Remove the Route values pointintg to us.
115
+ unless num_removes == 0
116
+ @headers["Route"].shift num_removes
117
+ @routes.shift num_removes
118
+ end
119
+ @routes.empty? and @routes = nil
120
+
121
+ # Return true if it is an in-dialog request and at least one top Route pointed to us.
122
+ # False otherwise as we shouldn't receive an in-dialog request with a top Route non
123
+ # pointing to us.
124
+ if in_dialog?
125
+ return ( num_removes > 0 ? true : false )
126
+ # Return true if it was an initial request and more Route headers remain after inspection.
127
+ elsif @routes
128
+ return true
129
+ # Return false if it was an initial request and all its Route headers pointed to the proxy.
130
+ else
131
+ return false
132
+ end
133
+ end
134
+
135
+
136
+ # Mira si el RURI es local. Se supone que antes se ha validado el Route y que el script
137
+ # no permite pre-loaded Route a otro destino..
138
+ def destination_myself?
139
+ return true if @destination_myself
140
+ return false if @destination_myself == false
141
+
142
+ if local_uri? @ruri
143
+ log_system_debug "RURI destination is myself" if $oversip_debug
144
+ return @destination_myself = true
145
+ else
146
+ log_system_debug "RURI destination is not myself" if $oversip_debug
147
+ return @destination_myself = false
148
+ end
149
+ end
150
+
151
+
152
+ def fix_nat
153
+ # Force rport usage for UDP clients.
154
+ @via_rport = @source_port
155
+
156
+ # Force outgoing Outbound.
157
+ if initial? and @num_vias == 1 and outbound_aware?
158
+ @force_outgoing_outbound = true
159
+ end
160
+ end
161
+
162
+
163
+ # TODO: It must be true if top Route or Contact has ;ob param, or also if the Contact
164
+ # has +sip.instance.
165
+ def outgoing_outbound_requested? ; @outgoing_outbound_requested end
166
+
167
+ def incoming_outbound_requested? ; @incoming_outbound_requested end
168
+
169
+
170
+ def connection_outbound_flow_token
171
+ @connection_outbound_flow_token ||= if @transport == :udp
172
+ # NOTE: Add "_" so later we can figure that this is for UDP.
173
+ # NOTE: Replace "=" with "-" so it can be added as a SIP URI param (when Contact mangling is used
174
+ # if the registrar does not support Path).
175
+ "_" << ::Base64.strict_encode64("#{@source_ip}_#{@source_port}").gsub(/=/,"-")
176
+ else
177
+ @connection.outbound_flow_token
178
+ end
179
+ end
180
+
181
+
182
+ private
183
+
184
+
185
+ def local_uri? uri
186
+ # NOTE: uri.host has been normalized during parsing in case it's an IPv6 and it's
187
+ # an :ipv6_reference.
188
+ ( uri.port and ::OverSIP::SIP.local_aliases["#{uri.host}:#{uri.port}"] ) or
189
+ ( not uri.port and ::OverSIP::SIP.local_aliases[uri.host] )
190
+ end
191
+
192
+ end # module Core
193
+ end # module Modules
194
+
195
+
196
+ class Request
197
+ include ::OverSIP::SIP::Modules::Core
198
+ end
199
+
200
+ end
@@ -0,0 +1,75 @@
1
+ module OverSIP::SIP
2
+
3
+ module Modules
4
+ module RegistrarWithoutPath
5
+
6
+ extend ::OverSIP::Logger
7
+
8
+ def self.log_id
9
+ @@log_id ||= "RegistrarWithoutPath module"
10
+ end
11
+
12
+ def self.add_outbound_to_contact request
13
+ unless request.sip_method == :REGISTER
14
+ raise ::OverSIP::LogicError, "request must be a REGISTER"
15
+ end
16
+
17
+ if request.contact and request.connection_outbound_flow_token
18
+ log_system_debug "performing Contact mangling (adding ;ov-ob Outbound param) for #{request.log_id}" if $oversip_debug
19
+
20
+ # Add the ;ov-ob param to the Contact URI.
21
+ request.contact.set_param "ov-ob", request.connection_outbound_flow_token
22
+ # TODO: This should be done automatically, right?
23
+ request.set_header "Contact", "#{request.contact.to_s}#{request.contact_params}"
24
+
25
+ return true
26
+
27
+ else
28
+ return false
29
+ end
30
+ end
31
+
32
+ def self.extract_outbound_from_ruri request
33
+ # Do nothing if the request already contains a Route header with the Outbound flow token (so
34
+ # the registrar *does* support Path.
35
+ unless request.incoming_outbound_requested?
36
+ if ov_ob = request.ruri.del_param("ov-ob")
37
+ log_system_debug "incoming Outbound flow token extracted from ;ov-ob param in RURI for #{request.log_id}" if $oversip_debug
38
+ request.route_outbound_flow_token = ov_ob
39
+ request.incoming_outbound_requested = true
40
+ return true
41
+ else
42
+ return false
43
+ end
44
+
45
+ else
46
+ # If the request already contains a proper Outbound Route header, then at least try to remove
47
+ # the ;ov-ob param from the RURI.
48
+ request.ruri.del_param("ov-ob")
49
+ return false
50
+ end
51
+ end
52
+
53
+ def self.remove_outbound_from_contact message
54
+ unless message.is_a? ::OverSIP::SIP::Message
55
+ raise ::OverSIP::LogicError, "message must be a OverSIP::SIP::Request or OverSIP::SIP::Response"
56
+ end
57
+
58
+ if (contacts = message.headers["Contact"])
59
+ log_system_debug "reverting original Contact value (removing ;ov-ob Outbound param) for response" if $oversip_debug
60
+
61
+ contacts.each do |contact|
62
+ contact.gsub! /;ov-ob=[_\-0-9A-Za-z]+/, ""
63
+ end
64
+
65
+ return true
66
+
67
+ else
68
+ return false
69
+ end
70
+ end
71
+
72
+ end # module RegistrarWithoutPath
73
+ end # module Modules
74
+
75
+ end # module OverSIP::SIP
@@ -0,0 +1,123 @@
1
+ module OverSIP::SIP
2
+
3
+ module Modules
4
+ module UserAssertion
5
+
6
+ extend ::OverSIP::Logger
7
+
8
+ def self.log_id
9
+ @@log_id ||= "UserAssertion module"
10
+ end
11
+
12
+ def self.assert_connection message
13
+ case message
14
+ when ::OverSIP::SIP::Request
15
+ request = message
16
+ when ::OverSIP::SIP::Response
17
+ request = message.request
18
+ else
19
+ raise ::OverSIP::LogicError, "message must be a OverSIP::SIP::Request or OverSIP::SIP::Response"
20
+ end
21
+
22
+ # Don't do this stuf for UDP or for outbound connections.
23
+ return false unless request.connection.class.reliable_transport_listener?
24
+ # Return if already set.
25
+ return request.connection.asserted_user if request.connection.asserted_user
26
+ # Don't do this stuf in case of P-Preferred-Identity header is present.
27
+ return false if request.headers["P-Preferred-Identity"]
28
+
29
+ log_system_debug "user #{request.from.uri} asserted to connection" if $oversip_debug
30
+ # Store the request From URI as "asserted_user" for this connection.
31
+ request.connection.asserted_user = request.from.uri
32
+ end
33
+
34
+ def self.revoke_assertion message
35
+ case message
36
+ when ::OverSIP::SIP::Request
37
+ request = message
38
+ when ::OverSIP::SIP::Response
39
+ request = message.request
40
+ else
41
+ raise ::OverSIP::LogicError, "message must be a OverSIP::SIP::Request or OverSIP::SIP::Response"
42
+ end
43
+
44
+ request.connection.asserted_user = false
45
+ true
46
+ end
47
+
48
+ def self.add_pai request
49
+ # Add P-Asserted-Identity if the user has previously been asserted but JUST
50
+ # in case it matches request From URI !
51
+ # NOTE: If the connection is not asserted (it's null) then it will not match this
52
+ # comparisson, so OK.
53
+ if request.connection.asserted_user == request.from.uri
54
+ # Don't add P-Asserted-Identity if the request contains P-Preferred-Identity header.
55
+ unless request.headers["P-Preferred-Identity"]
56
+ log_system_debug "user asserted, adding P-Asserted-Identity for #{request.log_id}" if $oversip_debug
57
+ request.set_header "P-Asserted-Identity", "<" << request.connection.asserted_user << ">"
58
+ return true
59
+ else
60
+ # Remove posible P-Asserted-Identity header!
61
+ log_system_debug "user asserted but P-Preferred-Identity header present, P-Asserted-Identity not added for #{request.log_id}" if $oversip_debug
62
+ request.headers.delete "P-Asserted-Identity"
63
+ end
64
+
65
+ # Otherwise ensure the request has no spoofed P-Asserted-Identity headers!
66
+ else
67
+ request.headers.delete "P-Asserted-Identity"
68
+ return false
69
+
70
+ end
71
+ end
72
+
73
+ end # module UserAssertion
74
+ end # module Modules
75
+
76
+ end # module OverSIP::SIP
77
+
78
+
79
+ module OverSIP::SIP
80
+ class Request
81
+ def asserted_user?
82
+ true if self.connection.asserted_user
83
+ end
84
+
85
+ def asserted_user
86
+ self.connection.asserted_user
87
+ end
88
+ end
89
+
90
+ class Response
91
+ def asserted_user?
92
+ true if self.request.connection.asserted_user
93
+ end
94
+
95
+ def asserted_user
96
+ self.request.connection.asserted_user
97
+ end
98
+ end
99
+
100
+ class TcpServer
101
+ attr_accessor :asserted_user
102
+ end
103
+
104
+ class TlsServer
105
+ attr_accessor :asserted_user
106
+ end
107
+
108
+ class TlsTunnelServer
109
+ attr_accessor :asserted_user
110
+ end
111
+
112
+ # This is never used since it's not a reliable connection, but it's required not to fail.
113
+ class UdpReactor
114
+ attr_accessor :asserted_user
115
+ end
116
+ end # OverSIP::SIP
117
+
118
+
119
+ module OverSIP::WebSocket
120
+ class WsSipApp
121
+ attr_accessor :asserted_user
122
+ end
123
+ end # OverSIP::WebSocket