Class Dsadmin::Admind::SocketListener
In: lib/dsadmin/admind/socket_listener.rb
Parent: Object

This class sets up TCP servers on the IPs/ports configured in the configfile, spawns a thread for each incoming connection and hands the requests off to the RequestProcessor.

Also handles ACL checking (by host/IP) for incoming connections.

Methods

Included Modules

Dsadmin::CoreClient Dsadmin::Contractor

Public Class methods

[Source]

    # File lib/dsadmin/admind/socket_listener.rb, line 74
74:       def initialize
75:         @in_shutdown = false
76:         @running = false
77:         @gc_counter = 0
78:       end

Public Instance methods

Shut down the system. Multiple startup/shutdown cycles for the same SocketListener are fine.

[Source]

    # File lib/dsadmin/admind/socket_listener.rb, line 55
55:       def shutdown
56:         return if @in_shutdown
57:         return unless @running
58:         @in_shutdown = true # don't accept any new frontend connections
59:         @running     = false
60:         
61:         log.notice("Shutting down ...")
62:         
63:         @servers.each { |server| server.close rescue nil }
64:         @listener_threads.each { |thread| thread.join }
65:         @connection_handlers.each { |handler| handler.shutdown }
66:         
67:         @in_shutdown = false
68:       end

Start the system. Multiple startup/shutdown cycles for the same SocketListener are fine.

[Source]

    # File lib/dsadmin/admind/socket_listener.rb, line 39
39:       def startup
40:         requireTrue(! @in_shutdown)
41:         return if @running
42:         
43:         @servers = []
44:         @net_acls = nil
45:         @connection_handlers = []
46:         @connection_handlers.extend(MonitorMixin)
47:         
48:         start_listeners
49:         
50:         @running = true
51:       end

Private Instance methods

Check if remote_host or remote_port are in the given accept_list

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 185
185:       def check_acl(accept_list, remote_host, remote_ip)
186:         #@log.debug "Checking incoming connection from #{remote_host}(#{remote_ip}"
187:         accept_list.each { |entry|
188:           if((entry.kind_of?(String) && (entry == remote_host)) ||
189:              (entry.kind_of?(IPAddr) && entry.include?(remote_ip))
190:             )
191:             return true
192:           end
193:         }
194:         
195:         return false
196:       end

Create a ConnectionHandler for the given connection and hand processing over to it

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 136
136:       def dispatch(connection)
137:         handler = ConnectionHandler.new
138:         handler.handle(connection)
139:         @connection_handlers.synchronize { @connection_handlers << handler }
140:       end

Remove leftover ConnectionHandler objects

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 144
144:       def garbage_collect
145:         if(@gc_counter < 100)
146:           @gc_counter += 1
147:           return
148:         end
149:         
150:         @gc_counter = 0
151:         
152:         @connnection_handlers.synchronize {
153:           @connection_handlers.delete_if { |handler|
154:             ! handler.active?
155:           }
156:         }
157:       end

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 114
114:       def listen(server)
115:         while ((! @in_shutdown) && (conn = server.accept))
116:           rhost = conn.peeraddr[2]
117:           rip   = IPAddr.new(conn.peeraddr[3])
118:           rport = conn.peeraddr[1]
119:           
120:           if(check_acl(net_acls, rhost, rip))
121:             log.notice("Accepting connection from #{rhost}(#{rip}):#{rport}")
122:             dispatch(conn)
123:           else
124:             log.warning("Rejecting connection attempt from #{rhost}(#{rip}):#{rport}")
125:             session.shutdown
126:           end
127:           
128:           garbage_collect
129:         end
130:         
131:         server.close
132:       end

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 95
 95:       def listener_thread(ip, port)
 96:         # We create the TCPServer outside of the thread to make sure that all servers are
 97:         # really listening before we return from startup() (which is typically followed by a
 98:         # drop_privileges in AdminDaemon)
 99:         server = TCPServer.new(ip, port)
100:         @servers << server
101:         log.notice "Now listening on '#{server.addr[2]}':#{server.addr[1]} ('#{server.addr[3]}':#{server.addr[1]})"
102:         
103:         spawnThread do
104:           begin
105:             listen(server)
106:           rescue IOError
107:             # ignore -- this is caused by the forced
108:             # close() on shutdown
109:           end
110:         end
111:       end

Get the list of hosts/ports (or port ranges/patterns) that are allowed to connect (configfile:/admind/net/accept-from). Caches the information.

[Source]

     # File lib/dsadmin/admind/socket_listener.rb, line 162
162:       def net_acls
163:         return @net_acls if @net_acls
164:         
165:         csect = cfg.net_config.get('accept_from', Array, false) || []
166:         
167:         accept = Array.new
168:         
169:         csect.each do |entry|
170:           host = entry
171:           
172:           begin
173:             ip = IPAddr.new(host)
174:             accept << ip     # Valid IP adress w/ optional mask
175:           rescue ArgumentError
176:             accept << host   # Hostname
177:           end
178:         end
179:         
180:         @net_acls = accept
181:       end

[Source]

    # File lib/dsadmin/admind/socket_listener.rb, line 81
81:       def start_listeners
82:         csect= cfg.net_config.get('listen', Array)
83:         
84:         @listener_threads = Array.new
85:         
86:         csect.each { |lsect|
87:           lhost = lsect.host
88:           lport = lsect.port.to_i
89:           
90:           @listener_threads <<  listener_thread(lhost, lport)
91:         }
92:       end

[Validate]