Class: TCPProxy
- Inherits:
-
Object
- Object
- TCPProxy
- Defined in:
- lib/tcp_proxy.rb
Overview
Proxies tcp connections on a machine from one port to the next. This is used for debugging and writing specifications for cod. This is not officially part of cod’s API.
Defined Under Namespace
Classes: Connection
Instance Attribute Summary collapse
-
#connections ⇒ Object
readonly
Returns the value of attribute connections.
Instance Method Summary collapse
- #accept_connections ⇒ Object
-
#allow ⇒ Object
Allows new connections to be made.
-
#block ⇒ Object
Disallows new connections.
-
#close ⇒ Object
Closes the proxy, disrupting every connection made to it.
-
#drop_all ⇒ Object
Drops all established connections.
- #forward_data ⇒ Object
-
#initialize(host, from_port, to_port) ⇒ TCPProxy
constructor
A new instance of TCPProxy.
-
#thread_main ⇒ Object
Internal thread that pumps messages from and to ports.
Constructor Details
#initialize(host, from_port, to_port) ⇒ TCPProxy
Returns a new instance of TCPProxy.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/tcp_proxy.rb', line 9 def initialize(host, from_port, to_port) @ins = TCPServer.new(host, from_port) @host = host @from_port, @to_port = from_port, to_port # Active connections and mutex to protect access to it. @connections = [] @connections_m = Mutex.new # Are we currently accepting new connections? @accept_new = true @thread = Thread.start(&method(:thread_main)) end |
Instance Attribute Details
#connections ⇒ Object (readonly)
Returns the value of attribute connections.
7 8 9 |
# File 'lib/tcp_proxy.rb', line 7 def connections @connections end |
Instance Method Details
#accept_connections ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/tcp_proxy.rb', line 136 def accept_connections loop do in_sock = @ins.accept_nonblock out_sock = TCPSocket.new(@host, @to_port) @connections_m.synchronize { @connections << Connection.new(in_sock, out_sock) } end rescue Errno::EAGAIN # No more connections pending, stop accepting new connections end |
#allow ⇒ Object
Allows new connections to be made. This is the default, so you only need this to reenable connections after a #block.
52 53 54 55 |
# File 'lib/tcp_proxy.rb', line 52 def allow @ins = TCPServer.new(@host, @from_port) @accept_new = true end |
#block ⇒ Object
Disallows new connections.
43 44 45 46 47 |
# File 'lib/tcp_proxy.rb', line 43 def block @accept_new = false @ins.close @ins = nil end |
#close ⇒ Object
Closes the proxy, disrupting every connection made to it.
27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tcp_proxy.rb', line 27 def close @shutdown = true @thread.join @thread = nil # Since the thread is stopped now, we can be sure no new connections are # accepted. This is why we access the collection without locking. @connections.each do |connection| connection.close end @ins.close if @ins end |
#drop_all ⇒ Object
Drops all established connections.
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/tcp_proxy.rb', line 59 def drop_all # Copy the connections and then empty the collection connections = @connections_m.synchronize { @connections.tap { @connections = [] } } connections.each do |conn| conn.close end end |
#forward_data ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/tcp_proxy.rb', line 149 def forward_data connections = @connections_m.synchronize { @connections.dup } remove_list = [] connections.each do |conn| begin conn.pump_synchronized rescue EOFError # Socket was closed, remove from the collection. remove_list << conn end end @connections_m.synchronize { @connections -= remove_list } end |
#thread_main ⇒ Object
Internal thread that pumps messages from and to ports.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/tcp_proxy.rb', line 74 def thread_main loop do accept_connections if @accept_new forward_data break if @shutdown end rescue Exception => ex p [:uncaught, ex] ex.backtrace.each do |line| puts line end raise end |