Class Jabber::Bytestreams::SOCKS5Bytestreams
In: lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb
Parent: Object

SOCKS5 Bytestreams (JEP-0065) implementation

Don‘t use directly, use SOCKS5BytestreamsInitiator and SOCKS5BytestreamsTarget

Methods

Attributes

connect_timeout  [RW]  SOCKS connection timeout (for trying multiple streamhosts)

default: nil, use the OS’ default timeout

streamhost_used  [R] 
StreamHost
the SOCKS connection is using

Public Class methods

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 26
26:       def initialize(stream, session_id, initiator_jid, target_jid)
27:         @stream = stream
28:         @session_id = session_id
29:         @initiator_jid = (initiator_jid.kind_of?(String) ? JID.new(initiator_jid) : initiator_jid)
30:         @target_jid = (target_jid.kind_of?(String) ? JID.new(target_jid) : target_jid)
31:         @socks = nil
32:         @connect_timeout = nil
33:         @streamhost_used = nil
34:         @streamhost_cbs = CallbackList.new
35:       end

Query a JID for its stream-host information

SOCKS5BytestreamsInitiator#add_streamhost can do this for you. Use this method if you plan to do multiple transfers, so you can cache the result.

stream:[Stream] to operate on
streamhost:[JID] of the proxy
my_jid:[JID] Optional sender JID for Component operation

[Source]

     # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 91
 91:       def self.query_streamhost(stream, streamhost, my_jid=nil)
 92:         res = nil
 93: 
 94:         iq = Iq::new(:get, streamhost)
 95:         iq.from = my_jid
 96:         iq.add(IqQueryBytestreams.new)
 97:         stream.send_with_id(iq) { |reply|
 98:           if reply.type == :result
 99:             reply.query.each_element { |e|
100:               if e.kind_of?(StreamHost)
101:                 e.jid = reply.from  # Help misconfigured proxys
102:                 res = e
103:               end
104:             }
105:           end
106:           true
107:         }
108: 
109:         if res and res.jid and res.host and res.port
110:           res
111:         else
112:           nil
113:         end
114:       end

Public Instance methods

Add a callback that will be called when there is action regarding SOCKS stream-hosts

Usage of this callback is optional and serves informational purposes only.

block takes three arguments:

  • The StreamHost instance that is currently being tried
  • State information (is either :connecting, :authenticating, :success or :failure)
  • The exception value for the state :failure, else nil

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 47
47:       def add_streamhost_callback(priority = 0, ref = nil, &block)
48:         @streamhost_cbs.add(priority, ref, block)
49:       end

Close the stream-host connection

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 78
78:       def close
79:         @socks.close
80:       end

Flush the SOCKS5 socket

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 61
61:       def flush
62:         @socks.flush
63:       end

Receive from the stream-host

length:[Fixnum] Amount of bytes (Will be passed to TCPSocket#read for the underlying SOCKS5 connection)
result:[String] (or [nil] if finished)

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 55
55:       def read(length=nil)
56:         @socks.read(length)
57:       end

Send to the stream-host

buf:[String] Data
result:[Fixnum] Amount of bytes sent

[Source]

    # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 69
69:       def write(buf)
70:         @socks.write(buf)
71:         # FIXME: On FreeBSD this throws Errno::EPERM after it has already written a few
72:         # kilobytes, and when there are multiple sockets. ktrace told, that this originates
73:         # from the syscall, not ruby.
74:       end

Private Instance methods

Try a streamhost

result:[SOCKS5Socket]

[Source]

     # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 131
131:       def connect_socks(streamhost)
132:         Timeout::timeout(@connect_timeout, Errno::ETIMEDOUT) {
133:           Jabber::debuglog("SOCKS5 Bytestreams: connecting to proxy #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})")
134:           @streamhost_cbs.process(streamhost, :connecting, nil)
135:           socks = SOCKS5Socket.new(streamhost.host, streamhost.port)
136: 
137:           Jabber::debuglog("SOCKS5 Bytestreams: connected, authenticating")
138:           @streamhost_cbs.process(streamhost, :authenticating, nil)
139:           socks.auth
140: 
141:           socks.connect_domain(stream_address, 0)
142: 
143:           Jabber::debuglog("SOCKS5 Bytestreams: connected")
144:           @streamhost_cbs.process(streamhost, :success, nil)
145: 
146:           socks
147:         }
148:       end

The address the stream-host expects from us. According to JEP-0096 this is the SHA1 hash of the concatenation of session_id, initiator_jid and target_jid.

result:[String] SHA1 hash

[Source]

     # File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 124
124:       def stream_address
125:         Digest::SHA1.new("#{@session_id}#{@initiator_jid}#{@target_jid}").hexdigest
126:       end

[Validate]