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,597 @@
1
+ module OverSIP::WebSocket
2
+
3
+ class WsFraming
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ OPCODE = {
8
+ 0 => :continuation,
9
+ 1 => :text,
10
+ 2 => :binary,
11
+ 8 => :close,
12
+ 9 => :ping,
13
+ 10 => :pong
14
+ }
15
+
16
+ keepalive_ping_frame = "".encode ::Encoding::BINARY
17
+ keepalive_ping_frame << 137
18
+ keepalive_ping_frame << "keep-alive".bytesize
19
+ keepalive_ping_frame << "keep-alive".encode(::Encoding::BINARY)
20
+ KEEPALIVE_PING_FRAME = keepalive_ping_frame
21
+
22
+
23
+ attr_writer :ws_app
24
+
25
+
26
+ def self.class_init
27
+ @@max_frame_size = ::OverSIP.configuration[:websocket][:max_ws_frame_size]
28
+ end
29
+
30
+
31
+ def log_id
32
+ @log_id ||= "WsFramming #{@connection.connection_log_id}"
33
+ end
34
+
35
+
36
+ def initialize connection, buffer
37
+ @connection = connection
38
+ @buffer = buffer
39
+ @utf8_validator = ::OverSIP::WebSocket::FramingUtils::Utf8Validator.allocate
40
+ @state = :init
41
+ end
42
+
43
+
44
+ def do_keep_alive interval
45
+ @keep_alive_timer = ::EM::PeriodicTimer.new(interval) do
46
+ log_system_debug "sending keep-alive ping frame: payload_length=10" if $oversip_debug
47
+ @connection.send_data KEEPALIVE_PING_FRAME
48
+ end
49
+ end
50
+
51
+
52
+ def receive_data
53
+ while (case @state
54
+ when :init
55
+ return false if @buffer.size < 2
56
+
57
+ byte1 = @buffer.read(1).getbyte(0)
58
+ byte2 = @buffer.read(1).getbyte(0)
59
+
60
+ # FIN is the bit 0.
61
+ @fin = (byte1 & 0b10000000) == 0b10000000
62
+
63
+ # RSV1-3 are bits 1-3.
64
+ @rsv1 = (byte1 & 0b01000000) == 0b01000000
65
+ @rsv2 = (byte1 & 0b00100000) == 0b00100000
66
+ @rsv3 = (byte1 & 0b00010000) == 0b00010000
67
+
68
+ if @rsv1 or @rsv2 or @rsv3
69
+ log_system_notice "frame has RSV bits set, clossing the connection"
70
+ send_close_frame 1002, "RSV bit set not supported"
71
+ return false
72
+ end
73
+
74
+ # opcode are bits 4-7.
75
+ @opcode = byte1 & 0b00001111
76
+ unless (@sym_opcode = OPCODE[@opcode])
77
+ send_close_frame 1002, "unknown opcode=#{@opcode}"
78
+ return false
79
+ end
80
+
81
+ # MASK is bit 8.
82
+ @mask = (byte2 & 0b10000000) == 0b10000000
83
+ unless @mask
84
+ send_close_frame 1002, "MASK bit not set"
85
+ return false
86
+ end
87
+
88
+ # payload_len are bits 9-15.
89
+ length = byte2 & 0b01111111
90
+
91
+ case length
92
+ # Length defined by 8 bytes.
93
+ when 127
94
+ @state = :payload_length_8_bytes
95
+ # Length defined by 2 bytes.
96
+ when 126
97
+ @state = :payload_length_2_bytes
98
+ # Length defined by already received 7 bits.
99
+ else
100
+ @payload_length = length
101
+ @state = :masking_key
102
+ end
103
+
104
+ @payload = nil
105
+ true
106
+
107
+ when :payload_length_2_bytes
108
+ return false if @buffer.size < 2
109
+
110
+ # Get the payload length and remove first two bytes fro
111
+ # the buffer at the same time.
112
+ @payload_length = @buffer.read(2).unpack('n').first
113
+
114
+ @state = :masking_key
115
+ true
116
+
117
+ when :payload_length_8_bytes
118
+ return false if @buffer.size < 8
119
+
120
+ # Get the payload length.
121
+ # NOTE: Just take the last 4 bytes (4 GB frame is enough!!!),
122
+ # Check that first 4 bytes are 0000. If not then the frame is bigger
123
+ # than 4 GB and must be rejected!
124
+
125
+ if @buffer.read(4).unpack('N').first != 0
126
+ log_system_notice "frame size bigger than 4 GB, rejected"
127
+ send_close_frame 1008
128
+ return false
129
+ end
130
+
131
+ @payload_length = @buffer.read(4).unpack('N').first
132
+
133
+ @state = :masking_key
134
+ true
135
+
136
+ when :masking_key
137
+ return false if @buffer.size < 4
138
+
139
+ # Get the masking key (4 bytes) and remove first 4 bytes
140
+ # from the buffer.
141
+ @masking_key = @buffer.read(4)
142
+
143
+ @state = :check_frame
144
+ true
145
+
146
+ when :check_frame
147
+ # All control frames MUST have a payload length of 125 bytes or
148
+ # less and MUST NOT be fragmented.
149
+ if control_frame? and @payload_length > 125
150
+ log_system_notice "received invalid control frame (payload_length > 125), sending close frame"
151
+ send_close_frame 1002
152
+ return false
153
+ end
154
+
155
+ if control_frame? and not @fin
156
+ log_system_notice "received invalid control frame (FIN=0), sending close frame"
157
+ send_close_frame 1002, "forbidden FIN=0 in control frame"
158
+ return false
159
+ end
160
+
161
+ # A continuation frame can only arrive if previously a text/binary frame
162
+ # arrived with FIN=0.
163
+ if continuation_frame? and not @msg_sym_opcode
164
+ log_system_notice "invalid continuation frame received (no previous unfinished message), sending close frame"
165
+ send_close_frame 1002, "invalid continuation frame received"
166
+ return false
167
+ end
168
+
169
+ # If a previous frame had FIN=0 and opcode=text/binary, then it cannot arrive
170
+ # a new frame with opcode=text/binary.
171
+ if @msg_sym_opcode and text_or_binary_frame?
172
+ log_system_notice "invalid text/binary frame received (expecting a continuation frame), sending close frame"
173
+ send_close_frame 1002, "expected a continuation frame"
174
+ return false
175
+ end
176
+
177
+ # Check max frame size.
178
+ if @payload_length > @@max_frame_size
179
+ send_close_frame 1009, "frame too big"
180
+ return false
181
+ end
182
+
183
+ @state = :payload_data
184
+ true
185
+
186
+ when :payload_data
187
+ return false if @buffer.size < @payload_length
188
+
189
+ unless @payload_length.zero?
190
+ # NOTE: @payload will always be Encoding::BINARY
191
+ @payload = ::OverSIP::WebSocket::FramingUtils.unmask @buffer.read(@payload_length), @masking_key
192
+ end
193
+ # NOTE: @payload could be nil.
194
+
195
+ @state = :process_frame
196
+ true
197
+
198
+ when :process_frame
199
+ # Set it here as it could be changed later in this block.
200
+ @state = :init
201
+
202
+ case @sym_opcode
203
+
204
+ when :text
205
+ log_system_debug "received text frame: FIN=#{@fin}, RSV1-3=#{@rsv1}/#{@rsv2}/#{@rsv3}, payload_length=#{@payload_length}" if $oversip_debug
206
+
207
+ # Store the opcode of the first frame (if there is more frames for same message
208
+ # they will have opcode=continuation).
209
+ @msg_sym_opcode = @sym_opcode
210
+
211
+ # Reset the UTF8 validator.
212
+ @utf8_validator.reset
213
+
214
+ if @payload
215
+ if (valid_utf8 = @utf8_validator.validate(@payload)) == false
216
+ log_system_notice "received single text frame contains invalid UTF-8, closing the connection"
217
+ send_close_frame 1007, "single text frame contains invalid UTF-8"
218
+ return false
219
+ end
220
+
221
+ if @fin and not valid_utf8
222
+ log_system_notice "received single text frame contains incomplete UTF-8, closing the connection"
223
+ send_close_frame 1007, "single text frame contains incomplete UTF-8"
224
+ return false
225
+ end
226
+
227
+ return false unless @ws_app.receive_payload_data @payload
228
+ end
229
+
230
+ # If message is finished tell it to the WS application.
231
+ if @fin
232
+ @ws_app.message_done @msg_sym_opcode
233
+ @msg_sym_opcode = nil
234
+ end
235
+
236
+ when :binary
237
+ log_system_debug "received binary frame: FIN=#{@fin}, RSV1-3=#{@rsv1}/#{@rsv2}/#{@rsv3}, payload_length=#{@payload_length}" if $oversip_debug
238
+
239
+ # Store the opcode of the first frame (if there is more frames for same message
240
+ # they will have opcode=continuation).
241
+ @msg_sym_opcode = @sym_opcode
242
+
243
+ if @payload
244
+ return false unless @ws_app.receive_payload_data @payload
245
+ end
246
+
247
+ # If message is finished tell it to the WS application.
248
+ if @fin
249
+ @ws_app.message_done @msg_sym_opcode
250
+ @msg_sym_opcode = nil
251
+ end
252
+
253
+ when :continuation
254
+ log_system_debug "received continuation frame: FIN=#{@fin}, RSV1-3=#{@rsv1}/#{@rsv2}/#{@rsv3}, payload_length=#{@payload_length}" if $oversip_debug
255
+
256
+ if @payload
257
+ if @msg_sym_opcode == :text
258
+ if (valid_utf8 = @utf8_validator.validate(@payload)) == false
259
+ log_system_notice "received continuation text frame contains invalid UTF-8, closing the connection"
260
+ send_close_frame 1007, "continuation text frame contains invalid UTF-8"
261
+ return false
262
+ end
263
+
264
+ if @fin and not valid_utf8
265
+ log_system_notice "received continuation final text frame contains incomplete UTF-8, closing the connection"
266
+ send_close_frame 1007, "continuation final text frame contains incomplete UTF-8"
267
+ return false
268
+ end
269
+ end
270
+
271
+ return false unless @ws_app.receive_payload_data @payload
272
+ end
273
+
274
+ # If message is finished tell it to the WS application.
275
+ if @fin
276
+ @ws_app.message_done @msg_sym_opcode
277
+ @msg_sym_opcode = nil
278
+ end
279
+
280
+ when :close
281
+ if @payload_length >= 2
282
+ status = ""
283
+ status << @payload.getbyte(0) << @payload.getbyte(1)
284
+ status = status.unpack('n').first
285
+ if (reason = @payload[2..-1])
286
+ # Reset the UTF8 validator.
287
+ @utf8_validator.reset
288
+
289
+ # The UTF-8 validator returns:
290
+ # - true: Valid UTF-8 string.
291
+ # - nil: Valid but not terminated UTF-8 string.
292
+ # - false: Invalid UTF-8 string.
293
+ # So it must be true for the close frame reason.
294
+ unless @utf8_validator.validate(reason)
295
+ log_system_notice "received close frame with invalid UTF-8 data in the reason: status=#{status.inspect}"
296
+ send_close_frame 1007, "close frame reason contains incomplete UTF-8"
297
+ return false
298
+ end
299
+ end
300
+ else
301
+ status = nil
302
+ end
303
+
304
+ case status
305
+ when 1002
306
+ log_system_notice "received close frame due to WS protocol error: status=1002, reason=#{reason.inspect}"
307
+ when 1003
308
+ log_system_notice "received close frame due to sent data type: status=1003, reason=#{reason.inspect}"
309
+ when 1007
310
+ log_system_notice "received close frame due to non valid UTF-8 data sent: status=1007, reason=#{reason.inspect}"
311
+ when 1009
312
+ log_system_notice "received close frame due to too big message sent: status=1009, reason=#{reason.inspect}"
313
+ when 1010
314
+ log_system_notice "received close frame due to extensions negotiation failure: status=1010, reason=#{reason.inspect}"
315
+ else
316
+ log_system_debug "received close frame: status=#{status.inspect}, reason=#{reason.inspect}" if $oversip_debug
317
+ end
318
+
319
+ send_close_frame nil, nil, true
320
+ return false
321
+
322
+ when :ping
323
+ log_system_debug "received ping frame: payload_length=#{@payload_length}" if $oversip_debug
324
+ send_pong_frame @payload
325
+
326
+ when :pong
327
+ log_system_debug "received pong frame: payload_length=#{@payload_length}" if $oversip_debug
328
+
329
+ end
330
+
331
+ true
332
+
333
+ when :ws_closed
334
+ false
335
+
336
+ when :tcp_closed
337
+ false
338
+
339
+ end)
340
+ end # while
341
+
342
+ end # receive_data
343
+
344
+
345
+ def control_frame?
346
+ @opcode > 2
347
+ end
348
+
349
+
350
+ def text_or_binary_frame?
351
+ @opcode == 1 or @opcode == 2
352
+ end
353
+
354
+
355
+ def continuation_frame?
356
+ @opcode == 0
357
+ end
358
+
359
+
360
+ # NOTE: A WS message is always set in a single WS frame.
361
+ def send_text_frame message
362
+ case @state
363
+ when :ws_closed
364
+ log_system_debug "cannot send text frame, WebSocket session is closed" if $oversip_debug
365
+ return false
366
+ when :tcp_closed
367
+ log_system_debug "cannot send text frame, TCP session is closed" if $oversip_debug
368
+ return false
369
+ end
370
+ log_system_debug "sending text frame: payload_length=#{message.bytesize}" if $oversip_debug
371
+
372
+ frame = "".encode ::Encoding::BINARY
373
+
374
+ # byte1 = OPCODE_TO_INT[:text] | 0b10000000 => 129
375
+ #
376
+ # - FIN bit set.
377
+ # - RSV1-3 bits not set.
378
+ # - opcode = 1
379
+ frame << 129
380
+
381
+ length = message.bytesize
382
+ if length <= 125
383
+ frame << length # since rsv4 is 0
384
+ elsif length < 65536 # write 2 byte length
385
+ frame << 126
386
+ frame << [length].pack('n')
387
+ else # write 8 byte length
388
+ frame << 127
389
+ frame << [length >> 32, length & 0xFFFFFFFF].pack("NN")
390
+ end
391
+
392
+ if message.encoding == ::Encoding::BINARY
393
+ frame << message
394
+ else
395
+ frame << message.force_encoding(::Encoding::BINARY)
396
+ end
397
+
398
+ @connection.send_data frame
399
+ true
400
+ end
401
+
402
+
403
+ def send_binary_frame message
404
+ case @state
405
+ when :ws_closed
406
+ log_system_debug "cannot send binary frame, WebSocket session is closed" if $oversip_debug
407
+ return false
408
+ when :tcp_closed
409
+ log_system_debug "cannot send binary frame, TCP session is closed" if $oversip_debug
410
+ return false
411
+ end
412
+ log_system_debug "sending binary frame: payload_length=#{message.bytesize}" if $oversip_debug
413
+
414
+ frame = "".encode ::Encoding::BINARY
415
+
416
+ # byte1 = OPCODE_TO_INT[:binary] | 0b10000000 => 130
417
+ #
418
+ # - FIN bit set.
419
+ # - RSV1-3 bits not set.
420
+ # - opcode = 2
421
+ frame << 130
422
+
423
+ length = message.bytesize
424
+ if length <= 125
425
+ frame << length # since rsv4 is 0
426
+ elsif length < 65536 # write 2 byte length
427
+ frame << 126
428
+ frame << [length].pack('n')
429
+ else # write 8 byte length
430
+ frame << 127
431
+ frame << [length >> 32, length & 0xFFFFFFFF].pack("NN")
432
+ end
433
+
434
+ if message.encoding == ::Encoding::BINARY
435
+ frame << message
436
+ else
437
+ frame << message.force_encoding(::Encoding::BINARY)
438
+ end
439
+
440
+ @connection.send_data frame
441
+ true
442
+ end
443
+
444
+
445
+ def send_ping_frame data=nil
446
+ case @state
447
+ when :ws_closed
448
+ log_system_debug "cannot send ping frame, WebSocket session is closed" if $oversip_debug
449
+ return false
450
+ when :tcp_closed
451
+ log_system_debug "cannot send ping frame, TCP session is closed" if $oversip_debug
452
+ return false
453
+ end
454
+ if data
455
+ log_system_debug "sending ping frame: payload_length=#{data.bytesize}" if $oversip_debug
456
+ else
457
+ log_system_debug "sending ping frame: payload_length=0" if $oversip_debug
458
+ end
459
+
460
+ frame = "".encode ::Encoding::BINARY
461
+
462
+ # byte1 = OPCODE_TO_INT[:ping] | 0b10000000 => 137
463
+ #
464
+ # - FIN bit set.
465
+ # - RSV1-3 bits not set.
466
+ # - opcode = 9
467
+ frame << 137
468
+
469
+ length = ( data ? data.bytesize : 0 )
470
+ frame << length
471
+
472
+ if data
473
+ if data.encoding == ::Encoding::BINARY
474
+ frame << data
475
+ else
476
+ frame << data.force_encoding(::Encoding::BINARY)
477
+ end
478
+ end
479
+
480
+ @connection.send_data frame
481
+ true
482
+ end
483
+
484
+
485
+ def send_pong_frame data=nil
486
+ case @state
487
+ when :ws_closed
488
+ log_system_debug "cannot send pong frame, WebSocket session is closed" if $oversip_debug
489
+ return false
490
+ when :tcp_closed
491
+ log_system_debug "cannot send pong frame, TCP session is closed" if $oversip_debug
492
+ return false
493
+ end
494
+ if data
495
+ log_system_debug "sending pong frame: payload_length=#{data.bytesize}" if $oversip_debug
496
+ else
497
+ log_system_debug "sending pong frame: payload_length=0" if $oversip_debug
498
+ end
499
+
500
+ frame = "".encode ::Encoding::BINARY
501
+
502
+ # byte1 = OPCODE_TO_INT[:pong] | 0b10000000 => 138
503
+ #
504
+ # - FIN bit set.
505
+ # - RSV1-3 bits not set.
506
+ # - opcode = 10
507
+ frame << 138
508
+
509
+ length = ( data ? data.bytesize : 0 )
510
+ frame << length
511
+
512
+ if data
513
+ if data.encoding == ::Encoding::BINARY
514
+ frame << data
515
+ else
516
+ frame << data.force_encoding(::Encoding::BINARY)
517
+ end
518
+ end
519
+
520
+ @connection.send_data frame
521
+ true
522
+ end
523
+
524
+
525
+ def send_close_frame status=nil, reason=nil, in_reply_to_close=nil
526
+ @keep_alive_timer.cancel if @keep_alive_timer
527
+
528
+ case @state
529
+ when :ws_closed
530
+ log_system_debug "cannot send close frame, WebSocket session is closed" if $oversip_debug
531
+ return false
532
+ when :tcp_closed
533
+ log_system_debug "cannot send close frame, TCP session is closed" if $oversip_debug
534
+ return false
535
+ end
536
+
537
+ unless in_reply_to_close
538
+ log_system_notice "sending close frame: status=#{status.inspect}, reason=#{reason.inspect}"
539
+ else
540
+ log_system_debug "sending reply close frame: status=#{status.inspect}, reason=#{reason.inspect}" if $oversip_debug
541
+ end
542
+
543
+ @state = :ws_closed
544
+ @buffer.clear
545
+
546
+ frame = "".encode ::Encoding::BINARY
547
+
548
+ # byte1 = OPCODE_TO_INT[:close] | 0b10000000 => 136
549
+ #
550
+ # - FIN bit set.
551
+ # - RSV1-3 bits not set.
552
+ # - opcode = 8
553
+ frame << 136
554
+ if status
555
+ length = ( reason ? 2 + reason.bytesize : 2 )
556
+ else
557
+ length = 0
558
+ end
559
+
560
+ frame << length # since rsv4 is 0
561
+ if status
562
+ frame << [status].pack('n')
563
+ if reason
564
+ if reason.encoding == ::Encoding::BINARY
565
+ frame << reason
566
+ else
567
+ frame << reason.force_encoding(::Encoding::BINARY)
568
+ end
569
+ end
570
+ end
571
+
572
+ @connection.ignore_incoming_data
573
+ @connection.send_data frame
574
+
575
+ unless in_reply_to_close
576
+ # Let's some time for the client to send us a close frame (it will
577
+ # be ignored anyway) before closing the TCP connection.
578
+ EM.add_timer(0.2) do
579
+ @connection.close_connection_after_writing
580
+ end
581
+ else
582
+ @connection.close_connection_after_writing
583
+ end
584
+ true
585
+ end
586
+
587
+
588
+ def tcp_closed
589
+ @keep_alive_timer.cancel if @keep_alive_timer
590
+ @state = :tcp_closed
591
+ # Tell it to the WS application.
592
+ @ws_app.tcp_closed rescue nil
593
+ end
594
+
595
+ end # class WsFraming
596
+
597
+ end
data/lib/oversip.rb ADDED
@@ -0,0 +1,59 @@
1
+ # Ruby built-in libraries.
2
+
3
+ require "etc"
4
+ require "fileutils"
5
+ require "socket"
6
+ require "timeout"
7
+ require "yaml"
8
+ require "tempfile"
9
+
10
+
11
+ # Ruby external gems.
12
+
13
+ require "term/ansicolor"
14
+ require "posix_mq"
15
+
16
+
17
+ # OverSIP files.
18
+
19
+ require "oversip/version.rb"
20
+ require "oversip/logger.rb"
21
+ require "oversip/config.rb"
22
+ require "oversip/config_validators.rb"
23
+ require "oversip/proxies_config.rb"
24
+ require "oversip/errors.rb"
25
+ require "oversip/launcher.rb"
26
+ require "oversip/utils.so"
27
+ require "oversip/utils.rb"
28
+ require "oversip/posix_mq.rb"
29
+
30
+
31
+
32
+
33
+ module OverSIP
34
+
35
+ class << self
36
+ attr_accessor :pid_file, :master_name, :master_pid, :daemonized,
37
+ :syslogger_pid, :syslogger_mq_name,
38
+ :configuration,
39
+ :proxies,
40
+ :tls, :tls_public_cert, :tls_private_cert, :tls_proxy_ipv4, :tls_proxy_ipv6
41
+
42
+ def master?
43
+ @master_pid == $$
44
+ end
45
+
46
+ def daemonized?
47
+ @daemonized
48
+ end
49
+
50
+ def syslogger_ready?
51
+ @syslogger_pid and true
52
+ end
53
+ end
54
+
55
+ # Pre-declare internal modules.
56
+ module SIP ; end
57
+ module WebSocket ; end
58
+
59
+ end
@@ -0,0 +1,20 @@
1
+ require "test/unit"
2
+ require "oversip"
3
+ require "oversip/master_process"
4
+
5
+
6
+ class OverSIPTest < Test::Unit::TestCase
7
+
8
+ def assert_true(object, message="")
9
+ assert_equal(object, true, message)
10
+ end
11
+
12
+ def assert_false(object, message="")
13
+ assert_equal(object, false, message)
14
+ end
15
+
16
+ def assert_equal_options(options, element)
17
+ assert options.include?(element)
18
+ end
19
+
20
+ end