webrick 1.3.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webrick might be problematic. Click here for more details.
- checksums.yaml +7 -0
 - data/lib/webrick.rb +6 -6
 - data/lib/webrick/accesslog.rb +9 -1
 - data/lib/webrick/cgi.rb +58 -5
 - data/lib/webrick/compat.rb +2 -1
 - data/lib/webrick/config.rb +47 -10
 - data/lib/webrick/cookie.rb +69 -7
 - data/lib/webrick/htmlutils.rb +4 -2
 - data/lib/webrick/httpauth.rb +6 -5
 - data/lib/webrick/httpauth/authenticator.rb +13 -8
 - data/lib/webrick/httpauth/basicauth.rb +16 -8
 - data/lib/webrick/httpauth/digestauth.rb +35 -32
 - data/lib/webrick/httpauth/htdigest.rb +12 -8
 - data/lib/webrick/httpauth/htgroup.rb +10 -6
 - data/lib/webrick/httpauth/htpasswd.rb +46 -9
 - data/lib/webrick/httpauth/userdb.rb +1 -0
 - data/lib/webrick/httpproxy.rb +93 -48
 - data/lib/webrick/httprequest.rb +192 -27
 - data/lib/webrick/httpresponse.rb +182 -62
 - data/lib/webrick/https.rb +90 -2
 - data/lib/webrick/httpserver.rb +45 -15
 - data/lib/webrick/httpservlet.rb +6 -5
 - data/lib/webrick/httpservlet/abstract.rb +5 -6
 - data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
 - data/lib/webrick/httpservlet/cgihandler.rb +22 -10
 - data/lib/webrick/httpservlet/erbhandler.rb +4 -3
 - data/lib/webrick/httpservlet/filehandler.rb +136 -65
 - data/lib/webrick/httpservlet/prochandler.rb +15 -1
 - data/lib/webrick/httpstatus.rb +24 -14
 - data/lib/webrick/httputils.rb +132 -13
 - data/lib/webrick/httpversion.rb +28 -1
 - data/lib/webrick/log.rb +25 -5
 - data/lib/webrick/server.rb +234 -74
 - data/lib/webrick/ssl.rb +100 -12
 - data/lib/webrick/utils.rb +98 -69
 - data/lib/webrick/version.rb +6 -1
 - metadata +66 -72
 - data/README.txt +0 -21
 - data/sample/webrick/demo-app.rb +0 -66
 - data/sample/webrick/demo-multipart.cgi +0 -12
 - data/sample/webrick/demo-servlet.rb +0 -6
 - data/sample/webrick/demo-urlencoded.cgi +0 -12
 - data/sample/webrick/hello.cgi +0 -11
 - data/sample/webrick/hello.rb +0 -8
 - data/sample/webrick/httpd.rb +0 -23
 - data/sample/webrick/httpproxy.rb +0 -25
 - data/sample/webrick/httpsd.rb +0 -33
 - data/test/openssl/utils.rb +0 -313
 - data/test/ruby/envutil.rb +0 -208
 - data/test/webrick/test_cgi.rb +0 -134
 - data/test/webrick/test_cookie.rb +0 -131
 - data/test/webrick/test_filehandler.rb +0 -285
 - data/test/webrick/test_httpauth.rb +0 -167
 - data/test/webrick/test_httpproxy.rb +0 -282
 - data/test/webrick/test_httprequest.rb +0 -411
 - data/test/webrick/test_httpresponse.rb +0 -49
 - data/test/webrick/test_httpserver.rb +0 -305
 - data/test/webrick/test_httputils.rb +0 -96
 - data/test/webrick/test_httpversion.rb +0 -40
 - data/test/webrick/test_server.rb +0 -67
 - data/test/webrick/test_utils.rb +0 -64
 - data/test/webrick/utils.rb +0 -58
 - data/test/webrick/webrick.cgi +0 -36
 - data/test/webrick/webrick_long_filename.cgi +0 -36
 
    
        data/lib/webrick/httpversion.rb
    CHANGED
    
    | 
         @@ -1,3 +1,4 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
       1 
2 
     | 
    
         
             
            #--
         
     | 
| 
       2 
3 
     | 
    
         
             
            # HTTPVersion.rb -- presentation of HTTP version
         
     | 
| 
       3 
4 
     | 
    
         
             
            #
         
     | 
| 
         @@ -8,15 +9,33 @@ 
     | 
|
| 
       8 
9 
     | 
    
         
             
            # $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
            module WEBrick
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              ##
         
     | 
| 
      
 14 
     | 
    
         
            +
              # Represents an HTTP protocol version
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       11 
16 
     | 
    
         
             
              class HTTPVersion
         
     | 
| 
       12 
17 
     | 
    
         
             
                include Comparable
         
     | 
| 
       13 
18 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
      
 19 
     | 
    
         
            +
                ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                # The major protocol version number
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                attr_accessor :major
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                ##
         
     | 
| 
      
 25 
     | 
    
         
            +
                # The minor protocol version number
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                attr_accessor :minor
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                ##
         
     | 
