class Growl::UDP

Implements the UDP growl protocol used in growl 1.2 and older.

Constants

GNN_FORMAT

Growl Network Notification Packet pack Format

GNR_FORMAT

Growl Network Registration Packet pack Format

GROWL_PROTOCOL_VERSION

Growl Protocol Version

GROWL_TYPE_NOTIFICATION

Growl Notification Packet Id

GROWL_TYPE_REGISTRATION

Growl Registration Packet Id

LITTLE_ENDIAN

Endianness of this machine

PORT

Growl UDP Port

Public Class Methods

new(host, app_name, all_notifies, default_notifies = nil, password = nil) click to toggle source

Creates a new Growl UDP notifier and automatically registers any notifications with the remote machine.

host is the host to contact.

app_name is the name of the application sending the notifications.

all_notifies is a list of notification types your application sends.

default_notifies is a list of notification types that are turned on by default.

I'm not sure about what default_notifies is supposed to be set to, since there is a comment that says “not a subset of all_notifies” in the code.

password is the password needed to send notifications to host.

# File lib/ruby-growl/udp.rb, line 120
def initialize(host, app_name, all_notifies, default_notifies = nil,
               password = nil)
  @socket = socket host
  @app_name = app_name
  @all_notifies = all_notifies
  @default_notifies = default_notifies.nil? ? all_notifies : default_notifies
  @password = password

  register
end

Public Instance Methods

notification_packet(name, title, description, priority, sticky) click to toggle source

Builds a Growl notification packet

# File lib/ruby-growl/udp.rb, line 219
def notification_packet(name, title, description, priority, sticky)
  flags = 0
  data = []

  packet = [
    GROWL_PROTOCOL_VERSION,
    GROWL_TYPE_NOTIFICATION,
  ]

  flags = 0
  flags |= ((0x7 & priority) << 1) # 3 bits for priority
  flags |= 1 if sticky # 1 bit for sticky

  packet << flags
  packet << name.bytesize
  packet << title.length
  packet << description.bytesize
  packet << @app_name.bytesize

  data << name
  data << title
  data << description
  data << @app_name

  packet << data.join
  packet = packet.pack GNN_FORMAT

  checksum = Digest::MD5.new << packet
  checksum.update @password unless @password.nil?

  packet << checksum.digest

  return packet
end
notify(notify_type, title, message, priority = 0, sticky = false) click to toggle source

Sends a notification.

notify_type is the type of notification to send.

title is a title for the notification.

message is the body of the notification.

priority is the priorty of message to send.

sticky makes the notification stick until clicked.

# File lib/ruby-growl/udp.rb, line 144
def notify(notify_type, title, message, priority = 0, sticky = false)
  raise Growl::Error, "Unknown Notification" unless
    @all_notifies.include? notify_type

  raise Growl::Error, "Invalid Priority" unless
    priority >= -2 and priority <= 2

  send notification_packet(notify_type, title, message, priority, sticky)
end
register() click to toggle source

Registers the notification types with host.

# File lib/ruby-growl/udp.rb, line 157
def register
  send registration_packet
end
registration_packet() click to toggle source

Builds a Growl registration packet

# File lib/ruby-growl/udp.rb, line 173
def registration_packet
  data = []
  data_format = ""

  packet = [
    GROWL_PROTOCOL_VERSION,
    GROWL_TYPE_REGISTRATION
  ]

  packet << @app_name.bytesize
  packet << @all_notifies.length
  packet << @default_notifies.length

  data << @app_name
  data_format = "a#{@app_name.bytesize}"

  @all_notifies.each do |notify|
    data << notify.length
    data << notify
    data_format << "na#{notify.length}"
  end

  @default_notifies.each do |notify|
    data << @all_notifies.index(notify) if @all_notifies.include? notify
    data_format << "C"
  end

  data_format.gsub!(/n/, 'v') if BROKEN_PACK

  data = data.pack data_format

  packet << data

  packet = packet.pack GNR_FORMAT

  checksum = Digest::MD5.new << packet
  checksum.update @password unless @password.nil?

  packet << checksum.digest

  return packet
end
send(packet) click to toggle source

Sends a Growl packet

# File lib/ruby-growl/udp.rb, line 164
def send(packet)
  set_sndbuf packet.length
  @socket.send packet, 0
  @socket.flush
end
set_sndbuf(length) click to toggle source

Set the size of the send buffer

# File lib/ruby-growl/udp.rb, line 259
def set_sndbuf(length)
  @socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDBUF, length
end
socket(host) click to toggle source
# File lib/ruby-growl/udp.rb, line 263
def socket host
  addrinfo = Addrinfo.udp host, PORT

  socket = Socket.new addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol

  if addrinfo.ip_address == '255.255.255.255' then
    socket.setsockopt :SOL_SOCKET, :SO_BROADCAST, true
  elsif Socket.respond_to?(:getifaddrs) and
          Socket.getifaddrs.any? do |ifaddr|
            ifaddr.broadaddr and
              ifaddr.broadaddr.ip_address == addrinfo.ip_address
          end then
    socket.setsockopt :SOL_SOCKET, :SO_BROADCAST, true
  end

  socket.connect addrinfo

  socket
end