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