| 
      
 30 
     | 
    
         
            +
                # Converts +version+ into an HTTPVersion
         
     | 
| 
       15 
31 
     | 
    
         | 
| 
       16 
32 
     | 
    
         
             
                def self.convert(version)
         
     | 
| 
       17 
33 
     | 
    
         
             
                  version.is_a?(self) ? version : new(version)
         
     | 
| 
       18 
34 
     | 
    
         
             
                end
         
     | 
| 
       19 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
                ##
         
     | 
| 
      
 37 
     | 
    
         
            +
                # Creates a new HTTPVersion from +version+.
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       20 
39 
     | 
    
         
             
                def initialize(version)
         
     | 
| 
       21 
40 
     | 
    
         
             
                  case version
         
     | 
| 
       22 
41 
     | 
    
         
             
                  when HTTPVersion
         
     | 
| 
         @@ -32,6 +51,10 @@ module WEBrick 
     | 
|
| 
       32 
51 
     | 
    
         
             
                  end
         
     | 
| 
       33 
52 
     | 
    
         
             
                end
         
     | 
| 
       34 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
                ##
         
     | 
| 
      
 55 
     | 
    
         
            +
                # Compares this version with +other+ according to the HTTP specification
         
     | 
| 
      
 56 
     | 
    
         
            +
                # rules.
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
       35 
58 
     | 
    
         
             
                def <=>(other)
         
     | 
| 
       36 
59 
     | 
    
         
             
                  unless other.is_a?(self.class)
         
     | 
| 
       37 
60 
     | 
    
         
             
                    other = self.class.new(other)
         
     | 
| 
         @@ -42,6 +65,10 @@ module WEBrick 
     | 
|
| 
       42 
65 
     | 
    
         
             
                  return ret
         
     | 
| 
       43 
66 
     | 
    
         
             
                end
         
     | 
| 
       44 
67 
     | 
    
         | 
| 
      
 68 
     | 
    
         
            +
                ##
         
     | 
| 
      
 69 
     | 
    
         
            +
                # The HTTP version as show in the HTTP request and response.  For example,
         
     | 
| 
      
 70 
     | 
    
         
            +
                # "1.1"
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
       45 
72 
     | 
    
         
             
                def to_s
         
     | 
| 
       46 
73 
     | 
    
         
             
                  format("%d.%d", @major, @minor)
         
     | 
| 
       47 
74 
     | 
    
         
             
                end
         
     | 
    
        data/lib/webrick/log.rb
    CHANGED
    
    | 
         @@ -1,3 +1,4 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
       1 
2 
     | 
    
         
             
            #--
         
     | 
| 
       2 
3 
     | 
    
         
             
            # log.rb -- Log Class
         
     | 
| 
       3 
4 
     | 
    
         
             
            #
         
     | 
| 
         @@ -14,8 +15,27 @@ module WEBrick 
     | 
|
| 
       14 
15 
     | 
    
         
             
              # A generic logging class
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
              class BasicLog
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Fatal log level which indicates a server crash
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                FATAL = 1
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Error log level which indicates a recoverable error
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                ERROR = 2
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                # Warning log level which indicates a possible problem
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                WARN  = 3
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                # Information log level which indicates possibly useful information
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                INFO  = 4
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # Debugging error level for messages used in server development or
         
     | 
| 
      
 36 
     | 
    
         
            +
                # debugging
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                DEBUG = 5
         
     | 
| 
       19 
39 
     | 
    
         | 
| 
       20 
40 
     | 
    
         
             
                # log-level, messages above this level will be logged
         
     | 
| 
       21 
41 
     | 
    
         
             
                attr_accessor :level
         
     | 
| 
         @@ -31,7 +51,7 @@ module WEBrick 
     | 
|
| 
       31 
51 
     | 
    
         
             
                  @level = level || INFO
         
     | 
| 
       32 
52 
     | 
    
         
             
                  case log_file
         
     | 
| 
       33 
53 
     | 
    
         
             
                  when String
         
     | 
| 
       34 
     | 
    
         
            -
                    @log = open(log_file, "a+")
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @log = File.open(log_file, "a+")
         
     | 
| 
       35 
55 
     | 
    
         
             
                    @log.sync = true
         
     | 
| 
       36 
56 
     | 
    
         
             
                    @opened = true
         
     | 
| 
       37 
57 
     | 
    
         
             
                  when NilClass
         
     | 
| 
         @@ -98,10 +118,10 @@ module WEBrick 
     | 
|
| 
       98 
118 
     | 
    
         
             
                # * Otherwise it will return +arg+.inspect.
         
     | 
| 
       99 
119 
     | 
    
         
             
                def format(arg)
         
     | 
| 
       100 
120 
     | 
    
         
             
                  if arg.is_a?(Exception)
         
     | 
| 
       101 
     | 
    
         
            -
                    "#{arg.class}: #{arg.message}\n\t" <<
         
     | 
| 
      
 121 
     | 
    
         
            +
                    "#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" <<
         
     | 
