Module: RTunnel::SocketFactory

Defined in:
lib/rtunnel/socket_factory.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.bind(socket, options) ⇒ Object



65
66
67
# File 'lib/rtunnel/socket_factory.rb', line 65

def self.bind(socket, options)
  socket.bind bind_socket_address(options)
end

.bind_host(options) ⇒ Object



25
26
27
# File 'lib/rtunnel/socket_factory.rb', line 25

def self.bind_host(options)
  options[:in_host] or host_from_address(options[:in_addr]) or '0.0.0.0'
end

.bind_port(options) ⇒ Object



29
30
31
# File 'lib/rtunnel/socket_factory.rb', line 29

def self.bind_port(options)
  options[:in_port] or port_from_address(options[:in_addr]) or 0
end

.bind_socket_address(options) ⇒ Object



33
34
35
# File 'lib/rtunnel/socket_factory.rb', line 33

def self.bind_socket_address(options)
  Socket::pack_sockaddr_in bind_port(options), bind_host(options)
end

.connect(socket, options) ⇒ Object



69
70
71
# File 'lib/rtunnel/socket_factory.rb', line 69

def self.connect(socket, options)
  socket.connect connect_socket_address(options)
end

.connect_host(options) ⇒ Object



37
38
39
# File 'lib/rtunnel/socket_factory.rb', line 37

def self.connect_host(options)
  options[:out_host] or host_from_address(options[:out_addr])
end

.connect_port(options) ⇒ Object



41
42
43
# File 'lib/rtunnel/socket_factory.rb', line 41

def self.connect_port(options)
  options[:out_port] or port_from_address(options[:out_addr])
end

.connect_socket_address(options) ⇒ Object



45
46
47
# File 'lib/rtunnel/socket_factory.rb', line 45

def self.connect_socket_address(options)
  Socket::pack_sockaddr_in connect_port(options), connect_host(options)
end

.host_from_address(address) ⇒ Object



13
14
15
# File 'lib/rtunnel/socket_factory.rb', line 13

def self.host_from_address(address)
  address and split_address(address)[0]
end

.inbound?(options) ⇒ Boolean

Returns:

  • (Boolean)


21
22
23
# File 'lib/rtunnel/socket_factory.rb', line 21

def self.inbound?(options)
  options[:inbound] or [:in_port, :in_host, :in_addr].any? { |k| options[k] }
end

.new_socket(options) ⇒ Object



61
62
63
# File 'lib/rtunnel/socket_factory.rb', line 61

def self.new_socket(options)
  tcp?(options) ? new_tcp_socket : new_udp_socket
end

.new_tcp_socketObject



53
54
55
# File 'lib/rtunnel/socket_factory.rb', line 53

def self.new_tcp_socket
  Socket.new Socket::AF_INET, Socket::SOCK_STREAM, Socket::PF_UNSPEC
end

.new_udp_socketObject



57
58
59
# File 'lib/rtunnel/socket_factory.rb', line 57

def self.new_udp_socket
  Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, Socket::PF_UNSPEC
end

.port_from_address(address) ⇒ Object



17
18
19
# File 'lib/rtunnel/socket_factory.rb', line 17

def self.port_from_address(address)
  address and (port_string = split_address(address)[1]) and port_string.to_i
end

.set_options(socket, options) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rtunnel/socket_factory.rb', line 73

def self.set_options(socket, options)
  if options[:no_delay]
    socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true
    socket.sync = true
  end
  
  if options[:reuse_addr]
    socket.setsockopt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true
  end
  
  unless options[:reverse_lookup]
    if socket.respond_to? :do_not_reverse_lookup
      socket.do_not_reverse_lookup = true
    else
      # work around until the patch below actually gets committed:
      # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/2346
      BasicSocket.do_not_reverse_lookup = true
    end
  end
end

.set_options_on_accept_sockets(socket, options) ⇒ Object

new sockets coming out of socket.accept will have the given options set



95
96
97
98
99
100
101
102
# File 'lib/rtunnel/socket_factory.rb', line 95

def self.set_options_on_accept_sockets(socket, options)
  socket.instance_variable_set :@rtunnel_factory_options, options
  def socket.accept(*args)
    sock, addr = super
    RTunnel::SocketFactory.set_options sock, @rtunnel_factory_options
    return sock, addr
  end
end

.socket(options = {}) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rtunnel/socket_factory.rb', line 104

def self.socket(options = {})    
  s = new_socket options
  set_options s, options
  if inbound? options
    bind s, options    
    set_options_on_accept_sockets s, options
  else
    connect s, options
  end
  s
end

.split_address(address) ⇒ Object



4
5
6
7
8
9
10
11
# File 'lib/rtunnel/socket_factory.rb', line 4

def self.split_address(address)
  port_index = address.index /[^:]\:[^:]/
  if port_index
    [address[0, port_index + 1], address[port_index + 2, address.length]]
  else
    [address, nil]
  end
end

.tcp?(options) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/rtunnel/socket_factory.rb', line 49

def self.tcp?(options)
  options[:tcp] or !options[:udp]
end

Instance Method Details

#socket(options = {}) ⇒ Object



116
117
118
# File 'lib/rtunnel/socket_factory.rb', line 116

def socket(options = {})
  RTunnel::SocketFactory.socket(options)
end