break
###--------------------------------------------------------------------------
+### Address manipulation.
+
+def parse_address(addrstr):
+ return unpack('>L', S.inet_aton(addrstr))[0]
+
+def parse_net(netstr):
+ try: sl = netstr.index('/')
+ except ValueError: raise ValueError('missing mask')
+ addr = parse_address(netstr[:sl])
+ if netstr[sl + 1:].isdigit():
+ n = int(netstr[sl + 1:], 10)
+ mask = (1 << 32) - (1 << 32 - n)
+ else:
+ mask = parse_address(netstr[sl + 1:])
+ if addr&~mask: raise ValueError('network contains bits set beyond mask')
+ return addr, mask
+
+def straddr(a): return a is None and '#<none>' or S.inet_ntoa(pack('>L', a))
+def strmask(m):
+ for i in xrange(33):
+ if m == 0xffffffff ^ ((1 << (32 - i)) - 1): return str(i)
+ return straddr(m)
+
+###--------------------------------------------------------------------------
### Parse the configuration file.
## Hmm. Should I try to integrate this with the peers database? It's not a
## Syntax of a net is ADDRESS/MASK, where ADDRESS is a dotted-quad,
## and MASK is either a dotted-quad or a single integer N indicating
## a mask with N leading ones followed by trailing zeroes.
- slash = net.index('/')
- addr, = unpack('>L', S.inet_aton(net[:slash]))
- if net.find('.', slash + 1) >= 0:
- mask, = unpack('>L', S.inet_aton(net[:slash]))
- else:
- n = int(net[slash + 1:], 10)
- mask = (1 << 32) - (1 << 32 - n)
- pats.append((tag, peer, addr & mask, mask))
+ addr, mask = parse_net(net)
+ pats.append((tag, peer, addr, mask))
## Annoyingly, RawConfigParser doesn't preserve the order of options.
## In order to make things vaguely sane, we topologically sort the
### This will be a configuration file.
CF = None
-def straddr(a): return a is None and '#<none>' or S.inet_ntoa(pack('>L', a))
-def strmask(m):
- for i in xrange(33):
- if m == 0xffffffff ^ ((1 << (32 - i)) - 1): return i
- return straddr(m)
-
def cmd_showconfig():
T.svcinfo('test-addr=%s' % CF.testaddr)
def cmd_showgroups():
try:
sk.connect((peer, 1))
addr, _ = sk.getsockname()
- addr, = unpack('>L', S.inet_aton(addr))
+ addr = parse_address(addr)
return addr
except S.error:
return None
sk.close()
_kick = T.Queue()
+_delay = None
+
+def cancel_delay():
+ global _delay
+ if _delay is not None:
+ if T._debug: print '# cancel delayed kick'
+ G.source_remove(_delay)
+ _delay = None
+
+def netupdown(upness, reason):
+ """
+ Add or kill peers according to whether the network is up or down.
+
+ UPNESS is true if the network is up, or false if it's down.
+ """
+
+ _kick.put((upness, reason))
+
+def delay_netupdown(upness, reason):
+ global _delay
+ cancel_delay()
+ def _func():
+ global _delay
+ if T._debug: print '# delayed %s: %s' % (upness, reason)
+ _delay = None
+ netupdown(upness, reason)
+ return False
+ if T._debug: print '# delaying %s: %s' % (upness, reason)
+ _delay = G.timeout_add(2000, _func)
+
def kickpeers():
while True:
upness, reason = _kick.get()
if T._debug: print '# kickpeers %s: %s' % (upness, reason)
select = []
+ cancel_delay()
## Make sure the configuration file is up-to-date. Don't worry if we
## can't do anything useful.
SM.notify('conntrack', upness and 'up' or 'down', *select + reason)
for c in changes: c()
-def netupdown(upness, reason):
- """
- Add or kill peers according to whether the network is up or down.
-
- UPNESS is true if the network is up, or false if it's down.
- """
-
- _kick.put((upness, reason))
-
###--------------------------------------------------------------------------
### NetworkManager monitor.
def _nm_state(me, state):
if state in NM_CONNSTATES:
- netupdown(True, ['nm', 'connected'])
+ delay_netupdown(True, ['nm', 'connected'])
else:
- netupdown(False, ['nm', 'disconnected'])
+ delay_netupdown(False, ['nm', 'disconnected'])
def _nm_connchange(me, props):
- if props.get('Default', False):
- netupdown(True, ['nm', 'default-connection-change'])
+ if props.get('Default', False) or props.get('Default6', False):
+ delay_netupdown(True, ['nm', 'default-connection-change'])
##--------------------------------------------------------------------------
### Connman monitor.
def _cm_state(me, prop, value):
if prop != 'State': return
- netupdown(value == 'online', ['connman', value])
+ delay_netupdown(value == 'online', ['connman', value])
###--------------------------------------------------------------------------
### Maemo monitor.
def _icd_state(me, iap, ty, state, hunoz):
if state == 'CONNECTED':
me._iap = iap
- netupdown(True, ['icd', 'connected', iap])
+ delay_netupdown(True, ['icd', 'connected', iap])
elif state == 'IDLE' and iap == me._iap:
me._iap = None
- netupdown(False, ['icd', 'idle'])
+ delay_netupdown(False, ['icd', 'idle'])
###--------------------------------------------------------------------------
### D-Bus connection tracking.
DBM.addmon(NetworkManagerMonitor())
DBM.addmon(ConnManMonitor())
DBM.addmon(MaemoICdMonitor())
- G.timeout_add_seconds(30, lambda: (netupdown(True, ['interval-timer'])
- or True))
+ G.timeout_add_seconds(30, lambda: (_delay is not None or
+ netupdown(True, ['interval-timer']) or
+ True))
def parse_options():
"""