| 
       102 
122 
     | 
    
         
             
                    arg.backtrace.join("\n\t") << "\n"
         
     | 
| 
       103 
123 
     | 
    
         
             
                  elsif arg.respond_to?(:to_str)
         
     | 
| 
       104 
     | 
    
         
            -
                    arg.to_str
         
     | 
| 
      
 124 
     | 
    
         
            +
                    AccessLog.escape(arg.to_str)
         
     | 
| 
       105 
125 
     | 
    
         
             
                  else
         
     | 
| 
       106 
126 
     | 
    
         
             
                    arg.inspect
         
     | 
| 
       107 
127 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/webrick/server.rb
    CHANGED
    
    | 
         @@ -1,3 +1,4 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
       1 
2 
     | 
    
         
             
            #
         
     | 
| 
       2 
3 
     | 
    
         
             
            # server.rb -- GenericServer Class
         
     | 
| 
       3 
4 
     | 
    
         
             
            #
         
     | 
| 
         @@ -8,16 +9,25 @@ 
     | 
|
| 
       8 
9 
     | 
    
         
             
            #
         
     | 
| 
       9 
10 
     | 
    
         
             
            # $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            require 'thread'
         
     | 
| 
       12 
12 
     | 
    
         
             
            require 'socket'
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
            require_relative 'config'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require_relative 'log'
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
            module WEBrick
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
              ##
         
     | 
| 
      
 19 
     | 
    
         
            +
              # Server error exception
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       18 
21 
     | 
    
         
             
              class ServerError < StandardError; end
         
     | 
| 
       19 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
              ##
         
     | 
| 
      
 24 
     | 
    
         
            +
              # Base server class
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       20 
26 
     | 
    
         
             
              class SimpleServer
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                ##
         
     | 
| 
      
 29 
     | 
    
         
            +
                # A SimpleServer only yields when you start it
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       21 
31 
     | 
    
         
             
                def SimpleServer.start
         
     | 
| 
       22 
32 
     | 
    
         
             
                  yield
         
     | 
| 
       23 
33 
     | 
    
         
             
                end
         
     | 
| 
         @@ -33,20 +43,47 @@ module WEBrick 
     | 
|
| 
       33 
43 
     | 
    
         
             
                # block, if given.
         
     | 
| 
       34 
44 
     | 
    
         | 
| 
       35 
45 
     | 
    
         
             
                def Daemon.start
         
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
       37 
     | 
    
         
            -
                   
     | 
| 
       38 
     | 
    
         
            -
                  exit!(0) if fork
         
     | 
| 
       39 
     | 
    
         
            -
                  Dir::chdir("/")
         
     | 
| 
       40 
     | 
    
         
            -
                  File::umask(0)
         
     | 
| 
       41 
     | 
    
         
            -
                  STDIN.reopen("/dev/null")
         
     | 
| 
       42 
     | 
    
         
            -
                  STDOUT.reopen("/dev/null", "w")
         
     | 
| 
       43 
     | 
    
         
            -
                  STDERR.reopen("/dev/null", "w")
         
     | 
| 
      
 46 
     | 
    
         
            +
                  Process.daemon
         
     | 
| 
      
 47 
     | 
    
         
            +
                  File.umask(0)
         
     | 
| 
       44 
48 
     | 
    
         
             
                  yield if block_given?
         
     | 
| 
       45 
49 
     | 
    
         
             
                end
         
     | 
| 
       46 
50 
     | 
    
         
             
              end
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
      
 52 
     | 
    
         
            +
              ##
         
     | 
| 
      
 53 
     | 
    
         
            +
              # Base TCP server class.  You must subclass GenericServer and provide a #run
         
     | 
| 
      
 54 
     | 
    
         
            +
              # method.
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
       48 
56 
     | 
    
         
             
              class GenericServer
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                ##
         
     | 
| 
      
 59 
     | 
    
         
            +
                # The server status.  One of :Stop, :Running or :Shutdown
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                attr_reader :status
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                ##
         
     | 
| 
      
 64 
     | 
    
         
            +
                # The server configuration
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                attr_reader :config
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                ##
         
     | 
| 
      
 69 
     | 
    
         
            +
                # The server logger.  This is independent from the HTTP access log.
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                attr_reader :logger
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                ##
         
     | 
| 
      
 74 
     | 
    
         
            +
                # Tokens control the number of outstanding clients.  The
         
     | 
| 
      
 75 
     | 
    
         
            +
                # <code>:MaxClients</code> configuration sets this.
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                attr_reader :tokens
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                ##
         
     | 
| 
      
 80 
     | 
    
         
            +
                # Sockets listening for connections.
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                attr_reader :listeners
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                ##
         
     | 
| 
      
 85 
     | 
    
         
            +
                # Creates a new generic server from +config+.  The default configuration
         
     | 
| 
      
 86 
     | 
    
         
            +
                # comes from +default+.
         
     | 
| 
       50 
87 
     | 
    
         | 
| 
       51 
88 
     | 
    
         
             
                def initialize(config={}, default=Config::General)
         
     | 
