rbkb 0.6.10

Sign up to get free protection for your applications and to get access to all the features.
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
+