rbkb 0.6.12 → 0.7.0

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.
Files changed (50) hide show
  1. checksums.yaml +15 -0
  2. data/.bnsignore +25 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +27 -0
  6. data/History.txt +8 -0
  7. data/LICENSE.txt +22 -0
  8. data/Rakefile +10 -45
  9. data/experimental/cap2files +21 -0
  10. data/experimental/cap2yaml +20 -0
  11. data/experimental/colordif.rb +72 -0
  12. data/experimental/deezee +91 -0
  13. data/experimental/feed +225 -0
  14. data/experimental/fmagic.rb +51 -0
  15. data/experimental/magicrip.c +92 -0
  16. data/experimental/magicripper.rb +63 -0
  17. data/lib/rbkb.rb +2 -48
  18. data/lib/rbkb/cli.rb +3 -2
  19. data/lib/rbkb/cli/bgrep.rb +1 -4
  20. data/lib/rbkb/cli/blit.rb +4 -0
  21. data/lib/rbkb/cli/crc32.rb +4 -1
  22. data/lib/rbkb/cli/dedump.rb +1 -0
  23. data/lib/rbkb/cli/rstrings.rb +1 -7
  24. data/lib/rbkb/extends.rb +8 -787
  25. data/lib/rbkb/extends/array.rb +29 -0
  26. data/lib/rbkb/extends/common.rb +13 -0
  27. data/lib/rbkb/extends/enumerable.rb +9 -0
  28. data/lib/rbkb/extends/float.rb +17 -0
  29. data/lib/rbkb/extends/numeric.rb +83 -0
  30. data/lib/rbkb/extends/object.rb +7 -0
  31. data/lib/rbkb/extends/string.rb +624 -0
  32. data/lib/rbkb/extends/symbol.rb +8 -0
  33. data/lib/rbkb/plug/blit.rb +21 -1
  34. data/lib/rbkb/plug/peer.rb +5 -0
  35. data/lib/rbkb/plug/plug.rb +6 -2
  36. data/lib/rbkb/version.rb +3 -0
  37. data/rbkb.gemspec +20 -34
  38. data/reference/blackbag-0.9.1.tgz +0 -0
  39. data/reference/note_http_unit_tests +3 -0
  40. data/spec/spec_helper.rb +5 -14
  41. data/spec/string_extends_spec.rb +129 -0
  42. data/test/{test_cli_blit.rb → disabled_test_cli_blit.rb} +0 -0
  43. data/test/{test_cli_feed.rb → disabled_test_cli_feed.rb} +0 -0
  44. data/test/{test_cli_telson.rb → disabled_test_cli_telson.rb} +0 -0
  45. data/test/test_cli_chars.rb +2 -0
  46. data/test/test_cli_helper.rb +3 -5
  47. data/test/test_cli_rstrings.rb +2 -0
  48. data/test/test_helper.rb +8 -0
  49. metadata +107 -89
  50. data/test/test_rbkb.rb +0 -19
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NmUwMGU3OGM4ZTEwZTZjMWViOTQxODg1NWNjODVmZWRhOWI1ZTY3Mg==
5
+ data.tar.gz: !binary |-
6
+ YWIwMTg4MjliZWVjOTZjNjg3ZjQ4YWI5NTE2MTQ5ZDk1MzNhNTQwMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MzAwYjE4ZDEyNDdjZDZhZTJiODFkNDc5MWU0NDNhZjQ4YTM4Y2JiMzY4NWQx
10
+ MzMwMDk5MTJjNzA1OGM0ZGRhOTU3NDRiNTVhMWIzNGJlYWU5NjBjZTYwZDc4
11
+ Y2Q0ODY0YjE3NGNjOGY4ZTE3MmY0MTA3MTY0NmI2YWZiMGMzMDU=
12
+ data.tar.gz: !binary |-
13
+ ODkwNzFkZWY2ZmQ2NzIzZWM2NWNmM2NkMDIyM2ZkYWQzNjcwYjQwZTc0NzM2
14
+ MzE2YjBhN2E4NjQ3YWU1NjkzMTY0NTg0Y2UzMzZlMjk2M2Y3ZWJmODBiZDY2
15
+ MDBhNjdiNDc2YTY3YzE2M2RjMzhjY2FkMzg5NjEwMzA1OTZjOTc=
data/.bnsignore ADDED
@@ -0,0 +1,25 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # PROJ.ignore_file = '.gitignore'
8
+ #
9
+ # For a project with a C extension, the following would be a good set of
10
+ # exclude patterns (uncomment them if you want to use them):
11
+ # *.[oa]
12
+
13
+ .*
14
+ *~
15
+ *.swp
16
+ .*.swp
17
+ .yardoc
18
+ announcement.txt
19
+ coverage*/
20
+ doc
21
+ pkg
22
+ bin/experimental
23
+ reference
24
+ *.gem
25
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rbkb.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rbkb (0.7.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.1)
10
+ rake (10.1.0)
11
+ rspec (2.13.0)
12
+ rspec-core (~> 2.13.0)
13
+ rspec-expectations (~> 2.13.0)
14
+ rspec-mocks (~> 2.13.0)
15
+ rspec-core (2.13.1)
16
+ rspec-expectations (2.13.0)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.13.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.3)
25
+ rake
26
+ rbkb!
27
+ rspec
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.6.14 / 2010-11-29
2
+ * Minor fixes to cli offset and integer hexification formatting
3
+ * Unit tests got some more love for ruby 1.9 unit test compatability
4
+
5
+ == 0.6.13 / 2009-10-15
6
+ * got strings working using scan() in 1.9 had to punt ':align' option for now
7
+ * Added -S (starttls) arg. to blit for initiating SSL on a plug peer
8
+
1
9
  == 0.6.12 / 2009-10-15
