diff --git a/lib/socksify.rb b/lib/socksify.rb index 3299801..dfa4439 100644 --- a/lib/socksify.rb +++ b/lib/socksify.rb @@ -92,43 +92,60 @@ def self.for_response_code(code) end class TCPSocket - @@socks_version ||= "5" - + class << self + %w[socks_server socks_port socks_username socks_password].each do |new_method_name| + define_method new_method_name do + if Thread.current.respond_to? :thread_variable_get + Thread.current.thread_variable_get(new_method_name) + else + Thread.current[new_method_name] + end + end + end + + %w[socks_server socks_port socks_username socks_password socks_ignores].each do |new_method_name| + define_method "#{new_method_name}=" do |val| + if Thread.current.respond_to? :thread_variable_set + Thread.current.thread_variable_set(new_method_name, val) + else + Thread.current[new_method_name] = val + end + end + end + end + def self.socks_version - (@@socks_version == "4a" or @@socks_version == "4") ? "\004" : "\005" + default = '5' + if Thread.current.respond_to?(:thread_variable_get) + version = Thread.current.thread_variable_get('socks_version') + + version.nil? ? Thread.current.thread_variable_set('socks_version', default) : version + else + version = Thread.current['socks_version'] + + version.nil? ? Thread.current['socks_version'] = default : version + end end + def self.socks_version=(version) - @@socks_version = version.to_s - end - def self.socks_server - @@socks_server ||= nil - end - def self.socks_server=(host) - @@socks_server = host + Thread.current.respond_to?(:thread_variable_get) ? Thread.current.thread_variable_set('socks_version', version.to_s) : Thread.current['socks_version'] end - def self.socks_port - @@socks_port ||= nil - end - def self.socks_port=(port) - @@socks_port = port - end - def self.socks_username - @@socks_username ||= nil - end - def self.socks_username=(username) - @@socks_username = username - end - def self.socks_password - @@socks_password ||= nil - end - def self.socks_password=(password) - @@socks_password = password + + def self.encoded_socks_version + (socks_version == "4a" or socks_version == "4") ? "\004" : "\005" end + def self.socks_ignores - @@socks_ignores ||= %w(localhost) - end - def self.socks_ignores=(ignores) - @@socks_ignores = ignores + default = %w(localhost) + if Thread.current.respond_to?(:thread_variable_get) + version = Thread.current.thread_variable_get('socks_ignores') + + version.nil? ? Thread.current.thread_variable_set('socks_ignores', default) : version + else + version = Thread.current['socks_ignores'] + + version.nil? ? Thread.current['socks_ignores'] = default : version + end end class SOCKSConnectionPeerAddress < String @@ -168,7 +185,7 @@ def initialize(host=nil, port=0, local_host=nil, local_port=nil) Socksify::debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}" initialize_tcp socks_server, socks_port - socks_authenticate unless @@socks_version =~ /^4/ + socks_authenticate unless TCPSocket::socks_version =~ /^4/ if host socks_connect(host, port) @@ -218,18 +235,18 @@ def socks_authenticate # Connect def socks_connect(host, port) Socksify::debug_debug "Sending destination address" - write TCPSocket.socks_version - Socksify::debug_debug TCPSocket.socks_version.unpack "H*" + write TCPSocket::encoded_socks_version + Socksify::debug_debug TCPSocket::encoded_socks_version.unpack "H*" write "\001" - write "\000" if @@socks_version == "5" - write [port].pack('n') if @@socks_version =~ /^4/ + write "\000" if TCPSocket::socks_version == "5" + write [port].pack('n') if TCPSocket::socks_version =~ /^4/ - if @@socks_version == "4" + if TCPSocket::socks_version == "4" host = Resolv::DNS.new.getaddress(host).to_s end Socksify::debug_debug host if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address - write "\001" if @@socks_version == "5" + write "\001" if TCPSocket::socks_version == "5" _ip = [$1.to_i, $2.to_i, $3.to_i, @@ -240,7 +257,7 @@ def socks_connect(host, port) raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor" write "\004" else # to hostname - if @@socks_version == "5" + if TCPSocket::socks_version == "5" write "\003" + [host.size].pack('C') + host else write "\000\000\000\001" @@ -250,7 +267,7 @@ def socks_connect(host, port) write "\000" end end - write [port].pack('n') if @@socks_version == "5" + write [port].pack('n') if TCPSocket::socks_version == "5" socks_receive_reply Socksify::debug_notice "Connected to #{host}:#{port} over SOCKS" @@ -259,7 +276,7 @@ def socks_connect(host, port) # returns [bind_addr: String, bind_port: Fixnum] def socks_receive_reply Socksify::debug_debug "Waiting for SOCKS reply" - if @@socks_version == "5" + if TCPSocket::socks_version == "5" connect_reply = recv(4) Socksify::debug_debug connect_reply.unpack "H*" if connect_reply[0..0] != "\005" @@ -329,7 +346,7 @@ def self.resolve(host) s.write "\xF0\000\003" + [host.size].pack('C') + host end s.write [0].pack('n') # Port - + addr, port = s.socks_receive_reply Socksify::debug_notice "Resolved #{host} as #{addr} over SOCKS" addr