class ServerEngine::SocketManager::Server

Attributes

path[R]

Public Class Methods

generate_path() click to toggle source
# File lib/serverengine/socket_manager.rb, line 73
def self.generate_path
  if ServerEngine.windows?
    port = ENV['SERVERENGINE_SOCKETMANAGER_PORT']
    return port.to_i if port

    for port in get_dynamic_port_range
      if `netstat -na | findstr "#{port}"`.length == 0
        return port
      end
    end
  else
    base_dir = (ENV['SERVERENGINE_SOCKETMANAGER_SOCK_DIR'] || '/tmp')
    File.join(base_dir, 'SERVERENGINE_SOCKETMANAGER_' + Time.now.utc.iso8601 + '_' + Process.pid.to_s)
  end
end
new(path) click to toggle source
# File lib/serverengine/socket_manager.rb, line 93
def initialize(path)
  @tcp_sockets = {}
  @udp_sockets = {}
  @mutex = Mutex.new
  @path = start_server(path)
end
open(path) click to toggle source
# File lib/serverengine/socket_manager.rb, line 89
def self.open(path)
  new(path)
end

Private Class Methods

get_dynamic_port_range() click to toggle source
# File lib/serverengine/socket_manager.rb, line 175
def self.get_dynamic_port_range
  numbers = []
  # Example output of netsh (actual output is localized):
  #
  # Protocol tcp Dynamic Port Range
  # ---------------------------------
  # Start Port      : 49152
  # Number of Ports : 16384
  #
  str = `netsh int ipv4 show dynamicport tcp`.force_encoding("ASCII-8BIT")
  str.each_line { |line| numbers << $1.to_i if line.match(/.*: (\d+)/) }

  start_port, n_ports = numbers[0], numbers[1]
  end_port = start_port + n_ports - 1

  if valid_dynamic_port_range(start_port, end_port)
    return start_port..end_port
  else
    # The default dynamic port range is 49152 - 65535 as of Windows Vista
    # and Windows Server 2008.
    # https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/default-dynamic-port-range-tcpip-chang
    return 49152..65535
  end
end
valid_dynamic_port_range(start_port, end_port) click to toggle source
# File lib/serverengine/socket_manager.rb, line 168
def self.valid_dynamic_port_range(start_port, end_port)
  return false if start_port < 1025 or start_port > 65535
  return false if end_port < 1025 or end_port > 65535
  return false if start_port > end_port
  true
end

Public Instance Methods

close() click to toggle source
# File lib/serverengine/socket_manager.rb, line 106
def close
  stop_server
  nil
end
new_client() click to toggle source
# File lib/serverengine/socket_manager.rb, line 102
def new_client
  Client.new(@path)
end

Private Instance Methods

listen(proto, bind, port) click to toggle source
# File lib/serverengine/socket_manager.rb, line 113
def listen(proto, bind, port)
  sockets, new_method = case proto
                        when :tcp then [@tcp_sockets, :listen_tcp_new]
                        when :udp then [@udp_sockets, :listen_udp_new]
                        else
                          raise ArgumentError, "invalid protocol: #{proto}"
                        end
  key, bind_ip = resolve_bind_key(bind, port)

  @mutex.synchronize do
    unless sockets.has_key?(key)
      sockets[key] = send(new_method, bind_ip, port)
    end
    return sockets[key]
  end
end
listen_tcp(bind, port) click to toggle source
# File lib/serverengine/socket_manager.rb, line 130
def listen_tcp(bind, port)
  listen(:tcp, bind, port)
end
listen_udp(bind, port) click to toggle source
# File lib/serverengine/socket_manager.rb, line 134
def listen_udp(bind, port)
  listen(:udp, bind, port)
end
process_peer(peer) click to toggle source
# File lib/serverengine/socket_manager.rb, line 151
def process_peer(peer)
  while true
    res = SocketManager.recv_peer(peer)
    return if res.nil?

    pid, method, bind, port = *res
    begin
      send_socket(peer, pid, method, bind, port)
    rescue => e
      SocketManager.send_peer(peer, e)
    end
  end
ensure
  peer.close
end
resolve_bind_key(bind, port) click to toggle source
# File lib/serverengine/socket_manager.rb, line 138
def resolve_bind_key(bind, port)
  bind_ip = IPAddr.new(IPSocket.getaddress(bind))
  if bind_ip.ipv6?
    return "[#{bind_ip}]:#{port}", bind_ip
  else
    # assuming ipv4
    if bind_ip == "127.0.0.1" or bind_ip == "0.0.0.0"
      return "localhost:#{port}", bind_ip
    end
    return "#{bind_ip}:#{port}", bind_ip
  end
end