| 
       52 
89 
     | 
    
         
             
                  @config = default.dup.update(config)
         
     | 
| 
         @@ -54,7 +91,7 @@ module WEBrick 
     | 
|
| 
       54 
91 
     | 
    
         
             
                  @config[:Logger] ||= Log::new
         
     | 
| 
       55 
92 
     | 
    
         
             
                  @logger = @config[:Logger]
         
     | 
| 
       56 
93 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                  @tokens = SizedQueue.new(@config[:MaxClients])
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @tokens = Thread::SizedQueue.new(@config[:MaxClients])
         
     | 
| 
       58 
95 
     | 
    
         
             
                  @config[:MaxClients].times{ @tokens.push(nil) }
         
     | 
| 
       59 
96 
     | 
    
         | 
| 
       60 
97 
     | 
    
         
             
                  webrickv = WEBrick::VERSION
         
     | 
| 
         @@ -63,9 +100,10 @@ module WEBrick 
     | 
|
| 
       63 
100 
     | 
    
         
             
                  @logger.info("ruby #{rubyv}")
         
     | 
| 
       64 
101 
     | 
    
         | 
| 
       65 
102 
     | 
    
         
             
                  @listeners = []
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @shutdown_pipe = nil
         
     | 
| 
       66 
104 
     | 
    
         
             
                  unless @config[:DoNotListen]
         
     | 
| 
       67 
105 
     | 
    
         
             
                    if @config[:Listen]
         
     | 
| 
       68 
     | 
    
         
            -
                      warn(":Listen option is deprecated; use GenericServer#listen")
         
     | 
| 
      
 106 
     | 
    
         
            +
                      warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
         
     | 
| 
       69 
107 
     | 
    
         
             
                    end
         
     | 
| 
       70 
108 
     | 
    
         
             
                    listen(@config[:BindAddress], @config[:Port])
         
     | 
| 
       71 
109 
     | 
    
         
             
                    if @config[:Port] == 0
         
     | 
| 
         @@ -74,108 +112,176 @@ module WEBrick 
     | 
|
| 
       74 
112 
     | 
    
         
             
                  end
         
     | 
| 
       75 
113 
     | 
    
         
             
                end
         
     | 
| 
       76 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                ##
         
     | 
| 
      
 116 
     | 
    
         
            +
                # Retrieves +key+ from the configuration
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       77 
118 
     | 
    
         
             
                def [](key)
         
     | 
| 
       78 
119 
     | 
    
         
             
                  @config[key]
         
     | 
| 
       79 
120 
     | 
    
         
             
                end
         
     | 
| 
       80 
121 
     | 
    
         | 
| 
      
 122 
     | 
    
         
            +
                ##
         
     | 
| 
      
 123 
     | 
    
         
            +
                # Adds listeners from +address+ and +port+ to the server.  See
         
     | 
| 
      
 124 
     | 
    
         
            +
                # WEBrick::Utils::create_listeners for details.
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
       81 
126 
     | 
    
         
             
                def listen(address, port)
         
     | 
