Class: Growl::UDP
- Inherits:
-
Object
- Object
- Growl::UDP
- Defined in:
- lib/ruby-growl/udp.rb
Overview
Implements the UDP growl protocol used in growl 1.2 and older.
Constant Summary collapse
- BROKEN_PACK =
The Ruby that ships with Tiger has a broken #pack, so ‘v’ means network byte order instead of ‘n’.
[1].pack("n") != "\000\001"
- LITTLE_ENDIAN =
Endianness of this machine
little_endian
- GNR_FORMAT =
Growl Network Registration Packet
pack
Format – Format:struct GrowlNetworkRegistration { struct GrowlNetworkPacket { unsigned char version; unsigned char type; } __attribute__((packed)); unsigned short appNameLen; unsigned char numAllNotifications; unsigned char numDefaultNotifications; /* * Variable sized. Format: * <application name><all notifications><default notifications><checksum> * where <all notifications> is of the form (<length><name>){num} and * <default notifications> is an array of indices into the all notifications * array, each index being 8 bits. */ unsigned char data[]; } __attribute__((packed));
"CCnCCa*"
- GNN_FORMAT =
Growl Network Notification Packet
pack
Format – Format:struct GrowlNetworkNotification { struct GrowlNetworkPacket { unsigned char version; unsigned char type; } __attribute__((packed)); struct GrowlNetworkNotificationFlags { unsigned reserved: 12; signed priority: 3; unsigned sticky: 1; } __attribute__((packed)) flags; //size = 16 (12 + 3 + 1) unsigned short nameLen; unsigned short titleLen; unsigned short descriptionLen; unsigned short appNameLen; /* * Variable sized. Format: * <notification name><title><description><application name><checksum> */ unsigned char data[]; } __attribute__((packed));
"CCnnnnna*"
- GROWL_PROTOCOL_VERSION =
Growl Protocol Version
1
- GROWL_TYPE_REGISTRATION =
Growl Registration Packet Id
0
- GROWL_TYPE_NOTIFICATION =
Growl Notification Packet Id
1
- PORT =
Growl UDP Port
9887
Instance Method Summary collapse
-
#initialize(host, app_name, all_notifies, default_notifies = nil, password = nil) ⇒ UDP
constructor
Creates a new Growl UDP notifier and automatically registers any notifications with the remote machine.
-
#notification_packet(name, title, description, priority, sticky) ⇒ Object
Builds a Growl notification packet.
-
#notify(notify_type, title, message, priority = 0, sticky = false) ⇒ Object
Sends a notification.
-
#register ⇒ Object
Registers the notification types with
host
. -
#registration_packet ⇒ Object
Builds a Growl registration packet.
-
#send(packet) ⇒ Object
Sends a Growl packet.
-
#set_sndbuf(length) ⇒ Object
Set the size of the send buffer – Is this truly necessary?.
- #socket(host) ⇒ Object
Constructor Details
#initialize(host, app_name, all_notifies, default_notifies = nil, password = nil) ⇒ UDP
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
.
120 121 122 123 124 125 126 127 128 129 |
# 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 |
Instance Method Details
#notification_packet(name, title, description, priority, sticky) ⇒ Object
Builds a Growl notification packet
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# 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) ⇒ Object
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.
144 145 146 147 148 149 150 151 152 |
# File 'lib/ruby-growl/udp.rb', line 144 def notify(notify_type, title, , 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, , priority, sticky) end |
#register ⇒ Object
Registers the notification types with host
.
157 158 159 |
# File 'lib/ruby-growl/udp.rb', line 157 def register send registration_packet end |
#registration_packet ⇒ Object
Builds a Growl registration packet
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# 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) ⇒ Object
Sends a Growl packet
164 165 166 167 168 |
# 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) ⇒ Object
Set the size of the send buffer – Is this truly necessary?
259 260 261 |
# File 'lib/ruby-growl/udp.rb', line 259 def set_sndbuf(length) @socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDBUF, length end |
#socket(host) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# 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 |