From 79a66d1289d8d3c247c1caff1164df1cdd0abc43 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Mon, 17 Aug 2015 09:22:29 +0900 Subject: [PATCH 01/26] Replace proxy server implementation --- lib/pacproxy/pacproxy.rb | 251 +++++++++++++++------------------------ spec/spec_helper.rb | 2 + 2 files changed, 101 insertions(+), 152 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 7a71706..249bf73 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -1,14 +1,23 @@ require 'pacproxy' -require 'webrick/httpproxy' +require 'socket' require 'uri' module Pacproxy # Pacproxy::Pacproxy represent http/https proxy server - class Pacproxy < WEBrick::HTTPProxyServer # rubocop:disable ClassLength + class Pacproxy include Loggable - def initialize(config = {}, default = WEBrick::Config::HTTP) - super({ Port: config['port'], Logger: general_logger }, default) + attr_reader :status + + REQUEST_LINE_REGEXP = + /^(?\w+)\s+(?\S+)\s+HTTP\/(?\d\.\d)\s*$/ + BUFFER_SIZE = 1024 * 16 + + def initialize(config = {}) + # TODO: Logger + @status = :Stop + @host = config['host'] + @port = config['port'] @auth = config['auth'] return unless config['pac_file'] && config['pac_file']['location'] @@ -16,140 +25,112 @@ def initialize(config = {}, default = WEBrick::Config::HTTP) config['pac_file']['update_interval']) end + def start + @socket = TCPServer.new(@host, @port) + @status = :Running + loop do + s = @socket.accept + Thread.new(s, &method(:handle_request)) + end + ensure + shutdown + end + def shutdown + @socket.close if @socket @pac.shutdown if @pac - super + @status = :Stop end - def proxy_uri(req, res) - super(req, res) - return unless @pac - - proxy_line = @pac.find(request_uri(req)) - proxy = lookup_proxy_uri(proxy_line) - create_proxy_uri(proxy, req.header) - end + private - def create_proxy_uri(proxy, header) - return nil unless proxy - return URI.parse("http://#{proxy}") unless - @auth || header.key?('proxy-authorization') - - if @auth - basic_auth = "#{@auth['user']}:#{@auth['password']}" - elsif header.key?('proxy-authorization') - auth = header['proxy-authorization'][0] - pattern = /basic (\S+)/i - basic_auth = pattern.match(auth)[1].unpack('m').first - header.delete('proxy-authorization') + def handle_request(client_s) + request_line = client_s.readline + match_result = request_line.match(REQUEST_LINE_REGEXP) + method = match_result[:method] + unparsed_uri = match_result[:unparsed_uri] + version = match_result[:version] + + proxy = if method == 'CONNECT' + @pac.find("https://#{unparsed_uri}") + else + @pac.find(unparsed_uri) + end + # TODO: recover + if method == 'CONNECT' && proxy == 'DIRECT' + do_connect(client_s, method, unparsed_uri, version) + else + unparsed_uri = "https://#{unparsed_uri}" if method == 'CONNECT' + do_request(client_s, method, unparsed_uri, version, proxy) end - - URI.parse("http://#{basic_auth}@#{proxy}") end - # This method is mainly from WEBrick::HTTPProxyServer. - # To allow upstream proxy authentication, - # it operate 407 response from an upstream proxy. - # see: https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpproxy.rb - # rubocop:disable all - def do_CONNECT(req, res) - # Proxy Authentication - proxy_auth(req, res) - - ua = Thread.current[:WEBrickSocket] # User-Agent - raise WEBrick::HTTPStatus::InternalServerError, - "[BUG] cannot get socket" unless ua - - host, port = req.unparsed_uri.split(":", 2) - # Proxy authentication for upstream proxy server - if proxy = proxy_uri(req, res) - proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0" - if proxy.userinfo - credentials = "Basic " + [proxy.userinfo].pack("m").delete("\n") - end - host, port = proxy.host, proxy.port - end - - begin - @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.") - os = TCPSocket.new(host, port) # origin server - - if proxy - @logger.debug("CONNECT: sending a Request-Line") - os << proxy_request_line << WEBrick::CRLF - @logger.debug("CONNECT: > #{proxy_request_line}") - if credentials - @logger.debug("CONNECT: sending a credentials") - os << "Proxy-Authorization: " << credentials << WEBrick::CRLF - end - os << WEBrick::CRLF - proxy_status_line = os.gets(WEBrick::LF) - @logger.debug("CONNECT: read a Status-Line form the upstream server") - @logger.debug("CONNECT: < #{proxy_status_line}") - if /^HTTP\/\d+\.\d+\s+(?200|407)\s*/ =~ proxy_status_line - res.status = st.to_i - while line = os.gets(WEBrick::LF) - res.header['Proxy-Authenticate'] = - line.split(':')[1] if /Proxy-Authenticate/i =~ line - break if /\A(#{WEBrick::CRLF}|#{WEBrick::LF})\z/om =~ line - end - else - raise WEBrick::HTTPStatus::BadGateway - end - end - @logger.debug("CONNECT #{host}:#{port}: succeeded") - rescue => ex - @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'") - res.set_error(ex) - raise WEBrick::HTTPStatus::EOFError - ensure - if handler = @config[:ProxyContentHandler] - handler.call(req, res) - end - res.send_response(ua) - accesslog(req, res) - - # Should clear request-line not to send the response twice. - # see: HTTPServer#run - req.parse(WEBrick::NullReader) rescue nil + def do_request(client_s, method, unparsed_uri, version, proxy) + if proxy =~ /^proxy/i + host, port = find_proxy_uri(proxy).split(':') + port ||= 80 + server_s = TCPSocket.new(host, port) + server_s.write("#{method} #{unparsed_uri} HTTP/#{version}\r\n") + write_proxy_credential(server_s) + else + uri = URI.parse(unparsed_uri) + # TODO: recover + server_s = TCPSocket.new(uri.host, uri.port) + server_s.write("#{method} #{uri.path}?#{uri.query} HTTP/#{version}\r\n") end - begin - while fds = IO::select([ua, os]) - if fds[0].member?(ua) - buf = ua.sysread(1024); - @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent") - os.syswrite(buf) - elsif fds[0].member?(os) - buf = os.sysread(1024); - @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}") - ua.syswrite(buf) - end + # TODO: write log + loop do + line = client_s.readline + if line =~ /^proxy/i && proxy == 'DIRECT' + # Strip proxy headers + next + elsif line.strip.empty? + server_s.write("Connection: close\r\n\r\n") + break + else + server_s.write(line) end - rescue - os.close - @logger.debug("CONNECT #{host}:#{port}: closed") end - raise WEBrick::HTTPStatus::EOFError + transfer_data(client_s, server_s) + ensure + client_s.close + server_s.close end - # rubocop:enable all - def proxy_auth(req, res) - @config[:ProxyAuthProc].call(req, res) if @config[:ProxyAuthProc] + def do_connect(client_s, _method, unparsed_uri, _version) + uri = URI.parse("https://#{unparsed_uri}") + # TODO: recover + server_s = TCPSocket.new(uri.host, uri.port) + client_s.read_nonblock(BUFFER_SIZE) + client_s.write("HTTP/1.0 200 Connection Established\r\n\r\n") + + # TODO: write log + transfer_data(client_s, server_s) + ensure + client_s.close + server_s.close end - private - - def request_uri(request) - if 'CONNECT' == request.request_method - "https://#{request.unparsed_uri}/" - else - request.unparsed_uri + def transfer_data(client_s, server_s) + while (fds = IO.select([client_s, server_s])) + if fds[0].member?(client_s) + server_s.write(client_s.read_nonblock(BUFFER_SIZE)) + elsif fds[0].member?(server_s) + client_s.write(server_s.read_nonblock(BUFFER_SIZE)) + end end end - def lookup_proxy_uri(proxy_line) + def write_proxy_credential(server_s) + return unless @auth + credentials = 'Basic ' + + ["#{@auth['user']}:#{@auth['password']}"].pack('m').delete("\n") + server_s.write('Proxy-authorization: ' + credentials + "\r\n") + end + + def find_proxy_uri(proxy_line) case proxy_line when /^DIRECT/ nil @@ -158,39 +139,5 @@ def lookup_proxy_uri(proxy_line) /PROXY (.*)/.match(primary_proxy)[1] end end - - # This method is mainly from WEBrick::HTTPProxyServer. - # proxy-authenticate can be transferred from a upstream proxy server - # to a client - # see: https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpproxy.rb - HOP_BY_HOP = %w( connection keep-alive upgrade - proxy-authorization te trailers transfer-encoding ) - SHOULD_NOT_TRANSFER = %w( set-cookie proxy-connection ) - def choose_header(src, dst) - connections = split_field(src['connection']) - src.each do |key, value| - key = key.downcase - next if HOP_BY_HOP.member?(key) || # RFC2616: 13.5.1 - connections.member?(key) || # RFC2616: 14.10 - SHOULD_NOT_TRANSFER.member?(key) # pragmatics - - dst[key] = value - end - end - - def perform_proxy_request(req, res) - super - accesslog(req, res) - end - - # allow PUT method on proxy server - # method names for webrick is indicated by rubocop - # rubocop:disable all - def do_PUT(req, res) - perform_proxy_request(req, res) do |http, path, header| - http.put(path, req.body || '', header) - end - end - # rubocop:enable all end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 76191a9..0eab376 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -14,3 +14,5 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'pacproxy' +require 'webrick' +require 'webrick/httpproxy' From 2c626f99399181bcac8f47e3f4a0d5f90d026daa Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Mon, 17 Aug 2015 16:38:24 +0900 Subject: [PATCH 02/26] Change .travis.yml because of indications http://docs.travis-ci.com/user/migrating-from-legacy/ --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f6cdf4f..27156be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,13 @@ +sudo: false language: ruby cache: bundler +addons: + apt: + packages: + - node + before_install: - - 'test Node = "$PACPROXY_RUNTIME" && sudo apt-get update || true' - - 'test Node = "$PACPROXY_RUNTIME" && sudo apt-get install node || true' - 'test Node = "$PACPROXY_RUNTIME" && (cd lib/pacproxy/runtimes/node ; npm install) || true' rvm: From f8475c5b51b8609149e680d6651820581d78daf6 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Tue, 18 Aug 2015 22:02:44 +0900 Subject: [PATCH 03/26] Ignore exception when shuting down no node process running --- lib/pacproxy/runtimes/node/node.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/pacproxy/runtimes/node/node.rb b/lib/pacproxy/runtimes/node/node.rb index eb484ec..ca294a1 100644 --- a/lib/pacproxy/runtimes/node/node.rb +++ b/lib/pacproxy/runtimes/node/node.rb @@ -63,7 +63,11 @@ def shutdown if OS.windows? stop_server(@server_pid) else - Process.kill(:INT, @server_pid) + begin + Process.kill(:INT, @server_pid) + rescue Errno::ESRCH + lwarn('No process is Running.') + end end end @@ -150,7 +154,11 @@ def start_server def stop_server(server_info) require 'win32/process' return unless server_info || server_info.respond_to?(:process_id) - Process.kill('ExitProcess', [server_info.process_id]) + begin + Process.kill('ExitProcess', [server_info.process_id]) + rescue Errno::ESRCH + lwarn('No process is Running.') + end end end end From 2f01a58238194cded833e2f833ab1b451f80cc39 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 22 Aug 2015 15:56:21 +0900 Subject: [PATCH 04/26] Temp add log --- lib/pacproxy/pacproxy.rb | 8 +++++--- spec/pacproxy_spec.rb | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 249bf73..70a8953 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -108,9 +108,6 @@ def do_connect(client_s, _method, unparsed_uri, _version) # TODO: write log transfer_data(client_s, server_s) - ensure - client_s.close - server_s.close end def transfer_data(client_s, server_s) @@ -121,6 +118,11 @@ def transfer_data(client_s, server_s) client_s.write(server_s.read_nonblock(BUFFER_SIZE)) end end + rescue => e + STDOUT.puts('Error' + e) + ensure + server_s.close unless server_s.open? + client_s.close unless client_s.open? end def write_proxy_credential(server_s) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 550e75d..28a9d5f 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -3,6 +3,9 @@ require 'webrick/https' def wait_server_status(servers, status) + STDOUT.puts(status.to_s) + STDOUT + .puts(`netstat -ant | grep tcp4 | grep LISTEN | grep 13| sort`) return unless servers || status servers = [servers] unless servers.respond_to?(:all?) return unless servers.all? { |s| s.respond_to?(:status) } From 9ea84e9845b00b5e21961457fa243cb67024c69e Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Thu, 27 Aug 2015 09:39:09 +0900 Subject: [PATCH 05/26] Temp add a hook for method call --- lib/pacproxy/pacproxy.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 70a8953..b9b5df7 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -2,6 +2,10 @@ require 'socket' require 'uri' +set_trace_func proc { |event, _file, _line, id, _binding, classname| + puts "#{classname} #{id} called" if event == 'call' && !(classname.to_s.include?('SimpleCov')) +} + module Pacproxy # Pacproxy::Pacproxy represent http/https proxy server class Pacproxy From e90a332941aa3ce7ebe9329fc123b23b727aae76 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Thu, 27 Aug 2015 21:17:55 +0900 Subject: [PATCH 06/26] Temp modify output --- lib/pacproxy/pacproxy.rb | 4 ---- spec/pacproxy_spec.rb | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index b9b5df7..70a8953 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -2,10 +2,6 @@ require 'socket' require 'uri' -set_trace_func proc { |event, _file, _line, id, _binding, classname| - puts "#{classname} #{id} called" if event == 'call' && !(classname.to_s.include?('SimpleCov')) -} - module Pacproxy # Pacproxy::Pacproxy represent http/https proxy server class Pacproxy diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 28a9d5f..457a5ae 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -4,8 +4,6 @@ def wait_server_status(servers, status) STDOUT.puts(status.to_s) - STDOUT - .puts(`netstat -ant | grep tcp4 | grep LISTEN | grep 13| sort`) return unless servers || status servers = [servers] unless servers.respond_to?(:all?) return unless servers.all? { |s| s.respond_to?(:status) } @@ -43,15 +41,18 @@ def wait_server_status(servers, status) after(:each) do $stdout, $stderr = STDOUT, STDERR + STDERR.puts 'after called' @http_server.shutdown @https_server.shutdown @proxy_server.shutdown @pacproxy_server.shutdown + STDERR.puts 'shutdwon call done' wait_server_status([@http_server, @https_server, @proxy_server, @pacproxy_server], :Stop) + STDERR.puts 'wait_server_status done' end it 'transfer request to server directly' do From ee6adf274b6456b6d95bf85e0033f9b485efe2b0 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Fri, 28 Aug 2015 08:34:10 +0900 Subject: [PATCH 07/26] Temp Add more log --- spec/pacproxy_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 457a5ae..10b1de9 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -72,20 +72,28 @@ def wait_server_status(servers, status) end it 'transfer request to server directly via HTTPS' do + STDERR.puts 'transfer request to server directly via HTTPS started' c = Pacproxy::Config.instance.config c['port'] = 13_128 c['pac_file']['location'] = 'spec/all_direct.pac' @pacproxy_server = Pacproxy::Pacproxy.new(c) Thread.new { @pacproxy_server.start } wait_server_status(@pacproxy_server, :Running) + STDERR.puts 'pacproxy_server started' + STDERR.puts 'HTTPClient creating' c = HTTPClient.new('http://127.0.0.1:13128') c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE + STDERR.puts 'HTTPClient requesting 1' res = c.get('https://127.0.0.1:13443/') + STDERR.puts 'HTTPClient request 1 done' expect(res.status).to eq(200) + STDERR.puts 'HTTPClient requesting 2' res = c.get('https://127.0.0.1:13443/noproxy/') + STDERR.puts 'HTTPClient request 2 done' expect(res.status).to eq(200) + STDERR.puts 'transfer request to server directly via HTTPS exiting' end it 'transfer request to server directly with PUT method' do From 574f8ec92a38f3c2384cfb508f4cac5915e99274 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Fri, 28 Aug 2015 09:09:39 +0900 Subject: [PATCH 08/26] Add more log --- spec/pacproxy_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 10b1de9..a892b5d 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -74,10 +74,14 @@ def wait_server_status(servers, status) it 'transfer request to server directly via HTTPS' do STDERR.puts 'transfer request to server directly via HTTPS started' c = Pacproxy::Config.instance.config + STDERR.puts 'Pacproxy::Config.instance.config' c['port'] = 13_128 c['pac_file']['location'] = 'spec/all_direct.pac' + STDERR.puts 'Pacproxy::Pacproxy.new(c)' @pacproxy_server = Pacproxy::Pacproxy.new(c) + STDERR.puts 'Thread.new { @pacproxy_server.start } start' Thread.new { @pacproxy_server.start } + STDERR.puts 'Thread.new { @pacproxy_server.start } end' wait_server_status(@pacproxy_server, :Running) STDERR.puts 'pacproxy_server started' From 000305d0893a2e3ede43ad4a3edc9ff2dacb1720 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 06:36:35 +0900 Subject: [PATCH 09/26] Add more log --- spec/pacproxy_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index a892b5d..95cf55e 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -7,7 +7,10 @@ def wait_server_status(servers, status) return unless servers || status servers = [servers] unless servers.respond_to?(:all?) return unless servers.all? { |s| s.respond_to?(:status) } - sleep(0.01) until servers.all? { |s| s.status == status } + sleep(0.01) until servers.all? do |s| + puts("#{s.class}: #{s.status}") + s.status == status + end end describe Pacproxy do From 29fa7ddcb22bcd33a3acb85088245ccc969fc70e Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 06:50:16 +0900 Subject: [PATCH 10/26] Add rescue --- lib/pacproxy/pacproxy.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 70a8953..81c5224 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -32,6 +32,8 @@ def start s = @socket.accept Thread.new(s, &method(:handle_request)) end + rescue => e + STDERR.puts e ensure shutdown end From 245bd7ed5645fc5a2322f7bf09820bbd3b99bcb6 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:06:49 +0900 Subject: [PATCH 11/26] Add more log --- lib/pacproxy/pacproxy.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 81c5224..99b810f 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -39,9 +39,11 @@ def start end def shutdown + STDERR.puts("start: pacproxy socket.closed?:#{@socket.closed?}") if @socket @socket.close if @socket @pac.shutdown if @pac @status = :Stop + STDERR.puts("done: pacproxy socket.closed?:#{@socket.closed?}") if @socket end private From 3c9d9802147ed9c466eda4bec7aee9acba108317 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:16:04 +0900 Subject: [PATCH 12/26] Add retry --- lib/pacproxy/pacproxy.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 99b810f..b227a26 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -32,8 +32,10 @@ def start s = @socket.accept Thread.new(s, &method(:handle_request)) end - rescue => e + rescue Errno::EADDRINUSE => e STDERR.puts e + sleep 3 + retry ensure shutdown end From d8d57705c4250cea64fb2eb93ad7c496b8e296ba Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:21:42 +0900 Subject: [PATCH 13/26] Add sleep --- spec/pacproxy_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 95cf55e..8c44dab 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -11,6 +11,7 @@ def wait_server_status(servers, status) puts("#{s.class}: #{s.status}") s.status == status end + sleep 3 end describe Pacproxy do From 62ce2c14042b419f6251206a0f897f05894a4e61 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:30:32 +0900 Subject: [PATCH 14/26] Add write \0 --- lib/pacproxy/pacproxy.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index b227a26..b68ef55 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -42,7 +42,10 @@ def start def shutdown STDERR.puts("start: pacproxy socket.closed?:#{@socket.closed?}") if @socket - @socket.close if @socket + if @socket && !@socket.closed? + @socket.write_nonblock("\0") + @socket.close + end @pac.shutdown if @pac @status = :Stop STDERR.puts("done: pacproxy socket.closed?:#{@socket.closed?}") if @socket From 95f5d9bbd226db6900beebcaab05c7749947333b Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:39:48 +0900 Subject: [PATCH 15/26] Change close method if condition --- lib/pacproxy/pacproxy.rb | 9 +++------ spec/pacproxy_spec.rb | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index b68ef55..e844ad1 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -34,16 +34,13 @@ def start end rescue Errno::EADDRINUSE => e STDERR.puts e - sleep 3 - retry ensure shutdown end def shutdown STDERR.puts("start: pacproxy socket.closed?:#{@socket.closed?}") if @socket - if @socket && !@socket.closed? - @socket.write_nonblock("\0") + if @socket @socket.close end @pac.shutdown if @pac @@ -130,8 +127,8 @@ def transfer_data(client_s, server_s) rescue => e STDOUT.puts('Error' + e) ensure - server_s.close unless server_s.open? - client_s.close unless client_s.open? + server_s.close if server_s.open? + client_s.close if client_s.open? end def write_proxy_credential(server_s) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 8c44dab..95cf55e 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -11,7 +11,6 @@ def wait_server_status(servers, status) puts("#{s.class}: #{s.status}") s.status == status end - sleep 3 end describe Pacproxy do From af51886bf88ef37f8b2fbcfdf4872f9bc203f3a3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 07:42:01 +0900 Subject: [PATCH 16/26] Add write \0 --- lib/pacproxy/pacproxy.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index e844ad1..2fe090d 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -124,6 +124,8 @@ def transfer_data(client_s, server_s) client_s.write(server_s.read_nonblock(BUFFER_SIZE)) end end + server_s.write_nonblock("\0") + client_s.write_nonblock("\0") rescue => e STDOUT.puts('Error' + e) ensure From a2a567bf61ea1415077bb7dbec55b20861e7476d Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 08:31:07 +0900 Subject: [PATCH 17/26] Add condiftion to close socket --- lib/pacproxy/pacproxy.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 2fe090d..9101c52 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -101,8 +101,8 @@ def do_request(client_s, method, unparsed_uri, version, proxy) transfer_data(client_s, server_s) ensure - client_s.close - server_s.close + server_s.close if server_s.open? + client_s.close if client_s.open? end def do_connect(client_s, _method, unparsed_uri, _version) From 65099d5e02b01055378c508e7b18984cb2ad4930 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 08:39:30 +0900 Subject: [PATCH 18/26] Replace open? method to closed? and change condition --- lib/pacproxy/pacproxy.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 9101c52..268997b 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -101,8 +101,8 @@ def do_request(client_s, method, unparsed_uri, version, proxy) transfer_data(client_s, server_s) ensure - server_s.close if server_s.open? - client_s.close if client_s.open? + server_s.close unless server_s.closed? + client_s.close unless client_s.closed? end def do_connect(client_s, _method, unparsed_uri, _version) @@ -129,8 +129,8 @@ def transfer_data(client_s, server_s) rescue => e STDOUT.puts('Error' + e) ensure - server_s.close if server_s.open? - client_s.close if client_s.open? + server_s.close unless server_s.closed? + client_s.close unless client_s.closed? end def write_proxy_credential(server_s) From 0385e82f0af57317b192c450b716c86bc2937e91 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 10:56:36 +0900 Subject: [PATCH 19/26] Add more log --- lib/pacproxy/pacproxy.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 268997b..fe5a140 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -124,13 +124,14 @@ def transfer_data(client_s, server_s) client_s.write(server_s.read_nonblock(BUFFER_SIZE)) end end - server_s.write_nonblock("\0") client_s.write_nonblock("\0") + server_s.write_nonblock("\0") rescue => e STDOUT.puts('Error' + e) ensure server_s.close unless server_s.closed? client_s.close unless client_s.closed? + STDOUT.puts('server_s client_s closed') end def write_proxy_credential(server_s) From 7b2b1bc694b347570a80b69fb045464fa762bdd3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 11:33:03 +0900 Subject: [PATCH 20/26] Add reset --- spec/pacproxy_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 95cf55e..10acb7a 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -69,9 +69,9 @@ def wait_server_status(servers, status) c = HTTPClient.new('http://127.0.0.1:13128') res = c.get('http://127.0.0.1:13080/') expect(res.status).to eq(200) - res = c.get('http://127.0.0.1:13080/noproxy/') expect(res.status).to eq(200) + c.reset_all end it 'transfer request to server directly via HTTPS' do From a30737df9c3b69577cdef295880d40c0221efdce Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sat, 29 Aug 2015 11:55:30 +0900 Subject: [PATCH 21/26] Add retry and socket clear --- lib/pacproxy/pacproxy.rb | 3 +++ spec/pacproxy_spec.rb | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index fe5a140..e2c50a3 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -34,6 +34,8 @@ def start end rescue Errno::EADDRINUSE => e STDERR.puts e + sleep 3 + retry ensure shutdown end @@ -42,6 +44,7 @@ def shutdown STDERR.puts("start: pacproxy socket.closed?:#{@socket.closed?}") if @socket if @socket @socket.close + @socket = nil end @pac.shutdown if @pac @status = :Stop diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 10acb7a..21ccd38 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -72,6 +72,7 @@ def wait_server_status(servers, status) res = c.get('http://127.0.0.1:13080/noproxy/') expect(res.status).to eq(200) c.reset_all + STDERR.puts('##c.reset_all##') end it 'transfer request to server directly via HTTPS' do From 5a5d92b57a194841bce00e9bb0584ccc3efc70fe Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Sun, 30 Aug 2015 06:38:20 +0900 Subject: [PATCH 22/26] Temp change to no container --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27156be..de9c287 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -sudo: false +sudo: true language: ruby cache: bundler From a3a4278f41600d7e9d04809b45104d9d8c8ad320 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Mon, 31 Aug 2015 16:52:24 +0900 Subject: [PATCH 23/26] Temp add c.reset --- lib/pacproxy/pacproxy.rb | 7 +++---- spec/pacproxy_spec.rb | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index e2c50a3..73c8672 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -117,6 +117,9 @@ def do_connect(client_s, _method, unparsed_uri, _version) # TODO: write log transfer_data(client_s, server_s) + ensure + server_s.close unless server_s.closed? + client_s.close unless client_s.closed? end def transfer_data(client_s, server_s) @@ -127,13 +130,9 @@ def transfer_data(client_s, server_s) client_s.write(server_s.read_nonblock(BUFFER_SIZE)) end end - client_s.write_nonblock("\0") - server_s.write_nonblock("\0") rescue => e STDOUT.puts('Error' + e) ensure - server_s.close unless server_s.closed? - client_s.close unless client_s.closed? STDOUT.puts('server_s client_s closed') end diff --git a/spec/pacproxy_spec.rb b/spec/pacproxy_spec.rb index 21ccd38..7756f73 100644 --- a/spec/pacproxy_spec.rb +++ b/spec/pacproxy_spec.rb @@ -22,6 +22,7 @@ def wait_server_status(servers, status) describe 'Pacproxy#proxy_uri' do before(:each) do + STDERR.puts(`netstat -an | grep \'.13\'`) $stdout, $stderr = StringIO.new, StringIO.new @http_server = WEBrick::HTTPServer.new(Port: 13_080) @http_server.define_singleton_method(:service) do |_req, res| @@ -56,6 +57,7 @@ def wait_server_status(servers, status) @pacproxy_server], :Stop) STDERR.puts 'wait_server_status done' + STDERR.puts(`netstat -an | grep \'.13\'|grep tcp4`) end it 'transfer request to server directly' do @@ -102,6 +104,7 @@ def wait_server_status(servers, status) STDERR.puts 'HTTPClient request 2 done' expect(res.status).to eq(200) STDERR.puts 'transfer request to server directly via HTTPS exiting' + c.reset_all end it 'transfer request to server directly with PUT method' do From ea89f947bec5752fd18745fd2e14e3bf3b3333b6 Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Tue, 1 Sep 2015 22:01:44 +0900 Subject: [PATCH 24/26] Add to set socket reuseaddr true --- lib/pacproxy/pacproxy.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 73c8672..f76e708 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -27,6 +27,7 @@ def initialize(config = {}) def start @socket = TCPServer.new(@host, @port) + @socket.setsockopt(:SOCKET, :REUSEADDR, true) @status = :Running loop do s = @socket.accept From 3cf1f5db32611ebb9b08fb3b37bd4cf1b330077c Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Wed, 2 Sep 2015 08:34:30 +0900 Subject: [PATCH 25/26] Delete sock time_wait true and rescue exception when start --- lib/pacproxy/pacproxy.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index f76e708..6786b78 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -27,7 +27,6 @@ def initialize(config = {}) def start @socket = TCPServer.new(@host, @port) - @socket.setsockopt(:SOCKET, :REUSEADDR, true) @status = :Running loop do s = @socket.accept @@ -37,6 +36,8 @@ def start STDERR.puts e sleep 3 retry + rescue => e + STDERR.puts e ensure shutdown end From 71b8b2599fc84e30b0c5b439ef87fb56c0fdd7da Mon Sep 17 00:00:00 2001 From: Hiroshi Ota Date: Mon, 14 Sep 2015 09:13:22 +0900 Subject: [PATCH 26/26] Temp add socks close --- lib/pacproxy/pacproxy.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pacproxy/pacproxy.rb b/lib/pacproxy/pacproxy.rb index 6786b78..e1e1bf3 100644 --- a/lib/pacproxy/pacproxy.rb +++ b/lib/pacproxy/pacproxy.rb @@ -26,6 +26,7 @@ def initialize(config = {}) end def start + @socks = [] @socket = TCPServer.new(@host, @port) @status = :Running loop do @@ -48,6 +49,9 @@ def shutdown @socket.close @socket = nil end + @socks.each do |s| + s.close unless s.closed? + end @pac.shutdown if @pac @status = :Stop STDERR.puts("done: pacproxy socket.closed?:#{@socket.closed?}") if @socket @@ -56,6 +60,7 @@ def shutdown private def handle_request(client_s) + @socks << client_s request_line = client_s.readline match_result = request_line.match(REQUEST_LINE_REGEXP) method = match_result[:method]