class Jabber::Bytestreams::SOCKS5BytestreamsServer

The SOCKS5BytestreamsServer is an implementation of a SOCKS5 server.

You can use it if you're reachable by your SOCKS5Bytestreams peers, thus avoiding use of an external proxy.

Usage:

Public Class Methods

new(port, listen_on=nil) click to toggle source

Start a local SOCKS5BytestreamsServer

Will start to listen on the given TCP port and accept new peers

port
Fixnum

TCP port to listen on

listen_on
String

Optional address for the server socket to listen on (i.e. '0.0.0.0' or '::')

# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb, line 27
def initialize(port, listen_on=nil)
  @port = port
  @addresses = []
  @peers = []
  @peers_lock = Mutex.new
  if listen_on
    socket = TCPServer.new(listen_on, port)
  else
    socket = TCPServer.new(port)
  end

  Thread.new do
    Thread.current.abort_on_exception = true
    loop do
      peer = SOCKS5BytestreamsPeer.new(socket.accept)
      Thread.new do
        Thread.current.abort_on_exception = true
        begin
          peer.start
        rescue
          Jabber::debuglog("SOCKS5 BytestreamsServer: Error accepting peer: #{$!}")
        end
      end
      @peers_lock.synchronize do
        @peers << peer
      end
    end
  end
end

Public Instance Methods

add_address(address) click to toggle source

Add an external IP address

This is a must-have, as SOCKS5BytestreamsInitiator must inform the target where to connect

# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb, line 104
def add_address(address)
  @addresses << address
end
each_streamhost(my_jid) { |socks5_bytestreams_server_stream_host| ... } click to toggle source

Iterate through all configured addresses, yielding SOCKS5BytestreamsServerStreamHost instances, which should be passed to Jabber::Bytestreams::SOCKS5BytestreamsInitiator#add_streamhost

This will be automatically invoked if you pass an instance of SOCKS5BytestreamsServer to Jabber::Bytestreams::SOCKS5BytestreamsInitiator#add_streamhost

my_jid
JID

My Jabber-ID

# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb, line 118
def each_streamhost(my_jid, &block)
  @addresses.each { |address|
    yield SOCKS5BytestreamsServerStreamHost.new(self, my_jid, address, @port)
  }
end
peer_sock(addr) click to toggle source

Find the socket a peer is associated to

This method also performs some housekeeping, ie. removing peers with closed sockets.

addr
String

Address like Jabber::Bytestreams::SOCKS5Bytestreams#stream_address

result
TCPSocker

or [nil]

# File lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb, line 64
def peer_sock(addr)
  res = nil
  @peers_lock.synchronize {
    removes = []

    @peers.each { |peer|
      if peer.socket and peer.socket.closed?
        # Queue peers with closed socket for removal
        removes << peer
      elsif peer.address == addr and res.nil?
        res = peer.socket
      end

      # If we sent multiple addresses of our own, clients may
      # connect multiple times. DO NOT close any other connections
      # here. These may belong to other concurrent bytestreams,
      # believe that the peer will close any unneeded sockets
      # which will then be picked up by the next call to peer_sock.
    }

    # If we sent multiple addresses of our own, clients may
    # connect multiple times. Close these connections here.
    @peers.delete_if { |peer|
      if removes.include? peer
        peer.socket.close rescue IOError
        true
      else
        false
      end
    }
  }

  res
end