##// END OF EJS Templates
zeroconf: don't allow ipv6 addresses
Alexander Solovyov -
r7777:e3425726 default
parent child Browse files
Show More
@@ -1,159 +1,159 b''
1 1 # zeroconf.py - zeroconf support for Mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of
6 6 # the GNU General Public License (version 2), incorporated herein by
7 7 # reference.
8 8
9 9 '''zeroconf support for mercurial repositories
10 10
11 11 Zeroconf enabled repositories will be announced in a network without the need
12 12 to configure a server or a service. They can be discovered without knowing
13 13 their actual IP address.
14 14
15 15 To use the zeroconf extension add the following entry to your hgrc file:
16 16
17 17 [extensions]
18 18 hgext.zeroconf =
19 19
20 20 To allow other people to discover your repository using run "hg serve" in your
21 21 repository.
22 22
23 23 $ cd test
24 24 $ hg serve
25 25
26 26 You can discover zeroconf enabled repositories by running "hg paths".
27 27
28 28 $ hg paths
29 29 zc-test = http://example.com:8000/test
30 30 '''
31 31
32 32 import Zeroconf, socket, time, os
33 33 from mercurial import ui
34 34 from mercurial import extensions
35 35 from mercurial.hgweb import hgweb_mod
36 36 from mercurial.hgweb import hgwebdir_mod
37 37
38 38 # publish
39 39
40 40 server = None
41 41 localip = None
42 42
43 43 def getip():
44 44 # finds external-facing interface without sending any packets (Linux)
45 45 try:
46 46 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
47 47 s.connect(('1.0.0.1', 0))
48 48 ip = s.getsockname()[0]
49 49 return ip
50 50 except:
51 51 pass
52 52
53 53 # Generic method, sometimes gives useless results
54 54 dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
55 if not dumbip.startswith('127.'):
55 if not dumbip.startswith('127.') and ':' not in dumbip:
56 56 return dumbip
57 57
58 58 # works elsewhere, but actually sends a packet
59 59 try:
60 60 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
61 61 s.connect(('1.0.0.1', 1))
62 62 ip = s.getsockname()[0]
63 63 return ip
64 64 except:
65 65 pass
66 66
67 67 return dumbip
68 68
69 69 def publish(name, desc, path, port):
70 70 global server, localip
71 71 if not server:
72 72 try:
73 73 server = Zeroconf.Zeroconf()
74 74 except socket.gaierror:
75 75 # if we have no internet connection, this can happen.
76 76 return
77 77 ip = getip()
78 78 localip = socket.inet_aton(ip)
79 79
80 80 parts = socket.gethostname().split('.')
81 81 host = parts[0] + ".local"
82 82
83 83 # advertise to browsers
84 84 svc = Zeroconf.ServiceInfo('_http._tcp.local.',
85 85 name + '._http._tcp.local.',
86 86 server = host,
87 87 port = port,
88 88 properties = {'description': desc,
89 89 'path': "/" + path},
90 90 address = localip, weight = 0, priority = 0)
91 91 server.registerService(svc)
92 92
93 93 # advertise to Mercurial clients
94 94 svc = Zeroconf.ServiceInfo('_hg._tcp.local.',
95 95 name + '._hg._tcp.local.',
96 96 server = host,
97 97 port = port,
98 98 properties = {'description': desc,
99 99 'path': "/" + path},
100 100 address = localip, weight = 0, priority = 0)
101 101 server.registerService(svc)
102 102
103 103 class hgwebzc(hgweb_mod.hgweb):
104 104 def __init__(self, repo, name=None):
105 105 super(hgwebzc, self).__init__(repo, name)
106 106 name = self.reponame or os.path.basename(repo.root)
107 107 desc = self.repo.ui.config("web", "description", name)
108 108 publish(name, desc, name, int(repo.ui.config("web", "port", 8000)))
109 109
110 110 class hgwebdirzc(hgwebdir_mod.hgwebdir):
111 111 def run(self):
112 112 for r, p in self.repos:
113 113 u = ui.ui(parentui=self.parentui)
114 114 u.readconfig(os.path.join(p, '.hg', 'hgrc'))
115 115 n = os.path.basename(r)
116 116 publish(n, "hgweb", p, int(u.config("web", "port", 8000)))
117 117 return super(hgwebdirzc, self).run()
118 118
119 119 # listen
120 120
121 121 class listener(object):
122 122 def __init__(self):
123 123 self.found = {}
124 124 def removeService(self, server, type, name):
125 125 if repr(name) in self.found:
126 126 del self.found[repr(name)]
127 127 def addService(self, server, type, name):
128 128 self.found[repr(name)] = server.getServiceInfo(type, name)
129 129
130 130 def getzcpaths():
131 131 server = Zeroconf.Zeroconf()
132 132 l = listener()
133 133 browser = Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l)
134 134 time.sleep(1)
135 135 server.close()
136 136 for v in l.found.values():
137 137 n = v.name[:v.name.index('.')]
138 138 n.replace(" ", "-")
139 139 u = "http://%s:%s%s" % (socket.inet_ntoa(v.address), v.port,
140 140 v.properties.get("path", "/"))
141 141 yield "zc-" + n, u
142 142
143 143 def config(orig, self, section, key, default=None, untrusted=False):
144 144 if section == "paths" and key.startswith("zc-"):
145 145 for n, p in getzcpaths():
146 146 if n == key:
147 147 return p
148 148 return orig(self, section, key, default, untrusted)
149 149
150 150 def configitems(orig, self, section, untrusted=False):
151 151 r = orig(self, section, untrusted)
152 152 if section == "paths":
153 153 r += getzcpaths()
154 154 return r
155 155
156 156 extensions.wrapfunction(ui.ui, 'config', config)
157 157 extensions.wrapfunction(ui.ui, 'configitems', configitems)
158 158 hgweb_mod.hgweb = hgwebzc
159 159 hgwebdir_mod.hgwebdir = hgwebdirzc
General Comments 0
You need to be logged in to leave comments. Login now