SOCKS5 Bytestreams (JEP-0065) implementation
Don't use directly, use SOCKS5BytestreamsInitiator and SOCKS5BytestreamsTarget
SOCKS connection timeout (for trying multiple streamhosts)
default: nil, use the OS' default timeout
the SOCKS connection is using
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 30 def initialize(stream, session_id, initiator_jid, target_jid) @stream = stream @session_id = session_id @initiator_jid = (initiator_jid.kind_of?(String) ? JID.new(initiator_jid) : initiator_jid) @target_jid = (target_jid.kind_of?(String) ? JID.new(target_jid) : target_jid) @socks = nil @connect_timeout = nil @streamhost_used = nil @streamhost_cbs = CallbackList.new end
Query a JID for its stream-host information
Jabber::Bytestreams::SOCKS5BytestreamsInitiator#add_streamhost can do this for you. Use this method if you plan to do multiple transfers, so you can cache the result.
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 95 def self.query_streamhost(stream, streamhost, my_jid=nil) res = nil iq = Iq.new(:get, streamhost) iq.from = my_jid iq.add(IqQueryBytestreams.new) stream.send_with_id(iq) { |reply| reply.query.each_element { |e| if e.kind_of?(StreamHost) e.jid = reply.from # Help misconfigured proxys res = e end } } if res and res.jid and res.host and res.port res else nil end end
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
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 51 def add_streamhost_callback(priority = 0, ref = nil, &block) @streamhost_cbs.add(priority, ref, block) end
Close the stream-host connection
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 82 def close @socks.close end
Flush the SOCKS5 socket
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 65 def flush @socks.flush end
Receive from the stream-host
Amount of bytes (Will be passed to TCPSocket#read for the underlying SOCKS5 connection)
(or [nil] if finished)
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 59 def read(length=nil) @socks.read(length) end
Send to the stream-host
Data
Amount of bytes sent
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 73 def write(buf) @socks.write(buf) # FIXME: On FreeBSD this throws Errno::EPERM after it has already written a few # kilobytes, and when there are multiple sockets. ktrace told, that this originates # from the syscall, not ruby. end
Try a streamhost
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 132 def connect_socks(streamhost) Timeout::timeout(@connect_timeout, Errno::ETIMEDOUT) { Jabber::debuglog("SOCKS5 Bytestreams: connecting to proxy #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})") @streamhost_cbs.process(streamhost, :connecting, nil) socks = SOCKS5Socket.new(streamhost.host, streamhost.port) Jabber::debuglog("SOCKS5 Bytestreams: connected, authenticating") @streamhost_cbs.process(streamhost, :authenticating, nil) socks.auth socks.connect_domain(stream_address, 0) Jabber::debuglog("SOCKS5 Bytestreams: connected") @streamhost_cbs.process(streamhost, :success, nil) socks } 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.
SHA1 hash
# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb, line 125 def stream_address Digest::SHA1.hexdigest("#{@session_id}#{@initiator_jid}#{@target_jid}") end