Class: Nonnative::SocketPair

Inherits:
Object
  • Object
show all
Defined in:
lib/nonnative/socket_pair.rb

Overview

Base socket-pair implementation used by TCP proxies.

A socket-pair connects an accepted local socket to a remote upstream socket and forwards bytes in both directions. When one direction reaches EOF (for example a client that half-closes its write side after sending a request), the paired write side is closed and the other direction keeps forwarding until it too ends, so an in-flight response is delivered rather than dropped.

This is used by FaultInjectionProxy to implement pass-through forwarding, and is subclassed to inject failures (close immediately, delay reads, corrupt writes, etc).

The proxy argument is expected to provide host and port for the upstream connection (typically a ConfigurationProxy).

Instance Method Summary collapse

Constructor Details

#initialize(proxy) ⇒ SocketPair

Returns a new instance of SocketPair.

Parameters:

  • proxy (#host, #port, #options)

    proxy configuration used to connect upstream



25
26
27
# File 'lib/nonnative/socket_pair.rb', line 25

def initialize(proxy)
  @proxy = proxy
end

Instance Method Details

#closevoid

This method returns an undefined value.

Closes any open sockets managed by this pair.



54
55
56
57
# File 'lib/nonnative/socket_pair.rb', line 54

def close
  close_socket @local_socket
  close_socket @remote_socket
end

#connect(local_socket) ⇒ void

This method returns an undefined value.

Connects the given local socket to an upstream socket and pipes data until the connection ends.

Parameters:

  • local_socket (TCPSocket)

    the accepted client socket



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/nonnative/socket_pair.rb', line 33

def connect(local_socket)
  @local_socket = local_socket
  @remote_socket = create_remote_socket
  @open = [@local_socket, @remote_socket]

  loop do
    ready = select(@open, nil, nil)

    break if pipe?(ready, @local_socket, @remote_socket)
    break if pipe?(ready, @remote_socket, @local_socket)
    break if @open.empty?
  end
ensure
  Nonnative.logger.info "finished connect for local socket '#{@local_socket.inspect}' and '#{@remote_socket&.inspect}' for 'socket_pair'"

  close
end