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.
- data/AUTHORS.txt +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +55 -0
- data/bin/oversip +182 -0
- data/ext/common/c_util.h +74 -0
- data/ext/common/ruby_c_util.h +88 -0
- data/ext/sip_parser/common_headers.h +209 -0
- data/ext/sip_parser/ext_help.h +18 -0
- data/ext/sip_parser/extconf.rb +3 -0
- data/ext/sip_parser/sip_parser.c +29649 -0
- data/ext/sip_parser/sip_parser.h +227 -0
- data/ext/sip_parser/sip_parser_ruby.c +1292 -0
- data/ext/stud/extconf.rb +27 -0
- data/ext/stud/stud.tar.gz +0 -0
- data/ext/stun/ext_help.h +16 -0
- data/ext/stun/extconf.rb +3 -0
- data/ext/stun/stun_ruby.c +391 -0
- data/ext/utils/ext_help.h +14 -0
- data/ext/utils/extconf.rb +3 -0
- data/ext/utils/haproxy_protocol.c +6163 -0
- data/ext/utils/haproxy_protocol.h +27 -0
- data/ext/utils/ip_utils.c +5952 -0
- data/ext/utils/ip_utils.h +61 -0
- data/ext/utils/outbound_utils.c +3227 -0
- data/ext/utils/outbound_utils.h +27 -0
- data/ext/utils/utils_ruby.c +384 -0
- data/ext/utils/utils_ruby.h +75 -0
- data/ext/websocket_framing_utils/ext_help.h +18 -0
- data/ext/websocket_framing_utils/extconf.rb +3 -0
- data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
- data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
- data/ext/websocket_http_parser/ext_help.h +18 -0
- data/ext/websocket_http_parser/extconf.rb +3 -0
- data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
- data/ext/websocket_http_parser/ws_http_parser.h +86 -0
- data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
- data/lib/oversip/config.rb +541 -0
- data/lib/oversip/config_validators.rb +126 -0
- data/lib/oversip/errors.rb +7 -0
- data/lib/oversip/fiber_pool.rb +56 -0
- data/lib/oversip/launcher.rb +507 -0
- data/lib/oversip/logger.rb +170 -0
- data/lib/oversip/master_process.rb +67 -0
- data/lib/oversip/posix_mq.rb +121 -0
- data/lib/oversip/proxies_config.rb +169 -0
- data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
- data/lib/oversip/sip/client_transaction.rb +587 -0
- data/lib/oversip/sip/constants.rb +87 -0
- data/lib/oversip/sip/grammar/name_addr.rb +27 -0
- data/lib/oversip/sip/grammar/uri.rb +116 -0
- data/lib/oversip/sip/launcher.rb +180 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/reactor.rb +39 -0
- data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
- data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
- data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
- data/lib/oversip/sip/listeners/tls_client.rb +117 -0
- data/lib/oversip/sip/listeners/tls_server.rb +70 -0
- data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
- data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
- data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
- data/lib/oversip/sip/listeners.rb +28 -0
- data/lib/oversip/sip/logic.rb +14 -0
- data/lib/oversip/sip/message.rb +168 -0
- data/lib/oversip/sip/message_processor.rb +202 -0
- data/lib/oversip/sip/modules/core.rb +200 -0
- data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
- data/lib/oversip/sip/modules/user_assertion.rb +123 -0
- data/lib/oversip/sip/proxy.rb +460 -0
- data/lib/oversip/sip/request.rb +128 -0
- data/lib/oversip/sip/response.rb +30 -0
- data/lib/oversip/sip/rfc3263.rb +646 -0
- data/lib/oversip/sip/server_transaction.rb +295 -0
- data/lib/oversip/sip/sip.rb +74 -0
- data/lib/oversip/sip/tags.rb +39 -0
- data/lib/oversip/sip/timers.rb +55 -0
- data/lib/oversip/sip/transport_manager.rb +129 -0
- data/lib/oversip/syslogger_process.rb +119 -0
- data/lib/oversip/tls.rb +179 -0
- data/lib/oversip/utils.rb +25 -0
- data/lib/oversip/version.rb +23 -0
- data/lib/oversip/websocket/constants.rb +56 -0
- data/lib/oversip/websocket/default_policy.rb +19 -0
- data/lib/oversip/websocket/http_request.rb +63 -0
- data/lib/oversip/websocket/launcher.rb +207 -0
- data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
- data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
- data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
- data/lib/oversip/websocket/listeners.rb +12 -0
- data/lib/oversip/websocket/ws_app.rb +75 -0
- data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
- data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
- data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
- data/lib/oversip/websocket/ws_apps.rb +9 -0
- data/lib/oversip/websocket/ws_framing.rb +597 -0
- data/lib/oversip.rb +59 -0
- data/test/oversip_test_helper.rb +20 -0
- data/test/test_http_parser.rb +73 -0
- data/test/test_sip_parser.rb +139 -0
- metadata +256 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
module OverSIP
|
|
2
|
+
|
|
3
|
+
# Logging client module. Any class desiring to log messages must include (or extend) this module.
|
|
4
|
+
# In order to identify itself in the logs, the class can define log_ig() method or set @log_id
|
|
5
|
+
# attribute.
|
|
6
|
+
module Logger
|
|
7
|
+
|
|
8
|
+
SYSLOG_POSIXMQ_MAPPING = {
|
|
9
|
+
"debug" => 0,
|
|
10
|
+
"info" => 1,
|
|
11
|
+
"notice" => 2,
|
|
12
|
+
"warn" => 3,
|
|
13
|
+
"error" => 4,
|
|
14
|
+
"crit" => 5,
|
|
15
|
+
"alert" => 6,
|
|
16
|
+
"emerg" => 7
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
def self.init_logger_mq(group = nil)
|
|
20
|
+
OverSIP.syslogger_mq_name = "/#{OverSIP.master_name}_syslogger"
|
|
21
|
+
|
|
22
|
+
@@logger_mq = ::OverSIP::PosixMQ.create_queue({
|
|
23
|
+
:name => ::OverSIP.syslogger_mq_name,
|
|
24
|
+
:mode => :write,
|
|
25
|
+
:maxmsg => 1000,
|
|
26
|
+
:msgsize => 2000,
|
|
27
|
+
:group => group
|
|
28
|
+
})
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def self.load_methods
|
|
33
|
+
begin
|
|
34
|
+
@@threshold = SYSLOG_POSIXMQ_MAPPING[::OverSIP.configuration[:core][:syslog_level]]
|
|
35
|
+
rescue
|
|
36
|
+
@@threshold = 0 # debug.
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
$oversip_debug = ( @@threshold == 0 ? true : false )
|
|
40
|
+
|
|
41
|
+
@@congested = false
|
|
42
|
+
|
|
43
|
+
SYSLOG_POSIXMQ_MAPPING.each do |level, level_value|
|
|
44
|
+
method_str = "
|
|
45
|
+
def log_system_#{level}(msg)
|
|
46
|
+
"
|
|
47
|
+
|
|
48
|
+
if ::OverSIP.syslogger_ready?
|
|
49
|
+
method_str << "
|
|
50
|
+
return false if @@threshold > #{level_value} || @@congested
|
|
51
|
+
begin
|
|
52
|
+
unless @@logger_mq.trysend ::OverSIP::Logger.syslog_system_msg2str(#{level_value}, msg, log_id), 0
|
|
53
|
+
@@congested = true
|
|
54
|
+
EM.add_timer(1) do
|
|
55
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_system_msg2str(4, \"logger message queue was full, some logs have been lost\", log_id), 1
|
|
56
|
+
@@congested = false
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
rescue Errno::EMSGSIZE
|
|
60
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_system_msg2str(4, \"too long message could not be logged\", log_id), 1 rescue nil
|
|
61
|
+
rescue => e
|
|
62
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_system_msg2str(4, \"unexpected logging error (\#{e.class}: \#{e.message})\", log_id), 1 rescue nil
|
|
63
|
+
end
|
|
64
|
+
"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
unless ::OverSIP.daemonized?
|
|
68
|
+
if %w{debug info notice}.include? level
|
|
69
|
+
method_str << "
|
|
70
|
+
puts ::OverSIP::Logger.fg_system_msg2str('#{level}', msg, log_id)
|
|
71
|
+
"
|
|
72
|
+
else
|
|
73
|
+
method_str << "
|
|
74
|
+
$stderr.puts ::OverSIP::Logger.fg_system_msg2str('#{level}', msg, log_id)
|
|
75
|
+
"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
method_str << "end"
|
|
80
|
+
|
|
81
|
+
self.module_eval method_str
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if ::OverSIP.syslogger_ready?
|
|
85
|
+
# User/script logs.
|
|
86
|
+
method_str = "
|
|
87
|
+
def log_#{level}(msg)
|
|
88
|
+
return false if @@threshold > #{level_value} || @@congested
|
|
89
|
+
begin
|
|
90
|
+
unless @@logger_mq.trysend ::OverSIP::Logger.syslog_user_msg2str(#{level_value}, msg, log_id), 0
|
|
91
|
+
@@congested = true
|
|
92
|
+
EM.add_timer(1) do
|
|
93
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_user_msg2str(4, \"logger message queue was full, some logs have been lost\", log_id), 1
|
|
94
|
+
@@congested = false
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
rescue Errno::EMSGSIZE
|
|
98
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_user_msg2str(4, \"too long message could not be logged\", log_id), 1 rescue nil
|
|
99
|
+
rescue => e
|
|
100
|
+
@@logger_mq.trysend ::OverSIP::Logger.syslog_user_msg2str(4, \"unexpected logging error (\#{e.class}: \#{e.message})\", log_id), 1 rescue nil
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
"
|
|
104
|
+
|
|
105
|
+
self.module_eval method_str
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end # .each
|
|
109
|
+
|
|
110
|
+
# A convenient method to ensure that fatal logs are properly logged and program
|
|
111
|
+
# exited with error status.
|
|
112
|
+
def fatal msg
|
|
113
|
+
log_system_crit msg
|
|
114
|
+
log_system_crit "exiting with error status"
|
|
115
|
+
|
|
116
|
+
::OverSIP::Launcher.terminate error=true
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Generate nice log messages. It accepst three parameters:
|
|
121
|
+
# - level_value: Integer representing the log level.
|
|
122
|
+
# - msg: the String or Exception to be logged.
|
|
123
|
+
# - log_id: a String helping to identify the generator of this log message.
|
|
124
|
+
def self.syslog_system_msg2str(level_value, msg, log_id)
|
|
125
|
+
case msg
|
|
126
|
+
when ::String
|
|
127
|
+
level_value.to_s << "<" << log_id << "> " << msg
|
|
128
|
+
when ::Exception
|
|
129
|
+
"#{level_value}<#{log_id}> #{msg.message} (#{msg.class })\n#{(msg.backtrace || [])[0..3].join("\n")}"
|
|
130
|
+
else
|
|
131
|
+
level_value.to_s << "<" << log_id << "> " << msg.inspect
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def self.syslog_user_msg2str(level_value, msg, log_id)
|
|
136
|
+
case msg
|
|
137
|
+
when ::String
|
|
138
|
+
level_value.to_s << "<" << log_id << "> script: " << msg
|
|
139
|
+
when ::Exception
|
|
140
|
+
"#{level_value}<#{log_id}> script: #{msg.message} (#{msg.class })\n#{(msg.backtrace || [])[0..3].join("\n")}"
|
|
141
|
+
else
|
|
142
|
+
level_value.to_s << "<" << log_id << "> script: " << msg.inspect
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.fg_system_msg2str(level, msg, log_id)
|
|
147
|
+
case msg
|
|
148
|
+
when ::String
|
|
149
|
+
"#{level.upcase}: <#{log_id}> " << msg
|
|
150
|
+
when ::Exception
|
|
151
|
+
"#{level.upcase}: <#{log_id}> #{msg.message} (#{msg.class })\n#{(msg.backtrace || [])[0..3].join("\n")}"
|
|
152
|
+
else
|
|
153
|
+
"#{level.upcase}: <#{log_id}> " << msg.inspect
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.close
|
|
158
|
+
@@logger_mq.close rescue nil
|
|
159
|
+
@@logger_mq.unlink rescue nil
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Default logging identifier is the class name. If log_id() method is redefined by the
|
|
163
|
+
# class including this module, or it sets @log_id, then such value takes preference.
|
|
164
|
+
def log_id
|
|
165
|
+
@log_id ||= self.class.name
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
end # module Logger
|
|
169
|
+
|
|
170
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Ruby built-in libraries.
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "digest/md5"
|
|
5
|
+
require "digest/sha1"
|
|
6
|
+
require "securerandom"
|
|
7
|
+
require "fiber"
|
|
8
|
+
require "openssl"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Ruby external gems.
|
|
12
|
+
|
|
13
|
+
gem "eventmachine-le", ">= 1.1.0"
|
|
14
|
+
require "eventmachine-le"
|
|
15
|
+
|
|
16
|
+
gem "iobuffer", ">= 1.1.2"
|
|
17
|
+
require "iobuffer"
|
|
18
|
+
gem "em-udns", ">= 0.3.6"
|
|
19
|
+
require "em-udns"
|
|
20
|
+
gem "escape_utils", ">= 0.2.4"
|
|
21
|
+
require "escape_utils"
|
|
22
|
+
gem "posix-spawn", ">= 0.3.6"
|
|
23
|
+
require "posix-spawn"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# OverSIP files.
|
|
27
|
+
|
|
28
|
+
require "oversip/ruby_ext/eventmachine.rb"
|
|
29
|
+
|
|
30
|
+
require "oversip/sip/sip.rb"
|
|
31
|
+
require "oversip/sip/sip_parser.so"
|
|
32
|
+
require "oversip/sip/constants.rb"
|
|
33
|
+
require "oversip/sip/message.rb"
|
|
34
|
+
require "oversip/sip/request.rb"
|
|
35
|
+
require "oversip/sip/response.rb"
|
|
36
|
+
require "oversip/sip/grammar/uri.rb"
|
|
37
|
+
require "oversip/sip/grammar/name_addr.rb"
|
|
38
|
+
require "oversip/sip/message_processor.rb"
|
|
39
|
+
require "oversip/sip/listeners.rb"
|
|
40
|
+
require "oversip/sip/launcher.rb"
|
|
41
|
+
require "oversip/sip/server_transaction.rb"
|
|
42
|
+
require "oversip/sip/client_transaction.rb"
|
|
43
|
+
require "oversip/sip/transport_manager.rb"
|
|
44
|
+
require "oversip/sip/timers.rb"
|
|
45
|
+
require "oversip/sip/tags.rb"
|
|
46
|
+
require "oversip/sip/rfc3263.rb"
|
|
47
|
+
require "oversip/sip/logic.rb"
|
|
48
|
+
require "oversip/sip/proxy.rb"
|
|
49
|
+
|
|
50
|
+
require "oversip/websocket/ws_http_parser.so"
|
|
51
|
+
require "oversip/websocket/constants.rb"
|
|
52
|
+
require "oversip/websocket/http_request.rb"
|
|
53
|
+
require "oversip/websocket/default_policy.rb"
|
|
54
|
+
require "oversip/websocket/listeners.rb"
|
|
55
|
+
require "oversip/websocket/launcher.rb"
|
|
56
|
+
require "oversip/websocket/ws_framing_utils.so"
|
|
57
|
+
require "oversip/websocket/ws_framing.rb"
|
|
58
|
+
require "oversip/websocket/ws_app.rb"
|
|
59
|
+
require "oversip/websocket/ws_apps.rb"
|
|
60
|
+
|
|
61
|
+
require "oversip/fiber_pool.rb"
|
|
62
|
+
require "oversip/tls.rb"
|
|
63
|
+
require "oversip/stun.so"
|
|
64
|
+
|
|
65
|
+
require "oversip/sip/modules/core.rb"
|
|
66
|
+
require "oversip/sip/modules/user_assertion.rb"
|
|
67
|
+
require "oversip/sip/modules/registrar_without_path.rb"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module OverSIP
|
|
2
|
+
|
|
3
|
+
class PosixMQ
|
|
4
|
+
|
|
5
|
+
extend ::OverSIP::Logger
|
|
6
|
+
|
|
7
|
+
def self.create_queue options={}
|
|
8
|
+
@log_id = "PosixMQ #{options[:name]}"
|
|
9
|
+
@total_size ||= 0
|
|
10
|
+
|
|
11
|
+
# Queue attributes.
|
|
12
|
+
mq_name = options[:name]
|
|
13
|
+
mq_mode = case options[:mode]
|
|
14
|
+
when :read then IO::RDONLY
|
|
15
|
+
when :write then IO::WRONLY
|
|
16
|
+
when :read_write then IO::RDWR
|
|
17
|
+
end
|
|
18
|
+
mq_group = options[:group]
|
|
19
|
+
mq_attr = ::POSIX_MQ::Attr.new
|
|
20
|
+
# NOTE: maximun value for maxmsg is 65536.
|
|
21
|
+
mq_attr.maxmsg = options[:maxmsg]
|
|
22
|
+
mq_attr.msgsize = options[:msgsize]
|
|
23
|
+
mq_attr.flags = 0
|
|
24
|
+
mq_attr.curmsgs = 0
|
|
25
|
+
|
|
26
|
+
# Delete the queue if it exists.
|
|
27
|
+
begin
|
|
28
|
+
::POSIX_MQ.unlink mq_name
|
|
29
|
+
rescue ::Errno::ENOENT
|
|
30
|
+
rescue ::Errno::EACCES => e
|
|
31
|
+
fatal "queue already exists and cannot remove it due file permissions"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Set the UMASK in a way that the group has permission to delete the queue.
|
|
35
|
+
orig_umask = File.umask(0007)
|
|
36
|
+
|
|
37
|
+
# Change the effective group for the Posix queue. Keep the original
|
|
38
|
+
# group.
|
|
39
|
+
orig_gid = Process::GID.eid
|
|
40
|
+
if mq_group
|
|
41
|
+
gid = Etc.getgrnam(mq_group).gid
|
|
42
|
+
Process::GID.change_privilege(gid)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
### TODO: Este tamaño debe multiplicarse por el num de queues!
|
|
46
|
+
# System limits required size (ulimit -q).
|
|
47
|
+
mq_size = case 1.size
|
|
48
|
+
# 32 bits OS.
|
|
49
|
+
when 4 then mq_attr.maxmsg * 4 + mq_attr.maxmsg * mq_attr.msgsize
|
|
50
|
+
# 64 bits OS.
|
|
51
|
+
when 8 then mq_attr.maxmsg * 8 + mq_attr.maxmsg * mq_attr.msgsize
|
|
52
|
+
end
|
|
53
|
+
log_system_debug "queue requires #{mq_size} bytes" if $oversip_debug
|
|
54
|
+
|
|
55
|
+
# Set RLIMIT_MSGQUEUE (ulimit) in order to create the queue with required
|
|
56
|
+
# ammount of memory.
|
|
57
|
+
@total_size += mq_size
|
|
58
|
+
if ( current_rlimit = ::Process.getrlimit(12)[1] ) < @total_size
|
|
59
|
+
log_system_debug "incrementing rlimits (currently #{current_rlimit} bytes) to #{@total_size} bytes (ulimit -q)" if $oversip_debug
|
|
60
|
+
begin
|
|
61
|
+
::Process.setrlimit(12, @total_size)
|
|
62
|
+
rescue Errno::EPERM
|
|
63
|
+
fatal "current user has no permissions to increase rlimits to #{@total_size} bytes (ulimit -q)"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Create the Posix message queue to write into it.
|
|
68
|
+
# - IO::WRONLY => Just write.
|
|
69
|
+
# - IO::CREAT => Create if it doesn't exist.
|
|
70
|
+
# - IO::EXCL => Raise if the queue already exists.
|
|
71
|
+
# - IO::NONBLOCK => Don't block when sending (instead raise Errno::EAGAIN).
|
|
72
|
+
# - mode: 00660 => User and group can write and read.
|
|
73
|
+
# - mq_attr => Set maxmsg and msgsize.
|
|
74
|
+
begin
|
|
75
|
+
mq = ::POSIX_MQ.new mq_name, mq_mode | IO::CREAT | IO::EXCL | IO::NONBLOCK, 00660, mq_attr
|
|
76
|
+
|
|
77
|
+
# Kernel has no support for posix message queues.
|
|
78
|
+
rescue Errno::ENOSYS => e
|
|
79
|
+
fatal "the kernel has no support for posix messages queues, enable it (#{e.class}: #{e.message})"
|
|
80
|
+
|
|
81
|
+
# http://linux.die.net/man/3/mq_open
|
|
82
|
+
#
|
|
83
|
+
# O_CREAT was specified in oflag, and attr was not NULL, but attr->mq_maxmsg or attr->mq_msqsize was
|
|
84
|
+
# invalid. Both of these fields must be greater than zero. In a process that is unprivileged (does not
|
|
85
|
+
# have the CAP_SYS_RESOURCE capability), attr->mq_maxmsg must be less than or equal to the msg_max
|
|
86
|
+
# limit, and attr->mq_msgsize must be less than or equal to the msgsize_max limit. In addition, even
|
|
87
|
+
# in a privileged process, attr->mq_maxmsg cannot exceed the HARD_MAX limit. (See mq_overview(7) for
|
|
88
|
+
# details of these limits.)
|
|
89
|
+
rescue Errno::EINVAL
|
|
90
|
+
log_system_warn "cannot set queue attributes due to user permissions, using system default values"
|
|
91
|
+
mq = ::POSIX_MQ.new mq_name, mq_mode | IO::CREAT | IO::NONBLOCK, 00660
|
|
92
|
+
rescue Errno::ENOMEM => e
|
|
93
|
+
fatal "insufficient memory (#{e.class}: #{e.message})"
|
|
94
|
+
rescue Errno::EMFILE => e
|
|
95
|
+
fatal "the process already has the maximum number of files and message queues open (#{e.class}: #{e.message})"
|
|
96
|
+
rescue Errno::ENFILE => e
|
|
97
|
+
fatal "the system limit on the total number of open files and message queues has been reached (#{e.class}: #{e.message})"
|
|
98
|
+
rescue Errno::ENOSPC => e
|
|
99
|
+
fatal "insufficient space for the creation of a new message queue, probably occurred because the queues_max limit was encountered (#{e.class}: #{e.message})"
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Recover the original Umask settings.
|
|
104
|
+
File.umask(orig_umask)
|
|
105
|
+
|
|
106
|
+
# Recover the original effective group.
|
|
107
|
+
Process::GID.change_privilege(orig_gid) if mq_group
|
|
108
|
+
|
|
109
|
+
if mq.attr.maxmsg == mq_attr.maxmsg and mq.attr.msgsize == mq_attr.msgsize
|
|
110
|
+
log_system_debug "maxmsg=#{mq.attr.maxmsg}, msgsize=#{mq.attr.msgsize}" if $oversip_debug
|
|
111
|
+
else
|
|
112
|
+
log_system_warn "maxmsg=#{mq.attr.maxmsg}, msgsize=#{mq.attr.msgsize}, " \
|
|
113
|
+
"but recommended values are maxmsg=#{mq_attr.maxmsg}, msgsize=#{mq_attr.msgsize}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
mq
|
|
117
|
+
end # self.create_queue
|
|
118
|
+
|
|
119
|
+
end # class PosixMQ
|
|
120
|
+
|
|
121
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
module OverSIP
|
|
2
|
+
|
|
3
|
+
module ProxiesConfig
|
|
4
|
+
|
|
5
|
+
extend ::OverSIP::Logger
|
|
6
|
+
extend ::OverSIP::Config::Validators
|
|
7
|
+
|
|
8
|
+
def self.log_id
|
|
9
|
+
@log_id ||= "ProxiesConfig"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
@proxies = {}
|
|
13
|
+
|
|
14
|
+
@proxy_configuration = {
|
|
15
|
+
:do_loose_routing => true,
|
|
16
|
+
:use_dns => true,
|
|
17
|
+
:use_dns_cache => true,
|
|
18
|
+
:dns_cache_time => 300,
|
|
19
|
+
:use_naptr => true,
|
|
20
|
+
:use_srv => true,
|
|
21
|
+
:transport_preference => ["tls", "tcp", "udp"],
|
|
22
|
+
:force_transport_preference => false,
|
|
23
|
+
:ip_type_preference => ["ipv6", "ipv4"],
|
|
24
|
+
:dns_failover_on_503 => true,
|
|
25
|
+
:timer_B => 32,
|
|
26
|
+
:timer_C => 120,
|
|
27
|
+
:timer_F => 32,
|
|
28
|
+
:tls_validation => false
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
PROXY_CONFIG_VALIDATIONS = {
|
|
32
|
+
:do_loose_routing => :boolean,
|
|
33
|
+
:use_dns => :boolean,
|
|
34
|
+
:use_dns_cache => :boolean,
|
|
35
|
+
:dns_cache_time => [ :fixnum, [ :greater_equal_than, 300 ] ],
|
|
36
|
+
:use_naptr => :boolean,
|
|
37
|
+
:use_srv => :boolean,
|
|
38
|
+
:transport_preference => [ [ :choices, %w{tls tcp udp}], :multi_value, :non_empty ],
|
|
39
|
+
:force_transport_preference => :boolean,
|
|
40
|
+
:ip_type_preference => [ [ :choices, %w{ipv4 ipv6}], :multi_value, :non_empty ],
|
|
41
|
+
:dns_failover_on_503 => :boolean,
|
|
42
|
+
:timer_B => [ :fixnum, [ :greater_equal_than, 2 ], [ :minor_equal_than, 64 ] ],
|
|
43
|
+
:timer_C => [ :fixnum, [ :greater_equal_than, 8 ], [ :minor_equal_than, 180 ] ],
|
|
44
|
+
:timer_F => [ :fixnum, [ :greater_equal_than, 2 ], [ :minor_equal_than, 64 ] ],
|
|
45
|
+
:tls_validation => :boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
def self.load proxies_yaml
|
|
49
|
+
unless proxies_yaml.is_a? Hash
|
|
50
|
+
fatal "invalid proxies configuration file, it is not a collection"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
begin
|
|
54
|
+
proxies_yaml.each do |proxy, conf|
|
|
55
|
+
unless proxy.is_a? String
|
|
56
|
+
fatal "proxy name is not a string (#{proxy.inspect})"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@proxies[proxy.to_sym] = @proxy_configuration.dup
|
|
60
|
+
@proxies[proxy.to_sym].each do |parameter, default_value|
|
|
61
|
+
@proxies[proxy.to_sym][parameter] = default_value.clone rescue default_value
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
PROXY_CONFIG_VALIDATIONS.each do |parameter, validations|
|
|
65
|
+
values = proxies_yaml[proxy][parameter.to_s]
|
|
66
|
+
validations = [ validations ] unless validations.is_a?(Array)
|
|
67
|
+
|
|
68
|
+
if values == nil
|
|
69
|
+
if validations.include? :required
|
|
70
|
+
fatal "#{proxy}[#{parameter}] requires a value"
|
|
71
|
+
end
|
|
72
|
+
next
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if values.is_a? Array
|
|
76
|
+
unless validations.include? :multi_value
|
|
77
|
+
fatal "#{proxy}[#{parameter}] does not allow multiple values"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if validations.include? :non_empty and values.empty?
|
|
81
|
+
fatal "#{proxy}[#{parameter}] does not allow empty values"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
values = ( values.is_a?(Array) ? values : [ values ] )
|
|
86
|
+
|
|
87
|
+
values.each do |value|
|
|
88
|
+
validations.each do |validation|
|
|
89
|
+
|
|
90
|
+
if validation.is_a? Symbol
|
|
91
|
+
args = []
|
|
92
|
+
elsif validation.is_a? Array
|
|
93
|
+
args = validation[1..-1]
|
|
94
|
+
validation = validation[0]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
next if [:required, :multi_value, :non_empty].include? validation
|
|
98
|
+
|
|
99
|
+
unless send validation, value, *args
|
|
100
|
+
fatal "#{proxy}[#{parameter}] has invalid value '#{::OverSIP::Config.humanize_value value}' (does not satisfy '#{validation}' validation requirement)"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
@proxies[proxy.to_sym][parameter] = ( validations.include?(:multi_value) ? values : values[0] )
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end # PROXY_CONFIG_VALIDATIONS[section].each
|
|
108
|
+
end # proxies_yaml.each
|
|
109
|
+
|
|
110
|
+
post_process
|
|
111
|
+
|
|
112
|
+
rescue OverSIP::ConfigurationError => e
|
|
113
|
+
fatal "proxies configuration error: #{e.message}"
|
|
114
|
+
rescue => e
|
|
115
|
+
fatal e
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
::OverSIP.proxies = @proxies
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def self.post_process
|
|
123
|
+
@proxies.each_key do |proxy|
|
|
124
|
+
# Add a string parameter with the proxy name itself.
|
|
125
|
+
@proxies[proxy][:name] = proxy.to_s
|
|
126
|
+
|
|
127
|
+
# If use_srv is not set then ensure use_naptr is also not set.
|
|
128
|
+
@proxies[proxy][:use_naptr] = false unless @proxies[proxy][:use_srv]
|
|
129
|
+
|
|
130
|
+
# Convert transport values into Symbols.
|
|
131
|
+
@proxies[proxy][:transport_preference] = @proxies[proxy][:transport_preference].map do |transport|
|
|
132
|
+
transport.to_sym
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Ensure there are not duplicate transports.
|
|
136
|
+
@proxies[proxy][:transport_preference].uniq!
|
|
137
|
+
|
|
138
|
+
# Remove transports that are not supported.
|
|
139
|
+
@proxies[proxy][:transport_preference].delete :tls unless ::OverSIP.configuration[:sip][:sip_tls]
|
|
140
|
+
@proxies[proxy][:transport_preference].delete :tcp unless ::OverSIP.configuration[:sip][:sip_tcp]
|
|
141
|
+
@proxies[proxy][:transport_preference].delete :udp unless ::OverSIP.configuration[:sip][:sip_udp]
|
|
142
|
+
|
|
143
|
+
# Convert IP type values into Symbols.
|
|
144
|
+
@proxies[proxy][:ip_type_preference] = @proxies[proxy][:ip_type_preference].map do |ip_type|
|
|
145
|
+
ip_type.to_sym
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Ensure there are not duplicate IP types.
|
|
149
|
+
@proxies[proxy][:ip_type_preference].uniq!
|
|
150
|
+
|
|
151
|
+
# Remove IP types that are not supported.
|
|
152
|
+
@proxies[proxy][:ip_type_preference].delete :ipv4 unless ::OverSIP.configuration[:sip][:listen_ipv4]
|
|
153
|
+
@proxies[proxy][:ip_type_preference].delete :ipv6 unless ::OverSIP.configuration[:sip][:listen_ipv6]
|
|
154
|
+
|
|
155
|
+
# Add new parameters for fast access.
|
|
156
|
+
@proxies[proxy][:has_sip_ipv4] = @proxies[proxy][:ip_type_preference].include?(:ipv4)
|
|
157
|
+
@proxies[proxy][:has_sip_ipv6] = @proxies[proxy][:ip_type_preference].include?(:ipv6)
|
|
158
|
+
@proxies[proxy][:has_sip_udp] = @proxies[proxy][:transport_preference].include?(:udp)
|
|
159
|
+
@proxies[proxy][:has_sip_tcp] = @proxies[proxy][:transport_preference].include?(:tcp)
|
|
160
|
+
@proxies[proxy][:has_sip_tls] = @proxies[proxy][:transport_preference].include?(:tls)
|
|
161
|
+
|
|
162
|
+
# Add a hash for the DNS cache.
|
|
163
|
+
@proxies[proxy][:dns_cache] = {} if @proxies[proxy][:use_dns_cache]
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module EventMachine
|
|
2
|
+
|
|
3
|
+
# Fast method for setting an outgoing TCP connection.
|
|
4
|
+
def self.oversip_connect_tcp_server bind_addr, server, port, klass, *args
|
|
5
|
+
s = bind_connect_server bind_addr, 0, server, port
|
|
6
|
+
c = klass.new s, *args
|
|
7
|
+
@conns[s] = c
|
|
8
|
+
block_given? and yield c
|
|
9
|
+
c
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Connection
|
|
14
|
+
|
|
15
|
+
# We require Ruby 1.9 so don't check String#bytesize method.
|
|
16
|
+
def send_data data
|
|
17
|
+
::EventMachine::send_data @signature, data, data.bytesize
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def send_datagram data, address, port
|
|
21
|
+
::EventMachine::send_datagram @signature, data, data.bytesize, address, port
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Rewrite close_connection so it set an internal attribute (which can be
|
|
25
|
+
# inspected when unbind() callback is called).
|
|
26
|
+
alias _em_close_connection close_connection
|
|
27
|
+
def close_connection after_writing=false
|
|
28
|
+
@local_closed = true
|
|
29
|
+
_em_close_connection after_writing
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def close_connection_after_writing
|
|
33
|
+
close_connection true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|