| 
       82 
     | 
    
         
            -
                  @listeners += Utils::create_listeners(address, port 
     | 
| 
      
 127 
     | 
    
         
            +
                  @listeners += Utils::create_listeners(address, port)
         
     | 
| 
       83 
128 
     | 
    
         
             
                end
         
     | 
| 
       84 
129 
     | 
    
         | 
| 
      
 130 
     | 
    
         
            +
                ##
         
     | 
| 
      
 131 
     | 
    
         
            +
                # Starts the server and runs the +block+ for each connection.  This method
         
     | 
| 
      
 132 
     | 
    
         
            +
                # does not return until the server is stopped from a signal handler or
         
     | 
| 
      
 133 
     | 
    
         
            +
                # another thread using #stop or #shutdown.
         
     | 
| 
      
 134 
     | 
    
         
            +
                #
         
     | 
| 
      
 135 
     | 
    
         
            +
                # If the block raises a subclass of StandardError the exception is logged
         
     | 
| 
      
 136 
     | 
    
         
            +
                # and ignored.  If an IOError or Errno::EBADF exception is raised the
         
     | 
| 
      
 137 
     | 
    
         
            +
                # exception is ignored.  If an Exception subclass is raised the exception
         
     | 
| 
      
 138 
     | 
    
         
            +
                # is logged and re-raised which stops the server.
         
     | 
| 
      
 139 
     | 
    
         
            +
                #
         
     | 
| 
      
 140 
     | 
    
         
            +
                # To completely shut down a server call #shutdown from ensure:
         
     | 
| 
      
 141 
     | 
    
         
            +
                #
         
     | 
| 
      
 142 
     | 
    
         
            +
                #   server = WEBrick::GenericServer.new
         
     | 
| 
      
 143 
     | 
    
         
            +
                #   # or WEBrick::HTTPServer.new
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                #   begin
         
     | 
| 
      
 146 
     | 
    
         
            +
                #     server.start
         
     | 
| 
      
 147 
     | 
    
         
            +
                #   ensure
         
     | 
| 
      
 148 
     | 
    
         
            +
                #     server.shutdown
         
     | 
| 
      
 149 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
       85 
151 
     | 
    
         
             
                def start(&block)
         
     | 
| 
       86 
152 
     | 
    
         
             
                  raise ServerError, "already started." if @status != :Stop
         
     | 
| 
       87 
153 
     | 
    
         
             
                  server_type = @config[:ServerType] || SimpleServer
         
     | 
| 
       88 
154 
     | 
    
         | 
| 
      
 155 
     | 
    
         
            +
                  setup_shutdown_pipe
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
       89 
157 
     | 
    
         
             
                  server_type.start{
         
     | 
| 
       90 
158 
     | 
    
         
             
                    @logger.info \
         
     | 
| 
       91 
159 
     | 
    
         
             
                      "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
         
     | 
| 
      
 160 
     | 
    
         
            +
                    @status = :Running
         
     | 
| 
       92 
161 
     | 
    
         
             
                    call_callback(:StartCallback)
         
     | 
| 
       93 
162 
     | 
    
         | 
| 
      
 163 
     | 
    
         
            +
                    shutdown_pipe = @shutdown_pipe
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
       94 
165 
     | 
    
         
             
                    thgroup = ThreadGroup.new
         
     | 
| 
       95 
     | 
    
         
            -
                     
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                          svrs[ 
     | 
| 
       100 
     | 
    
         
            -
                             
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                               
     | 
| 
       103 
     | 
    
         
            -
                               
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                               
     | 
| 
       106 
     | 
    
         
            -
                            else
         
     | 
| 
       107 
     | 
    
         
            -
                              @tokens.push(nil)
         
     | 
| 
      
 166 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 167 
     | 
    
         
            +
                      while @status == :Running
         
     | 
| 
      
 168 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 169 
     | 
    
         
            +
                          sp = shutdown_pipe[0]
         
     | 
| 
      
 170 
     | 
    
         
            +
                          if svrs = IO.select([sp, *@listeners])
         
     | 
| 
      
 171 
     | 
    
         
            +
                            if svrs[0].include? sp
         
     | 
| 
      
 172 
     | 
    
         
            +
                              # swallow shutdown pipe
         
     | 
| 
      
 173 
     | 
    
         
            +
                              buf = String.new
         
     | 
| 
      
 174 
     | 
    
         
            +
                              nil while String ===
         
     | 
| 
      
 175 
     | 
    
         
            +
                                        sp.read_nonblock([sp.nread, 8].max, buf, exception: false)
         
     | 
| 
      
 176 
     | 
    
         
            +
                              break
         
     | 
| 
       108 
177 
     | 
    
         
             
                            end
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
      
 178 
     | 
    
         
            +
                            svrs[0].each{|svr|
         
     | 
| 
      
 179 
     | 
    
         
            +
                              @tokens.pop          # blocks while no token is there.
         
     | 
| 
      
 180 
     | 
    
         
            +
                              if sock = accept_client(svr)
         
     | 
| 
      
 181 
     | 
    
         
            +
                                unless config[:DoNotReverseLookup].nil?
         
     | 
| 
      
 182 
     | 
    
         
            +
                                  sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup]
         
     | 
| 
      
 183 
     | 
    
         
            +
                                end
         
     | 
| 
      
 184 
     | 
    
         
            +
                                th = start_thread(sock, &block)
         
     | 
| 
      
 185 
     | 
    
         
            +
                                th[:WEBrickThread] = true
         
     | 
| 
      
 186 
     | 
    
         
            +
                                thgroup.add(th)
         
     | 
| 
      
 187 
     | 
    
         
            +
                              else
         
     | 
| 
      
 188 
     | 
    
         
            +
                                @tokens.push(nil)
         
     | 
| 
      
 189 
     | 
    
         
            +
                              end
         
     | 
| 
      
 190 
     | 
    
         
            +
                            }
         
     | 
| 
      
 191 
     | 
    
         
            +
                          end
         
     | 
| 
      
 192 
     | 
    
         
            +
                        rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex
         
     | 
| 
      
 193 
     | 
    
         
            +
                          # if the listening socket was closed in GenericServer#shutdown,
         
     | 
| 
      
 194 
     | 
    
         
            +
                          # IO::select raise it.
         
     | 
| 
      
 195 
     | 
    
         
            +
                        rescue StandardError => ex
         
     | 
| 
      
 196 
     | 
    
         
            +
                          msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
         
     | 
| 
      
 197 
     | 
    
         
            +
                          @logger.error msg
         
     | 
| 
      
 198 
     | 
    
         
            +
                        rescue Exception => ex
         
     | 
| 
      
 199 
     | 
    
         
            +
                          @logger.fatal ex
         
     | 
| 
      
 200 
     | 
    
         
            +
                          raise
         
     | 
| 
       110 
201 
     | 
    
         
             
                        end
         
     | 
| 
       111 
     | 
    
         
            -
                      rescue Errno::EBADF, IOError => ex
         
     | 
| 
       112 
     | 
    
         
            -
                        # if the listening socket was closed in GenericServer#shutdown,
         
     | 
| 
       113 
     | 
    
         
            -
                        # IO::select raise it.
         
     | 
| 
       114 
     | 
    
         
            -
                      rescue Exception => ex
         
     | 
| 
       115 
     | 
    
         
            -
                        msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
         
     | 
| 
       116 
     | 
    
         
            -
                        @logger.error msg
         
     | 
| 
       117 
202 
     | 
    
         
             
                      end
         
     | 
| 
      
 203 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 204 
     | 
    
         
            +
                      cleanup_shutdown_pipe(shutdown_pipe)
         
     | 
| 
      
 205 
     | 
    
         
            +
                      cleanup_listener
         
     | 
| 
      
 206 
     | 
    
         
            +
                      @status = :Shutdown
         
     | 
| 
      
 207 
     | 
    
         
            +
                      @logger.info "going to shutdown ..."
         
     | 
| 
      
 208 
     | 
    
         
            +
                      thgroup.list.each{|th| th.join if th[:WEBrickThread] }
         
     | 
| 
      
 209 
     | 
    
         
            +
                      call_callback(:StopCallback)
         
     | 
| 
      
 210 
     | 
    
         
            +
                      @logger.info "#{self.class}#start done."
         
     | 
| 
      
 211 
     | 
    
         
            +
                      @status = :Stop
         
     | 
| 
       118 
212 
     | 
    
         
             
                    end
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
                    @logger.info "going to shutdown ..."
         
     | 
| 
       121 
     | 
    
         
            -
                    thgroup.list.each{|th| th.join if th[:WEBrickThread] }
         
     | 
| 
       122 
     | 
    
         
            -
                    call_callback(:StopCallback)
         
     | 
| 
       123 
     | 
    
         
            -
                    @logger.info "#{self.class}#start done."
         
     | 
| 
       124 
     | 
    
         
            -
                    @status = :Stop
         
     | 
| 
       125 
213 
     | 
    
         
             
                  }
         
     | 
| 
       126 
214 
     | 
    
         
             
                end
         
     | 
| 
       127 
215 
     | 
    
         | 
| 
      
 216 
     | 
    
         
            +
                ##
         
     | 
| 
      
 217 
     | 
    
         
            +
                # Stops the server from accepting new connections.
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
       128 
219 
     | 
    
         
             
                def stop
         
     | 
| 
       129 
220 
     | 
    
         
             
                  if @status == :Running
         
     | 
| 
       130 
221 
     | 
    
         
             
                    @status = :Shutdown
         
     | 
| 
       131 
222 
     | 
    
         
             
                  end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                  alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
         
     | 
| 
       132 
225 
     | 
    
         
             
                end
         
     | 
| 
       133 
226 
     | 
    
         | 
| 
      
 227 
     | 
    
         
            +
                ##
         
     | 
| 
      
 228 
     | 
    
         
            +
                # Shuts down the server and all listening sockets.  New listeners must be
         
     | 
| 
      
 229 
     | 
    
         
            +
                # provided to restart the server.
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
       134 
231 
     | 
    
         
             
                def shutdown
         
     | 
| 
       135 
232 
     | 
    
         
             
                  stop
         
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                      addr = s.addr
         
     | 
| 
       139 
     | 
    
         
            -
                      @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
         
     | 
| 
       140 
     | 
    
         
            -
                    end
         
     | 
| 
       141 
     | 
    
         
            -
                    begin
         
     | 
| 
       142 
     | 
    
         
            -
                      s.shutdown
         
     | 
| 
       143 
     | 
    
         
            -
                    rescue Errno::ENOTCONN
         
     | 
| 
       144 
     | 
    
         
            -
                      # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
         
     | 
| 
       145 
     | 
    
         
            -
                      # call #close instead of #shutdown.
         
     | 
| 
       146 
     | 
    
         
            -
                      # (ignore @config[:ShutdownSocketWithoutClose])
         
     | 
| 
       147 
     | 
    
         
            -
                      s.close
         
     | 
| 
       148 
     | 
    
         
            -
                    else
         
     | 
| 
       149 
     | 
    
         
            -
                      unless @config[:ShutdownSocketWithoutClose]
         
     | 
| 
       150 
     | 
    
         
            -
                        s.close
         
     | 
| 
       151 
     | 
    
         
            -
                      end
         
     | 
| 
       152 
     | 
    
         
            -
                    end
         
     | 
| 
       153 
     | 
    
         
            -
                  }
         
     | 
