class Reactomatic::TcpConnection

Public Class Methods

new(opts = {}) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 3
def initialize(opts = {})
  @opts = opts

  @reactor = opts[:reactor] || Reactomatic.reactor
  @socket = opts[:socket]
  @write_buffer = opts[:write_buffer] || Buffer.new
  @read_count = 0
  @write_count = 0
  @read_eof = false
  @lock = Monitor.new

  on_initialize
  register if @socket
end

Public Instance Methods

close() click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 42
def close
  @lock.synchronize do
    if @socket
      @reactor.deregister(@socket)
      @socket.close
      @socket = nil
      on_disconnect
    end
  end

  nil
end
connect(host, port) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 26
def connect(host, port)
  raise 'Not implemented yet.'
end
reactor() click to toggle source

Public methods.

# File lib/reactomatic/tcp_connection.rb, line 22
def reactor
  return @reactor
end
send_data(data) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 30
def send_data(data)
  @lock.synchronize do
    return nil if @socket.nil?

    @write_buffer.append(data)
    write_nonblock
    register
  end

  nil
end

Private Instance Methods

on_connect() click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 65
def on_connect
  puts "connected!"
end
on_disconnect() click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 78
def on_disconnect
  puts "disconnected! read bytes: #{@read_count}, wrote bytes: #{@write_count}"
end
on_initialize() click to toggle source

Event handlers (override these in your subclasses).

# File lib/reactomatic/tcp_connection.rb, line 61
def on_initialize
  puts "initialized!"
end
on_receive_data(data) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 69
def on_receive_data(data)
  puts "received #{data.bytesize} bytes of data and echoing back!"
  send_data(data)
end
on_sent_data(num_bytes) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 74
def on_sent_data(num_bytes)
  puts "sent #{num_bytes} of data!"
end
read_nonblock() click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 111
def read_nonblock
  begin
    data = @socket.read_nonblock(1024**2)
    on_receive_data(data)
    @read_count += data.bytesize
  rescue EOFError
    @read_eof = true
  rescue IO::WaitReadable
  end
end
register() click to toggle source

Internal methods (don’t use).

# File lib/reactomatic/tcp_connection.rb, line 86
def register
  @reactor.deregister(@socket)

  if !@write_buffer.empty? && !@read_eof
    interest = :rw
  elsif @write_buffer.empty? && !@read_eof
    interest = :r
  elsif !@write_buffer.empty?
    interest = :w
  elsif @read_eof
    close
    return
  end

  @reactor.register(@socket, interest, method(:selected))
end
selected(monitor) click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 103
def selected(monitor)
  @lock.synchronize do
    read_nonblock if monitor.readable?
    write_nonblock if monitor.writable?
    register
  end
end
write_nonblock() click to toggle source
# File lib/reactomatic/tcp_connection.rb, line 122
def write_nonblock
  return if @write_buffer.empty?

  begin
    num_bytes = @socket.write_nonblock(@write_buffer.read)
    @write_buffer.consume(num_bytes)
    @write_count += num_bytes
    on_sent_data(num_bytes)
  rescue IO::WaitWritable
  end
end