ronin-support 0.4.1 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/ChangeLog.md +75 -32
  2. data/Gemfile +17 -18
  3. data/README.md +9 -10
  4. data/Rakefile +10 -2
  5. data/gemspec.yml +1 -1
  6. data/lib/ronin/binary.rb +21 -0
  7. data/lib/ronin/binary/hexdump.rb +20 -0
  8. data/lib/ronin/binary/hexdump/parser.rb +411 -0
  9. data/lib/ronin/binary/struct.rb +579 -0
  10. data/lib/ronin/binary/template.rb +437 -0
  11. data/lib/ronin/extensions/ip_addr.rb +17 -13
  12. data/lib/ronin/extensions/regexp.rb +45 -0
  13. data/lib/ronin/extensions/string.rb +3 -3
  14. data/lib/ronin/formatting/extensions/binary.rb +1 -0
  15. data/lib/ronin/formatting/extensions/binary/array.rb +63 -0
  16. data/lib/ronin/formatting/extensions/binary/base64.rb +106 -0
  17. data/lib/ronin/formatting/extensions/binary/file.rb +39 -6
  18. data/lib/ronin/formatting/extensions/binary/float.rb +65 -0
  19. data/lib/ronin/formatting/extensions/binary/integer.rb +56 -43
  20. data/lib/ronin/formatting/extensions/binary/string.rb +75 -187
  21. data/lib/ronin/formatting/extensions/text/string.rb +61 -0
  22. data/lib/ronin/fuzzing/extensions/string.rb +21 -8
  23. data/lib/ronin/fuzzing/fuzzing.rb +19 -17
  24. data/lib/ronin/network.rb +2 -1
  25. data/lib/ronin/network/dns.rb +57 -15
  26. data/lib/ronin/network/extensions.rb +0 -1
  27. data/lib/ronin/network/ftp.rb +145 -0
  28. data/lib/ronin/network/http/http.rb +13 -14
  29. data/lib/ronin/network/imap.rb +11 -10
  30. data/lib/ronin/network/mixins.rb +1 -0
  31. data/lib/ronin/network/mixins/ftp.rb +155 -0
  32. data/lib/ronin/network/mixins/ssl.rb +1 -1
  33. data/lib/ronin/network/mixins/tcp.rb +39 -6
  34. data/lib/ronin/network/mixins/udp.rb +121 -1
  35. data/lib/ronin/network/mixins/unix.rb +279 -0
  36. data/lib/ronin/network/pop3.rb +5 -5
  37. data/lib/ronin/network/proxy.rb +578 -0
  38. data/lib/ronin/network/smtp/email.rb +1 -1
  39. data/lib/ronin/network/smtp/smtp.rb +7 -8
  40. data/lib/ronin/network/ssl.rb +1 -6
  41. data/lib/ronin/network/tcp.rb +2 -305
  42. data/lib/ronin/network/tcp/proxy.rb +377 -0
  43. data/lib/ronin/network/tcp/tcp.rb +435 -0
  44. data/lib/ronin/network/telnet.rb +27 -23
  45. data/lib/ronin/network/udp.rb +2 -266
  46. data/lib/ronin/network/udp/proxy.rb +169 -0
  47. data/lib/ronin/network/udp/udp.rb +442 -0
  48. data/lib/ronin/network/unix.rb +287 -0
  49. data/lib/ronin/path.rb +2 -2
  50. data/lib/ronin/spec/ui/output.rb +1 -7
  51. data/lib/ronin/support.rb +1 -0
  52. data/lib/ronin/support/inflector.rb +3 -7
  53. data/lib/ronin/support/support.rb +2 -1
  54. data/lib/ronin/support/version.rb +1 -1
  55. data/lib/ronin/ui/output/helpers.rb +13 -15
  56. data/lib/ronin/ui/output/output.rb +2 -2
  57. data/lib/ronin/ui/output/terminal/color.rb +10 -4
  58. data/lib/ronin/wordlist.rb +92 -17
  59. data/ronin-support.gemspec +38 -109
  60. data/spec/binary/hexdump/helpers/hexdumps.rb +13 -0
  61. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/ascii.bin +0 -0
  62. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_decimal_shorts.txt +0 -0
  63. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_bytes.txt +0 -0
  64. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_shorts.txt +0 -0
  65. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_bytes.txt +0 -0
  66. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_shorts.txt +0 -0
  67. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_repeated.txt +0 -0
  68. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_bytes.txt +0 -0
  69. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_ints.txt +0 -0
  70. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_quads.txt +0 -0
  71. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_shorts.txt +0 -0
  72. data/spec/binary/hexdump/helpers/hexdumps/od_doubles.txt +17 -0
  73. data/spec/binary/hexdump/helpers/hexdumps/od_floats.txt +17 -0
  74. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_bytes.txt +0 -0
  75. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_ints.txt +0 -0
  76. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_quads.txt +0 -0
  77. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_shorts.txt +0 -0
  78. data/spec/binary/hexdump/helpers/hexdumps/od_named_chars.txt +17 -0
  79. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_bytes.txt +0 -0
  80. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_ints.txt +0 -0
  81. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_quads.txt +0 -0
  82. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_shorts.txt +0 -0
  83. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_repeated.txt +0 -0
  84. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/repeated.bin +0 -0
  85. data/spec/binary/hexdump/parser_spec.rb +302 -0
  86. data/spec/binary/struct_spec.rb +496 -0
  87. data/spec/binary/template_spec.rb +400 -0
  88. data/spec/extensions/ip_addr_spec.rb +58 -32
  89. data/spec/extensions/regexp_spec.rb +60 -0
  90. data/spec/extensions/string_spec.rb +1 -1
  91. data/spec/formatting/binary/array_spec.rb +22 -0
  92. data/spec/formatting/binary/base64_spec.rb +50 -0
  93. data/spec/formatting/binary/float_spec.rb +30 -0
  94. data/spec/formatting/binary/integer_spec.rb +54 -40
  95. data/spec/formatting/binary/string_spec.rb +69 -182
  96. data/spec/formatting/text/string_spec.rb +30 -0
  97. data/spec/network/dns_spec.rb +64 -0
  98. data/spec/network/ftp_spec.rb +65 -0
  99. data/spec/network/proxy_spec.rb +121 -0
  100. data/spec/network/shared/unix_server.rb +31 -0
  101. data/spec/network/tcp/proxy_spec.rb +116 -0
  102. data/spec/network/{tcp_spec.rb → tcp/tcp_spec.rb} +24 -1
  103. data/spec/network/telnet_spec.rb +67 -0
  104. data/spec/network/{udp_spec.rb → udp/udp_spec.rb} +24 -1
  105. data/spec/network/unix_spec.rb +183 -0
  106. data/spec/wordlist_spec.rb +74 -13
  107. metadata +129 -85
  108. data/spec/formatting/binary/helpers/hexdumps.rb +0 -16
