oversip 0.9.0

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