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