@@ -117,7 +117,7 @@ module Ronin
117
117
  # @return [String]
118
118
  # Properly formatted SMTP message.
119
119
  #
120
- # @see http://www.ruby-doc.org/stdlib/libdoc/net/smtp/rdoc/classes/Net/SMTP.html
120
+ # @see http://rubydoc.info/stdlib/net/Net/SMTP
121
121
  #
122
122
  # @api public
123
123
  #
@@ -36,7 +36,7 @@ module Ronin
36
36
  #
37
37
  # @api public
38
38
  #
39
- def SMTP.default_port
39
+ def self.default_port
40
40
  @default_port ||= DEFAULT_PORT
41
41
  end
42
42
 
@@ -48,7 +48,7 @@ module Ronin
48
48
  #
49
49
  # @api public
50
50
  #
51
- def SMTP.default_port=(port)
51
+ def self.default_port=(port)
52
52
  @default_port = port
53
53
  end
54
54
 
@@ -69,7 +69,7 @@ module Ronin
69
69
  #
70
70
  # @api public
71
71
  #
72
- def SMTP.message(options={},&block)
72
+ def self.message(options={},&block)
73
73
  Email.new(options,&block).to_s
74
74
  end
75
75
 
@@ -136,10 +136,9 @@ module Ronin
136
136
  host = host.to_s
137
137
  port = (options[:port] || SMTP.default_port)
138
138
 
139
- helo = options[:helo]
140
-
141
- auth = options[:auth]
142
- user = options[:user]
139
+ helo = options[:helo]
140
+ auth = options[:auth]
141
+ user = options[:user]
143
142
  password = options[:password]
