Implement offline timeouts

This commit is contained in:
Juhani Krekelä 2019-07-15 19:14:03 +03:00
parent 7d4e304565
commit d406d269da
1 changed files with 35 additions and 3 deletions

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
libexec_dir = __LIBEXECDIR__
offline_timeout = 5 * 60
import enum
import select
import subprocess
@ -143,8 +145,6 @@ def handle_status(mac, status, nick):
peers[mac] = Peer(nick = None, status = None, lastseen = None)
peers[mac].lastseen = time.monotonic()
if peers[mac].nick is not None and peers[mac].status != statuses.offline and nick != peers[mac].nick:
print('=== ~%s -> ~%s [%s]' % (peers[mac].nick, nick, format_mac(mac)))
@ -193,6 +193,8 @@ def handle_message(mac, message):
print('<%s> %s' % (nick, line))
def eventloop(proc):
global peers
# Create unbuffered version of stdin and close the old one as we
# won't need it anymore
unbuf_stdin = open(sys.stdin.buffer.fileno(), 'rb', buffering = 0)
@ -207,7 +209,30 @@ def eventloop(proc):
running = True
while running:
for fd, event in poll.poll():
# Handle offline timeouts
now = time.monotonic()
for mac, peer in peers.items():
if peer.lastseen + offline_timeout < now:
peer.status = statuses.offline
print('<<< (timeout) ~%s [%s]' % (peer.nick, format_mac(mac)))
# Figure out how long to wait in poll()
wait = None
for peer in peers.values():
if peer.status != statuses.offline:
if wait is None or wait >= peer.lastseen + offline_timeout - now:
wait = peer.lastseen + offline_timeout - now
# Clamp at 0
if wait is not None and wait < 0:
wait = 0
# Convert s to ms
if wait is not None:
wait = wait * 1000
# Process events
for fd, event in poll.poll(wait):
if fd == proc.stdout.fileno() and event & select.POLLIN:
event_type = readall(proc.stdout, 1)
if event_type == b's':
@ -219,6 +244,8 @@ def eventloop(proc):
handle_status(source_mac, statuses(status), nick.decode('utf-8'))
peers[source_mac].lastseen = time.monotonic()
elif event_type == b'i':
# Msgid for message
msgid = readall_u16(proc.stdout)
@ -234,6 +261,8 @@ def eventloop(proc):
msgid = readall_u16(proc.stdout)
print('(ack: %s %i)' % (format_mac(source_mac), msgid)) #debg
peers[source_mac].lastseen = time.monotonic()
elif event_type == b'A':
# ACK not received (and message send failed)
print('(ack failed)') #debg
@ -246,6 +275,8 @@ def eventloop(proc):
handle_message(source_mac, message.decode('utf-8'))
peers[source_mac].lastseen = time.monotonic()
else:
raise ValueError('Unknown event type from backend: %s' % repr(event_type))
@ -272,6 +303,7 @@ def eventloop(proc):
else:
raise Exception('Unreachable')
def main():
global own_nick, own_status