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
@@ -0,0 +1,279 @@
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/mixins/mixin'
21
+ require 'ronin/network/unix'
22
+
23
+ module Ronin
24
+ module Network
25
+ module Mixins
26
+ #
27
+ # Adds UNIX Socket convenience methods and connection parameters to a
28
+ # class.
29
+ #
30
+ # Defines the following parameters:
31
+ #
32
+ # * `path` (`String`) - UNIX Socket path.
33
+ #
34
+ # @since 0.5.0
35
+ #
36
+ module UNIX
37
+ include Mixin, Network::UNIX
38
+
39
+ # UNIX path
40
+ parameter :path, :type => String,
41
+ :description => 'UNIX Socket path'
42
+
43
+ protected
44
+
45
+ #
46
+ # Connects to a UNIX socket specified by the `path` parameter.
47
+ #
48
+ # @yield [socket]
49
+ # If a block is given, it will be passed an UNIX socket object.
50
+ #
51
+ # @yieldparam [UNIXSocket] socket
52
+ # The UNIX socket.
53
+ #
54
+ # @return [UNIXSocket]
55
+ # The UNIX socket.
56
+ #
57
+ # @example
58
+ # socket = unix_connect
59
+ #
60
+ # @see Network::UNIX#unix_connect
61
+ #
62
+ # @api public
63
+ #
64
+ def unix_connect(&block)
65
+ print_info "Connecting to #{self.path} ..."
66
+
67
+ super(self.path,&block)
68
+ end
69
+
70
+ #
71
+ # Creates a new UNIXSocket object, connected to the `path` parameter.
72
+ # The given data will then be written to the newly created UNIXSocket.
73
+ #
74
+ # @param [String] data
75
+ # The data to send to the socket.
76
+ #
77
+ # @yield [socket]
78
+ # If a block is given, it will be passed the newly created socket.
79
+ #
80
+ # @yieldparam [UNIXSocket] socket
81
+ # The newly created UNIXSocket object.
82
+ #
83
+ # @return [UNIXSocket]
84
+ # The newly created UNIXSocket object.
85
+ #
86
+ # @see Network::UNIX#unix_connect_and_send
87
+ #
88
+ # @api public
89
+ #
90
+ def unix_connect_and_send(data,&block)
91
+ print_info "Connecting to #{self.path} ..."
92
+ print_debug "Sending data: #{data.inspect}"
93
+
94
+ return super(data,self.path,&block)
95
+ end
96
+
97
+ #
98
+ # Creates a UNIX session to the host and port specified by the
99
+ # `host` and `port` parameters. If the `local_host` and `local_port`
100
+ # parameters are set, they will be used for the local host and port
101
+ # of the UNIX connection.
102
+ #
103
+ # @yield [socket]
104
+ # If a block is given, it will be passed the newly created socket.
105
+ # After the block has returned, the socket will then be closed.
106
+ #
107
+ # @yieldparam [UNIXsocket] socket
108
+ # The newly created UNIXSocket object.
109
+ #
110
+ # @see Network::UNIX#unix_session
111
+ #
112
+ # @api public
113
+ #
114
+ def unix_session(&block)
115
+ print_info "Connecting to #{self.path} ..."
116
+
117
+ super(self.host,&block)
118
+
119
+ print_info "Disconnected from #{self.path}"
120
+ return nil
121
+ end
122
+
123
+ #
124
+ # Connects to the UNIX socket, specified by the `path` parameter,
125
+ # sends the given data and then disconnects.
126
+ #
127
+ # @param [String] data
128
+ # The data to send to the UNIX socket.
129
+ #
130
+ # @return [true]
131
+ # The data was successfully sent.
132
+ #
133
+ # @example
134
+ # buffer = "GET /" + ('A' * 4096) + "\n\r"
135
+ # unix_send(buffer)
136
+ # # => true
137
+ #
138
+ # @see Network::UNIX#unix_send
139
+ #
140
+ # @api public
141
+ #
142
+ # @since 0.4.0
143
+ #
144
+ def unix_send(data)
145
+ print_info "Connecting to #{self.path} ..."
146
+ print_debug "Sending data: #{data.inspect}"
147
+
148
+ super(data,self.path,&block)
149
+
150
+ print_info "Disconnected from #{self.path}"
151
+ return true
152
+ end
153
+
154
+ #
155
+ # Opens a UNIX socket, listening on the `path` parameter.
156
+ #
157
+ # @yield [server]
158
+ # The given block will be passed the newly created server.
159
+ #
160
+ # @yieldparam [UNIXServer] server
161
+ # The newly created server.
162
+ #
163
+ # @return [UNIXServer]
164
+ # The newly created server.
165
+ #
166
+ # @example
167
+ # unix_server
168
+ #
169
+ # @see Network::UNIX#unix_server
170
+ #
171
+ # @api public
172
+ #
173
+ def unix_server(&block)
174
+ print_info "Listening on #{self.path} ..."
175
+
176
+ return super(self.path,&block)
177
+ end
178
+
179
+ #
180
+ # Opens a UNIX socket temporarily, listening on the `path` parameter.
181
+ #
182
+ # @yield [server]
183
+ # The given block will be passed the newly created server.
184
+ # When the block has finished, the server will be closed.
185
+ #
186
+ # @yieldparam [UNIXServer] server
187
+ # The newly created server.
188
+ #
189
+ # @return [nil]
190
+ #
191
+ # @example
192
+ # unix_server_session do |server|
193
+ # # ...
194
+ # end
195
+ #
196
+ # @see Network::UNIX#unix_server_session
197
+ #
198
+ # @api public
199
+ #
200
+ def unix_server_session(&block)
201
+ print_info "Listening on #{self.path} ..."
202
+
203
+ super(self.path,&block)
204
+
205
+ print_info "Closed #{self.path}"
206
+ return nil
207
+ end
208
+
209
+ #
210
+ # Opens a UNIX socket specified by the `path` parameter,
211
+ # accepts a connection, then closes the socket.
212
+ #
213
+ # @yield [client]
214
+ # If a block is given, it will be passed the accepted connection.
215
+ #
216
+ # @yieldparam [UNIXSocket] client
217
+ # The accepted connection to UNIX socket.
218
+ #
219
+ # @example
220
+ # unix_accept do |client|
221
+ # # ...
222
+ # end
223
+ #
224
+ # @see Network::UNIX#unix_accept
225
+ #
226
+ # @api public
227
+ #
228
+ def unix_accept
229
+ print_info "Listening on #{self.path} ..."
230
+
231
+ super(self.path) do |client|
232
+ print_info "Client connected to #{self.path}"
233
+
234
+ yield client if block_given?
235
+
236
+ print_info "Client disconnecting from #{self.path} ..."
237
+ end
238
+
239
+ print_info "Closed #{self.path}"
240
+ return nil
241
+ end
242
+
243
+ #
244
+ # Opens a UNIX socket specified by the `path` parameter,
245
+ # accepts connections in a loop.
246
+ #
247
+ # @yield [client]
248
+ # If a block is given, it will be passed each accepted connection.
249
+ #
250
+ # @yieldparam [UNIXSocket] client
251
+ # An accepted connection to UNIX socket.
252
+ #
253
+ # @example
254
+ # unix_server_loop do |client|
255
+ # # ...
256
+ # end
257
+ #
258
+ # @see Network::UNIX#unix_server_loop
259
+ #
260
+ # @api public
261
+ #
262
+ def unix_server_loop
263
+ print_info "Listening on #{self.path} ..."
264
+
265
+ super(self.path) do |client|
266
+ print_info "Client connected: #{self.path}"
267
+
268
+ yield client if block_given?
269
+
270
+ print_info "Client disconnecting: #{self.path} ..."
271
+ end
272
+
273
+ print_info "Closed #{self.path}"
274
+ return nil
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
@@ -34,7 +34,7 @@ module Ronin
34
34
  #
