rbkb 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +74 -0
- data/README.rdoc +149 -0
- data/Rakefile +47 -0
- data/bin/b64 +5 -0
- data/bin/bgrep +5 -0
- data/bin/blit +5 -0
- data/bin/c +5 -0
- data/bin/crc32 +5 -0
- data/bin/d64 +5 -0
- data/bin/dedump +5 -0
- data/bin/feed +5 -0
- data/bin/hexify +5 -0
- data/bin/len +5 -0
- data/bin/plugsrv +271 -0
- data/bin/rex +10 -0
- data/bin/rstrings +5 -0
- data/bin/slice +5 -0
- data/bin/telson +5 -0
- data/bin/unhexify +5 -0
- data/bin/urldec +5 -0
- data/bin/urlenc +5 -0
- data/bin/xor +5 -0
- data/cli_usage.rdoc +285 -0
- data/doctor-bag.jpg +0 -0
- data/lib/rbkb.rb +51 -0
- data/lib/rbkb/cli.rb +219 -0
- data/lib/rbkb/cli/b64.rb +35 -0
- data/lib/rbkb/cli/bgrep.rb +86 -0
- data/lib/rbkb/cli/blit.rb +89 -0
- data/lib/rbkb/cli/chars.rb +24 -0
- data/lib/rbkb/cli/crc32.rb +35 -0
- data/lib/rbkb/cli/d64.rb +28 -0
- data/lib/rbkb/cli/dedump.rb +52 -0
- data/lib/rbkb/cli/feed.rb +229 -0
- data/lib/rbkb/cli/hexify.rb +65 -0
- data/lib/rbkb/cli/len.rb +76 -0
- data/lib/rbkb/cli/rstrings.rb +108 -0
- data/lib/rbkb/cli/slice.rb +47 -0
- data/lib/rbkb/cli/telson.rb +87 -0
- data/lib/rbkb/cli/unhexify.rb +50 -0
- data/lib/rbkb/cli/urldec.rb +35 -0
- data/lib/rbkb/cli/urlenc.rb +35 -0
- data/lib/rbkb/cli/xor.rb +43 -0
- data/lib/rbkb/extends.rb +725 -0
- data/lib/rbkb/http.rb +21 -0
- data/lib/rbkb/http/base.rb +172 -0
- data/lib/rbkb/http/body.rb +214 -0
- data/lib/rbkb/http/common.rb +74 -0
- data/lib/rbkb/http/headers.rb +370 -0
- data/lib/rbkb/http/parameters.rb +104 -0
- data/lib/rbkb/http/request.rb +58 -0
- data/lib/rbkb/http/response.rb +86 -0
- data/lib/rbkb/plug.rb +9 -0
- data/lib/rbkb/plug/blit.rb +222 -0
- data/lib/rbkb/plug/cli.rb +83 -0
- data/lib/rbkb/plug/feed_import.rb +74 -0
- data/lib/rbkb/plug/peer.rb +67 -0
- data/lib/rbkb/plug/plug.rb +215 -0
- data/lib/rbkb/plug/proxy.rb +26 -0
- data/lib/rbkb/plug/unix_domain.rb +75 -0
- data/lib_usage.rdoc +176 -0
- data/rbkb.gemspec +38 -0
- data/spec/rbkb_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/test_cli_b64.rb +35 -0
- data/test/test_cli_bgrep.rb +137 -0
- data/test/test_cli_blit.rb +11 -0
- data/test/test_cli_chars.rb +21 -0
- data/test/test_cli_crc32.rb +108 -0
- data/test/test_cli_d64.rb +22 -0
- data/test/test_cli_dedump.rb +118 -0
- data/test/test_cli_feed.rb +11 -0
- data/test/test_cli_helper.rb +96 -0
- data/test/test_cli_hexify.rb +63 -0
- data/test/test_cli_len.rb +96 -0
- data/test/test_cli_rstrings.rb +15 -0
- data/test/test_cli_slice.rb +73 -0
- data/test/test_cli_telson.rb +11 -0
- data/test/test_cli_unhexify.rb +43 -0
- data/test/test_cli_urldec.rb +50 -0
- data/test/test_cli_urlenc.rb +44 -0
- data/test/test_cli_xor.rb +71 -0
- data/test/test_helper.rb +5 -0
- data/test/test_http.rb +27 -0
- data/test/test_http_helper.rb +60 -0
- data/test/test_http_request.rb +136 -0
- data/test/test_http_response.rb +222 -0
- data/test/test_rbkb.rb +19 -0
- metadata +238 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rbkb::Http
|
2
|
+
|
3
|
+
# A Request encapsulates all the entities in a HTTP request message
|
4
|
+
# including the action header, general headers, and body.
|
5
|
+
class Request < Base
|
6
|
+
attr_accessor :action
|
7
|
+
|
8
|
+
alias first_entity action
|
9
|
+
alias first_entity= action=
|
10
|
+
|
11
|
+
def request_parameters
|
12
|
+
@action.parameters
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a new Headers object extended as RequestHeaders. This is the
|
16
|
+
# default object which will be used when composing fresh Request header
|
17
|
+
# entities.
|
18
|
+
def default_headers_obj(*args)
|
19
|
+
Headers.new(*args).extend(RequestHeaders)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a new BoundBody object. This is the default object which will
|
23
|
+
# be used when composing fresh Request body entities.
|
24
|
+
def default_body_obj(*args)
|
25
|
+
Body.new(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a raw HTTP request for this instance. The instance must have
|
29
|
+
# an action element defined at the bare minimum.
|
30
|
+
def to_raw(tmp_body=@body)
|
31
|
+
raise "this request has no action entity" unless first_entity()
|
32
|
+
self.headers ||= default_headers_obj()
|
33
|
+
self.body ||= default_body_obj()
|
34
|
+
|
35
|
+
if len=@opts[:static_length]
|
36
|
+
@body = Body.new(@body, @body.opts) {|x| x.base = self}
|
37
|
+
@headers.set_header("Content-Length", len.to_i)
|
38
|
+
elsif @opts[:ignore_content_length]
|
39
|
+
@headers.delete_header("Content-Length")
|
40
|
+
end
|
41
|
+
|
42
|
+
bstr = tmp_body.to_raw
|
43
|
+
hdrs = (@headers).to_raw_array.unshift(first_entity.to_raw)
|
44
|
+
return "#{hdrs.join("\r\n")}\r\n\r\n#{bstr}"
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# Parses a raw HTTP request and captures data into the current instance.
|
49
|
+
def capture(str)
|
50
|
+
raise "arg 0 must be a string" unless String === str
|
51
|
+
hstr, bstr = str.split(/\s*\r?\n\r?\n/, 2)
|
52
|
+
capture_headers(hstr)
|
53
|
+
self.body = content_length ? BoundBody.new : Body.new
|
54
|
+
capture_body(bstr)
|
55
|
+
return self
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
module Rbkb::Http
|
3
|
+
# A Response encapsulates all the entities in a HTTP response,
|
4
|
+
# including the status header, general headers, and body.
|
5
|
+
class Response < Base
|
6
|
+
attr_accessor :status
|
7
|
+
|
8
|
+
alias first_entity status
|
9
|
+
alias first_entity= status=
|
10
|
+
|
11
|
+
# Returns a raw HTTP response for this instance. Must have a status
|
12
|
+
# element defined at a bare minimum.
|
13
|
+
def to_raw(raw_body=nil)
|
14
|
+
raise "this response has no status" unless first_entity()
|
15
|
+
self.headers ||= default_headers_obj()
|
16
|
+
self.body = raw_body if raw_body
|
17
|
+
|
18
|
+
if do_chunked_encoding?(@headers)
|
19
|
+
unless @body.is_a? ChunkedBody
|
20
|
+
@body = ChunkedBody.new(@body, @body.opts)
|
21
|
+
end
|
22
|
+
@headers.delete_header("Content-Length")
|
23
|
+
elsif not opts[:ignore_content_length]
|
24
|
+
unless @body.is_a? BoundBody
|
25
|
+
@body = BoundBody.new(@body, @body.opts)
|
26
|
+
end
|
27
|
+
@headers.delete_header("Transfer-Encoding")
|
28
|
+
else
|
29
|
+
@body = Body.new(@body, @body.opts)
|
30
|
+
end
|
31
|
+
@body.base = self
|
32
|
+
|
33
|
+
yield(self) if block_given?
|
34
|
+
|
35
|
+
bstr = @body.to_raw
|
36
|
+
hdrs = @headers.to_raw_array.unshift(self.first_entity.to_raw)
|
37
|
+
return "#{hdrs.join("\r\n")}\r\n\r\n#{bstr}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parses a raw HTTP response and captures data into the current instance.
|
41
|
+
def capture(str)
|
42
|
+
raise "arg 0 must be a string" unless String === str
|
43
|
+
hstr, bstr = str.split(/\s*\r?\n\r?\n/, 2)
|
44
|
+
|
45
|
+
capture_headers(hstr)
|
46
|
+
|
47
|
+
yield(self, bstr) if block_given?
|
48
|
+
|
49
|
+
unless @body and @body.capture_complete?
|
50
|
+
@body =
|
51
|
+
if do_chunked_encoding?
|
52
|
+
ChunkedBody.new {|b| b.base = self }
|
53
|
+
elsif content_length()
|
54
|
+
BoundBody.new {|b| b.base = self }
|
55
|
+
else
|
56
|
+
Body.new {|b| b.base = self }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
capture_body(bstr)
|
61
|
+
|
62
|
+
return self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Indicates whether to use chunked encoding based on presence of
|
66
|
+
# the "Transfer-Encoding: chunked" header or the :ignore_chunked_encoding
|
67
|
+
# opts parameter.
|
68
|
+
def do_chunked_encoding?(hdrs=@headers)
|
69
|
+
( (not @opts[:ignore_chunked_encoding]) and
|
70
|
+
(hdrs.get_header_value("Transfer-Encoding").to_s =~ /(?:^|\W)chunked(?:\W|$)/) )
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns a new Headers object extended as ResponseHeaders. This is the
|
74
|
+
# default object which will be used when composing fresh Response header
|
75
|
+
# entities.
|
76
|
+
def default_headers_obj(*args)
|
77
|
+
Headers.new(*args).extend(ResponseHeaders)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a new BoundBody object. This is the default object which will
|
81
|
+
# be used when composing fresh Response body entities.
|
82
|
+
def default_body_obj(*args)
|
83
|
+
BoundBody.new(*args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/rbkb/plug.rb
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
module Plug
|
5
|
+
module Blit
|
6
|
+
include Base
|
7
|
+
|
8
|
+
DEFAULT_IPADDR = "127.0.0.1"
|
9
|
+
DEFAULT_PORT = 25195
|
10
|
+
DEFAULT_PROTOCOL = :TCP
|
11
|
+
|
12
|
+
OPCODES = {
|
13
|
+
0 => :squelch,
|
14
|
+
1 => :unsquelch,
|
15
|
+
2 => :delete,
|
16
|
+
5 => :sendmsg,
|
17
|
+
6 => :list_peers,
|
18
|
+
|
19
|
+
0xfe => :clear,
|
20
|
+
0xff => :kill,
|
21
|
+
}
|
22
|
+
|
23
|
+
attr_accessor :kind
|
24
|
+
|
25
|
+
def initialize(transport, slave)
|
26
|
+
super(transport)
|
27
|
+
|
28
|
+
@kind = :blitsrv
|
29
|
+
@slave = slave
|
30
|
+
@peers = slave.peers
|
31
|
+
initbuf
|
32
|
+
end
|
33
|
+
|
34
|
+
def post_init
|
35
|
+
# override so we don't get unneccessary "Start" message from Base
|
36
|
+
end
|
37
|
+
|
38
|
+
def unbind
|
39
|
+
# override so we don't get unneccessary "closed" message from Base
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
### Blit protocol stuff
|
44
|
+
SIG = "BLT"
|
45
|
+
|
46
|
+
# (re)initializes the blit buffer
|
47
|
+
def initbuf
|
48
|
+
@buf = StringIO.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def receive_data dat
|
52
|
+
return unless (@buf.write(dat) > SIG.size) or (@buf.pos > (SIG.size + 1))
|
53
|
+
|
54
|
+
@buf.rewind
|
55
|
+
|
56
|
+
return unless @buf.read(SIG.size) == SIG and
|
57
|
+
op = OPCODES[ @buf.read(1)[0] ]
|
58
|
+
|
59
|
+
initbuf if self.send(op)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def self.blit_header(op)
|
64
|
+
return nil unless opno = OPCODES.invert[op]
|
65
|
+
SIG + opno.chr
|
66
|
+
end
|
67
|
+
|
68
|
+
def mute
|
69
|
+
unless ( peerno=@buf.read(2) and peerno.size == 2 and
|
70
|
+
peer=@peers[peerno.dat_to_num(:big)] )
|
71
|
+
|
72
|
+
UI.log "** BLIT-ERROR(Malformed or missing peer for mute)"
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.make_mute(peerno)
|
78
|
+
self.blit_header(:squelch) +
|
79
|
+
peerno.to_bytes(:big, 2)
|
80
|
+
end
|
81
|
+
|
82
|
+
def unmute
|
83
|
+
unless ( peerno=@buf.read(2) and peerno.size == 2 and
|
84
|
+
peer=@peers[peerno.dat_to_num(:big)] )
|
85
|
+
UI.log "** BLIT-ERROR(Malformed or missing peer for unmute)"
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.make_squelch(peerno)
|
91
|
+
self.blit_header(:squelch) +
|
92
|
+
peerno.to_bytes(:big, 2)
|
93
|
+
end
|
94
|
+
|
95
|
+
def sendmsg
|
96
|
+
unless peerno=@buf.read(2) and peerno.size == 2 and
|
97
|
+
bufsiz=@buf.read(4) and bufsiz.size == 4
|
98
|
+
UI.log "** BLIT-ERROR(Malformed sendmsg)"
|
99
|
+
return true
|
100
|
+
end
|
101
|
+
|
102
|
+
peerno = peerno.dat_to_num(:big)
|
103
|
+
bufsiz = bufsiz.dat_to_num(:big)
|
104
|
+
|
105
|
+
if (rdat=@buf.read(bufsiz)).size == bufsiz
|
106
|
+
if peer=@peers[peerno]
|
107
|
+
peer.say(rdat, self)
|
108
|
+
return true
|
109
|
+
else
|
110
|
+
UI.log "** BLIT-ERROR(Invalid peer index #{peerno})"
|
111
|
+
return true
|
112
|
+
end
|
113
|
+
else
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Blit packed message format is (SUBJECT TO CHANGE):
|
119
|
+
# "BLT"
|
120
|
+
# char opcode
|
121
|
+
# uint16be idx = index of slave peer to send to
|
122
|
+
# uint32le size = length of data
|
123
|
+
# str data
|
124
|
+
def self.make_sendmsg(idx, dat)
|
125
|
+
self.blit_header(:sendmsg) +
|
126
|
+
idx.to_bytes(:big, 2) +
|
127
|
+
dat.size.to_bytes(:big, 4) +
|
128
|
+
dat
|
129
|
+
end
|
130
|
+
|
131
|
+
def kill
|
132
|
+
UI.log("** BLIT-KILL - Received shutdown command")
|
133
|
+
EM.stop
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.make_kill(idx=nil)
|
137
|
+
self.blit_header(:kill)
|
138
|
+
end
|
139
|
+
|
140
|
+
def clear
|
141
|
+
@peers.each { |p| p.close }
|
142
|
+
@peers.replace []
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.make_clear
|
146
|
+
self.blit_header(:clear)
|
147
|
+
end
|
148
|
+
|
149
|
+
def delete(peerno)
|
150
|
+
@peers.delete(peerno)
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.make_delete(idx=0)
|
154
|
+
self.blit_header(:delete) +
|
155
|
+
idx.to_bytes(:big, 2)
|
156
|
+
end
|
157
|
+
|
158
|
+
def list_peers
|
159
|
+
UI.log("** BLIT-LISTPEERS - Received list peers command")
|
160
|
+
|
161
|
+
@peers.each_index {|i| UI.log "** #{i} - #{@peers[i].name}"}
|
162
|
+
UI.log("** BLIT-LISTPEERS-END - End of peer list")
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.make_list_peers
|
166
|
+
self.blit_header(:list_peers)
|
167
|
+
end
|
168
|
+
|
169
|
+
#----------------------------------------------------------------------
|
170
|
+
# Convenience methods for blit clients
|
171
|
+
#----------------------------------------------------------------------
|
172
|
+
|
173
|
+
BLIT_HANDLERS = {
|
174
|
+
:TCP => lambda {|msg|
|
175
|
+
s=TCPSocket.new(@blit_addr, @blit_port)
|
176
|
+
wl=s.write(msg)
|
177
|
+
s.close
|
178
|
+
return wl
|
179
|
+
},
|
180
|
+
:UDP => lambda {|msg|
|
181
|
+
s=UDPSocket.new
|
182
|
+
wl=s.send( msg, 0, @blit_addr, @blit_port)
|
183
|
+
s.close
|
184
|
+
return wl
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
def self.blit_init(opts={})
|
189
|
+
@blit_addr = (opts[:addr] || DEFAULT_IPADDR)
|
190
|
+
@blit_port = (opts[:port] || DEFAULT_PORT)
|
191
|
+
proto = (opts[:protocol] || DEFAULT_PROTOCOL)
|
192
|
+
@blit_handler = BLIT_HANDLERS[ proto ]
|
193
|
+
raise "invalid blit transport protocol" unless @blit_handler
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.initialized?
|
197
|
+
@blit_addr and @blit_port and @blit_handler
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.blit_send(data, idx=0)
|
201
|
+
msg = make_sendmsg(idx, data)
|
202
|
+
blit_raw(msg)
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.blit_raw(buf)
|
206
|
+
raise "use blit_init first!" unless self.initialized?
|
207
|
+
@blit_handler.call buf
|
208
|
+
end
|
209
|
+
|
210
|
+
end # of module Blit
|
211
|
+
|
212
|
+
|
213
|
+
end # of module Plug
|
214
|
+
|
215
|
+
class String
|
216
|
+
#----------------------------------------------------------------------
|
217
|
+
# A Blit sender convenience method for strings
|
218
|
+
def blit(idx=0)
|
219
|
+
raise "blit must be initialized with blit_init" unless Plug::Blit.initialized?
|
220
|
+
Plug::Blit.blit_send(self, idx)
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rbkb/cli'
|
2
|
+
require 'rbkb/plug'
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
|
6
|
+
# Copyright 2009 emonti at matasano.com
|
7
|
+
# See README.rdoc for license information
|
8
|
+
#
|
9
|
+
module Rbkb::Cli
|
10
|
+
|
11
|
+
# Rbkb::Cli::Executable is an abstract class for creating command line
|
12
|
+
# executables using the Ruby Black Bag framework.
|
13
|
+
class PlugCli < Executable
|
14
|
+
RX_HOST_AND_PORT = /^([\w\._-]+):(\d+)$/
|
15
|
+
RX_PORT_OPT_ADDR = /^(?:([\w\._-]+):)?(\d+)$/
|
16
|
+
|
17
|
+
attr_accessor :blit_addr, :blit_port, :blit_proto,
|
18
|
+
:local_addr, :local_port, :transport,
|
19
|
+
:target_addr, :target_port, :plug_opts
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super(*args) do |this|
|
23
|
+
this.blit_addr ||= Plug::Blit::DEFAULT_IPADDR
|
24
|
+
this.blit_port ||= Plug::Blit::DEFAULT_PORT
|
25
|
+
this.transport ||= :TCP
|
26
|
+
this.plug_opts ||= {}
|
27
|
+
yield this if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO Plug::UI obviously need fixing.
|
31
|
+
# TODO It shouldn't be driven by constants for configuration
|
32
|
+
Plug::UI::LOGCFG[:verbose] = true
|
33
|
+
Plug::UI::LOGCFG[:dump] = :hex
|
34
|
+
Plug::UI::LOGCFG[:out] = @stderr
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_parser()
|
38
|
+
arg = super()
|
39
|
+
arg.banner << " host:port"
|
40
|
+
|
41
|
+
arg.on("-o", "--output=FILE", "Output to file") do |o|
|
42
|
+
Plug::UI::LOGCFG[:out] = File.open(o, "w") # XXX
|
43
|
+
end
|
44
|
+
|
45
|
+
arg.on("-q", "--quiet", "Turn off verbose logging") do
|
46
|
+
Plug::UI::LOGCFG[:verbose] = false # XXX
|
47
|
+
end
|
48
|
+
|
49
|
+
arg.on("-d", "--dump-format=hex/raw",
|
50
|
+
"Output conversations in hexdump or raw") do |d|
|
51
|
+
if m=/^(hex|raw)$/i.match(d)
|
52
|
+
Plug::UI::LOGCFG[:dump] = m[1].downcase.to_sym # XXX
|
53
|
+
else
|
54
|
+
bail "Invalid dump format: #{d.inspect}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
arg.on("-b", "--blit=ADDR:PORT", "Where to listen for blit") do |b|
|
59
|
+
unless m=RX_PORT_OPT_ADDR.match(b)
|
60
|
+
bail("Invalid blit address/port")
|
61
|
+
end
|
62
|
+
@blit_port = m[2].to_i
|
63
|
+
@blit_addr = m[1] if m[1]
|
64
|
+
end
|
65
|
+
|
66
|
+
arg.on("-u", "--udp", "UDP mode") { @transport=:UDP }
|
67
|
+
|
68
|
+
arg.on("-S", "--start-tls", "Initiate TLS") {|s| @plug_opts[:tls]=true }
|
69
|
+
|
70
|
+
return arg
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_target_argument()
|
74
|
+
unless (m = RX_HOST_AND_PORT.match(tgt=@argv.shift))
|
75
|
+
bail "Invalid target: #{tgt}\n Hint: use -h"
|
76
|
+
end
|
77
|
+
@target_addr = m[1]
|
78
|
+
@target_port = m[2].to_i
|
79
|
+
return m
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|