class ServerEngine::SocketManager::Server
Attributes
path[R]
Public Class Methods
generate_path()
click to toggle source
# File lib/serverengine/socket_manager.rb, line 75 def self.generate_path if ServerEngine.windows? port = ENV['SERVERENGINE_SOCKETMANAGER_PORT'] return port.to_i if port excluded_port_ranges = get_excluded_port_ranges get_dynamic_port_range .reject { |port| excluded_port_ranges.any? { |range| range.cover?(port) } } .find { |port| `netstat -na | findstr "#{port}"`.length == 0 } 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 99 def initialize(path) @tcp_sockets = {} @udp_sockets = {} @mutex = Mutex.new @path = start_server(path) end
open(path = nil)
click to toggle source
# File lib/serverengine/socket_manager.rb, line 90 def self.open(path = nil) return new(path) unless path.nil? if ServerEngine.windows? new(0) else new(self.generate_path) end end
Private Class Methods
get_dynamic_port_range()
click to toggle source
# File lib/serverengine/socket_manager.rb, line 181 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
get_excluded_port_ranges()
click to toggle source
# File lib/serverengine/socket_manager.rb, line 206 def self.get_excluded_port_ranges # Example output of netsh: # # Protocol tcp Port Exclusion Ranges # # Start Port End Port # ---------- -------- # 2869 2869 # 49152 49251 # 50000 50059 * # 57095 57194 # # * - Administered port exclusions. # `netsh int ipv4 show excludedportrange tcp` .force_encoding("ASCII-8BIT") .lines .map { |line| line.match(/\s*(\d+)\s*(\d+)[\s\*]*/) ? $1.to_i..$2.to_i : nil } .compact end
valid_dynamic_port_range(start_port, end_port)
click to toggle source
# File lib/serverengine/socket_manager.rb, line 174 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 112 def close stop_server nil end
new_client()
click to toggle source
# File lib/serverengine/socket_manager.rb, line 108 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 119 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 136 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 140 def listen_udp(bind, port) listen(:udp, bind, port) end
process_peer(peer)
click to toggle source
# File lib/serverengine/socket_manager.rb, line 157 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 144 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