| 
       154 
     | 
    
         
            -
                  @listeners.clear
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  alarm_shutdown_pipe(&:close)
         
     | 
| 
       155 
235 
     | 
    
         
             
                end
         
     | 
| 
       156 
236 
     | 
    
         | 
| 
      
 237 
     | 
    
         
            +
                ##
         
     | 
| 
      
 238 
     | 
    
         
            +
                # You must subclass GenericServer and implement \#run which accepts a TCP
         
     | 
| 
      
 239 
     | 
    
         
            +
                # client socket
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
       157 
241 
     | 
    
         
             
                def run(sock)
         
     | 
| 
       158 
242 
     | 
    
         
             
                  @logger.fatal "run() must be provided by user."
         
     | 
| 
       159 
243 
     | 
    
         
             
                end
         
     | 
| 
       160 
244 
     | 
    
         | 
| 
       161 
245 
     | 
    
         
             
                private
         
     | 
| 
       162 
246 
     | 
    
         | 
| 
      
 247 
     | 
    
         
            +
                # :stopdoc:
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                ##
         
     | 
| 
      
 250 
     | 
    
         
            +
                # Accepts a TCP client socket from the TCP server socket +svr+ and returns
         
     | 
| 
      
 251 
     | 
    
         
            +
                # the client socket.
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
       163 