2
10
  * better ruby 1.8 <-> 1.9 portability
3
11
  * tweaked rotate_bytes to "wrap" on char boundary and rotate backwards safely
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Eric Monti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,47 +1,12 @@
1
- # Look in the tasks/setup.rb file for the various options that can be
2
- # configured in this Rakefile. The .rake files in the tasks directory
3
- # are where the options are used.
1
+ require "bundler/gem_tasks"
4
2
 
5
- begin
6
- require 'bones'
7
- Bones.setup
8
- rescue LoadError
9
- begin
10
- load 'tasks/setup.rb'
11
- rescue LoadError
12
- raise RuntimeError, '### please install the "bones" gem ###'
13
- end
14
- end
15
-
16
- ensure_in_path 'lib'
17
- require 'rbkb'
18
-
19
- task :default => 'test:run'
20
-
21
- PROJ.name = 'rbkb'
22
- PROJ.authors = 'Eric Monti'
23
- PROJ.email = 'emonti@matasano.com'
24
- PROJ.description = 'Rbkb is a collection of ruby-based pen-testing and reversing tools. Inspired by Matasano Blackbag.'
25
- PROJ.url = 'http://emonti.github.com/rbkb'
26
- PROJ.version = Rbkb::VERSION
27
- PROJ.rubyforge.name = 'rbkb'
28
- PROJ.readme_file = 'README.rdoc'
29
-
30
- PROJ.spec.opts << '--color'
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new
5
+ task :default => :spec
31
6
 
