# class WEBrick::GenericServer

Base TCP server class. You must subclass `GenericServer` and provide a `run` method.

### Attributes

config[R]

The server configuration

listeners[R]

Sockets listening for connections.

logger[R]

The server logger. This is independent from the HTTP access log.

status[R]

The server status. One of :Stop, :Running or :Shutdown

tokens[R]

Tokens control the number of outstanding clients. The `:MaxClients` configuration sets this.

### Public Class Methods

new(config={}, default=Config::General) click to toggle source

Creates a new generic server from `config`. The default configuration comes from `default`.

    # File 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

### Public Instance Methods

[](key) click to toggle source

Retrieves `key` from the configuration

    # File lib/webrick/server.rb, line 118
    def [](key)
      @config[key]
    end

listen(address, port) click to toggle source

Adds listeners from `address` and `port` to the server. See `WEBrick::Utils::create_listeners` for details.

    # File lib/webrick/server.rb, line 126
    def listen(address, port)
      @listeners += Utils::create_listeners(address, port)
    end

run(sock) click to toggle source

You must subclass `GenericServer` and implement #run which accepts a TCP client socket

    # File lib/webrick/server.rb, line 241
    def run(sock)
      @logger.fatal "run() must be provided by user."
    end

shutdown() click to toggle source

Shuts down the server and all listening sockets. New listeners must be provided to restart the server.

    # File lib/webrick/server.rb, line 231
    def shutdown
      stop

      alarm_shutdown_pipe(&:close)
    end

ssl_servername_callback(sslsocket, hostname = nil) click to toggle source

ServerNameIndication callback

    # File lib/webrick/ssl.rb, line 210
    def ssl_servername_callback(sslsocket, hostname = nil)
      # default
    end

start(&block) click to toggle source

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 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

stop() click to toggle source

Stops the server from accepting new connections.

    # File lib/webrick/server.rb, line 219
    def stop
      if @status == :Running
        @status = :Shutdown
      end

      alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
    end