compatibility to nsca-2.9 (NSCA::Packet3__2_9)
This commit is contained in:
parent
8249577e7a
commit
a2b6bde057
50
lib/nsca.rb
50
lib/nsca.rb
|
@ -18,6 +18,35 @@ module NSCA
|
||||||
clname[0] = clname[0].upcase
|
clname[0] = clname[0].upcase
|
||||||
clname.to_sym
|
clname.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def xor_stream key
|
||||||
|
key = case key
|
||||||
|
when Array then key
|
||||||
|
when String then key.bytes.to_a
|
||||||
|
when Enumerable then key.to_a
|
||||||
|
end
|
||||||
|
return lambda{|x|x} if [nil, '', []].include? key
|
||||||
|
length = key.length
|
||||||
|
i = 0
|
||||||
|
lambda do |str|
|
||||||
|
r = ''
|
||||||
|
str.bytes.each_with_index do |c, j|
|
||||||
|
r[j] = (c ^ key[i]).chr
|
||||||
|
i = (i + 1) % length
|
||||||
|
end
|
||||||
|
r
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def crc32_stream
|
||||||
|
sum = 0xFFFFFFFF
|
||||||
|
lambda do |str|
|
||||||
|
sum = str.bytes.inject sum do |r, b|
|
||||||
|
8.times.inject( r^b) {|r,_i| (r>>1) ^ (0xEDB88320 * (r&1)) }
|
||||||
|
end if str
|
||||||
|
sum ^ 0xFFFFFFFF
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -28,6 +57,27 @@ module NSCA
|
||||||
NSCA.destinations.each {|server| server.send *results }
|
NSCA.destinations.each {|server| server.send *results }
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def xor key, msg = nil, key_a = nil
|
||||||
|
NSCA::Helper.xor_stream( key_a || key)[ msg]
|
||||||
|
end
|
||||||
|
|
||||||
|
def crc32 msg
|
||||||
|
NSCA::Helper.crc32_stream[ msg]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a null terminated, null padded string of length maxlen
|
||||||
|
def str2cstr( str, maxlen = nil)
|
||||||
|
str = str.to_s
|
||||||
|
str = str.to_s[0..(maxlen-2)] if maxlen
|
||||||
|
"#{str}\x00"
|
||||||
|
end
|
||||||
|
def str2nstr( str, maxlen = nil)
|
||||||
|
str = str.to_s.gsub( ' ', "\x00")
|
||||||
|
"#{str} "
|
||||||
|
end
|
||||||
|
def cstr2str( str, maxlen = nil) str[ 0, str.index( ?\0) || ((maxlen||str.length+1)-1)] end
|
||||||
|
def nstr2str( str, maxlen = nil) str[ 0, str.index( ' ') || ((maxlen||str.length+1)-1)].gsub( "\x00", ' ') end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,11 @@ module NSCA
|
||||||
{timestamp: timestamp, return_code: retcode, hostname: hostname, server: service, status: text}
|
{timestamp: timestamp, return_code: retcode, hostname: hostname, server: service, status: text}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_packet version = nil
|
||||||
|
version ||= PacketV3
|
||||||
|
version.new timestamp, retcode, hostname, service, text
|
||||||
|
end
|
||||||
|
|
||||||
class <<self
|
class <<self
|
||||||
attr_reader :service, :hostname, :perfdatas
|
attr_reader :service, :hostname, :perfdatas
|
||||||
def init *args
|
def init *args
|
||||||
|
|
|
@ -61,19 +61,26 @@ module NSCA
|
||||||
# @param [String(length<512)] status Status-line inclusive optional Performance Data.
|
# @param [String(length<512)] status Status-line inclusive optional Performance Data.
|
||||||
def build_packet timestamp, return_code, hostname, service, status
|
def build_packet timestamp, return_code, hostname, service, status
|
||||||
packet = @packet_version.new timestamp || @timestamp, return_code, hostname, service, status
|
packet = @packet_version.new timestamp || @timestamp, return_code, hostname, service, status
|
||||||
packet.build @iv_key, @password
|
packet.build
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sends a check-result.
|
# Sends a check-result.
|
||||||
# @see #build_packet
|
# @see #build_packet
|
||||||
def send_packet( *a) @socket.write build_packet( *a) end
|
def send_packet( *a)
|
||||||
|
packet = case a.first
|
||||||
|
when NSCA::Packet then a.first.build
|
||||||
|
when NSCA::Check::Base then a.first.to_packet( @packet_version).build
|
||||||
|
else build_packet( *a)
|
||||||
|
end
|
||||||
|
packet = NSCA::xor @iv_key, packet
|
||||||
|
packet = NSCA::xor @password, packet
|
||||||
|
@socket.write packet
|
||||||
|
end
|
||||||
|
|
||||||
# Sends check-results
|
# Sends check-results
|
||||||
# @param [Array<NSCA::Check::Base>] results
|
# @param [Array<NSCA::Check::Base>] results
|
||||||
def send *results
|
def send *results
|
||||||
results.flatten.each do |r|
|
results.flatten.each &method(:send_packet)
|
||||||
send_packet r.timestamp, r.retcode, r.hostname, r.service, r.text
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Closes connection to NSCA.
|
# Closes connection to NSCA.
|
||||||
|
@ -85,7 +92,7 @@ module NSCA
|
||||||
@hostname, @port, @password = hostname, port, password
|
@hostname, @port, @password = hostname, port, password
|
||||||
end
|
end
|
||||||
|
|
||||||
def open( &e) Connection.open @hostname, @port, @password, &e end
|
def open( &e) Connection.open hostname: @hostname, port: @port, password: @password, &e end
|
||||||
def send( *results) open {|conn| conn.send results } end
|
def send( *results) open {|conn| conn.send results } end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,29 +1,4 @@
|
||||||
module NSCA
|
module NSCA
|
||||||
class <<self
|
|
||||||
def xor key, msg, key_a = nil
|
|
||||||
key_a ||= key.unpack 'C*'
|
|
||||||
l = key_a.length
|
|
||||||
return msg if l < 1
|
|
||||||
# Slice the message in parts of length key_a.length.
|
|
||||||
# XOR each char of a part with char at the same index in key_a.
|
|
||||||
msg.unpack( 'C*').each_with_index.map {|c,i| c^key_a[i%l] }.pack 'C*'
|
|
||||||
end
|
|
||||||
|
|
||||||
def crc32 msg
|
|
||||||
(msg.each_byte.inject 0xFFFFFFFF do |r,b|
|
|
||||||
8.times.inject( r^b) {|r,_i| (r>>1) ^ (0xEDB88320 * (r&1)) }
|
|
||||||
end) ^ 0xFFFFFFFF
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds a null terminated, null padded string of length maxlen
|
|
||||||
def str2cstr( str, maxlen = nil)
|
|
||||||
str = str.to_s
|
|
||||||
str = str.to_s[0..(maxlen-2)] if maxlen
|
|
||||||
"#{str}\x00"
|
|
||||||
end
|
|
||||||
def cstr2str( str, maxlen = nil) str[ 0, x.index( ?\0) || ((maxlen||0)-1)] end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Packet
|
class Packet
|
||||||
class CSC32CheckFailed <Exception
|
class CSC32CheckFailed <Exception
|
||||||
end
|
end
|
||||||
|
@ -57,7 +32,7 @@ module NSCA
|
||||||
END_OF_TRANSMISSION = ?\x0a
|
END_OF_TRANSMISSION = ?\x0a
|
||||||
HOSTNAME_LENGTH = 64
|
HOSTNAME_LENGTH = 64
|
||||||
SERVICE_LENGTH = 128
|
SERVICE_LENGTH = 128
|
||||||
STATUS_LENGTH = 512
|
PLUGIN_OUTPUT_LENGTH = 512
|
||||||
|
|
||||||
# these line describes the data package:
|
# these line describes the data package:
|
||||||
# typedef struct data_packet_struct{
|
# typedef struct data_packet_struct{
|
||||||
|
@ -71,41 +46,54 @@ module NSCA
|
||||||
# char plugin_output[MAX_PLUGINOUTPUT_LENGTH];
|
# char plugin_output[MAX_PLUGINOUTPUT_LENGTH];
|
||||||
# /* two extra padding-xx, too. */
|
# /* two extra padding-xx, too. */
|
||||||
# }data_packet;
|
# }data_packet;
|
||||||
PACK_STRING = "s> xx L> L> s> Z#{HOSTNAME_LENGTH} Z#{SERVICE_LENGTH} Z#{STATUS_LENGTH} xx"
|
PACK_STRING = "s> xx L> L> s> A#{HOSTNAME_LENGTH} A#{SERVICE_LENGTH} A#{PLUGIN_OUTPUT_LENGTH} xx"
|
||||||
PACK_LENGTH = 2+2+4+4+2+HOSTNAME_LENGTH+SERVICE_LENGTH+STATUS_LENGTH+2
|
PACK_LENGTH = 2+2+4+4+2+HOSTNAME_LENGTH+SERVICE_LENGTH+PLUGIN_OUTPUT_LENGTH+2
|
||||||
register_version PACKET_VERSION, self
|
register_version PACKET_VERSION, self
|
||||||
|
|
||||||
# Builds a check-result-line for NSCA.
|
# Builds a check-result-line for NSCA.
|
||||||
#
|
#
|
||||||
# Will be terminated by end-of-terminate.
|
# Will be terminated by end-of-terminate.
|
||||||
def build key = nil, password = nil
|
def build slf = nil
|
||||||
|
cl = (slf || self).class
|
||||||
entry = [
|
entry = [
|
||||||
PACKET_VERSION,
|
cl::PACKET_VERSION,
|
||||||
0, # crc32 (unknown yet)
|
0, # crc32 (unknown yet)
|
||||||
(timestamp || Time.now).to_i,
|
(timestamp || Time.now).to_i,
|
||||||
return_code.to_i,
|
return_code.to_i,
|
||||||
NSCA::str2cstr( hostname || `hostname -f`, HOSTNAME_LENGTH),
|
NSCA::str2cstr( hostname || `hostname -f`, cl::HOSTNAME_LENGTH),
|
||||||
NSCA::str2cstr( service, SERVICE_LENGTH),
|
NSCA::str2cstr( service, cl::SERVICE_LENGTH),
|
||||||
NSCA::str2cstr( status, STATUS_LENGTH) # incl perfdata
|
NSCA::str2cstr( status, cl::PLUGIN_OUTPUT_LENGTH) # incl perfdata
|
||||||
]
|
]
|
||||||
# generate crc32 and put it at entry[2...6]
|
# generate crc32 and put it at entry[2...6]
|
||||||
entry[1] = NSCA::crc32 entry.pack( PACK_STRING)
|
entry[1] = NSCA::crc32 entry.pack( cl::PACK_STRING)
|
||||||
entry = entry.pack PACK_STRING
|
entry = entry.pack cl::PACK_STRING
|
||||||
entry = NSCA::xor key, entry if key
|
|
||||||
entry = NSCA::xor password, entry if password
|
|
||||||
entry
|
entry
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.parse entry, key = nil, password = nil, no_verification_checks = nil
|
def self.parse entry, no_verification_checks = nil
|
||||||
entry = NSCA::xor key, entry if key
|
entry = entry.to_s.dup
|
||||||
entry = NSCA::xor password, entry if password
|
|
||||||
ver, crc32sum, *x = entry.unpack( PACK_STRING)
|
ver, crc32sum, *x = entry.unpack( PACK_STRING)
|
||||||
|
x[2] = NSCA::cstr2str x[2]
|
||||||
|
x[3] = NSCA::cstr2str x[3]
|
||||||
|
x[4] = NSCA::cstr2str x[4]
|
||||||
raise VersionCheckFailed, "Packet version 3 expected. (recv: #{ver})" \
|
raise VersionCheckFailed, "Packet version 3 expected. (recv: #{ver})" \
|
||||||
unless no_verification_checks or 3 == ver
|
unless no_verification_checks or 3 == ver
|
||||||
entry[4..7] = ?\x00*4
|
entry[4..7] = ?\x00*4
|
||||||
raise CSC32CheckFailed, "crc32-check failed. packet seems to be broken." \
|
crc32 = NSCA::crc32 entry
|
||||||
unless no_verification_checks or crc32sum == NSCA::crc32( entry)
|
raise CSC32CheckFailed, "crc32-check failed. packet seems to be broken: #{crc32sum.inspect} != #{crc32.inspect}" \
|
||||||
|
unless no_verification_checks or crc32sum == crc32
|
||||||
new *x
|
new *x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class PacketV3__2_9 < PacketV3
|
||||||
|
NAGIOS_VERSION = 2.7
|
||||||
|
PACKET_VERSION = 3
|
||||||
|
END_OF_TRANSMISSION = ?\x0a
|
||||||
|
PLUGIN_OUTPUT_LENGTH = 4096
|
||||||
|
HOSTNAME_LENGTH = 64
|
||||||
|
SERVICE_LENGTH = 128
|
||||||
|
PACK_STRING = "s> xx L> L> s> A#{HOSTNAME_LENGTH} A#{SERVICE_LENGTH} A#{PLUGIN_OUTPUT_LENGTH} xx"
|
||||||
|
PACK_LENGTH = 2+2+4+4+2+HOSTNAME_LENGTH+SERVICE_LENGTH+PLUGIN_OUTPUT_LENGTH+2
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,12 @@ module NSCA
|
||||||
class Server
|
class Server
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
attr_reader :iv_key, :server, :packet_version, :password
|
attr_reader :iv_key, :server, :packet_version, :password, :xor_iv_key, :xor_password
|
||||||
def initialize *args
|
def initialize *args
|
||||||
opts = {}
|
opts = {}
|
||||||
opts = args.pop.dup if args.last.is_a? Hash
|
opts = args.pop.dup if args.last.is_a? Hash
|
||||||
opts[:host] ||= opts[:hostname]
|
opts[:host] ||= opts[:hostname]
|
||||||
opts[:sock] ||= opts[:socket]
|
opts[:serv] ||= opts[:server]
|
||||||
opts[:pass] ||= opts[:password]
|
opts[:pass] ||= opts[:password]
|
||||||
|
|
||||||
case args[0]
|
case args[0]
|
||||||
|
@ -15,7 +15,7 @@ module NSCA
|
||||||
opts[:port] = args[0]
|
opts[:port] = args[0]
|
||||||
opts[:host] ||= args[1]
|
opts[:host] ||= args[1]
|
||||||
when IO
|
when IO
|
||||||
opts[:sock] = args[0]
|
opts[:serv] = args[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
@packet_version = opts[:packet_version] || PacketV3
|
@packet_version = opts[:packet_version] || PacketV3
|
||||||
|
@ -25,7 +25,7 @@ module NSCA
|
||||||
@server = if opts[:serv].is_a?( TCPServer) or opts[:serv].is_a?( UNIXServer)
|
@server = if opts[:serv].is_a?( TCPServer) or opts[:serv].is_a?( UNIXServer)
|
||||||
opts[:serv]
|
opts[:serv]
|
||||||
elsif opts[:port].is_a? Integer
|
elsif opts[:port].is_a? Integer
|
||||||
TCPServer.new *[opts[:port], opts[:host]].compact
|
TCPServer.new *[opts[:host], opts[:port]].compact
|
||||||
else
|
else
|
||||||
raise ArgumentError, "Server or port-number expected"
|
raise ArgumentError, "Server or port-number expected"
|
||||||
end
|
end
|
||||||
|
@ -50,22 +50,36 @@ module NSCA
|
||||||
@packet_version = server.packet_version
|
@packet_version = server.packet_version
|
||||||
@packet_length = @packet_version::PACK_LENGTH
|
@packet_length = @packet_version::PACK_LENGTH
|
||||||
@socket.write [@iv_key, Time.now.to_i].pack( 'a* L>')
|
@socket.write [@iv_key, Time.now.to_i].pack( 'a* L>')
|
||||||
|
@xor_password = NSCA::Helper.xor_stream @password
|
||||||
|
@xor_iv_key = NSCA::Helper.xor_stream @iv_key
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch
|
def fetch
|
||||||
data = read
|
iv_key = NSCA::Helper.xor_stream @iv_key
|
||||||
@packet_version.parse data, @iv_key, @password if data
|
password = NSCA::Helper.xor_stream @password
|
||||||
|
packet_version = iv_key[ password[ read PacketV3::PACKET_VERSION]]
|
||||||
|
v = packet_version.unpack( 's>').first
|
||||||
|
case v
|
||||||
|
when 3
|
||||||
|
data = packet_version + iv_key[ password[ read( PacketV3::PACK_LENGTH - PacketV3::PACKET_VERSION)]]
|
||||||
|
begin
|
||||||
|
return PacketV3.parse( data)
|
||||||
|
rescue NSCA::Packet::CSC32CheckFailed
|
||||||
|
x = read( PacketV3__2_9::PACK_LENGTH - data.length)
|
||||||
|
raise if x.nil?
|
||||||
|
return PacketV3__2_9.parse( data + iv_key[ password[ x]])
|
||||||
|
end
|
||||||
|
else raise "Unknown Version #{v.inspect}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def each &block
|
def each &block
|
||||||
return Enumerator.new( self) unless block_given?
|
return Enumerator.new( self) unless block_given?
|
||||||
while data = fetch
|
yield fetch until eof?
|
||||||
yield data
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def eof?() @socket.eof? end
|
def eof?() @socket.eof? end
|
||||||
def read() @socket.read @packet_length end
|
def read( len = nil) @socket.read( len || @packet_length) end
|
||||||
def close() @socket.close end
|
def close() @socket.close end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,20 +18,34 @@ end
|
||||||
|
|
||||||
class TestNSCACommunication < Test::Unit::TestCase
|
class TestNSCACommunication < Test::Unit::TestCase
|
||||||
Port = 5787
|
Port = 5787
|
||||||
|
def dummy_server *args
|
||||||
|
server = Thread.new do
|
||||||
|
begin
|
||||||
|
NSCA.dummy_server *args
|
||||||
|
rescue Object
|
||||||
|
#STDERR.puts "#{$!.class}: #{$!}", $!.backtrace.map{|bt|" #{bt}"}
|
||||||
|
raise
|
||||||
|
ensure
|
||||||
|
#STDERR.puts "Dummy Server Shutdown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep 1 # server needs time to start...
|
||||||
|
server
|
||||||
|
end
|
||||||
|
|
||||||
include NSCA::Checks
|
include NSCA::Checks
|
||||||
|
|
||||||
context "our dummy test server on localhost:#{Port} with random password" do
|
context "our dummy test server on localhost:#{Port} with random password" do
|
||||||
should 'receive data' do
|
should 'receive data' do
|
||||||
password = SecureRandom.random_bytes
|
password = 'password' || SecureRandom.random_bytes
|
||||||
timestamp = Time.now
|
timestamp = Time.now
|
||||||
|
|
||||||
PD1 = perfdata :pd1_in_sec, :s, 10, 20, 0, 30
|
PD1 = perfdata :pd1_in_sec, :s, 10, 20, 0, 30
|
||||||
PD2 = perfdata :pd2_in_1, 1, 0.99, 0.98, 0, 1
|
PD2 = perfdata :pd2_in_1, 1, 0.99, 0.98, 0, 1
|
||||||
PD3 = perfdata :pd3_count, :c, 3, 5, 0
|
PD3 = perfdata :pd3_count, :c, 3, 5, 0
|
||||||
T0 = check 'TestNSCA0', 'uxnags01-sbe.net.mobilkom.at'
|
T0 = check 'TestNSCA0', 'localhost'
|
||||||
T1 = check 'TestNSCA1', 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2]
|
T1 = check 'TestNSCA1', 'localhost', [PD1, PD2]
|
||||||
T2 = check :TestNSCA2, 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2, PD3]
|
T2 = check :TestNSCA2, 'localhost', [PD1, PD2, PD3]
|
||||||
|
|
||||||
checks = []
|
checks = []
|
||||||
t0 = T0.new( 1, "0123456789"*51+"AB", nil, timestamp) # oversized service name
|
t0 = T0.new( 1, "0123456789"*51+"AB", nil, timestamp) # oversized service name
|
||||||
|
@ -44,10 +58,9 @@ class TestNSCACommunication < Test::Unit::TestCase
|
||||||
checks << t1
|
checks << t1
|
||||||
|
|
||||||
NSCA::destinations.clear
|
NSCA::destinations.clear
|
||||||
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password: password)
|
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password)
|
||||||
|
|
||||||
server = Thread.new { NSCA.dummy_server Port, password: password }
|
server = dummy_server port: Port, password: password
|
||||||
sleep 1 # server needs time to start...
|
|
||||||
NSCA::send *checks
|
NSCA::send *checks
|
||||||
pc0, pc1 = server.value
|
pc0, pc1 = server.value
|
||||||
|
|
||||||
|
@ -57,20 +70,19 @@ class TestNSCACommunication < Test::Unit::TestCase
|
||||||
assert_equal timestamp.to_i, packet.timestamp.to_i
|
assert_equal timestamp.to_i, packet.timestamp.to_i
|
||||||
assert_equal test.retcode, packet.return_code
|
assert_equal test.retcode, packet.return_code
|
||||||
end
|
end
|
||||||
# original with B, but B is char 512 and will be replaced by \0
|
# original with AB, but B is char 512 and will be replaced by \0
|
||||||
assert_equal "0123456789"*51+"A", pc0.status
|
assert_equal "0123456789"*51+"A", pc0.status
|
||||||
assert_equal "Should be OK | 'pd1_in_sec'=3s,10,20,0,30 'pd2_in_1'=0.99961,0.99,0.98,0,1 'pd3_count'=2c,3,5,0,", pc1.status
|
assert_equal "Should be OK | 'pd1_in_sec'=3s,10,20,0,30 'pd2_in_1'=0.99961,0.99,0.98,0,1 'pd3_count'=2c,3,5,0,", pc1.status
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'fail crc32 if wrong password' do
|
should 'fail crc32 if wrong password' do
|
||||||
password = SecureRandom.random_bytes
|
password = 'password' || SecureRandom.random_bytes
|
||||||
timestamp = Time.now
|
timestamp = Time.now
|
||||||
T3 = check 'TestNSCA0', 'uxnags01-sbe.net.mobilkom.at'
|
T3 = check 'TestNSCA0', 'localhost'
|
||||||
NSCA::destinations.clear
|
NSCA::destinations.clear
|
||||||
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password: password+'a')
|
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password+'a')
|
||||||
server = Thread.new { NSCA.dummy_server Port, password: password }
|
server = dummy_server hostname: 'localhost', port: Port, password: password
|
||||||
sleep 1 # server needs time to start...
|
NSCA::send [T3.new( 1, 'status', nil, timestamp)]
|
||||||
NSCA::send T3.new( 1, 'status', nil, timestamp)
|
|
||||||
assert_raise( NSCA::Packet::CSC32CheckFailed) { server.join }
|
assert_raise( NSCA::Packet::CSC32CheckFailed) { server.join }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue