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.
Files changed (101) hide show
  1. data/History.txt +74 -0
  2. data/README.rdoc +149 -0
  3. data/Rakefile +47 -0
  4. data/bin/b64 +5 -0
  5. data/bin/bgrep +5 -0
  6. data/bin/blit +5 -0
  7. data/bin/c +5 -0
  8. data/bin/crc32 +5 -0
  9. data/bin/d64 +5 -0
  10. data/bin/dedump +5 -0
  11. data/bin/feed +5 -0
  12. data/bin/hexify +5 -0
  13. data/bin/len +5 -0
  14. data/bin/plugsrv +271 -0
  15. data/bin/rex +10 -0
  16. data/bin/rstrings +5 -0
  17. data/bin/slice +5 -0
  18. data/bin/telson +5 -0
  19. data/bin/unhexify +5 -0
  20. data/bin/urldec +5 -0
  21. data/bin/urlenc +5 -0
  22. data/bin/xor +5 -0
  23. data/cli_usage.rdoc +285 -0
  24. data/doctor-bag.jpg +0 -0
  25. data/lib/rbkb.rb +51 -0
  26. data/lib/rbkb/cli.rb +219 -0
  27. data/lib/rbkb/cli/b64.rb +35 -0
  28. data/lib/rbkb/cli/bgrep.rb +86 -0
  29. data/lib/rbkb/cli/blit.rb +89 -0
  30. data/lib/rbkb/cli/chars.rb +24 -0
  31. data/lib/rbkb/cli/crc32.rb +35 -0
  32. data/lib/rbkb/cli/d64.rb +28 -0
  33. data/lib/rbkb/cli/dedump.rb +52 -0
  34. data/lib/rbkb/cli/feed.rb +229 -0
  35. data/lib/rbkb/cli/hexify.rb +65 -0
  36. data/lib/rbkb/cli/len.rb +76 -0
  37. data/lib/rbkb/cli/rstrings.rb +108 -0
  38. data/lib/rbkb/cli/slice.rb +47 -0
  39. data/lib/rbkb/cli/telson.rb +87 -0
  40. data/lib/rbkb/cli/unhexify.rb +50 -0
  41. data/lib/rbkb/cli/urldec.rb +35 -0
  42. data/lib/rbkb/cli/urlenc.rb +35 -0
  43. data/lib/rbkb/cli/xor.rb +43 -0
  44. data/lib/rbkb/extends.rb +725 -0
  45. data/lib/rbkb/http.rb +21 -0
  46. data/lib/rbkb/http/base.rb +172 -0
  47. data/lib/rbkb/http/body.rb +214 -0
  48. data/lib/rbkb/http/common.rb +74 -0
  49. data/lib/rbkb/http/headers.rb +370 -0
  50. data/lib/rbkb/http/parameters.rb +104 -0
  51. data/lib/rbkb/http/request.rb +58 -0
  52. data/lib/rbkb/http/response.rb +86 -0
  53. data/lib/rbkb/plug.rb +9 -0
  54. data/lib/rbkb/plug/blit.rb +222 -0
  55. data/lib/rbkb/plug/cli.rb +83 -0
  56. data/lib/rbkb/plug/feed_import.rb +74 -0
  57. data/lib/rbkb/plug/peer.rb +67 -0
  58. data/lib/rbkb/plug/plug.rb +215 -0
  59. data/lib/rbkb/plug/proxy.rb +26 -0
  60. data/lib/rbkb/plug/unix_domain.rb +75 -0
  61. data/lib_usage.rdoc +176 -0
  62. data/rbkb.gemspec +38 -0
  63. data/spec/rbkb_spec.rb +7 -0
  64. data/spec/spec_helper.rb +16 -0
  65. data/tasks/ann.rake +80 -0
  66. data/tasks/bones.rake +20 -0
  67. data/tasks/gem.rake +201 -0
  68. data/tasks/git.rake +40 -0
  69. data/tasks/notes.rake +27 -0
  70. data/tasks/post_load.rake +34 -0
  71. data/tasks/rdoc.rake +51 -0
  72. data/tasks/rubyforge.rake +55 -0
  73. data/tasks/setup.rb +292 -0
  74. data/tasks/spec.rake +54 -0
  75. data/tasks/svn.rake +47 -0
  76. data/tasks/test.rake +40 -0
  77. data/test/test_cli_b64.rb +35 -0
  78. data/test/test_cli_bgrep.rb +137 -0
  79. data/test/test_cli_blit.rb +11 -0
  80. data/test/test_cli_chars.rb +21 -0
  81. data/test/test_cli_crc32.rb +108 -0
  82. data/test/test_cli_d64.rb +22 -0
  83. data/test/test_cli_dedump.rb +118 -0
  84. data/test/test_cli_feed.rb +11 -0
  85. data/test/test_cli_helper.rb +96 -0
  86. data/test/test_cli_hexify.rb +63 -0
  87. data/test/test_cli_len.rb +96 -0
  88. data/test/test_cli_rstrings.rb +15 -0
  89. data/test/test_cli_slice.rb +73 -0
  90. data/test/test_cli_telson.rb +11 -0
  91. data/test/test_cli_unhexify.rb +43 -0
  92. data/test/test_cli_urldec.rb +50 -0
  93. data/test/test_cli_urlenc.rb +44 -0
  94. data/test/test_cli_xor.rb +71 -0
  95. data/test/test_helper.rb +5 -0
  96. data/test/test_http.rb +27 -0
  97. data/test/test_http_helper.rb +60 -0
  98. data/test/test_http_request.rb +136 -0
  99. data/test/test_http_response.rb +222 -0
  100. data/test/test_rbkb.rb +19 -0
  101. metadata +238 -0