253 
     | 
    
         
             
                def accept_client(svr)
         
     | 
| 
       164 
     | 
    
         
            -
                  sock =  
     | 
| 
       165 
     | 
    
         
            -
                   
     | 
| 
       166 
     | 
    
         
            -
                     
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
                     
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
             
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
                     
     | 
| 
      
 254 
     | 
    
         
            +
                  case sock = svr.to_io.accept_nonblock(exception: false)
         
     | 
| 
      
 255 
     | 
    
         
            +
                  when :wait_readable
         
     | 
| 
      
 256 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 257 
     | 
    
         
            +
                  else
         
     | 
| 
      
 258 
     | 
    
         
            +
                    if svr.respond_to?(:start_immediately)
         
     | 
| 
      
 259 
     | 
    
         
            +
                      sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
         
     | 
| 
      
 260 
     | 
    
         
            +
                      sock.sync_close = true
         
     | 
| 
      
 261 
     | 
    
         
            +
                      # we cannot do OpenSSL::SSL::SSLSocket#accept here because
         
     | 
| 
      
 262 
     | 
    
         
            +
                      # a slow client can prevent us from accepting connections
         
     | 
| 
      
 263 
     | 
    
         
            +
                      # from other clients
         
     | 
| 
      
 264 
     | 
    
         
            +
                    end
         
     | 
| 
      
 265 
     | 
    
         
            +
                    sock
         
     | 
| 
       175 
266 
     | 
    
         
             
                  end
         
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
      
 267 
     | 
    
         
            +
                rescue Errno::ECONNRESET, Errno::ECONNABORTED,
         
     | 
| 
      
 268 
     | 
    
         
            +
                       Errno::EPROTO, Errno::EINVAL
         
     | 
| 
      
 269 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 270 
     | 
    
         
            +
                rescue StandardError => ex
         
     | 
| 
      
 271 
     | 
    
         
            +
                  msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
         
     | 
| 
      
 272 
     | 
    
         
            +
                  @logger.error msg
         
     | 
| 
      
 273 
     | 
    
         
            +
                  nil
         
     | 
| 
       177 
274 
     | 
    
         
             
                end
         
     | 
| 
       178 
275 
     | 
    
         | 
| 
      
 276 
     | 
    
         
            +
                ##
         
     | 
| 
      
 277 
     | 
    
         
            +
                # Starts a server thread for the client socket +sock+ that runs the given
         
     | 
| 
      
 278 
     | 
    
         
            +
                # +block+.
         
     | 
| 
      
 279 
     | 
    
         
            +
                #
         
     | 
| 
      
 280 
     | 
    
         
            +
                # Sets the socket to the <code>:WEBrickSocket</code> thread local variable
         
     | 
| 
      
 281 
     | 
    
         
            +
                # in the thread.
         
     | 
| 
      
 282 
     | 
    
         
            +
                #
         
     | 
| 
      
 283 
     | 
    
         
            +
                # If any errors occur in the block they are logged and handled.
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
       179 
285 
     | 
    
         
             
                def start_thread(sock, &block)
         
     | 
| 
       180 
286 
     | 
    
         
             
                  Thread.start{
         
     | 
| 
       181 
287 
     | 
    
         
             
                    begin
         
     | 
| 
         @@ -187,6 +293,16 @@ module WEBrick 
     | 
|
| 
       187 
293 
     | 
    
         
             
                        @logger.debug "accept: <address unknown>"
         
     | 
| 
       188 
294 
     | 
    
         
             
                        raise
         
     | 
| 
       189 
295 
     | 
    
         
             
                      end
         
     | 
| 
      
 296 
     | 
    
         
            +
                      if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately]
         
     | 
| 
      
 297 
     | 
    
         
            +
                        WEBrick::Utils.timeout(@config[:RequestTimeout]) do
         
     | 
| 
      
 298 
     | 
    
         
            +
                          begin
         
     | 
| 
      
 299 
     | 
    
         
            +
                            sock.accept # OpenSSL::SSL::SSLSocket#accept
         
     | 
| 
      
 300 
     | 
    
         
            +
                          rescue Errno::ECONNRESET, Errno::ECONNABORTED,
         
     | 
