Alessio Caiazza is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this againavahiserve / avahiserve.py
- commit
- a4eaadad9216
- parent
- 2de4c35d30c8
- branch
- default
Verbosity aligned with mercurial state, more verbose on TXT data
1 |
2de4c35d30c8
|
#!/usr/bin/env python |
2 |
2de4c35d30c8
|
|
3 |
2de4c35d30c8
|
from mercurial import hg |
4 |
2de4c35d30c8
|
from mercurial import commands |
5 |
2de4c35d30c8
|
|
6 |
2de4c35d30c8
|
import dbus |
7 |
2de4c35d30c8
|
import gobject |
8 |
2de4c35d30c8
|
import avahi |
9 |
2de4c35d30c8
|
from dbus.mainloop.glib import DBusGMainLoop |
10 |
2de4c35d30c8
|
|
11 |
2de4c35d30c8
|
class AvahiReg: |
12 |
2de4c35d30c8
|
|
13 |
2de4c35d30c8
|
def __init__(self, name, port): |
14 |
a4eaadad9216
|
self.verbose = False |
15 |
a4eaadad9216
|
self.serviceName = "Mercurial" |
16 |
a4eaadad9216
|
if name != '': |
17 |
a4eaadad9216
|
self.serviceName += ": " + name |
18 |
2de4c35d30c8
|
self.serviceType = "_http._tcp" # See http://www.dns-sd.org/ServiceTypes.html |
19 |
2de4c35d30c8
|
self.servicePort = port |
20 |
2de4c35d30c8
|
self.serviceTXT = ["extension's author=Alessio Caiazza"] #TXT record for the service |
21 |
2de4c35d30c8
|
|
22 |
2de4c35d30c8
|
self.domain = "" # Domain to publish on, default to .local |
23 |
2de4c35d30c8
|
self.host = "" # Host to publish records for, default to localhost |
24 |
2de4c35d30c8
|
|
25 |
2de4c35d30c8
|
self.group = None #our entry group |
26 |
2de4c35d30c8
|
self.rename_count = 12 # Counter so we only rename after collisions a sensible number of times |
27 |
2de4c35d30c8
|
|
28 |
2de4c35d30c8
|
def add_service(self): |
29 |
2de4c35d30c8
|
if self.group is None: |
30 |
2de4c35d30c8
|
self.group = dbus.Interface( |
31 |
2de4c35d30c8
|
self.bus.get_object( avahi.DBUS_NAME, self.server.EntryGroupNew()), |
32 |
2de4c35d30c8
|
avahi.DBUS_INTERFACE_ENTRY_GROUP) |
33 |
2de4c35d30c8
|
self.group.connect_to_signal('StateChanged', self.entry_group_state_changed) |
34 |
a4eaadad9216
|
if self.verbose: |
35 |
a4eaadad9216
|
print "Adding service '%s' of type '%s' ..." % (self.serviceName, self.serviceType) |
36 |
2de4c35d30c8
|
self.group.AddService( |
37 |
2de4c35d30c8
|
avahi.IF_UNSPEC, #interface |
38 |
2de4c35d30c8
|
avahi.PROTO_UNSPEC, #protocol |
39 |
2de4c35d30c8
|
0, #flags |
40 |
2de4c35d30c8
|
self.serviceName, self.serviceType, |
41 |
2de4c35d30c8
|
self.domain, self.host, |
42 |
2de4c35d30c8
|
dbus.UInt16(self.servicePort), |
43 |
2de4c35d30c8
|
avahi.string_array_to_txt_array(self.serviceTXT)) |
44 |
2de4c35d30c8
|
self.group.Commit() |
45 |
2de4c35d30c8
|
|
46 |
2de4c35d30c8
|
def remove_service(self): |
47 |
a4eaadad9216
|
if not group is None: |
48 |
a4eaadad9216
|
group.Reset() |
49 |
2de4c35d30c8
|
|
50 |
2de4c35d30c8
|
def server_state_changed(self, state): |
51 |
2de4c35d30c8
|
if state == avahi.SERVER_COLLISION: |
52 |
a4eaadad9216
|
if self.verbose: |
53 |
a4eaadad9216
|
print "WARNING: Server name collision" |
54 |
2de4c35d30c8
|
remove_service() |
55 |
2de4c35d30c8
|
elif state == avahi.SERVER_RUNNING: |
56 |
2de4c35d30c8
|
self.add_service() |
57 |
2de4c35d30c8
|
|
58 |
2de4c35d30c8
|
def entry_group_state_changed(self,state, error): |
59 |
2de4c35d30c8
|
|
60 |
a4eaadad9216
|
if self.verbose: |
61 |
a4eaadad9216
|
print "state change: %i" % state |
62 |
2de4c35d30c8
|
|
63 |
2de4c35d30c8
|
if state == avahi.ENTRY_GROUP_ESTABLISHED: |
64 |
2de4c35d30c8
|
print "Service established." |
65 |
2de4c35d30c8
|
elif state == avahi.ENTRY_GROUP_COLLISION: |
66 |
2de4c35d30c8
|
|
67 |
2de4c35d30c8
|
rename_count = rename_count - 1 |
68 |
2de4c35d30c8
|
if rename_count > 0: |
69 |
2de4c35d30c8
|
name = server.GetAlternativeServiceName(name) |
70 |
a4eaadad9216
|
if self.verbose: |
71 |
a4eaadad9216
|
print "WARNING: Service name collision, changing name to '%s' ..." % name |
72 |
2de4c35d30c8
|
remove_service() |
73 |
2de4c35d30c8
|
add_service() |
74 |
2de4c35d30c8
|
|
75 |
2de4c35d30c8
|
else: |
76 |
a4eaadad9216
|
if self.verbose: |
77 |
a4eaadad9216
|
print "ERROR: No suitable service name found after %i retries, exiting." % n_rename |
78 |
2de4c35d30c8
|
main_loop.quit() |
79 |
2de4c35d30c8
|
elif state == avahi.ENTRY_GROUP_FAILURE: |
80 |
a4eaadad9216
|
if self.verbose: |
81 |
a4eaadad9216
|
print "Error in group state changed", error |
82 |
2de4c35d30c8
|
main_loop.quit() |
83 |
2de4c35d30c8
|
return |
84 |
a4eaadad9216
|
|
85 |
2de4c35d30c8
|
def start(self): |
86 |
2de4c35d30c8
|
DBusGMainLoop( set_as_default=True ) |
87 |
2de4c35d30c8
|
self.bus = dbus.SystemBus() |
88 |
2de4c35d30c8
|
|
89 |
2de4c35d30c8
|
self.server = dbus.Interface( |
90 |
2de4c35d30c8
|
self.bus.get_object( avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER ), |
91 |
2de4c35d30c8
|
avahi.DBUS_INTERFACE_SERVER ) |
92 |
2de4c35d30c8
|
|
93 |
2de4c35d30c8
|
self.server.connect_to_signal( "StateChanged", self.server_state_changed ) |
94 |
2de4c35d30c8
|
self.server_state_changed( self.server.GetState() ) |
95 |
a4eaadad9216
|
|
96 |
a4eaadad9216
|
def stop(self): |
97 |
a4eaadad9216
|
if self.verbose: |
98 |
a4eaadad9216
|
print "Stopping avahi-publish-service" |
99 |
a4eaadad9216
|
if not self.group is None: |
100 |
a4eaadad9216
|
self.group.Free() |
101 |
2de4c35d30c8
|
|
102 |
2de4c35d30c8
|
# every command must take a ui and and repo as arguments. |
103 |
2de4c35d30c8
|
# opts is a dict where you can find other command line flags |
104 |
2de4c35d30c8
|
# |
105 |
2de4c35d30c8
|
# Other parameters are taken in order from items on the command line that |
106 |
2de4c35d30c8
|
# don't start with a dash. If no default value is given in the parameter list, |
107 |
2de4c35d30c8
|
# they are required. |
108 |
2de4c35d30c8
|
def avahi_serve(ui, repo, **opts): |
109 |
2de4c35d30c8
|
# The doc string below will show up in hg help |
110 |
2de4c35d30c8
|
"""Serve and publish on avahi zeroconf""" |
111 |
2de4c35d30c8
|
|
112 |
2de4c35d30c8
|
#print opts |
113 |
2de4c35d30c8
|
if opts['port'] != 0: |
114 |
2de4c35d30c8
|
port = int(opts['port']) |
115 |
2de4c35d30c8
|
else: |
116 |
2de4c35d30c8
|
port = 8000 |
117 |
2de4c35d30c8
|
a = AvahiReg(opts['name'], port) |
118 |
a4eaadad9216
|
|
119 |
a4eaadad9216
|
if ui.cdata.has_option('web', 'description'): |
120 |
a4eaadad9216
|
a.serviceTXT += ["description=" + ui.cdata.get('web','description')] |
121 |
a4eaadad9216
|
if ui.cdata.has_option('ui', 'username'): |
122 |
a4eaadad9216
|
#remove < and > cose make problems on Avahi Discovery |
123 |
a4eaadad9216
|
a.serviceTXT += ["owner=" + |
124 |
a4eaadad9216
|
ui.cdata.get('ui','username') |
125 |
a4eaadad9216
|
.replace('<','') |
126 |
a4eaadad9216
|
.replace('>','')] |
127 |
a4eaadad9216
|
|
128 |
a4eaadad9216
|
a.verbose = ui.verbose |
129 |
2de4c35d30c8
|
a.start() |
130 |
a4eaadad9216
|
try: |
131 |
a4eaadad9216
|
commands.serve(ui,repo, **opts) |
132 |
a4eaadad9216
|
except KeyboardInterrupt: |
133 |
a4eaadad9216
|
pass |
134 |
2de4c35d30c8
|
|
135 |
a4eaadad9216
|
a.stop() |
136 |
2de4c35d30c8
|
|
137 |
2de4c35d30c8
|
cmdtable = { |
138 |
2de4c35d30c8
|
# cmd name function call |
139 |
2de4c35d30c8
|
"aserve": (avahi_serve, |
140 |
2de4c35d30c8
|
commands.table['^serve'][1], |
141 |
2de4c35d30c8
|
"hg aserve [OPTION]...") |
142 |
2de4c35d30c8
|
} |
143 |
2de4c35d30c8
|
|
144 |
2de4c35d30c8
|