Class: NIO::WebSocket::Adapter
- Inherits:
-
Object
- Object
- NIO::WebSocket::Adapter
- Defined in:
- lib/nio/websocket/adapter.rb,
lib/nio/websocket/adapter/client.rb,
lib/nio/websocket/adapter/server.rb
Defined Under Namespace
Instance Attribute Summary collapse
-
#driver ⇒ Object
readonly
Returns the value of attribute driver.
-
#inner ⇒ Object
readonly
Returns the value of attribute inner.
-
#monitor ⇒ Object
readonly
Returns the value of attribute monitor.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
- #add_to_reactor ⇒ Object
- #close(from = nil) ⇒ Object
-
#initialize(io, driver, options) ⇒ Adapter
constructor
A new instance of Adapter.
- #pump_buffer ⇒ Object
- #read ⇒ Object
- #teardown ⇒ Object
- #write(data) ⇒ Object
Constructor Details
#initialize(io, driver, options) ⇒ Adapter
Returns a new instance of Adapter.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/nio/websocket/adapter.rb', line 4 def initialize(io, driver, ) @inner = io @options = @driver = driver @buffer = '' @mutex = Mutex.new driver.on :close do |ev| WebSocket.logger.info "Driver initiated #{inner} close (code #{ev.code}): #{ev.reason}" close :driver end driver.on :error do |ev| WebSocket.logger.error "Driver reports error on #{inner}: #{ev.}" close :driver end end |
Instance Attribute Details
#driver ⇒ Object (readonly)
Returns the value of attribute driver.
20 21 22 |
# File 'lib/nio/websocket/adapter.rb', line 20 def driver @driver end |
#inner ⇒ Object (readonly)
Returns the value of attribute inner.
20 21 22 |
# File 'lib/nio/websocket/adapter.rb', line 20 def inner @inner end |
#monitor ⇒ Object (readonly)
Returns the value of attribute monitor.
20 21 22 |
# File 'lib/nio/websocket/adapter.rb', line 20 def monitor @monitor end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
20 21 22 |
# File 'lib/nio/websocket/adapter.rb', line 20 def @options end |
Instance Method Details
#add_to_reactor ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/nio/websocket/adapter.rb', line 38 def add_to_reactor @monitor = Reactor.selector.register(inner, :rw) # This can block if this is the main thread and the reactor is busy monitor.value = proc do begin read if monitor.readable? pump_buffer if monitor.writable? rescue Errno::ECONNRESET, EOFError driver.force_state :closed driver.emit :io_error teardown WebSocket.logger.info "#{inner} socket closed" rescue IO::WaitReadable # rubocop:disable Lint/HandleExceptions rescue IO::WaitWritable monitor.interests = :rw end if @closing if !monitor.readable? && @buffer.empty? teardown WebSocket.logger.info "#{inner} closed" else monitor.interests = :rw unless monitor.closed? # keep the :w interest so that our block runs each time # edge case: if monitor was readable this time, and the write buffer is empty, if we emptied the read buffer this time our block wouldn't run again end end end end |
#close(from = nil) ⇒ Object
28 29 30 31 32 33 34 35 36 |
# File 'lib/nio/websocket/adapter.rb', line 28 def close(from = nil) return false if @closing driver.close if from.nil? @closing = true monitor.interests = :rw Reactor.selector.wakeup true end |
#pump_buffer ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/nio/websocket/adapter.rb', line 83 def pump_buffer @mutex.synchronize do written = 0 begin written = inner.write_nonblock @buffer unless @buffer.empty? WebSocket.logger.debug { "Pumped #{written} bytes of data from buffer to #{inner}:\n#{@buffer}" } unless @buffer.empty? || !WebSocket.log_traffic? @buffer = @buffer.byteslice(written..-1) if written > 0 WebSocket.logger.debug { "The buffer is now:\n#{@buffer}" } unless @buffer.empty? || !WebSocket.log_traffic? rescue IO::WaitWritable, IO::WaitReadable return written ensure monitor.interests = @buffer.empty? ? :r : :rw end written end end |
#read ⇒ Object
65 66 67 68 69 70 71 72 |
# File 'lib/nio/websocket/adapter.rb', line 65 def read data = inner.read_nonblock(16384) if data WebSocket.logger.debug { "Incoming data on #{inner}:\n#{data}" } if WebSocket.log_traffic? driver.parse data end data end |
#teardown ⇒ Object
22 23 24 25 26 |
# File 'lib/nio/websocket/adapter.rb', line 22 def teardown @driver = nil # circular reference monitor.close inner.close end |