32
- PROJ.rdoc.opts << '--line-numbers'
33
-
34
- #PROJ.rdoc.opts << '--diagram'
35
- PROJ.notes.tags << "X"+"XX" # muhah! so we don't note our-self
36
-
37
- # exclude rcov.rb and external libs from rcov report
38
- PROJ.rcov.opts += [
39
- "--exclude", "rcov.rb",
40
- "--exclude", "eventmachine",
41
- "--exclude", "pcap_misc.rb",
42
- "--exclude", "pcaplet.rb"
43
- ]
44
-
45
- depend_on 'eventmachine', '>= 0.12.8'
46
-
47
- # EOF
7
+ require 'rake/testtask'
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.test_files = FileList['test/test*.rb']
11
+ t.verbose = true
12
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # extracts UDP/TCP data payload from packets to numbered files
3
+ # Usage: cap2files out_prefix pcap-file [filter]]
4
+
5
+ require 'rbkb/plug/feed_import'
6
+
7
+ begin
8
+ unless prefix = ARGV.shift and file = ARGV.shift
9
+ raise "Usage: #{File.basename $0} out_prefix pcap-file [filter]"
10
+ end
11
+
12
+ filter = ARGV.join(" ")
13
+
14
+ caps = FeedImport.import_pcap(file, filter)
15
+ i=0
16
+ caps.each {|p| File.open("#{prefix}.#{i}", "w") {|f| f.write p }; i+=1 }
17
+ rescue
18
+ STDERR.puts $!
19
+ exit 1
20
+ end
21
+
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # extracts UDP/TCP data payload from packets to an array encapsulated in yaml
3
+ # Usage: cap2yaml pcap-file [filter]]
4
+
5
+ require 'rbkb/plug/feed_import'
6
+
7
+ begin
8
+ unless file = ARGV.shift
9
+ raise "Usage: #{File.basename $0} pcap-file [filter]"
10
+ end
11
+
12
+ filter = ARGV.join(" ")
13
+
14
+ caps = FeedImport.import_pcap(file, filter)
15
+ puts caps.to_yaml
16
+ rescue
17
+ STDERR.puts $!
18
+ exit 1
19
+ end
20
+
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Sort of like vbindiff, except smaller with less functionality, and in our toolshed ;)
4
+ # Useful for encoded HTTP parameters, raw dumped pkts and other little things
5
+ # todo: print out like hexdump -C
6
+ # Chris at mtso
7
+
8
+ module ColorConstants
9
+ BLACK = "\e[1;30m"
10
+ RED = "\e[1;31m"
11
+ GREEN = "\e[1;32m"
12
+ BROWN = "\e[1;33m"
13
+ BLUE = "\e[1;34m"
14
+ PURPLE = "\e[1;35m"
15
+ CYAN = "\e[1;36m"
16
+ GRAY = "\e[1;37m"
17
+ NO_COLOR = "\e[0m"
18
+ end
19
+
20
+ class ColorDif
21
+
22
+ attr_accessor :file1, :file2
23
+
24
+ def initialize(file1, file2)
25
+ @file1 = IO.read(file1)
26
+ @file2 = IO.read(file2)
27
+ end
28
+
29
+ # Theres definitely a more elegant way to do this, whatever ...
30
+ def diffem
31
+ puts "\nFile 1 [#{file1.size} bytes]"
32
+ puts "File 2 [#{file2.size} bytes]\n\n"
33
+
34
+ count = 0
35
+
36
+ @file1.each_byte do |byte|
37
+ if byte == @file2[count]
38
+ print sprintf(ColorConstants::BLUE + "%02x ", byte)
39
+ else
40
+ print sprintf(ColorConstants::RED + "%02x ", byte)
41
+ end
42
+
43
+ count = count+1
44
+
45
+ if count % 32 == 0
46
+ print "\n"
47
+ end
48
+ end
49
+
50
+ puts ColorConstants::NO_COLOR + "\n---"
51
+ count = 0
52
+
53
+ @file2.each_byte do |byte|
54
+ if byte == @file1[count]
55
+ print sprintf(ColorConstants::BLUE + "%02x ", byte)
56
+ else
57
+ print sprintf(ColorConstants::RED + "%02x ", byte)
58
+ end
59
+
60
+ count = count+1
61
+
62
+ if count % 32 == 0
63
+ print "\n"
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ f = ColorDif.new(ARGV[0], ARGV[1])
70
+ f.diffem
71
+
72
+ puts ColorConstants::NO_COLOR + "\n\n"
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ # (emonti at matasano) Matasano Security LLC 2008
3
+
4
+ require 'rbkb'
5
+ require 'rbkb/command_line'
6
+ require 'stringio'
7
+
8
+ include RBkB::CommandLine
9
+
10
+ first = 0
11
+ last = nil
12
+ verbose=true
13
+
14
+ #------------------------------------------------------------------------------
15
+ # Init options and arg parsing
16
+ OPTS = {:len => 16}
17
+ arg = bkb_stdargs(nil, OPTS)
18
+
19
+ arg.banner += " <input-file | blank for stdin>"
20
+
21
+ arg.on("-q", "--[no-]quiet", "Stifle extra data info") {|q| verbose=(!q)}
22
+ arg.on("-s", "--start=OFF", Numeric, "Start at offset") {|s| first=s}
23
+ arg.on("-e", "--end=OFF", Numeric, "End at offset") {|e| last=e}
24
+
25
+ begin
26
+ #----------------------------------------------------------------------------
27
+ # Parse arguments
28
+
29
+ arg.parse!(ARGV)
30
+
31
+ inp = nil
32
+
33
+ if inpname=ARGV.shift
34
+ inp=File.open(inpname, "rb") rescue "Error: Can't open file '#{a}'"
35
+ else
36
+ inp = StringIO.new(STDIN.read())
37
+ inpname="stdin"
38
+ end
39
+
40
+ # catchall
41
+ if ARGV.length != 0
42
+ raise "bad arguments - #{ARGV.join(' ')}"
43
+ end
44
+
45
+ #----------------------------------------------------------------------------
46
+ # Do stuff
47
+
48
+ # Right now this only handles gzip files... no deflate, no stream, no raw LZ
49
+ gzc = "\x1f\x8b"
50
+
51
+ off = inp.pos = first
52
+ until inp.eof? or (last and inp.pos >= last)
53
+ # grab 2 byte signature
54
+ sig = inp.read(2)
55
+
56
+ break if inp.eof?
57
+
58
+ # compare with gzip signature
59
+ if sig == gzc
60
+ # return to start position
61
+ off = (inp.pos -= 2)
62
+
63
+ begin
64
+ gz = Zlib::GzipReader.new(inp)
65
+ dat = gz.read
66
+ gz_size = inp.pos
67
+
68
+ STDERR.puts "** %d bytes of gzip @ %0.8x" %[gz_size, off]
69
+ if verbose
70
+ STDERR.puts " Extra info:"
71
+ STDERR.puts " inflated size = #{ dat.size}"
72
+ gz.get_xtra_info.sort {|a,b| a.to_s <=> b.to_s }.each do |k,v|
73
+ STDERR.puts "#{k.to_s.rjust(18)} = #{v.inspect}"
74
+ end
75
+ end
76
+
77
+ # XXX assuming no better than 15% compression rate?
78
+ inp.pos = inp.pos / 4
79
+ next
80
+ rescue
81
+ end
82
+ end
83
+
84
+ # start again from next byte
85
+ off = (inp.pos -= 1)
86
+ end
87
+ rescue
88
+ bail $!
89
+ end
90
+
91
+
data/experimental/feed ADDED
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env ruby
2
+ # feed <emonti at matasano> 3/15/2008
3
+ #----------------------------------------------------------------------
4
+ #
5
+ # This is an eventmachine message feeder from static data sources.
6
+ # The "feed" handles messages opaquely and just plays them in the given
7
+ # sequence.
8
+ #
9
+ # Feed can do the following things with minimum fuss:
10
+ # - Import messages from files, yaml, or pcap
11
+ # - Inject custom/modified messages with "blit"
12
+ # - Run as a server or client using UDP or TCP
13
+ # - Bootstrap protocols without a lot of work up front
14
+ # - Skip uninteresting messages and focus attention on the fun ones.
15
+ # - Replay conversations for relatively unfamiliar protocols.
16
+ # - Observe client/server behaviors using different messages at
17
+ # various phases of a conversation.
18
+ #
19
+ #----------------------------------------------------------------------
20
+ #
21
+ # Usage: feed -h
22
+ #
23
+ #----------------------------------------------------------------------
24
+ # To-dos / Ideas:
25
+ # - Unix Domain Socket support?
26
+ # - more import options?
27
+ # - dynamic feed elements?
28
+ # - add/control feed elements while 'stepping'?
29
+ #
30
+
31
+ require 'rubygems'
32
+ require 'eventmachine'
33
+ require 'rbkb'
34
+ require 'rbkb/plug'
35
+ require 'rbkb/plug/feed_import'
36
+ require 'rbkb/command_line'
37
+
38
+ include RBkB::CommandLine
39
+
40
+ ## Default "UI" options
41
+ Plug::UI::LOGCFG[:verbose] = true
42
+ Plug::UI::LOGCFG[:dump] = :hex
43
+
44
+ ## Default options sent to the Feed handler
45
+ FEED_OPTS = {
46
+ :close_at_end => false,
47
+ :step => false,
48
+ :go_first => false
49
+ }
50
+
51
+ my_addr = "0.0.0.0"
52
+ my_port = nil
53
+ listen = false
54
+ persist = false
55
+
56
+ transport = :TCP
57
+
58
+ svr_method = :start_server
59
+ cli_method = :connect
60
+
61
+
62
+ b_addr = Plug::Blit::DEFAULT_IPADDR
63
+ b_port = Plug::Blit::DEFAULT_PORT
64
+
65
+ ## Parse command-line options
66
+ arg = bkb_stdargs(nil, {})
67
+ arg.banner += " host:port"
68
+
69
+ arg.separator " Options:"
70
+
71
+ arg.on("-o", "--output=FILE", "Output to file") do |o|
72
+ Plug::UI::LOGCFG[:out] = File.open(o, "w")
73
+ end
74
+
75
+ arg.on("-l", "--listen=(ADDR:?)PORT", "Server - on port (and addr?)") do |p|
76
+ if m=/^(?:([\w\.]+):)?(\d+)$/.match(p)
77
+ my_addr = $1 if $1
78
+ my_port = $2.to_i
79
+ listen = true
80
+ else
81
+ raise "Invalid listen argument: #{p.inspect}"
82
+ end
83
+ end
84
+
85
+ arg.on("-b", "--blit=(ADDR:)?PORT", "Where to listen for blit") do |b|
86
+ puts b
87
+ unless(m=/^(?:([\w\.]+):)?(\d+)$/.match(b))
88
+ raise "Invalid blit argument: #{b.inspect}"
89
+ end
90
+ b_port = m[2].to_i
91
+ b_addr = m[1] if m[1]
92
+ end
93
+
94
+ arg.on("-i", "--[no-]initiate", "Send the first message on connect") do |i|
95
+ FEED_OPTS[:go_first] = i
96
+ end
97
+
98
+ arg.on("-e", "--[no-]end", "End connection when feed is exhausted") do |c|
99
+ FEED_OPTS[:close_at_end] = c
100
+ end
101
+
102
+ arg.on("-s", "--[no-]step", "'Continue' prompt between messages") do |s|
103
+ FEED_OPTS[:step] = s
104
+ end
105
+
106
+ arg.on("-u", "--udp", "Use UDP instead of TCP" ) do
107
+ transport = :UDP
108
+ svr_method = cli_method = :open_datagram_socket
109
+ end
110
+
111
+ arg.on("-r", "--reconnect", "Attempt to reconnect endlessly.") do
112
+ persist=true
113
+ end
114
+
115
+ arg.on("-q", "--quiet", "Suppress verbose messages/dumps") do
116
+ Plug::UI::LOGCFG[:verbose] = false
117
+ end
118
+
119
+ arg.on("-S", "--squelch-exhausted", "Squelch 'FEED EXHAUSTED' messages") do |s|
120
+ FEED_OPTS[:squelch_exhausted] = true
121
+ end
122
+
123
+ arg.separator " Sources: (can be combined)"
124
+
125
+ arg.on("-f", "--from-files=GLOB", "Import messages from raw files") do |f|
126
+ FEED_OPTS[:feed] ||= []
127
+ FEED_OPTS[:feed] += FeedImport.import_rawfiles(f)
128
+ end
129
+
130
+ arg.on("-x", "--from-hex=FILE", "Import messages from hexdumps") do |x|
131
+ FEED_OPTS[:feed] ||= []
132
+ FEED_OPTS[:feed] += FeedImport.import_dump(x)
133
+ end
134
+
135
+ arg.on("-y", "--from-yaml=FILE", "Import messages from yaml") do |y|
136
+ FEED_OPTS[:feed] ||= []
137
+ FEED_OPTS[:feed] += FeedImport.import_yaml(y)
138
+ end
139
+
140
+ arg.on("-p", "--from-pcap=FILE[:FILTER]", "Import messages from pcap") do |p|
141
+ if /^([^:]+):(.+)$/.match(p)
142
+ file = $1
143
+ filter = $2
144
+ else
145
+ file = p
146
+ filter = nil
147
+ end
148
+
149
+ FEED_OPTS[:feed] ||= []
150
+ FEED_OPTS[:feed] += FeedImport.import_pcap(file, filter)
151
+ end
152
+
153
+ arg.parse!(ARGV) rescue bail "Error: #{$!}\nUse -h|--help for more info."
154
+
155
+ # parse OptionParser and import feed
156
+ begin
157
+ arg.parse!(ARGV)
158
+
159
+ # Prepare EventMachine arguments based on whether we are a client or server
160
+ if listen
161
+ evma_addr = my_addr
162
+ evma_port = my_port
163
+ meth = svr_method
164
+ FEED_OPTS[:kind] = :server
165
+ else
166
+
167
+ ## Get target/listen argument for client mode
168
+ unless (m = /^([\w\.]+):(\d+)$/.match(ARGV.shift)) and ARGV.shift.nil?
169
+ bail arg
170
+ end
171
+
172
+ t_addr = m[1]
173
+ t_port = m[2].to_i
174
+
175
+ if transport == :UDP
176
+ evma_addr = my_addr
177
+ evma_port = my_port || 0
178
+ else
179
+ evma_addr = t_addr
180
+ evma_port = t_port
181
+ end
182
+
183
+ meth = cli_method
184
+ FEED_OPTS[:kind] = :client
185
+ end
186
+
187
+ FEED_OPTS[:feed] ||= []
188
+ Plug::UI.verbose "** FEED CONTAINS #{FEED_OPTS[:feed].size} MESSAGES"
189
+
190
+ ## error out on unexpected arguments
191
+ raise "too many arguments" if ARGV.shift
192
+ rescue
193
+ bail "Error: #{$!}\nUse -h|--help for more information"
194
+ end
195
+
196
+
197
+ em_args=[
198
+ meth,
199
+ evma_addr,
200
+ evma_port,
201
+ Plug::ArrayFeeder,
202
+ transport,
203
+ FEED_OPTS
204
+ ].flatten
205
+
206
+
207
+ ## Start the eventmachine
208
+ loop do
209
+ EventMachine::run do
210
+ EventMachine.send(*em_args) do |c|
211
+ EventMachine.start_server(b_addr, b_port, Plug::Blit, :TCP, c)
212
+ Plug::UI::verbose("** BLITSRV-#{b_addr}:#{b_port}(TCP) Started")
213
+
214
+ # if this is a UDP client, we will always send the first message
215
+ if transport == :UDP and c.kind == :client and
216
+ c.feed_data(c.peers.add_peer_manually(t_addr, t_port))
217
+ c.go_first = false
218
+ end
219
+ end
220
+ end
221
+
222
+ break unless persist
223
+ Plug::UI::verbose("** RECONNECTING")
224
+ end
225
+