@@ -0,0 +1,35 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # b64 converts strings or raw data to base-64 encoding.
7
+ class Rbkb::Cli::B64 < Rbkb::Cli::Executable
8
+ def make_parser
9
+ super()
10
+ arg = @oparse
11
+ arg.banner += " <data | blank for stdin>"
12
+
13
+ add_std_file_opt(:indat)
14
+
15
+ arg.on("-l", "--length LEN", Numeric, "Output LEN chars per line") do |l|
16
+ bail("length must be > 0") unless l > 0
17
+ @opts[:len] = l
18
+ end
19
+ end
20
+
21
+ def parse(*args)
22
+ super(*args)
23
+ parse_string_argument(:indat)
24
+ parse_file_argument(:indat)
25
+ parse_catchall()
26
+ @opts[:indat] ||= @stdin.read
27
+ end
28
+
29
+ def go(*args)
30
+ super(*args)
31
+ @stdout << @opts[:indat].b64(opts[:len]).chomp + "\n"
32
+ self.exit(0)
33
+ end
34
+ end
35
+
@@ -0,0 +1,86 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # searches for a binary string in input. string can be provided 'hexified'
7
+ class Rbkb::Cli::Bgrep < Rbkb::Cli::Executable
8
+ def initialize(*args)
9
+ super(*args) do |this|
10
+ this.opts[:start_off] ||= 0
11
+ this.opts[:end_off] ||= -1
12
+ this.opts[:include_fname] ||= true
13
+ end
14
+ end
15
+
16
+ def make_parser
17
+ arg = super()
18
+ arg.banner += " <search> <file | blank for stdin>"
19
+
20
+ arg.on("-x", "--[no-]hex", "Search for hex (default: false)") do |x|
21
+ @opts[:hex] = x
22
+ end
23
+
24
+ arg.on("-r", "--[no-]regex", "Search for regex (default: false)") do |r|
25
+ @opts[:rx] = r
26
+ end
27
+
28
+ arg.on("-a", "--align=BYTES", Numeric,
29
+ "Only match on alignment boundary") do |a|
30
+ @opts[:align] = a
31
+ end
32
+
33
+ arg.on("-n", "--[no-]filename",
34
+ "Toggle filenames. (Default: #{@opts[:include_fname]})") do |n|
35
+ @opts[:include_fname] = n
36
+ end
37
+ return arg
38
+ end
39
+
40
+
41
+ def parse(*args)
42
+ super(*args)
43
+
44
+ bail "need search argument" unless @find = @argv.shift
45
+
46
+ if @opts[:hex] and @opts[:rx]
47
+ bail "-r and -x are mutually exclusive"
48
+ end
49
+
50
+ # ... filenames vs. stdin will be parsed in 'go'
51
+ end
52
+
53
+ def go(*args)
54
+ super(*args)
55
+
56
+ if @opts[:hex]
57
+ bail "you specified -x for hex and the subject isn't" unless @find.ishex?
58
+ @find = @find.unhexify
59
+ elsif @opts[:rx]
60
+ @find = Regexp.new(@find, Regexp::MULTILINE)
61
+ end
62
+
63
+ if fname = @argv.shift
64
+ dat = do_file_read(fname)
65
+ fname = nil unless @argv[0] # only print filenames for multiple files
66
+ else
67
+ dat = @stdin.read
68
+ end
69
+
70
+ loop do
71
+ dat.bgrep(@find, @opts[:align]) do |hit_start, hit_end, match|
72
+ @stdout.write "#{fname}:" if fname and @opts[:include_fname]
73
+
74
+ @stdout.write(
75
+ "#{(hit_start).to_hex.rjust(8,"0")}:"+
76
+ "#{(hit_end).to_hex.rjust(8,"0")}:b:"+
77
+ "#{match.inspect}\n")
78
+ end
79
+
80
+ break unless fname=@argv.shift
81
+ dat = do_file_read(fname)
82
+ end
83
+ self.exit(0)
84
+ end
85
+ end
86
+
@@ -0,0 +1,89 @@
1
+ require 'rbkb/cli'
2
+ require 'rbkb/plug'
3
+
4
+ # Copyright 2009 emonti at matasano.com
5
+ # See README.rdoc for license information
6
+ #
7
+ # blit is for use with any of the "plug" tools such as telson, feed, blitplug.
8
+ # It is used to send data over a socket via their OOB blit listener.
9
+ class Rbkb::Cli::Blit < Rbkb::Cli::Executable
10
+ attr_accessor :blit_msg
11
+
12
+ def initialize(*args)
13
+ super(*args)
14
+ {
15
+ :b_addr => Plug::Blit::DEFAULT_IPADDR,
16
+ :b_port => Plug::Blit::DEFAULT_PORT,
17
+ :bp_proto => :TCP,
18
+ :b_peeridx => 0,
19
+ }.each {|k, v| @opts[k] ||= v}
20
+ end
21
+
22
+ def make_parser()
23
+ super()
24
+ add_std_file_opt(:indat)
25
+ arg = @oparse
26
+
27
+ arg.banner += " <data | blank for stdin>"
28
+
29
+ arg.on("-t", "--trans-protocol=PROTO",
30
+ "Blit transport protocol TCP/UDP") do |t|
31
+ @opts[:b_proto] = t.upcase.to_sym
32
+ end
33
+
34
+ arg.on("-b", "--blitsrv=ADDR:PORT",
35
+ "Where to send blit messages") do |b|
36
+
37
+ unless(m=/^(?:([\w\.]+):)?(\d+)$/.match(b))
38
+ bail "invalid blit address/port"
39
+ end
40
+ @opts[:b_port] = m[2].to_i
41
+ @opts[:b_port] = m[1] if m[1]
42
+ end
43
+
44
+ arg.on("-i", "--peer-index=IDX", Numeric,
45
+ "Index for remote peer to receive") do |i|
46
+ @opts[:b_peeridx] = i
47
+ end
48
+
49
+ arg.on("-l", "--list-peers", "Lists the peer array for the target") do
50
+ @blit_msg = Plug::Blit.make_list_peers
51
+ end
52
+
53
+ arg.on("-k", "--kill", "Stops the remote event loop.") do
54
+ @blit_msg = Plug::Blit.make_kill
55
+ end
56
+
57
+ return arg
58
+ end
59
+
60
+ def parse(*args)
61
+ super(*args)
62
+
63
+ unless @blit_msg
64
+ if @opts[:indat].nil?
65
+ @opts[:indat] = (@argv.length > 0)? @argv.join(" ") : @stdin.read()
66
+ end
67
+ @blit_msg = Plug::Blit.make_sendmsg(@opts[:b_peeridx], @opts[:indat])
68
+ end
69
+ end
70
+
71
+ def go(*args)
72
+ super(*args)
73
+
74
+ begin
75
+ Plug::Blit.blit_init(
76
+ :addr => @opts[:b_addr],
77
+ :port => @opts[:b_port],
78
+ :protocol => @opts[:b_proto]
79
+ )
80
+
81
+ Plug::Blit.blit_raw(@blit_msg)
82
+ rescue
83
+ bail($!)
84
+ end
85
+
86
+ self.exit(0)
87
+ end
88
+
89
+ end
@@ -0,0 +1,24 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # Repeats an argument N times
7
+ class Rbkb::Cli::Chars < Rbkb::Cli::Executable
8
+ def make_parser
9
+ super()
10
+ @oparse.banner += " 100 A; # print 100 A's"
11
+ end
12
+
13
+ def parse(*args)
14
+ super(*args)
15
+ bail_args @argv.join(' ') unless @argv.size == 2
16
+ end
17
+
18
+ def go(*args)
19
+ super(*args)
20
+ @stdout << @argv[1] * @argv[0].to_i
21
+ self.exit(0)
22
+ end
23
+ end
24
+
@@ -0,0 +1,35 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # crc32 returns a crc32 checksum in hex from stdin or a file
7
+ class Rbkb::Cli::Crc32 < Rbkb::Cli::Executable
8
+ def initialize(*args)
9
+ super(*args)
10
+ @opts[:first] ||= 0
11
+ @opts[:last] ||= -1
12
+ end
13
+
14
+ def make_parser()
15
+ arg = super()
16
+ arg.banner += " [filename]"
17
+ add_std_file_opt(:indat)
18
+ add_range_opts(:first, :last)
19
+ end
20
+
21
+ def parse(*args)
22
+ super(*args)
23
+ parse_file_argument(:indat)
24
+ parse_catchall()
25
+ end
26
+
27
+ def go(*args)
28
+ super(*args)
29
+ @opts[:indat] ||= @stdin.read()
30
+ @stdout.puts @opts[:indat][ @opts[:first] .. @opts[:last] ].crc32.to_hex
31
+ self.exit(0)
32
+ end
33
+ end
34
+
35
+
@@ -0,0 +1,28 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # d64 converts a base-64 encoded string back to its orginal form.
7
+ class Rbkb::Cli::D64 < Rbkb::Cli::Executable
8
+ def make_parser
9
+ super()
10
+ @oparse.banner += " <data | blank for stdin>"
11
+ add_std_file_opt(:indat)
12
+ end
13
+
14
+ def parse(*args)
15
+ super(*args)
16
+ parse_string_argument(:indat)
17
+ parse_file_argument(:indat)
18
+ parse_catchall()
19
+ @opts[:indat] ||= @stdin.read
20
+ end
21
+
22
+ def go(*args)
23
+ super(*args)
24
+ @stdout << @opts[:indat].d64
25
+ self.exit(0)
26
+ end
27
+ end
28
+
@@ -0,0 +1,52 @@
1
+ require 'rbkb/cli'
2
+
3
+ # Copyright 2009 emonti at matasano.com
4
+ # See README.rdoc for license information
5
+ #
6
+ # Reverses a hexdump back to raw data. Designed to work with hexdumps created
7
+ # by Unix utilities like 'xxd' as well as 'hexdump -C'.
8
+ class Rbkb::Cli::Dedump < Rbkb::Cli::Executable
9
+ def initialize(*args)
10
+ super(*args) {|this|
11
+ this.opts[:len] ||= 16
12
+ yield this if block_given?
13
+ }
14
+ end
15
+
16
+ def make_parser()
17
+ arg = super()
18
+ arg.banner += " <input-file | blank for stdin>"
19
+
20
+ arg.on("-l", "--length LEN", Numeric,
21
+ "Bytes per line in hexdump (Default: #{@opts[:len]})") do |l|
22
+ bail("Length must be greater than zero") unless (@opts[:len] = l) > 0
23
+ end
24
+ return arg
25
+ end
26
+
27
+ def parse(*args)
28
+ super(*args)
29
+ parse_file_argument(:indat)
30
+ parse_catchall()
31
+ end
32
+
33
+ def go(*args)
34
+ super(*args)
35
+
36
+ # Default to standard input
37
+ @opts[:indat] ||= @stdin.read()
38
+
39
+ self.exit(1) unless((@opts[:len] ||= @opts[:indat].length) > 0)
40
+
41
+ begin
42
+ @opts[:indat].dehexdump( :len => @opts[:len], :out => @stdout)
43
+ rescue
44
+ bail "Error: #{$!}"
45
+ end
46
+
47
+ self.exit(0)
48
+ end
49
+ end
50
+
51
+
52
+
@@ -0,0 +1,229 @@
1
+ require 'rbkb/cli'
2
+ require 'rbkb/plug'
3
+ require 'rbkb/plug/feed_import'
4
+ require 'eventmachine'
5
+
6
+ # Copyright 2009 emonti at moatasano dot com
7
+ # See README.rdoc for license information
8
+ #
9
+ # This is a plug-board message feeder from static data sources.
10
+ # The "feed" handles messages opaquely and just plays them in the given
11
+ # sequence.
12
+ #
13
+ # Feed can do the following things with minimum fuss:
14
+ # - Import messages from files, yaml, or pcap
15
+ # - Inject custom/modified messages with "blit"
16
+ # - Run as a server or client using UDP or TCP
17
+ # - Bootstrap protocols without a lot of work up front
18
+ # - Skip uninteresting messages and focus attention on the fun ones.
19
+ # - Replay conversations for relatively unfamiliar protocols.
20
+ # - Observe client/server behaviors using different messages at
21
+ # various phases of a conversation.
22
+ #
23
+ # To-dos / Ideas:
24
+ # - Unix Domain Socket support?
25
+ # - more import options?
26
+ # - dynamic feed elements?
27
+ # - add/control feed elements while 'stepping'?
28
+ #
29
+
30
+ class Rbkb::Cli::Feed < Rbkb::Cli::Executable
31
+ def initialize(*args)
32
+ @local_addr = "0.0.0.0"
33
+ @local_port = nil
34
+ @listen = false
35
+ @persist = false
36
+ @transport = :TCP
37
+ @svr_method = :start_server
38
+ @cli_method = :bind_connect
39
+ @blit_addr = Plug::Blit::DEFAULT_IPADDR
40
+ @blit_port = Plug::Blit::DEFAULT_PORT
41
+
42
+
43
+ ## Default options sent to the Feed handler
44
+ @feed_opts = {
45
+ :close_at_end => false,
46
+ :step => false,
47
+ :go_first => false
48
+ }
49
+
50
+ super(*args)
51
+
52
+ # TODO Plug::UI obviously need fixing.
53
+ # TODO It shouldn't be driven by constants for configuration
54
+ Plug::UI::LOGCFG[:verbose] = true
55
+ Plug::UI::LOGCFG[:dump] = :hex
56
+ Plug::UI::LOGCFG[:out] = @stderr
57
+ end
58
+
59
+ def make_parser()
60
+ arg = super()
61
+ arg.banner += " host:port"
62
+
63
+ arg.on("-o", "--output=FILE", "Output to file") do |o|
64
+ Plug::UI::LOGCFG[:out] = File.open(o, "w")
65
+ end
66
+
67
+ arg.on("-l", "--listen=(ADDR:?)PORT", "Server - on port (and addr?)") do |p|
68
+ if m=/^(?:([\w\._-]+):)?(\d+)$/.match(p)
69
+ @local_addr = $1 if $1
70
+ @local_port = $2.to_i
71
+ @listen = true
72
+ else
73
+ raise "Invalid listen argument: #{p.inspect}"
74
+ end
75
+ end
76
+
77
+ arg.on("-s", "--source=(ADDR:?)PORT", "Bind client on port and addr") do |p|
78
+ if m=/^(?:([\w\.]+):)?(\d+)$/.match(p)
79
+ @local_addr = $1 if $1
80
+ @local_port = $2.to_i
81
+ else
82
+ bail("Invalid source argument: #{p.inspect}")
83
+ end
84
+ end
85
+
86
+ arg.on("-b", "--blit=(ADDR:)?PORT", "Where to listen for blit") do |b|
87
+ puts b
88
+ unless(m=/^(?:([\w\._-]+):)?(\d+)$/.match(b))
89
+ raise "Invalid blit argument: #{b.inspect}"
90
+ end
91
+ @blit_port = m[2].to_i
92
+ @blit_addr = m[1] if m[1]
93
+ end
94
+
95
+ arg.on("-i", "--[no-]initiate", "Send the first message on connect") do |i|
96
+ @feed_opts[:go_first] = i
97
+ end
98
+
99
+ arg.on("-e", "--[no-]end", "End connection when feed is exhausted") do |c|
100
+ @feed_opts[:close_at_end] = c
101
+ end
102
+
103
+ arg.on("--[no-]step", "'Continue' prompt between messages") do |s|
104
+ @feed_opts[:step] = s
105
+ end
106
+
107
+ arg.on("-u", "--udp", "Use UDP instead of TCP" ) do
108
+ @transport = :UDP
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("-Q", "--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
+ end
153
+
154
+ def parse(*args)
155
+ super(*args)
156
+
157
+ if @transport == :UDP
158
+ @svr_method = @cli_method = :open_datagram_socket
159
+ end
160
+
161
+ @local_port ||= 0
162
+ # Prepare EventMachine arguments based on whether we are a client or server
163
+ if @listen # server
164
+ @meth = @svr_method
165
+ addr_args = [@local_addr, @local_port]
166
+ @feed_opts[:kind] = :server
167
+ @feed_opts[:no_stop_on_unbind] = true
168
+ else # client
169
+
170
+ ## Get target/listen argument for client mode
171
+ unless (m = /^([\w\.]+):(\d+)$/.match(tgt=@argv.shift))
172
+ bail_args tgt
173
+ end
174
+
175
+ @target_addr = m[1]
176
+ @target_port = m[2].to_i
177
+
178
+ if @transport == :UDP
179
+ addr_args = [@local_addr, @local_port]
180
+ else
181
+ addr_args = [@local_addr, @local_port, @target_addr, @target_port]
182
+ end
183
+
184
+ @meth = @cli_method
185
+ @feed_opts[:kind] = :client
186
+ end
187
+
188
+ @feed_opts[:feed] ||= []
189
+
190
+ @em_args=[
191
+ @meth,
192
+ addr_args,
193
+ Plug::ArrayFeeder,
194
+ @transport,
195
+ @feed_opts
196
+ ].flatten
197
+
198
+ parse_catchall()
199
+ end
200
+
201
+
202
+ def go(*args)
203
+ super(*args)
204
+
205
+ Plug::UI.verbose "** FEED CONTAINS #{@feed_opts[:feed].size} MESSAGES"
206
+
207
+ ## Start the eventmachine
208
+ loop do
209
+ EventMachine::run do
210
+ EventMachine.send(*@em_args) do |c|
211
+ EventMachine.start_server(@blit_addr, @blit_port, Plug::Blit, :TCP, c)
212
+ Plug::UI::verbose("** BLITSRV-#{@blit_addr}:#{@blit_port}(TCP) Started")
213
+
214
+ # if this is a UDP client, we will always send the first message
215
+ if [:UDP, :client] == [@transport, c.kind]
216
+ peer = c.peers.add_peer_manually(@target_addr, @target_port)
217
+ c.feed_data(peer)
218
+ c.go_first = false
219
+ end
220
+ end
221
+ end
222
+
223
+ break unless @persist
224
+ Plug::UI::verbose("** RECONNECTING")
225
+ end
226
+
227
+ end
228
+ end
229
+