| Class | WEBrick::GenericServer |
| In: |
lib/webrick/server.rb
lib/webrick/ssl.rb |
| Parent: | Object |
| config | [R] | |
| listeners | [R] | |
| logger | [R] | |
| status | [R] | |
| tokens | [R] |
# 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
# File lib/webrick/server.rb, line 74
74: def listen(address, port)
75: @listeners += Utils::create_listeners(address, port, @logger)
76: end
# 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
# File lib/webrick/server.rb, line 138
138: def run(sock)
139: @logger.fatal "run() must be provided by user."
140: end
# 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
# 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
# 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
# File lib/webrick/server.rb, line 120
120: def stop
121: if @status == :Running
122: @status = :Shutdown
123: end
124: end
# 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
# 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
# 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