| 
      
 301 
     | 
    
         
            +
                                 Errno::EPROTO, Errno::EINVAL
         
     | 
| 
      
 302 
     | 
    
         
            +
                            Thread.exit
         
     | 
| 
      
 303 
     | 
    
         
            +
                          end
         
     | 
| 
      
 304 
     | 
    
         
            +
                        end
         
     | 
| 
      
 305 
     | 
    
         
            +
                      end
         
     | 
| 
       190 
306 
     | 
    
         
             
                      call_callback(:AcceptCallback, sock)
         
     | 
| 
       191 
307 
     | 
    
         
             
                      block ? block.call(sock) : run(sock)
         
     | 
| 
       192 
308 
     | 
    
         
             
                    rescue Errno::ENOTCONN
         
     | 
| 
         @@ -209,10 +325,54 @@ module WEBrick 
     | 
|
| 
       209 
325 
     | 
    
         
             
                  }
         
     | 
| 
       210 
326 
     | 
    
         
             
                end
         
     | 
| 
       211 
327 
     | 
    
         | 
| 
      
 328 
     | 
    
         
            +
                ##
         
     | 
| 
      
 329 
     | 
    
         
            +
                # Calls the callback +callback_name+ from the configuration with +args+
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
       212 
331 
     | 
    
         
             
                def call_callback(callback_name, *args)
         
     | 
| 
       213 
     | 
    
         
            -
                   
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
      
 332 
     | 
    
         
            +
                  @config[callback_name]&.call(*args)
         
     | 
| 
      
 333 
     | 
    
         
            +
                end
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
                def setup_shutdown_pipe
         
     | 
| 
      
 336 
     | 
    
         
            +
                  return @shutdown_pipe ||= IO.pipe
         
     | 
| 
      
 337 
     | 
    
         
            +
                end
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                def cleanup_shutdown_pipe(shutdown_pipe)
         
     | 
| 
      
 340 
     | 
    
         
            +
                  @shutdown_pipe = nil
         
     | 
| 
      
 341 
     | 
    
         
            +
                  shutdown_pipe&.each(&:close)
         
     | 
| 
      
 342 
     | 
    
         
            +
                end
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
                def alarm_shutdown_pipe
         
     | 
| 
      
 345 
     | 
    
         
            +
                  _, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe.
         
     | 
| 
      
 346 
     | 
    
         
            +
                  if pipe
         
     | 
| 
      
 347 
     | 
    
         
            +
                    if !pipe.closed?
         
     | 
| 
      
 348 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 349 
     | 
    
         
            +
                        yield pipe
         
     | 
| 
      
 350 
     | 
    
         
            +
                      rescue IOError # closed by another thread.
         
     | 
| 
      
 351 
     | 
    
         
            +
                      end
         
     | 
| 
      
 352 
     | 
    
         
            +
                    end
         
     | 
| 
       215 
353 
     | 
    
         
             
                  end
         
     | 
| 
       216 
354 
     | 
    
         
             
                end
         
     | 
| 
      
 355 
     | 
    
         
            +
             
     | 
| 
      
 356 
     | 
    
         
            +
                def cleanup_listener
         
     | 
| 
      
 357 
     | 
    
         
            +
                  @listeners.each{|s|
         
     | 
| 
      
 358 
     | 
    
         
            +
                    if @logger.debug?
         
     | 
| 
      
 359 
     | 
    
         
            +
                      addr = s.addr
         
     | 
| 
      
 360 
     | 
    
         
            +
                      @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
         
     | 
| 
      
 361 
     | 
    
         
            +
                    end
         
     | 
| 
      
 362 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 363 
     | 
    
         
            +
                      s.shutdown
         
     | 
| 
      
 364 
     | 
    
         
            +
                    rescue Errno::ENOTCONN
         
     | 
| 
      
 365 
     | 
    
         
            +
                      # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
         
     | 
| 
      
 366 
     | 
    
         
            +
                      # call #close instead of #shutdown.
         
     | 
| 
      
 367 
     | 
    
         
            +
                      # (ignore @config[:ShutdownSocketWithoutClose])
         
     | 
| 
      
 368 
     | 
    
         
            +
                      s.close
         
     | 
| 
      
 369 
     | 
    
         
            +
                    else
         
     | 
| 
      
 370 
     | 
    
         
            +
                      unless @config[:ShutdownSocketWithoutClose]
         
     | 
| 
      
 371 
     | 
    
         
            +
                        s.close
         
     | 
| 
      
 372 
     | 
    
         
            +
                      end
         
     | 
| 
      
 373 
     | 
    
         
            +
                    end
         
     | 
| 
      
 374 
     | 
    
         
            +
                  }
         
     | 
| 
      
 375 
     | 
    
         
            +
                  @listeners.clear
         
     | 
| 
      
 376 
     | 
    
         
            +
                end
         
     | 
| 
       217 
377 
     | 
    
         
             
              end    # end of GenericServer
         
     | 
| 
       218 
378 
     | 
    
         
             
            end
         
     |