Class: ZMachine::TCPChannel

Inherits:
Channel
  • Object
show all
Defined in:
lib/zmachine/tcp_channel.rb

Instance Attribute Summary

Attributes inherited from Channel

#socket

Instance Method Summary collapse

Methods inherited from Channel

#can_send?, #close_after_writing, #initialize

Constructor Details

This class inherits a constructor from ZMachine::Channel

Instance Method Details

#acceptObject



26
27
28
29
30
31
32
33
# File 'lib/zmachine/tcp_channel.rb', line 26

def accept
  client_socket = @socket.accept
  return unless client_socket
  client_socket.configure_blocking(false)
  TCPChannel.new.tap do |channel|
    channel.socket = client_socket
  end
end

#bind(address, port) ⇒ Object



15
16
17
18
19
20
# File 'lib/zmachine/tcp_channel.rb', line 15

def bind(address, port)
  address = InetSocketAddress.new(address, port)
  @socket = ServerSocketChannel.open
  @socket.configure_blocking(false)
  @socket.bind(address)
end

#bound?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/zmachine/tcp_channel.rb', line 22

def bound?
  @socket.is_a?(ServerSocketChannel) and @socket.bound?
end

#close(after_writing = false) ⇒ Object



105
106
107
108
# File 'lib/zmachine/tcp_channel.rb', line 105

def close(after_writing = false)
  super
  @socket.close unless can_send?
end

#closed?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/zmachine/tcp_channel.rb', line 110

def closed?
  @socket.socket.closed?
end

#connect(address, port) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/zmachine/tcp_channel.rb', line 35

def connect(address, port)
  address = InetSocketAddress.new(address, port)
  @socket = SocketChannel.open
  @socket.configure_blocking(false)
  if socket.connect(address)
    # Connection returned immediately. Can happen with localhost
    # connections.
    # WARNING, this code is untested due to lack of available test
    # conditions.  Ought to be be able to come here from a localhost
    # connection, but that doesn't happen on Linux. (Maybe on FreeBSD?)
    raise RuntimeError.new("immediate-connect unimplemented")
  end
end

#connected?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/zmachine/tcp_channel.rb', line 59

def connected?
  @socket.connected?
end

#connection_pending?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/zmachine/tcp_channel.rb', line 49

def connection_pending?
  @socket.connection_pending?
end

#finish_connectingObject



53
54
55
56
57
# File 'lib/zmachine/tcp_channel.rb', line 53

def finish_connecting
  return unless connection_pending?
  @socket.finish_connect # XXX: finish_connect might return false
  return true
end

#peerObject



114
115
116
# File 'lib/zmachine/tcp_channel.rb', line 114

def peer
  [@socket.socket.port, @socket.socket.inet_address.host_address]
end

#read_inbound_dataObject

Raises:

  • (IOException)


63
64
65
66
67
68
69
70
# File 'lib/zmachine/tcp_channel.rb', line 63

def read_inbound_data
  buffer = @inbound_buffer
  buffer.clear
  raise IOException.new("EOF") if @socket.read(buffer) == -1
  buffer.flip
  return if buffer.limit == 0
  String.from_java_bytes(buffer.array[buffer.position...buffer.limit])
end

#selectable_fdObject



11
12
13
# File 'lib/zmachine/tcp_channel.rb', line 11

def selectable_fd
  @socket
end

#send_data(data) ⇒ Object

Raises:

  • (RuntimeError)


72
73
74
75
76
77
78
79
80
# File 'lib/zmachine/tcp_channel.rb', line 72

def send_data(data)
  raise RuntimeError.new("send_data called after close") if @close_scheduled
  return unless data
  data = data.to_java_bytes if data.is_a?(String) # EM compat
  buffer = ByteBuffer.wrap(data)
  if buffer.has_remaining
    @outbound_queue << buffer
  end
end

#write_outbound_dataObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/zmachine/tcp_channel.rb', line 82

def write_outbound_data
  while can_send?
    buffer = @outbound_queue.first
    @socket.write(buffer) if buffer.has_remaining
    # Did we consume the whole outbound buffer? If yes,
    # pop it off and keep looping. If no, the outbound network
    # buffers are full, so break out of here.
    if buffer.remaining == 0
      @outbound_queue.shift
    else
      break
    end
  end

  if can_send?
    # network buffers are full
    return false
  end

  close if @close_scheduled
  return true
end