Route output from backend through frontend

This commit is contained in:
Juhani Krekelä 2019-07-13 19:34:54 +03:00
parent e8e4257baa
commit c7a773958d
2 changed files with 64 additions and 24 deletions

View File

@ -1049,7 +1049,8 @@ void eventloop(void) {
// Read a command
read_command();
} else if (pollfds[0].revents & POLLHUP) {
// Quit
// Quit on frontend exiting
warnx("Frontend exited unexpectedly");
running = false;
} else {
errx(1, "Got poll event %hd on stdin\n", pollfds[0].revents);
@ -1063,6 +1064,9 @@ void eventloop(void) {
if (pollfds[1].revents & POLLIN) {
// Process a frame
process_frame();
} else if (pollfds[1].revents & POLLERR) {
// Lost connection
errx(1, "Network went down");
} else {
errx(1, "Got poll event %hd on packet socket\n", pollfds[1].revents);
}
@ -1121,13 +1125,8 @@ int main(int argc, char **argv) {
memcpy(own_mac, ifr.ifr_hwaddr.sa_data, sizeof(own_mac));
// Print it out
char own_mac_str[18];
format_mac(own_mac, own_mac_str);
if (printf("%s\n", own_mac_str) == -1) {
err(1, "printf");
}
if (fflush(stdout) == EOF) {
err(1, "fflush");
if (write(1, own_mac, 6) != 6) {
err(1, "write");
}
// Initialize the message id cache

View File

@ -73,6 +73,15 @@ def writeall(f, b):
while written < len(b):
written += f.write(b[written:])
def readall(f, length):
read = bytearray()
while len(read) < length:
data = f.read(length - len(read))
if data is None:
raise ConnectionError('Could not satisfy read of %i bytes' % length)
read.extend(data)
return bytes(read)
def parse_mac(text):
parts = text.split(':')
if len(parts) != 6:
@ -85,19 +94,34 @@ def parse_mac(text):
return parsed
def format_mac(mac):
return ':'.join(mac[i:i+1].hex() for i in range(len(mac)))
class PollBasedThread(threading.Thread):
def run(self):
poll = select.poll()
for f in self.pollin:
poll.register(f, select.POLLIN)
while True:
restart = False
self.initialize()
self.initialize()
poll = select.poll()
for f in self.pollin:
poll.register(f, select.POLLIN)
running = True
while running:
for fd, event in poll.poll():
if self.poll_loop(fd, event) != None:
running = False
running = True
while running and not restart:
for fd, event in poll.poll():
command = self.poll_loop(fd, event)
if command == None:
pass
elif command == 'quit':
running = False
elif command == 'restart':
restart = True
else:
raise ValueError("poll_loop() needs to return either None, 'quit', or 'restart'")
if not restart:
break
self.finalize()
@ -111,15 +135,26 @@ class PollBasedThread(threading.Thread):
...
class Backend(PollBasedThread):
def __init__(self, interface, writes_channel, control_channel):
def __init__(self, interface, nick, writes_channel, control_channel):
self.interface = interface
self.nick = nick
self.writes_channel = writes_channel
self.control_channel = control_channel
self.pollin = [self.writes_channel, self.control_channel]
super().__init__()
def initialize(self):
self.proc = subprocess.Popen(['sudo', libexec_dir + '/ethermess-backend', self.interface], stdin = subprocess.PIPE, stdout = sys.stdout, stderr = sys.stderr, bufsize = 0)
self.proc = subprocess.Popen(['sudo', libexec_dir + '/ethermess-backend', self.interface], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = sys.stderr, bufsize = 0)
self.pollin = [self.writes_channel, self.control_channel, self.proc.stdout]
# Tell the backend the status and nick
status = 0
nick = self.nick.encode('utf-8')
writeall(self.proc.stdin, bytes([status, len(nick)]) + nick)
# Read our MAC
self.mac = readall(self.proc.stdout, 6)
print('Own mac: %s' % format_mac(self.mac))
def poll_loop(self, fd, event):
if fd == self.writes_channel.fileno() and event & select.POLLIN:
@ -134,6 +169,15 @@ class Backend(PollBasedThread):
else:
raise Exception('Unreachable')
elif fd == self.proc.stdout.fileno() and event & select.POLLIN:
data = self.proc.stdout.read(1024)
sys.stdout.buffer.write(data)
sys.stdout.flush()
elif fd == self.proc.stdout.fileno() and event & select.POLLHUP:
print('Backend exited')
return 'quit'
else:
raise Exception('Unreachable')
@ -183,8 +227,5 @@ control_channel = Channel()
_, interface, nick = sys.argv
nick = nick.encode('utf-8')
writes_channel.send((bytes([0, len(nick)]) + nick))
Backend(interface, writes_channel, control_channel).start()
Backend(interface, nick, writes_channel, control_channel).start()
Input(writes_channel, control_channel).start()