Class: Jabber::Bytestreams::SOCKS5BytestreamsServer

Inherits:
Object
  • Object
show all
Defined in:
lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb

Overview

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:

  • Instantiate with an unfirewalled port

  • Add your external IP addresses with SOCKS5BytestreamsServer#add_address

  • Once you've got an outgoing SOCKS5BytestreamsInitiator, do SOCKS5BytestreamsInitiator#add_streamhost(my_socks5bytestreamsserver) before you do SOCKS5BytestreamsInitiator#open

Instance Method Summary collapse

Constructor Details

#initialize(port, listen_on = nil) ⇒ SOCKS5BytestreamsServer

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 '::')


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 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

Instance Method Details

#add_address(address) ⇒ Object

Add an external IP address

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


104
105
106
# File 'lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb', line 104

def add_address(address)
  @addresses << address
end

#each_streamhost(my_jid, &block) ⇒ Object

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

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

my_jid
JID

My Jabber-ID


118
119
120
121
122
# 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) ⇒ Object

Find the socket a peer is associated to

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

addr
String

Address like SOCKS5Bytestreams#stream_address

result
TCPSocker

or [nil]


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# 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