Class WEBrick::GenericServer
In: lib/webrick/server.rb
lib/webrick/ssl.rb
Parent: Object

Methods

Attributes

config  [R] 
listeners  [R] 
logger  [R] 
status  [R] 
tokens  [R] 

Public Class methods

[Source]

    # File lib/webrick/server.rb, line 44
44:     def initialize(config={}, default=Config::General)
45:       @config = default.dup.update(config)
46:       @status = :Stop
47:       @config[:Logger] ||= Log::new
48:       @logger = @config[:Logger]
49: 
50:       @tokens = SizedQueue.new(@config[:MaxClients])
51:       @config[:MaxClients].times{ @tokens.push(nil) }
52: 
53:       webrickv = WEBrick::VERSION
54:       rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
55:       @logger.info("WEBrick #{webrickv}")
56:       @logger.info("ruby #{rubyv}")
57: 
58:       @listeners = []
59:       unless @config[:DoNotListen]
60:         if @config[:Listen]
61:           warn(":Listen option is deprecated; use GenericServer#listen")
62:         end
63:         listen(@config[:BindAddress], @config[:Port])
64:         if @config[:Port] == 0
65:           @config[:Port] = @listeners[0].addr[1]
66:         end
67:       end
68:     end

Public Instance methods

[Source]

    # File lib/webrick/server.rb, line 70
70:     def [](key)
71:       @config[key]
72:     end

[Source]

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

[Source]

     # File lib/webrick/ssl.rb, line 86
 86:     def listen(address, port)
 87:       listeners = Utils::create_listeners(address, port, @logger)
 88:       if @config[:SSLEnable]
 89:         unless ssl_context
 90:           @ssl_context = setup_ssl_context(@config)
 91:           @logger.info("\n" + @config[:SSLCertificate].to_text) 
 92:         end
 93:         listeners.collect!{|svr|
 94:           ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
 95:           ssvr.start_immediately = @config[:SSLStartImmediately]
 96:           ssvr
 97:         }
 98:       end
 99:       @listeners += listeners
100:     end

[Source]

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

[Source]

     # File lib/webrick/ssl.rb, line 102
102:     def setup_ssl_context(config)
103:       unless config[:SSLCertificate]
104:         cn = config[:SSLCertName]
105:         comment = config[:SSLCertComment]
106:         cert, key = Utils::create_self_signed_cert(1024, cn, comment)
107:         config[:SSLCertificate] = cert
108:         config[:SSLPrivateKey] = key
109:       end
110:       ctx = OpenSSL::SSL::SSLContext.new
111:       ctx.key = config[:SSLPrivateKey]
112:       ctx.cert = config[:SSLCertificate]
113:       ctx.client_ca = config[:SSLClientCA]
114:       ctx.extra_chain_cert = config[:SSLExtraChainCert]
115:       ctx.ca_file = config[:SSLCACertificateFile]
116:       ctx.ca_path = config[:SSLCACertificatePath]
117:       ctx.cert_store = config[:SSLCertificateStore]
118:       ctx.verify_mode = config[:SSLVerifyClient]
119:       ctx.verify_depth = config[:SSLVerifyDepth]
120:       ctx.verify_callback = config[:SSLVerifyCallback]
121:       ctx.timeout = config[:SSLTimeout]
122:       ctx.options = config[:SSLOptions]
123:       ctx
124:     end

[Source]

     # File lib/webrick/server.rb, line 126
126:     def shutdown
127:       stop
128:       @listeners.each{|s|
129:         if @logger.debug?
130:           addr = s.addr
131:           @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
132:         end
133:         s.close
134:       }
135:       @listeners.clear
136:     end

[Source]

    # File lib/webrick/ssl.rb, line 82
82:     def ssl_context
83:       @ssl_context ||= nil
84:     end

[Source]

     # File lib/webrick/server.rb, line 78
 78:     def start(&block)
 79:       raise ServerError, "already started." if @status != :Stop
 80:       server_type = @config[:ServerType] || SimpleServer
 81: 
 82:       server_type.start{
 83:         @logger.info \
 84:           "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
 85:         call_callback(:StartCallback)
 86: 
 87:         thgroup = ThreadGroup.new
 88:         @status = :Running
 89:         while @status == :Running
 90:           begin
 91:             if svrs = IO.select(@listeners, nil, nil, 2.0)
 92:               svrs[0].each{|svr|
 93:                 @tokens.pop          # blocks while no token is there.
 94:                 if sock = accept_client(svr)
 95:                   th = start_thread(sock, &block)
 96:                   th[:WEBrickThread] = true
 97:                   thgroup.add(th)
 98:                 else
 99:                   @tokens.push(nil)
100:                 end
101:               }
102:             end
103:           rescue Errno::EBADF, IOError => ex
104:             # if the listening socket was closed in GenericServer#shutdown,
105:             # IO::select raise it.
106:           rescue Exception => ex
107:             msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
108:             @logger.error msg
109:           end
110:         end
111: 
112:         @logger.info "going to shutdown ..."
113:         thgroup.list.each{|th| th.join if th[:WEBrickThread] }
114:         call_callback(:StopCallback)
115:         @logger.info "#{self.class}#start done."
116:         @status = :Stop
117:       }
118:     end

[Source]

     # File lib/webrick/server.rb, line 120
120:     def stop
121:       if @status == :Running
122:         @status = :Shutdown
123:       end
124:     end

Private Instance methods

[Source]

     # File lib/webrick/server.rb, line 144
144:     def accept_client(svr)
145:       sock = nil
146:       begin
147:         sock = svr.accept
148:         sock.sync = true
149:         Utils::set_non_blocking(sock)
150:         Utils::set_close_on_exec(sock)
151:       rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPROTO => ex
152:         # TCP connection was established but RST segment was sent
153:         # from peer before calling TCPServer#accept.
154:       rescue Exception => ex
155:         msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
156:         @logger.error msg
157:       end
158:       return sock
159:     end

[Source]

     # File lib/webrick/server.rb, line 194
194:     def call_callback(callback_name, *args)
195:       if cb = @config[callback_name]
196:         cb.call(*args)
197:       end
198:     end

[Source]

     # File lib/webrick/server.rb, line 161
161:     def start_thread(sock, &block)
162:       Thread.start{
163:         begin
164:           Thread.current[:WEBrickSocket] = sock
165:           begin
166:             addr = sock.peeraddr
167:             @logger.debug "accept: #{addr[3]}:#{addr[1]}"
168:           rescue SocketError
169:             @logger.debug "accept: <address unknown>"
170:             raise
171:           end
172:           call_callback(:AcceptCallback, sock)
173:           block ? block.call(sock) : run(sock)
174:         rescue Errno::ENOTCONN
175:           @logger.debug "Errno::ENOTCONN raised"
176:         rescue ServerError => ex
177:           msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
178:           @logger.error msg
179:         rescue Exception => ex
180:           @logger.error ex
181:         ensure
182:           @tokens.push(nil)
183:           Thread.current[:WEBrickSocket] = nil
184:           if addr
185:             @logger.debug "close: #{addr[3]}:#{addr[1]}"
186:           else
187:             @logger.debug "close: <address unknown>"
188:           end
189:           sock.close
190:         end
191:       }
192:     end

[Validate]