Class: DRb::DRbTCPSocket

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

Overview

The default drb protocol which communicates over a TCP socket.

The DRb TCP protocol URI looks like: druby://<host>:<port>?<option>. The option is optional.

Direct Known Subclasses

DRbSSLSocket, DRbUNIXSocket

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, soc, config = {}) ⇒ DRbTCPSocket

Create a new DRbTCPSocket instance.

uri is the URI we are connected to. soc is the tcp socket we are bound to. config is our configuration.



931
932
933
934
935
936
937
938
939
# File 'lib/drb/drb.rb', line 931

def initialize(uri, soc, config={})
  @uri = uri
  @socket = soc
  @config = config
  @acl = config[:tcp_acl]
  @msg = DRbMessage.new(config)
  set_sockopt(@socket)
  @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe
end

Instance Attribute Details

#uriObject (readonly)

Get the URI that we are connected to.



942
943
944
# File 'lib/drb/drb.rb', line 942

def uri
  @uri
end

Class Method Details

.getservernameObject

Returns the hostname of this server



873
874
875
876
877
878
879
880
881
882
883
884
# File 'lib/drb/drb.rb', line 873

def self.getservername
  host = Socket::gethostname
  begin
    Socket::getaddrinfo(host, nil,
                              Socket::AF_UNSPEC,
                              Socket::SOCK_STREAM,
                              0,
                              Socket::AI_PASSIVE)[0][3]
  rescue
    'localhost'
  end
end

.open(uri, config) ⇒ Object

Open a client connection to uri (DRb URI string) using configuration config.

This can raise DRb::DRbBadScheme or DRb::DRbBadURI if uri is not for a recognized protocol. See DRb::DRbServer.new for information on built-in URI protocols.



866
867
868
869
870
# File 'lib/drb/drb.rb', line 866

def self.open(uri, config)
  host, port, = parse_uri(uri)
  soc = TCPSocket.open(host, port)
  self.new(uri, soc, config)
end

.open_server(uri, config) ⇒ Object

Open a server listening for connections at uri using configuration config.



904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
# File 'lib/drb/drb.rb', line 904

def self.open_server(uri, config)
  uri = 'druby://:0' unless uri
  host, port, _ = parse_uri(uri)
  config = {:tcp_original_host => host}.update(config)
  if host.size == 0
    host = getservername
    soc = open_server_inaddr_any(host, port)
  else
    soc = TCPServer.open(host, port)
  end
  port = soc.addr[1] if port == 0
  config[:tcp_port] = port
  uri = "druby://#{host}:#{port}"
  self.new(uri, soc, config)
end

.open_server_inaddr_any(host, port) ⇒ Object

For the families available for host, returns a TCPServer on port. If port is 0 the first available port is used. IPv4 servers are preferred over IPv6 servers.



889
890
891
892
893
894
895
896
897
898
899
900
# File 'lib/drb/drb.rb', line 889

def self.open_server_inaddr_any(host, port)
  infos = Socket::getaddrinfo(host, nil,
                              Socket::AF_UNSPEC,
                              Socket::SOCK_STREAM,
                              0,
                              Socket::AI_PASSIVE)
  families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
  return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET')
  return TCPServer.open('::', port) if families.has_key?('AF_INET6')
  return TCPServer.open(port)
  # :stopdoc:
end

.uri_option(uri, config) ⇒ Object

Parse uri into a [uri, option] pair.



921
922
923
924
# File 'lib/drb/drb.rb', line 921

def self.uri_option(uri, config)
  host, port, option = parse_uri(uri)
  return "druby://#{host}:#{port}", option
end

Instance Method Details

#acceptObject

On the server side, for an instance returned by #open_server, accept a client connection and return a new instance to handle the server’s side of this client-server session.



999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
# File 'lib/drb/drb.rb', line 999

def accept
  while true
    s = accept_or_shutdown
    return nil unless s
    break if (@acl ? @acl.allow_socket?(s) : true)
    s.close
  end
  if @config[:tcp_original_host].to_s.size == 0
    uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}"
  else
    uri = @uri
  end
  self.class.new(uri, s, @config)
end

#alive?Boolean

Check to see if this connection is alive.

Returns:

  • (Boolean)


1029
1030
1031
1032
1033
1034
1035
1036
# File 'lib/drb/drb.rb', line 1029

def alive?
  return false unless @socket
  if @socket.to_io.wait_readable(0)
    close
    return false
  end
  true
end

#closeObject

Close the connection.

If this is an instance returned by #open_server, then this stops listening for new connections altogether. If this is an instance returned by #open or by #accept, then it closes this particular client-server session.



981
982
983
984
985
986
987
988
# File 'lib/drb/drb.rb', line 981

def close
  shutdown
  if @socket
    @socket.close
    @socket = nil
  end
  close_shutdown_pipe
end

#peeraddrObject

Get the address of our TCP peer (the other end of the socket we are bound to.



946
947
948
# File 'lib/drb/drb.rb', line 946

def peeraddr
  @socket.peeraddr
end

#recv_replyObject

On the client side, receive a reply from the server.



969
970
971
# File 'lib/drb/drb.rb', line 969

def recv_reply
  @msg.recv_reply(stream)
end

#recv_requestObject

On the server side, receive a request from the client.



959
960
961
# File 'lib/drb/drb.rb', line 959

def recv_request
  @msg.recv_request(stream)
end

#send_reply(succ, result) ⇒ Object

On the server side, send a reply to the client.



964
965
966
# File 'lib/drb/drb.rb', line 964

def send_reply(succ, result)
  @msg.send_reply(stream, succ, result)
end

#send_request(ref, msg_id, arg, b) ⇒ Object

On the client side, send a request to the server.



954
955
956
# File 'lib/drb/drb.rb', line 954

def send_request(ref, msg_id, arg, b)
  @msg.send_request(stream, ref, msg_id, arg, b)
end

#set_sockopt(soc) ⇒ Object

:nodoc:



1038
1039
1040
1041
1042
# File 'lib/drb/drb.rb', line 1038

def set_sockopt(soc) # :nodoc:
  soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
rescue IOError, Errno::ECONNRESET, Errno::EINVAL
  # closed/shutdown socket, ignore error
end

#shutdownObject

Graceful shutdown



1024
1025
1026
# File 'lib/drb/drb.rb', line 1024

def shutdown
  @shutdown_pipe_w.close
end

#streamObject

Get the socket.



951
# File 'lib/drb/drb.rb', line 951

def stream; @socket; end