Base TCP server class. You must subclass GenericServer
and provide a run
method.
The server status. One of :Stop, :Running or :Shutdown
The server configuration
The server logger. This is independent from the HTTP access log.
Tokens control the number of outstanding clients. The :MaxClients
configuration sets this.
Sockets listening for connections.
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 88
def initialize(config={}, default=Config::General)
@config = default.dup.update(config)
@status = :Stop
@config[:Logger] ||= Log::new
@logger = @config[:Logger]
@tokens = Thread::SizedQueue.new(@config[:MaxClients])
@config[:MaxClients].times{ @tokens.push(nil) }
webrickv = WEBrick::VERSION
rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
@logger.info("WEBrick #{webrickv}")
@logger.info("ruby #{rubyv}")
@listeners = []
@shutdown_pipe = nil
unless @config[:DoNotListen]
if @config[:Listen]
warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
end
listen(@config[:BindAddress], @config[:Port])
if @config[:Port] == 0
@config[:Port] = @listeners[0].addr[1]
end
end
end
Creates a new generic server from config
. The default configuration comes from default
.
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 118
def [](key)
@config[key]
end
Retrieves key
from the configuration
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 126
def listen(address, port)
@listeners += Utils::create_listeners(address, port)
end
Adds listeners from address
and port
to the server. See WEBrick::Utils::create_listeners
for details.
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 241
def run(sock)
@logger.fatal "run() must be provided by user."
end
You must subclass GenericServer
and implement #run which accepts a TCP client socket
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 231
def shutdown
stop
alarm_shutdown_pipe(&:close)
end
Shuts down the server and all listening sockets. New listeners must be provided to restart the server.
# File tmp/rubies/ruby-2.5.9/lib/webrick/ssl.rb, line 210
def ssl_servername_callback(sslsocket, hostname = nil)
# default
end
ServerNameIndication callback
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 151
def start(&block)
raise ServerError, "already started." if @status != :Stop
server_type = @config[:ServerType] || SimpleServer
setup_shutdown_pipe
server_type.start{
@logger.info \
"#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
@status = :Running
call_callback(:StartCallback)
shutdown_pipe = @shutdown_pipe
thgroup = ThreadGroup.new
begin
while @status == :Running
begin
sp = shutdown_pipe[0]
if svrs = IO.select([sp, *@listeners])
if svrs[0].include? sp
# swallow shutdown pipe
buf = String.new
nil while String ===
sp.read_nonblock([sp.nread, 8].max, buf, exception: false)
break
end
svrs[0].each{|svr|
@tokens.pop # blocks while no token is there.
if sock = accept_client(svr)
unless config[:DoNotReverseLookup].nil?
sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup]
end
th = start_thread(sock, &block)
th[:WEBrickThread] = true
thgroup.add(th)
else
@tokens.push(nil)
end
}
end
rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex
# if the listening socket was closed in GenericServer#shutdown,
# IO::select raise it.
rescue StandardError => ex
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
@logger.error msg
rescue Exception => ex
@logger.fatal ex
raise
end
end
ensure
cleanup_shutdown_pipe(shutdown_pipe)
cleanup_listener
@status = :Shutdown
@logger.info "going to shutdown ..."
thgroup.list.each{|th| th.join if th[:WEBrickThread] }
call_callback(:StopCallback)
@logger.info "#{self.class}#start done."
@status = :Stop
end
}
end
Starts the server and runs the block
for each connection. This method does not return until the server is stopped from a signal handler or another thread using stop
or shutdown
.
If the block raises a subclass of StandardError
the exception is logged and ignored. If an IOError
or Errno::EBADF exception is raised the exception is ignored. If an Exception
subclass is raised the exception is logged and re-raised which stops the server.
To completely shut down a server call shutdown
from ensure:
server = WEBrick::GenericServer.new # or WEBrick::HTTPServer.new begin server.start ensure server.shutdown end
# File tmp/rubies/ruby-2.5.9/lib/webrick/server.rb, line 219
def stop
if @status == :Running
@status = :Shutdown
end
alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
end
Stops the server from accepting new connections.