Start tracking peers
This commit is contained in:
parent
97d42bce52
commit
114d595ed2
103
ethermess.py
103
ethermess.py
|
@ -1,15 +1,36 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
libexec_dir = __LIBEXECDIR__
|
libexec_dir = __LIBEXECDIR__
|
||||||
|
|
||||||
|
import enum
|
||||||
import select
|
import select
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
class statuses(enum.Enum):
|
||||||
|
available = 0
|
||||||
|
unavailable = 1
|
||||||
|
offline = 2
|
||||||
|
|
||||||
own_nick = None
|
own_nick = None
|
||||||
own_status = None
|
own_status = None
|
||||||
|
|
||||||
default_target_mac = None
|
default_target_mac = None
|
||||||
|
|
||||||
|
peers = {}
|
||||||
|
class Peer:
|
||||||
|
def __init__(self, status, nick, lastseen):
|
||||||
|
self.status = status
|
||||||
|
self.nick = nick
|
||||||
|
self.lastseen = lastseen
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
r = 'Peer(%s, %s, %s)' % (repr(self.status), repr(self.nick), repr(self.lastseen))
|
||||||
|
if __name__ != '__main__':
|
||||||
|
return '%s.%s' % (__name__, r)
|
||||||
|
else:
|
||||||
|
return r
|
||||||
|
|
||||||
def writeall(f, b):
|
def writeall(f, b):
|
||||||
written = 0
|
written = 0
|
||||||
while written < len(b):
|
while written < len(b):
|
||||||
|
@ -62,7 +83,7 @@ def send_status_request(backend, mac):
|
||||||
|
|
||||||
def set_status_nick(backend, status, nick):
|
def set_status_nick(backend, status, nick):
|
||||||
encoded = nick.encode('utf-8')
|
encoded = nick.encode('utf-8')
|
||||||
writeall(backend, b's' + bytes([status, len(encoded)]) + encoded)
|
writeall(backend, b's' + bytes([status.value, len(encoded)]) + encoded)
|
||||||
|
|
||||||
def handle_user_command(backend, line):
|
def handle_user_command(backend, line):
|
||||||
global own_nick, own_status
|
global own_nick, own_status
|
||||||
|
@ -89,11 +110,11 @@ def handle_user_command(backend, line):
|
||||||
send_status_request(backend, mac)
|
send_status_request(backend, mac)
|
||||||
|
|
||||||
elif command == '/available' and rest == '':
|
elif command == '/available' and rest == '':
|
||||||
own_status = 0
|
own_status = statuses.available
|
||||||
set_status_nick(backend, own_status, own_nick)
|
set_status_nick(backend, own_status, own_nick)
|
||||||
|
|
||||||
elif command == '/unavailable' and rest == '':
|
elif command == '/unavailable' and rest == '':
|
||||||
own_status = 1
|
own_status = statuses.unavailable
|
||||||
set_status_nick(backend, own_status, own_nick)
|
set_status_nick(backend, own_status, own_nick)
|
||||||
|
|
||||||
elif command == '/nick':
|
elif command == '/nick':
|
||||||
|
@ -114,6 +135,63 @@ def handle_user_command(backend, line):
|
||||||
else:
|
else:
|
||||||
send_message(backend, default_target_mac, line)
|
send_message(backend, default_target_mac, line)
|
||||||
|
|
||||||
|
def handle_status(mac, status, nick):
|
||||||
|
global peers
|
||||||
|
|
||||||
|
if mac not in peers:
|
||||||
|
# Never seen before
|
||||||
|
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)))
|
||||||
|
|
||||||
|
peers[mac].nick = nick
|
||||||
|
|
||||||
|
if status != peers[mac].status:
|
||||||
|
if status == statuses.offline:
|
||||||
|
print('<<< ~%s [%s]' % (nick, format_mac(mac)))
|
||||||
|
elif peers[mac].status is None or peers[mac].status == statuses.offline:
|
||||||
|
if status == statuses.available:
|
||||||
|
print('>>> ~%s [%s]' % (nick, format_mac(mac)))
|
||||||
|
else:
|
||||||
|
print('>>> ~%s (%s) [%s]' % (nick, status.name, format_mac(mac)))
|
||||||
|
else:
|
||||||
|
print('=== ~%s (%s) [%s]' % (nick, status.name, format_mac(mac)))
|
||||||
|
|
||||||
|
peers[mac].status = status
|
||||||
|
|
||||||
|
def handle_message(mac, message):
|
||||||
|
global peers
|
||||||
|
|
||||||
|
if mac not in peers:
|
||||||
|
nick = format_mac(mac)
|
||||||
|
|
||||||
|
else:
|
||||||
|
nick = peers[mac].nick
|
||||||
|
|
||||||
|
# Ensure nicks are unique
|
||||||
|
unique = True
|
||||||
|
for peer_mac, peer in peers.items():
|
||||||
|
if peer_mac == mac: continue
|
||||||
|
|
||||||
|
if peer.nick == nick:
|
||||||
|
# Nick not unique
|
||||||
|
unique = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if unique:
|
||||||
|
# Unique nicks: ~nick
|
||||||
|
nick = '~' + nick
|
||||||
|
else:
|
||||||
|
# Non-unique nicks: [MAC]~nick
|
||||||
|
nick = '[%s]~%s' % (format_mac(mac), nick)
|
||||||
|
|
||||||
|
for line in message.split('\n'):
|
||||||
|
print('<%s> %s' % (nick, ascii(line)))
|
||||||
|
|
||||||
def eventloop(proc):
|
def eventloop(proc):
|
||||||
# Create unbuffered version of stdin
|
# Create unbuffered version of stdin
|
||||||
unbuf_stdin = open(sys.stdin.buffer.fileno(), 'rb', buffering = 0)
|
unbuf_stdin = open(sys.stdin.buffer.fileno(), 'rb', buffering = 0)
|
||||||
|
@ -137,7 +215,7 @@ def eventloop(proc):
|
||||||
nick_length, = readall(proc.stdout, 1)
|
nick_length, = readall(proc.stdout, 1)
|
||||||
nick = readall(proc.stdout, nick_length,)
|
nick = readall(proc.stdout, nick_length,)
|
||||||
|
|
||||||
print('%s (%s) ~%s' % (format_mac(source_mac), format_status(status), nick.decode('utf-8')))
|
handle_status(source_mac, statuses(status), nick.decode('utf-8'))
|
||||||
|
|
||||||
elif event_type == b'i':
|
elif event_type == b'i':
|
||||||
# Msgid for message
|
# Msgid for message
|
||||||
|
@ -164,17 +242,10 @@ def eventloop(proc):
|
||||||
message_length = readall_u16(proc.stdout)
|
message_length = readall_u16(proc.stdout)
|
||||||
message = readall(proc.stdout, message_length)
|
message = readall(proc.stdout, message_length)
|
||||||
|
|
||||||
print('<%s> %s' % (format_mac(source_mac), message.decode('utf-8'))) #debg
|
handle_message(source_mac, message.decode('utf-8'))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Not sth we handle yet
|
raise ValueError('Unknown event type from backend: %s' % repr(event_type))
|
||||||
data = proc.stdout.read(1023)
|
|
||||||
if data == b'':
|
|
||||||
data = b'[!] ' + event_type
|
|
||||||
else:
|
|
||||||
data = b'[!] ' + event_type + data
|
|
||||||
sys.stdout.buffer.write(data)
|
|
||||||
sys.stdout.buffer.flush()
|
|
||||||
|
|
||||||
elif fd == proc.stdout.fileno() and event & select.POLLHUP:
|
elif fd == proc.stdout.fileno() and event & select.POLLHUP:
|
||||||
print('Backend exited')
|
print('Backend exited')
|
||||||
|
@ -207,14 +278,14 @@ def main():
|
||||||
proc = subprocess.Popen(['sudo', libexec_dir + '/ethermess-backend', interface], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = sys.stderr, bufsize = 0)
|
proc = subprocess.Popen(['sudo', libexec_dir + '/ethermess-backend', interface], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = sys.stderr, bufsize = 0)
|
||||||
|
|
||||||
# Tell the backend the status and nick
|
# Tell the backend the status and nick
|
||||||
own_status = 0
|
own_status = statuses.available
|
||||||
encoded = own_nick.encode('utf-8')
|
encoded = own_nick.encode('utf-8')
|
||||||
writeall(proc.stdin, bytes([own_status, len(encoded)]) + encoded)
|
writeall(proc.stdin, bytes([own_status.value, len(encoded)]) + encoded)
|
||||||
|
|
||||||
# Read our MAC
|
# Read our MAC
|
||||||
mac = readall(proc.stdout, 6)
|
mac = readall(proc.stdout, 6)
|
||||||
|
|
||||||
print('Own mac: %s' % format_mac(mac))
|
print('--- MAC: %s' % format_mac(mac))
|
||||||
|
|
||||||
eventloop(proc)
|
eventloop(proc)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue