aboutsummaryrefslogtreecommitdiff
path: root/lib/mauve/sender.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mauve/sender.rb')
-rw-r--r--lib/mauve/sender.rb94
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/mauve/sender.rb b/lib/mauve/sender.rb
new file mode 100644
index 0000000..f27efe5
--- /dev/null
+++ b/lib/mauve/sender.rb
@@ -0,0 +1,94 @@
+# encoding: UTF-8
+require 'ipaddr'
+require 'resolv'
+require 'socket'
+require 'mauve/mauve_time'
+
+module Mauve
+ class Sender
+ DEFAULT_PORT = 32741
+ include Resolv::DNS::Resource::IN
+
+ def initialize(*destinations)
+ destinations = destinations.flatten
+
+ destinations = begin
+ File.read("/etc/mauvealert/mauvesend.destination").split(/\s+/)
+ rescue Errno::ENOENT => notfound
+ []
+ end if destinations.empty?
+
+ if !destinations || destinations.empty?
+ raise ArgumentError.new("No destinations specified, and could not read any destinations from /etc/mauvealert/mauvesend.destination")
+ end
+
+ @destinations = destinations.map do |spec|
+ next_spec = begin
+ # FIXME: for IPv6
+ port = spec.split(":")[1] || DEFAULT_PORT
+ IPAddr.new(spec.split(":")[0])
+ ["#{spec}:#{port}"]
+ rescue ArgumentError => not_an_ip_address
+ Resolv::DNS.open do |dns|
+ srv_spec = spec[0] == ?_ ? spec : "_mauvealert._udp.#{spec}"
+ list = dns.getresources(srv_spec, SRV).map do |srv|
+ srv.target.to_s + ":#{srv.port}"
+ end
+ list = [spec] if list.empty?
+ list.map do |spec2|
+ spec2_addr, spec2_port = spec2.split(":")
+ spec2_port ||= DEFAULT_PORT
+ dns.getresources(spec2_addr, A).map do |a|
+ "#{a.address}:#{spec2_port}"
+ end
+ end
+ end
+ end.flatten
+
+ error "Can't resolve destination #{spec}" if next_spec.empty?
+
+ next_spec
+ end.
+ flatten.
+ uniq
+ end
+
+ def send(update, verbose=0)
+
+ #
+ # Must have a source, so default to hostname if user doesn't care
+ update.source ||= `hostname -f`.chomp
+
+ #
+ # Make sure all alerts default to "-r now"
+ #
+ update.alert.each do |alert|
+ next if alert.raise_time || alert.clear_time
+ alert.raise_time = MauveTime.now.to_i
+ end
+
+ #
+ # Make sure we set the transmission time
+ #
+ update.transmission_time = MauveTime.now.to_i
+
+ data = update.serialize_to_string
+
+
+ if verbose == 1
+ print "#{update.transmission_id}\n"
+ elsif verbose >= 2
+ print "Sending #{update.inspect.chomp} to #{@destinations.join(", ")}\n"
+ end
+
+ @destinations.each do |spec|
+ UDPSocket.open do |sock|
+ ip = spec.split(":")[0]
+ port = spec.split(":")[1].to_i
+ sock.send(data, 0, ip, port)
+ end
+ end
+ end
+ end
+end
+