144
143
 
145
144
  session = Net::SMTP.start(host,port,helo,user,password,auth)
@@ -206,7 +205,7 @@ module Ronin
206
205
  # :message_id => 'XXXX',
207
206
  # :body => 'Hello'
208
207
  #
209
- # @example Using the block.
208
+ # @example Using the block:
210
209
  # smtp_send_message('www.example.com') do |email|
211
210
  # email.to = 'joe@example.com'
212
211
  # email.from 'eve@example.com'
@@ -22,7 +22,6 @@ require 'ronin/network/tcp'
22
22
  begin
23
23
  require 'openssl'
24
24
  rescue ::LoadError
25
- $stderr.puts "WARNING: Ruby was not compiled with OpenSSL support"
26
25
  end
27
26
 
28
27
  module Ronin
@@ -100,8 +99,6 @@ module Ronin
100
99
  # @example
101
100
  # socket = ssl_connect('twitter.com',443)
102
101
  #
103
- # @see http://rubydoc.info/stdlib/openssl/OpenSSL/SSL/SSLSocket
104
- #
105
102
  # @api public
106
103
  #
107
104
  def ssl_connect(host,port,options={})
@@ -168,13 +165,11 @@ module Ronin
168
165
  #
169
166
  # @example
170
167
  # ssl_session('twitter.com',443) do |sock|
171
- # sock.write("GET / HTTP/1.1\n\r\n\r")
168
+ # sock.write("GET /\n\n")
172
169
  #
173
170
  # sock.each_line { |line| puts line }
174
171
  # end
175
172
  #
176
- # @see http://rubydoc.info/stdlib/openssl/OpenSSL/SSL/SSLSocket
177
- #
178
173
  # @api public
179
174
  #
180
175
  def ssl_session(host,port,options={},&block)
@@ -17,308 +17,5 @@
17
17
  # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
- require 'socket'
21
-
22
- module Ronin
23
- module Network
24
- #
25
- # Provides helper methods for using the TCP protocol.
26
- #
27
- module TCP
28
- #
29
- # Creates a new TCPSocket object connected to a given host and port.
30
- #
31
- # @param [String] host
32
- # The host to connect to.
33
- #
34
- # @param [Integer] port
35
- # The port to connect to.
36
- #
37
- # @param [String] local_host ('0.0.0.0')
38
- # The local host to bind to.
39
- #
40
- # @param [Integer] local_port (nil)
41
- # The local port to bind to.
42
- #
43
- # @yield [socket]
44
- # If a block is given, it will be passed the newly created socket.
45
- #
46
- # @yieldparam [TCPsocket] socket
47
- # The newly created TCPSocket object.
48
- #
49
- # @return [TCPSocket]
50
- # The newly created TCPSocket object.
51
- #
52
- # @example
53
- # tcp_connect('www.hackety.org',80) # => TCPSocket
54
- #
55
- # @example
56
- # tcp_connect('www.wired.com',80) do |socket|
57
- # socket.write("GET / HTTP/1.1\n\r\n\r")
58
- #
59
- # puts socket.readlines
60
- # socket.close
61
- # end
62
- #
63
- # @api public
64
- #
65
- def tcp_connect(host,port,local_host=nil,local_port=0)
66
- host = host.to_s
67
- local_host = (local_host || '0.0.0.0').to_s
68
-
69
- socket = TCPSocket.new(host,port,local_host,local_port)
70
-
71
- yield socket if block_given?
72
- return socket
73
- end
74
-
75
- #
76
- # Creates a new TCPSocket object, connected to a given host and port.
77
- # The given data will then be written to the newly created TCPSocket.
78
- #
79
- # @param [String] data
80
- # The data to send through the connection.
81
- #
82
- # @param [String] host
83
- # The host to connect to.
84
- #
85
- # @param [Integer] port
86
- # The port to connect to.
87
- #
88
- # @param [String] local_host (nil)
89
- # The local host to bind to.
90
- #
91
- # @param [Integer] local_port (nil)
92
- # The local port to bind to.
93
- #
94
- # @yield [socket]
95
- # If a block is given, it will be passed the newly created socket.
96
- #
97
- # @yieldparam [TCPsocket] socket
98
- # The newly created TCPSocket object.
99
- #
100
- # @api public
101
- #
102
- def tcp_connect_and_send(data,host,port,local_host=nil,local_port=0)
103
- socket = tcp_connect(host,port,local_host,local_port)
104
- socket.write(data)
105
-
106
- yield socket if block_given?
107
- return socket
108
- end
109
-
110
- #
111
- # Creates a new temporary TCPSocket object, connected to the given host
112
- # and port.
113
- #
114
- # @param [String] host
115
- # The host to connect to.
116
- #
117
- # @param [Integer] port
118
- # The port to connect to.
119
- #
120
- # @param [String] local_host (nil)
121
- # The local host to bind to.
122
- #
123
- # @param [Integer] local_port (nil)
124
- # The local port to bind to.
125
- #
126
- # @yield [socket]
127
- # If a block is given, it will be passed the newly created socket.
128
- # After the block has returned, the socket will then be closed.
129
- #
130
- # @yieldparam [TCPsocket] socket
131
- # The newly created TCPSocket object.
132
- #
133
- # @return [nil]
134
- #
135
- # @api public
136
- #
137
- def tcp_session(host,port,local_host=nil,local_port=0)
138
- socket = tcp_connect(host,port,local_host,local_port)
139
-
140
- yield socket if block_given?
141
-
142
- socket.close
143
- return nil
144
- end
145
-
146
- #
147
- # Reads the banner from the service running on the given host and port.
148
- #
149
- # @param [String] host
150
- # The host to connect to.
151
- #
152
- # @param [Integer] port
153
- # The port to connect to.
154
- #
155
- # @param [String] local_host (nil)
156
- # The local host to bind to.
157
- #
158
- # @param [Integer] local_port (nil)
159
- # The local port to bind to.
160
- #
161
- # @yield [banner]
162
- # If a block is given, it will be passed the grabbed banner.
163
- #
164
- # @yieldparam [String] banner
165
- # The grabbed banner.
166
- #
167
- # @return [String]
168
- # The grabbed banner.
169
- #
170
- # @example
171
- # tcp_banner('pop.gmail.com',25)
172
- # # => "220 mx.google.com ESMTP c20sm3096959rvf.1"
173
- #
174
- # @api public
175
- #
176
- def tcp_banner(host,port,local_host=nil,local_port=0)
177
- banner = nil
178
-
179
- tcp_session(host,port,local_host,local_port) do |socket|
180
- banner = socket.readline.strip
181
- end
182
-
183
- yield banner if block_given?
184
- return banner
185
- end
186
-
187
- #
188
- # Connects to a specified host and port, sends the given data and then
189
- # closes the connection.
190
- #
191
- # @param [String] data
192
- # The data to send through the connection.
193
- #
194
- # @param [String] host
195
- # The host to connect to.
196
- #
197
- # @param [Integer] port
198
- # The port to connect to.
199
- #
200
- # @param [String] local_host (nil)
201
- # The local host to bind to.
202
- #
203
- # @param [Integer] local_port (nil)
204
- # The local port to bind to.
205
- #
206
- # @return [true]
207
- # The data was successfully sent.
208
- #
209
- # @example
210
- # buffer = "GET /" + ('A' * 4096) + "\n\r"
211
- # tcp_send(buffer,'victim.com',80)
212
- # # => true
213
- #
214
- # @api public
215
- #
216
- def tcp_send(data,host,port,local_host=nil,local_port=0)
217
- tcp_session(host,port,local_host,local_port) do |socket|
218
- socket.write(data)
219
- end
220
-
221
- return true
222
- end
223
-
224
- #
225
- # Creates a new TCPServer listening on a given host and port.
226
- #
227
- # @param [Integer] port
228
- # The local port to listen on.
229
- #
230
- # @param [String] host ('0.0.0.0')
231
- # The host to bind to.
232
- #
233
- # @return [TCPServer]
234
- # The new TCP server.
235
- #
236
- # @example
237
- # tcp_server(1337)
238
- #
239
- # @api public
240
- #
241
- def tcp_server(port=0,host=nil)
242
- host = (host || '0.0.0.0').to_s
243
-
244
- server = TCPServer.new(host,port)
245
- server.listen(3)
246
-
247
- yield server if block_given?
248
- return server
249
- end
250
-
251
- #
252
- # Creates a new temporary TCPServer listening on a host and port.
253
- #
254
- # @param [Integer] port
255
- # The local port to bind to.
256
- #
257
- # @param [String] host ('0.0.0.0')
258
- # The host to bind to.
259
- #
260
- # @yield [server]
261
- # The block which will be called after the server has been created.
262
- # After the block has finished, the server will be closed.
263
- #
264
- # @yieldparam [TCPServer] server
265
- # The newly created TCP server.
266
- #
267
- # @return [nil]
268
- #
269
- # @example
270
- # tcp_server_session(1337) do |server|
271
- # client1 = server.accept
272
- # client2 = server.accept
273
- #
274
- # client2.write(server.read_line)
275
- #
276
- # client1.close
277
- # client2.close
278
- # end
279
- #
280
- # @api public
281
- #
282
- def tcp_server_session(port=0,host=nil,&block)
283
- server = tcp_server(port,host,&block)
284
- server.close()
285
- return nil
286
- end
287
-
288
- #
289
- # Creates a new TCPServer listening on a given host and port,
290
- # accepts only one client and then stops listening.
291
- #
292
- # @param [Integer] port
293
- # After the block has finished, the client and the server will be
294
- # closed.
295
- #
296
- # @yieldparam [TCPSocket] client
297
- # The newly connected client.
298
- #
299
- # @return [nil]
300
- #
301
- # @example
302
- # tcp_single_server(1337) do |client|
303
- # client.puts 'lol'
304
- # end
305
- #
306
- # @api public
307
- #
308
- def tcp_single_server(port=0,host=nil)
309
- host = host.to_s
310
-
311
- server = TCPServer.new(host,port)
312
- server.listen(1)
313
-
314
- client = server.accept
315
-
316
- yield client if block_given?
317
-
318
- client.close
319
- server.close
320
- return nil
321
- end
322
- end
323
- end
324
- end
20
+ require 'ronin/network/tcp/tcp'
21
+ require 'ronin/network/tcp/proxy'
@@ -0,0 +1,377 @@
1
+ #
2
+ # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of Ronin Support.
5
+ #
6
+ # Ronin Support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Ronin Support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/network/proxy'
21
+
22
+ require 'socket'
23
+
24
+ module Ronin
25
+ module Network
26
+ module TCP
27
+ #
28
+ # The TCP Proxy allows for inspecting and manipulating TCP protocols.
29
+ #
30
+ # ## Callbacks
31
+ #
32
+ # In addition to the events supported by the {Network::Proxy Proxy}
33
+ # base class, the TCP Proxy also supports the following callbacks.
34
+ #
35
+ # ### client_connect
36
+ #
37
+ # When a client connects to the proxy:
38
+ #
39
+ # on_client_connect do |client|
40
+ # puts "[connected] #{client.remote_address.ip_address}:#{client.remote_addre
41
+ # end
42
+ #
43
+ # ### client_disconnect
44
+ #
45
+ # When a client disconnects from the proxy:
46
+ #
47
+ # on_client_disconnect do |client,server|
48
+ # puts "[disconnected] #{client.remote_address.ip_address}:#{client.remote_ad
49
+ # end
50
+ #
51
+ # ### server_connect
52
+ #
53
+ # When the server accepts a connection from the proxy:
54
+ #
55
+ # on_server_connect do |client,server|
56
+ # puts "[connected] #{proxy}"
57
+ # end
58
+ #
59
+ # ### server_disconnect
60
+ #
61
+ # When the server closes a connection from the proxy.
62
+ #
63
+ # on_server_disconnect do |client,server|
64
+ # puts "[disconnected] #{proxy}"
65
+ # end
66
+ #
67
+ # ### connect
68
+ #
69
+ # Alias for {#on_server_connect}.
70
+ #
71
+ # ### disconnect
72
+ #
73
+ # Alias for {#on_client_disconnect}.
74
+ #
75
+ # @since 0.5.0
76
+ #
77
+ class Proxy < Network::Proxy
78
+
79
+ #
80
+ # Creates a new TCP Proxy.
81
+ #
82
+ # @see Network::Proxy#initialize
83
+ #
84
+ def initialize(options={})
85
+ super(options) do |proxy|
86
+ @callbacks[:client_connect] = []
87
+ @callbacks[:client_disconnect] = []
88
+ @callbacks[:server_connect] = []
89
+ @callbacks[:server_disconnect] = []
90
+
91
+ yield proxy if block_given?
92
+ end
93
+ end
94
+
95
+ #
96
+ # Opens the proxy.
97
+ #
98
+ # @api public
99
+ #
100
+ def open
101
+ @socket = TCPServer.new(@host,@port)
102
+ end
103
+
104
+ #
105
+ # Polls the connections for data.
106
+ #
107
+ # @api public
108
+ #
109
+ def poll
110
+ sockets = [@socket] + client_connections + server_connections
111
+
112
+ readable, writtable, errors = IO.select(sockets,nil,sockets)
113
+
114
+ (errors & client_connections).each do |client_socket|
115
+ server_socket = server_connection_for(client_socket)
116
+
117
+ client_disconnect(client_socket,server_socket)
118
+ end
119
+
120
+ (errors & server_connections).each do |server_socket|
121
+ client_socket = client_connection_for(server_socket)
122
+
123
+ server_disconnect(client_socket,server_socket)
124
+ end
125
+
126
+ (readable & client_connections).each do |client_socket|
127
+ server_socket = server_connection_for(client_socket)
128
+ data = recv(client_socket)
129
+
130
+ unless data.empty?
131
+ client_data(client_socket,server_socket,data)
132
+ else
133
+ client_disconnect(client_socket,server_socket)
134
+ end
135
+ end
136
+
137
+ (readable & server_connections).each do |server_socket|
138
+ client_socket = client_connection_for(server_socket)
139
+ data = recv(server_socket)
140
+
141
+ unless data.empty?
142
+ server_data(client_socket,server_socket,data)
143
+ else
144
+ server_disconnect(client_socket,server_socket)
145
+ end
146
+ end
147
+
148
+ if readable.include?(@socket)
149
+ client_connect(@socket.accept)
150
+ end
151
+ end
152
+
153
+ #
154
+ # Sends data to a connection.
155
+ #
156
+ # @param [TCPSocket] connection
157
+ # A TCP connection to write data to.
158
+ #
159
+ # @param [String] data
160
+ # The data to write.
161
+ #
162
+ # @api public
163
+ #
164
+ def send(connection,data)
165
+ connection.send(data,0)
166
+ end
167
+
168
+ #
169
+ # Receives data from a connection.
170
+ #
171
+ # @param [TCPSocket] connection
172
+ # The TCP connection to receive data from.
173
+ #
174
+ # @return [String, nil]
175
+ # The received data.
176
+ #
177
+ # @api public
178
+ #
179
+ def recv(connection)
180
+ connection.recv(@buffer_size)
181
+ end
182
+
183
+ #
184
+ # Registers a callback for when a client connects.
185
+ #
186
+ # @yield [client]
187
+ # The block will be passed each newly connected client.
188
+ #
189
+ # @yieldparam [TCPSocket] client
190
+ # The connection from the client to the proxy.
191
+ #
192
+ # @example
193
+ # on_client_connect do |client|
194
+ # puts "[connected] #{client.remote_address.ip_address}:#{client.remote_address.ip_port}"
195
+ # end
196
+ #
197
+ # @api public
198
+ #
199
+ def on_client_connect(&block)
200
+ @callbacks[:client_connect] << block
201
+ end
202
+
203
+ #
204
+ # Registers a callback for when a client disconnects.
205
+ #
206
+ # @yield [client, server]
207
+ # The block will be passed each disconnected client and their
208
+ # connection to the server.
209
+ #
210
+ # @yieldparam [TCPSocket] client
211
+ # The connection from the client to the proxy.
212
+ #
213
+ # @yieldparam [TCPSocket] server
214
+ # The connection from the proxy to the server.
215
+ #
216
+ # @example
217
+ # on_client_disconnect do |client,server|
218
+ # puts "[disconnected] #{client.remote_address.ip_address}:#{client.remote_address.ip_port}"
219
+ # end
220
+ #
221
+ # @api public
222
+ #
223
+ def on_client_disconnect(&block)
224
+ @callbacks[:client_disconnect] << block
225
+ end
226
+
227
+ alias on_disconnect on_client_disconnect
228
+
229
+ #
230
+ # Registers a callback for when the server accepts a connection.
231
+ #
232
+ # @yield [client, server]
233
+ # The block will be passed each connected client and their newly
234
+ # formed connection to the server.
235
+ #
236
+ # @yieldparam [TCPSocket] client
237
+ # The connection from the client to the proxy.
238
+ #
239
+ # @yieldparam [TCPSocket] server
240
+ # The connection from the proxy to the server.
241
+ #
242
+ # @example
243
+ # on_server_connect do |client,server|
244
+ # puts "[connected] #{proxy}"
245
+ # end
246
+ #
247
+ # @api public
248
+ #
249
+ def on_server_connect(&block)
250
+ @callbacks[:server_connect] << block
251
+ end
252
+
253
+ alias on_connect on_server_connect
254
+
255
+ #
256
+ # Registers a callback for when the server closes a connection.
257
+ #
258
+ # @yield [client, server]
259
+ # The block will be passed the each client connection and the
260
+ # recently disconnected server connection.
261
+ #
262
+ # @yieldparam [TCPSocket] client
263
+ # The connection from the client to the proxy.
264
+ #
265
+ # @yieldparam [TCPSocket] server
266
+ # The connection from the proxy to the server.
267
+ #
268
+ # @example
269
+ # on_server_disconnect do |client,server|
270
+ # puts "[disconnected] #{proxy}"
271
+ # end
272
+ #
273
+ # @api public
274
+ #
275
+ def on_server_disconnect(&block)
276
+ @callbacks[:server_disconnect] << block
277
+ end
278
+
279
+ protected
280
+
281
+ #
282
+ # Creates a new connection to the server.
283
+ #
284
+ # @return [TCPSocket]
285
+ # A new connection.
286
+ #
287
+ def open_server_connection
288
+ TCPSocket.new(@server_host,@server_port)
289
+ end
290
+
291
+ #
292
+ # Closes a connection from the client.
293
+ #
294
+ # @param [TCPSocket] socket
295
+ # The connection from the client.
296
+ #
297
+ def close_client_connection(socket)
298
+ socket.close
299
+ end
300
+
301
+ #
302
+ # Closes a connection to the server.
303
+ #
304
+ # @param [TCPSocket] socket
305
+ # The connection to the server.
306
+ #
307
+ def close_server_connection(socket)
308
+ socket.close
309
+ end
310
+
311
+ #
312
+ # Closes the TCP proxy.
313
+ #
314
+ def close_proxy
315
+ @socket.close
316
+ end
317
+
318
+ #
319
+ # Triggers the `client_connect` event.
320
+ #
321
+ # @param [connection] client_connection
322
+ # The new connection from a client to the proxy.
323
+ #
324
+ def client_connect(client_connection)
325
+ callback(:client_connect,client_connection) do
326
+ server_connect(client_connection)
327
+ end
328
+ end
329
+
330
+ #
331
+ # Triggers the `client_disconnect` event.
332
+ #
333
+ # @param [connection] client_connection
334
+ # The connection from a client to the proxy.
335
+ #
336
+ # @param [connection] server_connection
337
+ # The connection from the proxy to the server.
338
+ #
339
+ def client_disconnect(client_connection,server_connection)
340
+ callback(:client_disconnect,client_connection,server_connection) do
341
+ close_connection(client_connection,server_connection)
342
+ end
343
+ end
344
+
345
+ #
346
+ # Triggers the `server_connect` event.
347
+ #
348
+ # @param [connection] client_connection
349
+ # The connection from a client to the proxy.
350
+ #
351
+ def server_connect(client_connection)
352
+ server_connection = open_server_connection
353
+
354
+ callback(:server_connect,client_connection,server_connection) do
355
+ @connections[client_connection] = server_connection
356
+ end
357
+ end
358
+
359
+ #
360
+ # Triggers the `server_disconnect` event.
361
+ #
362
+ # @param [connection] client_connection
363
+ # The connection from a client to the proxy.
364
+ #
365
+ # @param [connection] server_connection
366
+ # The connection from the proxy to the server.
367
+ #
368
+ def server_disconnect(client_connection,server_connection)
369
+ callback(:server_disconnect,client_connection,server_connection) do
370
+ close_connection(client_connection)
371
+ end
372
+ end
373
+
374
+ end
375
+ end
376
+ end
377
+ end