Skip to content
Browse files

Some minor code cleanup

  • Loading branch information...
1 parent 2145ac9 commit eaafa89103da2cff711cd3867344aff8df5c6e16 @meh meh committed with Sep 28, 2011
Showing with 150 additions and 153 deletions.
  1. +3 −1 lib/em-socksify.rb
  2. +9 −9 lib/em-socksify/errors.rb
  3. +105 −0 lib/em-socksify/socks5.rb
  4. +33 −143 lib/em-socksify/socksify.rb
View
4 lib/em-socksify.rb
@@ -1,3 +1,5 @@
require 'eventmachine'
-require 'em-socksify/socksify'
+require 'em-socksify/socksify'
+require 'em-socksify/errors'
+require 'em-socksify/socks5'
View
18 lib/em-socksify/errors.rb
@@ -1,4 +1,4 @@
-class SOCKSError < Exception
+class EventMachine::Socksify::SOCKSError < Exception
def self.define (message)
Class.new(self) {
def initialize
@@ -7,14 +7,14 @@ def initialize
}
end
- ServerFailure = SOCKSError.define('general SOCKS server failure')
- NotAllowed = SOCKSError.define('connection not allowed by ruleset')
- NetworkUnreachable = SOCKSError.define('Network unreachable')
- HostUnreachable = SOCKSError.define('Host unreachable')
- ConnectionRefused = SOCKSError.define('Connection refused')
- TTLExpired = SOCKSError.define('TTL expired')
- CommandNotSupported = SOCKSError.define('Command not supported')
- AddressTypeNotSupported = SOCKSError.define('Address type not supported')
+ ServerFailure = define('general SOCKS server failure')
+ NotAllowed = define('connection not allowed by ruleset')
+ NetworkUnreachable = define('Network unreachable')
+ HostUnreachable = define('Host unreachable')
+ ConnectionRefused = define('Connection refused')
+ TTLExpired = define('TTL expired')
+ CommandNotSupported = define('Command not supported')
+ AddressTypeNotSupported = define('Address type not supported')
def self.for_response_code(code)
case code.is_a?(String) ? code.ord : code
View
105 lib/em-socksify/socks5.rb
@@ -0,0 +1,105 @@
+module EventMachine::Socksify::SOCKS5
+ def socks_send_handshake
+ # Method Negotiation as described on
+ # http://www.faqs.org/rfcs/rfc1928.html Section 3
+ @socks_state = :method_negotiation
+
+ socks_methods.tap {|methods|
+ send_data [5, methods.size].pack('CC') + methods.pack('C*')
+ }
+ end
+
+ def socks_send_connect_request
+ @socks_state = :connecting
+
+ send_data [5, 1, 0].pack('CCC')
+
+ if matches = @socks_target_host.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)
+ send_data "\xF1\x00\x01" + matches.to_a[1 .. -1].map { |s| s.to_i }.pack('CCCC')
+ elsif @socks_target_host =~ /^[:0-9a-f]+$/
+ raise SOCKSError, 'TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor'
+ else
+ send_data [3, @socks_target_host.size, @socks_target_host].pack('CCA*')
+ end
+
+ send_data [@socks_target_port].pack('n')
+ end
+
+ def socks_send_authentication
+ @socks_state = :authenticating
+
+ send_data [5,
+ @socks_username.length, @socks_username,
+ @socks_password.length, @socks_password
+ ].pack('CCA*CA*')
+ end
+
+ private
+
+ # parses socks 5 server responses as specified
+ # on http://www.faqs.org/rfcs/rfc1928.html
+ def socks_parse_response
+ case @socks_state
+ when :method_negotiation
+ return unless @socks_data.size >= 2
+
+ _, method = @socks_data.slice!(0, 2).unpack('CC')
+
+ if socks_methods.include?(method)
+ case method
+ when 0 then socks_send_connect_request
+ when 2 then socks_send_authentication
+ end
+ else
+ raise SOCKSError, 'proxy did not accept method'
+ end
+
+ when :authenticating
+ return unless @socks_data.size >= 2
+
+ socks_version, status_code = @socks_data.slice!(0, 2).unpack('CC')
+
+ raise SOCKSError, "SOCKS version 5 not supported" unless socks_version == 5
+ raise SOCKSError, 'access denied by proxy' unless status_code == 0
+
+ send_socks_connect_request
+
+ when :connecting
+ return unless @socks_data.size >= 2
+
+ socks_version, status_code = @socks_data.slice(0, 2).unpack('CC')
+
+ raise SOCKSError, "SOCKS version #{socks_version} is not 5" unless socks_version == 5
+ raise SOCKSError.for_response_code(status_code) unless status_code == 0
+
+ min_size = @socks_data[3].ord == 3 ? 5 : 4
+
+ return unless @socks_data.size >= min_size
+
+ size = case @socks_data[3].ord
+ when 1 then 4
+ when 3 then @socks_data[4].ord
+ when 4 then 16
+ else raise SOCKSError.for_response_code(@socks_data[3])
+ end
+
+ return unless @socks_data.size >= min_size + size
+
+ bind_addr = @socks_data[min_size ... (min_size + size)]
+
+ socks_unhook(case @socks_data[3].ord
+ when 1 then bind_addr.bytes.to_a.join(?.)
+ when 3 then bind_addr
+ when 4 then # TODO: yeah, I'm a lazy italian
+ end)
+ end
+ end
+
+ def socks_methods
+ methods = []
+ methods << 2 if !@socks_username.nil? # 2 => Username/Password Authentication
+ methods << 0 # 0 => No Authentication Required
+
+ methods
+ end
+end
View
176 lib/em-socksify/socksify.rb
@@ -1,156 +1,46 @@
-require 'em-socksify/errors'
-
-module EventMachine
- module Socksify
- def socksify(host, port, username = nil, password = nil, version = 5, &blk)
- @socks_target_host = host
- @socks_target_port = port
- @socks_username = username
- @socks_password = password
- @socks_version = version
- @socks_callback = blk
- @socks_data = ''
+module EventMachine::Socksify
+ def socksify(host, port, username = nil, password = nil, version = 5, &blk)
+ @socks_target_host = host
+ @socks_target_port = port
+ @socks_username = username
+ @socks_password = password
+ @socks_version = version
+ @socks_callback = blk
+ @socks_data = ''
+
+ socks_hook
+ socks_send_handshake
+ end
- socks_hook
- socks_send_handshake
+ def socks_hook
+ if @socks_version == 5
+ extend SOCKS5
+ else
+ raise ArgumentError, 'SOCKS version unsupported'
end
- def socks_hook
- if @socks_version == 5
- extend SOCKS5
- else
- raise ArgumentError, 'SOCKS version unsupported'
- end
-
- class << self
- alias receive_data socks_receive_data
- end
+ class << self
+ alias receive_data socks_receive_data
end
+ end
- def socks_unhook(ip = nil)
- class << self
- remove_method :receive_data
- end
-
- callback = @socks_callback
-
- instance_variables.each {|name|
- remove_instance_variable name if name.to_s.start_with?('@socks_')
- }
-
- callback.call(ip)
- end
-
- def socks_receive_data(data)
- @socks_data << data
-
- socks_parse_response
+ def socks_unhook(ip = nil)
+ class << self
+ remove_method :receive_data
end
- module SOCKS5
- def socks_send_handshake
- # Method Negotiation as described on
- # http://www.faqs.org/rfcs/rfc1928.html Section 3
- @socks_state = :method_negotiation
-
- socks_methods.tap {|methods|
- send_data [5, methods.size].pack('CC') + methods.pack('C*')
- }
- end
-
- def socks_send_connect_request
- @socks_state = :connecting
-
- send_data [5, 1, 0].pack('CCC')
-
- if matches = @socks_target_host.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)
- send_data "\xF1\x00\x01" + matches.to_a[1 .. -1].map { |s| s.to_i }.pack('CCCC')
- elsif @socks_target_host =~ /^[:0-9a-f]+$/
- raise SOCKSError, 'TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor'
- else
- send_data [3, @socks_target_host.size, @socks_target_host].pack('CCA*')
- end
-
- send_data [@socks_target_port].pack('n')
- end
-
- def socks_send_authentication
- @socks_state = :authenticating
-
- send_data [5,
- @socks_username.length, @socks_username,
- @socks_password.length, @socks_password
- ].pack('CCA*CA*')
- end
+ callback = @socks_callback
- private
+ instance_variables.each {|name|
+ remove_instance_variable name if name.to_s.start_with?('@socks_')
+ }
- # parses socks 5 server responses as specified
- # on http://www.faqs.org/rfcs/rfc1928.html
- def socks_parse_response
- case @socks_state
- when :method_negotiation
- return unless @socks_data.size >= 2
-
- _, method = @socks_data.slice!(0, 2).unpack('CC')
-
- if socks_methods.include?(method)
- case method
- when 0 then socks_send_connect_request
- when 2 then socks_send_authentication
- end
- else
- raise SOCKSError, 'proxy did not accept method'
- end
-
- when :authenticating
- return unless @socks_data.size >= 2
-
- socks_version, status_code = @socks_data.slice!(0, 2).unpack('CC')
-
- raise SOCKSError, "SOCKS version 5 not supported" unless socks_version == 5
- raise SOCKSError, 'access denied by proxy' unless status_code == 0
-
- send_socks_connect_request
-
- when :connecting
- return unless @socks_data.size >= 2
-
- socks_version, status_code = @socks_data.slice(0, 2).unpack('CC')
-
- raise SOCKSError, "SOCKS version #{socks_version} is not 5" unless socks_version == 5
- raise SOCKSError.for_response_code(status_code) unless status_code == 0
-
- min_size = @socks_data[3].ord == 3 ? 5 : 4
-
- return unless @socks_data.size >= min_size
-
- size = case @socks_data[3].ord
- when 1 then 4
- when 3 then @socks_data[4].ord
- when 4 then 16
- else raise SOCKSError.for_response_code(@socks_data[3])
- end
-
- return unless @socks_data.size >= min_size + size
-
- bind_addr = @socks_data[min_size ... (min_size + size)]
-
- socks_unhook(case @socks_data[3].ord
- when 1 then bind_addr.bytes.to_a.join(?.)
- when 3 then bind_addr
- when 4 then # TODO: yeah, I'm a lazy italian
- end)
- end
- end
+ callback.call(ip)
+ end
- def socks_methods
- methods = []
- methods << 2 if !@socks_username.nil? # 2 => Username/Password Authentication
- methods << 0 # 0 => No Authentication Required
+ def socks_receive_data(data)
+ @socks_data << data
- methods
- end
- end
+ socks_parse_response
end
end

0 comments on commit eaafa89

Please sign in to comment.
Something went wrong with that request. Please try again.