35
35
  # @api public
36
36
  #
37
- def POP3.default_port
37
+ def self.default_port
38
38
  @default_port ||= DEFAULT_PORT
39
39
  end
40
40
 
@@ -46,7 +46,7 @@ module Ronin
46
46
  #
47
47
  # @api public
48
48
  #
49
- def POP3.default_port=(port)
49
+ def self.default_port=(port)
50
50
  @default_port = port
51
51
  end
52
52
 
@@ -80,9 +80,9 @@ module Ronin
80
80
  # @api public
81
81
  #
82
82
  def pop3_connect(host,options={})
83
- host = host.to_s
84
- port = (options[:port] || POP3.default_port)
85
- user = options[:user]
83
+ host = host.to_s
84
+ port = (options[:port] || POP3.default_port)
85
+ user = options[:user]
86
86
  password = options[:password]
87
87
 
88
88
  session = Net::POP3.start(host,port,user,password)
@@ -0,0 +1,578 @@
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
+ module Ronin
21
+ module Network
22
+ #
23
+ # Base class for {TCP::Proxy TCP} and {UDP::Proxy UDP} Proxies.
24
+ #
25
+ # ## Callbacks
26
+ #
27
+ # The Proxy base class supports several callbacks for proxy events.
28
+ #
29
+ # ### client_data
30
+ #
31
+ # When a client sends data to the proxy.
32
+ #
33
+ # on_client_data do |client,server,data|
34
+ # data.gsub!(/foo/,'bar')
35
+ # end
36
+ #
37
+ # ### server_data
38
+ #
39
+ # When the server sends data to the proxy.
40
+ #
41
+ # on_server_data do |client,server,data|
42
+ # data.gsub!(/foo/,'bar')
43
+ # end
44
+ #
45
+ # ### data
46
+ #
47
+ # Alias for {#on_client_data} and {#on_server_data}.
48
+ #
49
+ # ## Actions
50
+ #
51
+ # The Proxy base class also provides methods to change how events are
52
+ # handled.
53
+ #
54
+ # * {#ignore!}
55
+ # * {#close!}
56
+ # * {#reset!}
57
+ #
58
+ # @since 0.5.0
59
+ #
60
+ class Proxy
61
+
62
+ # Default host to bind to
63
+ DEFAULT_HOST = '0.0.0.0'
64
+
65
+ DEFAULT_BUFFER_SIZE = 4096
66
+
67
+ # The host the proxy will listen on
68
+ attr_reader :host
69
+
70
+ # The port the proxy will listen on
71
+ attr_reader :port
72
+
73
+ # The remote port the proxy will relay data to
74
+ attr_reader :server_host
75
+
76
+ # The remote host the proxy will relay data to
77
+ attr_reader :server_port
78
+
79
+ # The size of read buffer
80
+ attr_accessor :buffer_size
81
+
82
+ # The connections maintained by the proxy
83
+ attr_reader :connections
84
+
85
+ #
86
+ # Creates a new Proxy.
87
+ #
88
+ # @param [Hash] options
89
+ # Options for the proxy.
90
+ #
91
+ # @option options [String] :host (DEFAULT_HOST)
92
+ # The host to listen on.
93
+ #
94
+ # @option options [Integer] :port
95
+ # The port to listen on.
96
+ #
97
+ # @option options [String, (host, port)] :server
98
+ # The server to forward connections to.
99
+ #
100
+ # @option options [Integer] :buffer_size (DEFAULT_BUFFER_SIZE)
101
+ # The maximum amount of data to read in.
102
+ #
103
+ # @yield [proxy]
104
+ # If a block is given, it will be passed the new Proxy, before it
105
+ # has been configured.
106
+ #
107
+ # @yieldparam [Proxy] proxy
108
+ # The new Proxy object.
109
+ #
110
+ # @example Proxies `0.0.0.0:1337` to `victim.com:80`:
111
+ # Proxy.new(:port => 1337, :server => ['victim.com', 80])
112
+ #
113
+ # @example Proxies `localhost:25` to `victim.com:25`:
114
+ # Proxy.new(:port => 25, :host => 'localhost', :server => 'victim.com')
115
+ #
116
+ def initialize(options={})
117
+ @host = options.fetch(:host,DEFAULT_HOST)
118
+ @port = options.fetch(:port)
119
+
120
+ @server_host, @server_port = options.fetch(:server)
121
+ @server_port ||= @port
122
+
123
+ @callbacks = {
124
+ :client_data => [],
125
+ :server_data => []
126
+ }
127
+
128
+ @buffer_size = options.fetch(:buffer_size,DEFAULT_BUFFER_SIZE)
129
+ @connections = {}
130
+
131
+ yield self if block_given?
132
+ end
133
+
134
+ #
135
+ # Creates a new Proxy and begins relaying data.
136
+ #
137
+ # @see #initialize
138
+ #
139
+ # @api public
140
+ #
141
+ def self.start(options={},&block)
142
+ new(options,&block).start
143
+ end
144
+
145
+ #
146
+ # Starts the proxy and begins relaying data.
147
+ #
148
+ # @return [Proxy]
149
+ # The proxy object.
150
+ #
151
+ # @api public
152
+ #
153
+ def start
154
+ open
155
+ listen
156
+ close
157
+ return self
158
+ end
159
+
160
+ #
161
+ # Opens the proxy.
162
+ #
163
+ # @api public
164
+ #
165
+ # @abstract
166
+ #
167
+ def open
168
+ end
169
+
170
+ #
171
+ # Polls the connections for data or errors.
172
+ #
173
+ # @api public
174
+ #
175
+ # @abstract
176
+ #
177
+ def poll
178
+ end
179
+
180
+ #
181
+ # Polls the connections for data.
182
+ #
183
+ # @api public
184
+ #
185
+ def listen
186
+ @listening = true
187
+
188
+ while @listening
189
+ begin
190
+ poll
191
+ rescue Interrupt
192
+ @listening = false
193
+ break
194
+ end
195
+ end
196
+ end
197
+
198
+ #
199
+ # Sends data to a connection.
200
+ #
201
+ # @param [connection] connection
202
+ # The connection.
203
+ #
204
+ # @param [String] data
205
+ # The data to send.
206
+ #
207
+ # @api public
208
+ #
209
+ # @abstract
210
+ #
211
+ def send(connection,data)
212
+ end
213
+
214
+ #
215
+ # Receives data from a connection.
216
+ #
217
+ # @param [connection] connection
218
+ # The connection.
219
+ #
220
+ # @api public
221
+ #
222
+ # @abstract
223
+ #
224
+ def recv(connection)
225
+ end
226
+
227
+ #
228
+ # Closes the proxy.
229
+ #
230
+ # @api public
231
+ #
232
+ def close
233
+ close_connections
234
+ close_proxy
235
+ end
236
+
237
+ #
238
+ # Stops the proxy from listening.
239
+ #
240
+ # @api public
241
+ #
242
+ def stop
243
+ @listening = false
244
+ return self
245
+ end
246
+
247
+ #
248
+ # Registers a callback for when a client sends data.
249
+ #
250
+ # @yield [client, server, data]
251
+ #
252
+ # @yieldparam [String] data
253
+ #
254
+ # @api public
255
+ #
256
+ def on_client_data(&block)
257
+ @callbacks[:client_data] << block
258
+ end
259
+
260
+ #
261
+ # Registers a callback for when a server sends data.
262
+ #
263
+ # @yield [client, server, data]
264
+ #
265
+ # @yieldparam [String] data
266
+ #
267
+ # @api public
268
+ #
269
+ def on_server_data(&block)
270
+ @callbacks[:server_data] << block
271
+ end
272
+
273
+ #
274
+ # Registers a callback for when either the client or the server sends
275
+ # data.
276
+ #
277
+ # @yield [client, server, data]
278
+ #
279
+ # @yieldparam [String] data
280
+ #
281
+ # @api public
282
+ #
283
+ def on_data(&block)
284
+ on_client_data(&block)
285
+ on_server_data(&block)
286
+ end
287
+
288
+ #
289
+ # Causes the proxy to ignore a message.
290
+ #
291
+ # @api public
292
+ #
293
+ def ignore!
294
+ throw(:action,:ignore)
295
+ end
296
+
297
+ #
298
+ # Causes the proxy to close a connection.
299
+ #
300
+ # @api public
301
+ #
302
+ def close!
303
+ throw(:action,:close)
304
+ end
305
+
306
+ #
307
+ # Causes the proxy to restart a connection.
308
+ #
309
+ # @api public
310
+ #
311
+ def reset!
312
+ throw(:action,:reset)
313
+ end
314
+
315
+ #
316
+ # Causes the proxy to stop processing data entirely.
317
+ #
318
+ # @api public
319
+ #
320
+ def stop!
321
+ throw(:action,:stop)
322
+ end
323
+
324
+ #
325
+ # Connections from clients.
326
+ #
327
+ # @return [Array<connection>]
328
+ # Client connections.
329
+ #
330
+ def client_connections
331
+ @connections.keys
332
+ end
333
+
334
+ #
335
+ # Connections to the server.
336
+ #
337
+ # @return [Array<connection>]
338
+ # Server connections.
339
+ #
340
+ def server_connections
341
+ @connections.values
342
+ end
343
+
344
+ #
345
+ # Finds the connection to the server, associated with the client.
346
+ #
347
+ # @param [connection] client_connection
348
+ # The connection from the client.
349
+ #
350
+ # @return [connection]
351
+ # The connection to the server.
352
+ #
353
+ def server_connection_for(client_connection)
354
+ @connections[client_connection]
355
+ end
356
+
357
+ if RUBY_VERSION < '1.9.'
358
+ #
359
+ # Finds the connection from the client, associated with the server
360
+ # connection.
361
+ #
362
+ # @param [connection] server_connection
363
+ # The connection to the server.
364
+ #
365
+ # @return [connection]
366
+ # The connection from the client.
367
+ #
368
+ def client_connection_for(server_connection)
369
+ @connections.index(server_connection)
370
+ end
371
+ else
372
+ #
373
+ # Finds the connection from the client, associated with the server
374
+ # connection.
375
+ #
376
+ # @param [connection] server_connection
377
+ # The connection to the server.
378
+ #
379
+ # @return [connection]
380
+ # The connection from the client.
381
+ #
382
+ def client_connection_for(server_connection)
383
+ @connections.key(server_connection)
384
+ end
385
+ end
386
+
387
+ #
388
+ # Converts the proxy to a String.
389
+ #
390
+ # @return [String]
391
+ # The String form of the proxy.
392
+ #
393
+ def to_s
394
+ "#{@host}:#{@port} <-> #{@server_host}:#{@server_port}"
395
+ end
396
+
397
+ #
398
+ # Inspects the proxy.
399
+ #
400
+ # @return [String]
401
+ # The inspected proxy.
402
+ #
403
+ def inspect
404
+ "#<#{self.class}:#{self.object_id}: #{self}>"
405
+ end
406
+
407
+ protected
408
+
409
+ #
410
+ # Creates a new connection to the server.
411
+ #
412
+ # @return [connection]
413
+ # The new connection.
414
+ #
415
+ # @abstract
416
+ #
417
+ def open_server_connection
418
+ end
419
+
420
+ #
421
+ # Closes a client connection to the proxy.
422
+ #
423
+ # @param [connection] connection
424
+ # The client connection.
425
+ #
426
+ # @abstract
427
+ #
428
+ def close_client_connection(connection)
429
+ end
430
+
431
+ #
432
+ # Closes a connection to the server.
433
+ #
434
+ # @param [connection] connection
435
+ # The server connection.
436
+ #
437
+ # @abstract
438
+ #
439
+ def close_server_connection(connection)
440
+ end
441
+
442
+ #
443
+ # Closes the proxy.
444
+ #
445
+ # @abstract
446
+ #
447
+ def close_proxy
448
+ end
449
+
450
+ #
451
+ # Resets a server connection.
452
+ #
453
+ # @param [connection] client_connection
454
+ # The connection from the client to the proxy.
455
+ #
456
+ # @param [connection] server_connection
457
+ # The connection from the proxy to the server.
458
+ #
459
+ def reset_connection(client_connection,server_connection)
460
+ close_server_connection(server_connection) if server_connection
461
+
462
+ @connections[client_connection] = open_server_connection
463
+ end
464
+
465
+ #
466
+ # Closes both the client and server connections.
467
+ #
468
+ # @param [connection] client_connection
469
+ # The connection from the client to the proxy.
470
+ #
471
+ # @param [connection] server_connection
472
+ # The connection from the proxy to the server.
473
+ #
474
+ def close_connection(client_connection,server_connection=nil)
475
+ close_server_connection(server_connection) if server_connection
476
+ close_client_connection(client_connection)
477
+
478
+ @connections.delete(client_connection)
479
+ end
480
+
481
+ #
482
+ # Closes all active connections.
483
+ #
484
+ def close_connections
485
+ @connections.each do |client_connection,server_connection|
486
+ close_server_connection(server_connection)
487
+ close_client_connection(client_connection)
488
+ end
489
+
490
+ @connections.clear
491
+ end
492
+
493
+ #
494
+ # Triggers the callbacks registered for an event.
495
+ #
496
+ # @param [Symbol] event
497
+ # The event being triggered.
498
+ #
499
+ # @param [connection] client_connection
500
+ # The connection from the client to the proxy.
501
+ #
502
+ # @param [connection] server_connection
503
+ # The connection from the proxy to the server.
504
+ #
505
+ # @param [String] data
506
+ # The data being sent.
507
+ #
508
+ # @yield []
509
+ # If none of the callbacks interrupted the event, the given block
510
+ # will be called.
511
+ #
512
+ def callback(event,client_connection,server_connection=nil,data=nil)
513
+ action = catch(:action) do
514
+ @callbacks[event].each do |block|
515
+ case block.arity
516
+ when 1
517
+ block.call(client_connection)
518
+ when 2
519
+ block.call(client_connection,server_connection)
520
+ when 3, -1
521
+ block.call(client_connection,server_connection,data)
522
+ end
523
+ end
524
+ end
525
+
526
+ case action
527
+ when :ignore
528
+ # no-op
529
+ when :reset
530
+ reset_connection(client_connection,server_connection)
531
+ when :close
532
+ close_connection(client_connection,server_connection)
533
+ when :stop
534
+ stop
535
+ else
536
+ yield if block_given?
537
+ end
538
+ end
539
+
540
+ #
541
+ # Triggers the `client_data` event.
542
+ #
543
+ # @param [connection] client_connection
544
+ # The connection from a client to the proxy.
545
+ #
546
+ # @param [connection] server_connection
547
+ # The connection from the proxy to the server.
548
+ #
549
+ # @param [String] data
550
+ # The data sent by the client.
551
+ #
552
+ def client_data(client_connection,server_connection,data)
553
+ callback(:client_data,client_connection,server_connection,data) do
554
+ send(server_connection,data)
555
+ end
556
+ end
557
+
558
+ #
559
+ # Triggers the `server_data` event.
560
+ #
561
+ # @param [connection] client_connection
562
+ # The connection from a client to the proxy.
563
+ #
564
+ # @param [connection] server_connection
565
+ # The connection from the proxy to the server.
566
+ #
567
+ # @param [String] data
568
+ # The data sent from the server.
569
+ #
570
+ def server_data(client_connection,server_connection,data)
571
+ callback(:server_data,client_connection,server_connection,data) do
572
+ send(client_connection,data)
573
+ end
574
+ end
575
+
576
+ end
577
+ end
578
+ end