Skip to content

Instantly share code, notes, and snippets.

@millenomi
Created October 14, 2010 09:24
Show Gist options
  • Select an option

  • Save millenomi/625930 to your computer and use it in GitHub Desktop.

Select an option

Save millenomi/625930 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'osx/cocoa'
require 'optparse'
include OSX
$service_name = nil
$service_port = nil
$service_type = nil
$service_txt = {}
target_plist_file = nil
$avail_debug = false
def log(s)
$stderr.puts s if $avail_debug
end
OptionParser.new do |o|
o.on('-s', '--service TYPE', 'The Bonjour service type to publish.') do |name|
$service_type = name
end
o.on('-n', '--name NAME', 'The name of the service. If unspecified, uses hostname') do |name|
$service_name = name
end
o.on('-p', '--port NAME', 'The port to publish.') do |port|
$service_port = port.to_i
end
o.on('-t', '--txt VAL', 'The value to add to the service data dictionary. VAL is of the form "key=value". Strings will be encoded as UTF-8.') do |val|
split = val.split('=')
key = split[0]
split.delete_at 0
value = split.join('=')
$service_txt[key] = value
end
o.on('-P', '--launchd-plist FILE', 'If specified, does not run. Instead, produces a launchd plist file that runs this copy of $0 with the same parameters you passed in.') do |file|
target_plist_file = file
end
o.on('-D', '--debug', 'Shows debug output.') do
$avail_debug = true
end
o.on('--http PATH', 'Shorthand that registers a HTTP service on the given port. You can still provide a name with -n and a port with -p.') do |path|
$service_type = '_http._tcp.'
$service_txt['path'] = path
end
end.parse!
raise "You must specify both service type and port!" unless $service_type and $service_port
if target_plist_file
label = File.basename(target_plist_file, '.plist')
args = [
File.expand_path(__FILE__),
'-s', $service_type,
'-p', $service_port.to_s
]
if $service_name
args << '-n'
args << $service_name
end
$service_txt.each do |key, value|
args << '-t'
args << "#{key}=#{value}"
end
if $avail_debug
args << '--debug'
end
plist = {
'Label' => label,
'ProgramArguments' => args,
'KeepAlive' => true,
'RunAtLoad' => true,
}
saved = NSDictionary.dictionaryWithDictionary(plist).writeToFile_atomically(target_plist_file, true)
if saved
exit 1
else
exit 0
end
end
unless $service_name
$service_name = NSHost.currentHost.name
end
class Publisher < NSObject
def initialize()
@running = true
@services = {}
@domains = []
@browser = NSNetServiceBrowser.alloc.init
@browser.setDelegate self
@browser.searchForRegistrationDomains
log "Will start looking for domains."
end
def netServiceBrowser_didFindDomain_moreComing(browser, domain, coming)
log "Domain found: #{domain}"
return if @domains.include? domain
domain = domain.to_s
@domains << domain
s = NSNetService.alloc.initWithDomain_type_name_port_(domain, $service_type, $service_name, $service_port)
s.TXTRecordData = NSNetService.dataFromTXTRecordDictionary($service_txt)
log "Created service: #{s}"
s.setDelegate self
@services[domain.to_s] = s
log "Services now: #{@services.inspect}"
s.publish
end
def netServiceBrowser_didRemoveDomain_moreComing(browser, domain, coming)
domain = domain.to_s
@domains.delete domain
@services[domain].setDelegate nil
@services[domain].stop
@services.delete domain
end
def netServiceWillPublish(service)
log "About to publish service: #{service}"
end
def netServiceDidPublish(service)
log "Did publish service: #{service}"
end
def netService_didNotPublish(service, error)
log "Did not publish #{service}, because: #{error}"
@services[service.domain.to_s] = nil
end
def running
@running
end
def stop_asap
@running = false
end
def stop
@services.each do |domain, service|
service.setDelegate nil
service.stop
end
@services = nil
@domains = nil
@browser.stop
@browser.setDelegate nil
@browser = nil
end
end
publisher = Publisher.new
trap "SIGTERM" do
publisher.stop_asap
end
while publisher.running
begin
NSRunLoop.currentRunLoop.runUntilDate NSDate.dateWithTimeIntervalSinceNow(2)
rescue Interrupt
publisher.stop_asap
end
end
publisher.stop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment