Class: Wamupd::AvahiModel

Inherits:
Object
  • Object
show all
Includes:
Signals
Defined in:
lib/wamupd/avahi_model.rb

Overview

Model for Avahi’s registered services. Uses D-BUS to talk to the system Avahi daemon and pull down service information. It’s kind of a hack because Avahi has a really (really!) horrible D-BUS interface.

Signals

:added

A service was added from the system Avahi. Includes the service as a parameter.

:removed

A service was removed from the system Avahi. Includes the service as a paramter.

:quit

The model is quitting.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Signals

#on

Constructor Details

#initializeAvahiModel

Constructor. Boring.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/wamupd/avahi_model.rb', line 47

def initialize
    @bus = DBus::SystemBus.instance
    @service = @bus.service("org.freedesktop.Avahi")
    @service.introspect
    @server = @service.object("/")
    @server.introspect
    @server = @server["org.freedesktop.Avahi.Server"]

    @service_types = Set.new
    @count = 0

    @known_services = Hash.new
    @handlers = Hash.new
end

Class Method Details

.pack_txt_param(strs) ⇒ Object

Pack an array of TXT parameters into a single TXT record appropriately

Note: The actual TXT record should consist of name-value pairs, with each pair delimited by its length.

As of 2010-04-21, Dnsruby internally converts double-quoted, space-separted strings into the appropriate format. Most annoyingly, if you provide it input already in the right format, it sticks a completely unnecessary byte on the front and screws it up.

Aren’t you happy you know that now?



157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/wamupd/avahi_model.rb', line 157

def self.pack_txt_param(strs)
    val = ""
    strs.each { |c|
        # Dnsruby uses multi-byte lengths if any of your records are
        # over 255 characters, though. This makes mDNSResponder get
        # amusingly confused.
        if (c.length > 255)
            next
        end
        val += "\"#{c.pack("c*")}\" "
    }
    return val.chop
end

Instance Method Details

#add_service_record(name, type, host, port, txt) ⇒ Object

Construct an AvahiService from the given parameters



172
173
174
175
176
177
178
179
# File 'lib/wamupd/avahi_model.rb', line 172

def add_service_record(name, type, host, port, txt)
    # Replace the .local that Avahi sticks at the end of the host (why
    # doesn't it just use the domain field? who knows?)
    host.sub!(/\.local$/, "")
    a = AvahiService.new(name, {:type=>type, :hostname=>host, :port=>port, :txt=>txt})
    @known_services[a.identifier] = a
    signal(:added, a)
end

#exitObject

Exit the listener



191
192
193
# File 'lib/wamupd/avahi_model.rb', line 191

def exit
    signal(:quit)
end

#remove_service_record(name, type, host, port, txt) ⇒ Object

Remove an AvahiService using the given parameters.



182
183
184
185
186
187
188
# File 'lib/wamupd/avahi_model.rb', line 182

def remove_service_record(name, type, host, port, txt)
    a = AvahiService.new(name, {:type=>type, :hostname=>host, :port=>port, :txt=>txt})
    if (@known_services.has_key?(a.identifier))
        @known_services.delete(a.identifier)
    end
    signal(:removed, a)
end

#runObject

Run the listener. This function doesn’t return until exit is called.



197
198
199
200
201
202
203
204
205
206
# File 'lib/wamupd/avahi_model.rb', line 197

def run
    start_listen

    @main_loop = DBus::Main.new
    self.on(:quit) {
        @main_loop.quit
    }
    @main_loop << @bus
    @main_loop.run
end

#start_listenObject

Actually starts listening.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/wamupd/avahi_model.rb', line 63

def start_listen
    stb = @server.ServiceTypeBrowserNew(-1,-1,"",0)
    mr = DBus::MatchRule.new
    mr.type = "signal"
    mr.interface = "org.freedesktop.Avahi.ServiceTypeBrowser"
    mr.path = stb.first
    mr.member = "ItemNew"
    @bus.add_match(mr) do |msg, first_param|
        type = msg.params[2]
        if (not @service_types.member?(type))
            @service_types.add(msg.params[2])
            add_type_listener(msg.params[2])
        end
    end
end