From c9f21862006f50937f22f51155ee81ff47399730 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Sat, 7 Mar 2020 16:27:55 +0100 Subject: bump --- notmuch-tcp-server | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 notmuch-tcp-server (limited to 'notmuch-tcp-server') diff --git a/notmuch-tcp-server b/notmuch-tcp-server new file mode 100644 index 0000000..328b72c --- /dev/null +++ b/notmuch-tcp-server @@ -0,0 +1,142 @@ +#!@python@/bin/python + +from os import environ +from os.path import expanduser +import socket +import ssl +import shlex +from sys import argv, stdin, stdout, exit +from multiprocessing import Process +from select import select +from io import BytesIO +import subprocess +from time import sleep + +import logging + + +logger = logging.getLogger('notmuch-tcp-server') +logger.setLevel(logging.DEBUG) +lh = logging.StreamHandler() +lh.setLevel(logging.DEBUG) +lh.setFormatter(logging.Formatter( fmt = '{levelname} - {message}', style = '{' )) +logger.addHandler(lh) + + +port = environ.get('NOTMUCH_TCP') +host = environ.get('NOTMUCH_HOST') +hostname = socket.gethostname() + +if port is None: + port = 2010 +if host is None: + host = "odin.asgard.yggdrasil" + +sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) +sslcontext.load_verify_locations(cafile = expanduser('~/.notmuch-tcp/ca.pem')) +sslcontext.load_cert_chain(certfile = expanduser(f"~/.notmuch-tcp/{hostname}.pem"), keyfile = expanduser(f"~/.notmuch-tcp/{hostname}.key")) + +s = None +for res in socket.getaddrinfo(host, int(port), socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + af, socktype, proto, canonname, sa = res + try: + s = socket.socket(af, socktype, proto) + except OSError as msg: + logger.error(f"Could not create socket: {msg}") + s = None + continue + try: + s.bind(sa) + s.listen() + except OSError as msg: + logger.error(f"Could not bind socket: {msg}") + s.close() + s = None + continue + break +if s is None: + logger.error('Could not open any sockets') + exit(1) + +with s as sock: + with sslcontext.wrap_socket(sock, server_side = True) as ssock: + while True: + logger.debug('waiting...') + conn = None + try: + conn, client_addr = ssock.accept() + client_host, client_port = client_addr + logger.info(f"Connected: {client_host}:{client_port}") + + with BytesIO() as buffer: + while True: + resp = conn.recv(256) + buffer.write(resp) + buffer.seek(0) + start_index = 0 + for line in buffer: + start_index += len(line) + escaped_args = line[:-1].decode() + break + if start_index: + buffer.seek(start_index) + remaining = buffer.read() + buffer.truncate(0) + buffer.seek(0) + buffer.write(remaining) + break + else: + buffer.seek(0, 2) + + logger.info(f"Arguments: {escaped_args}") + + sproc = subprocess.Popen(["notmuch"] + shlex.split(escaped_args), shell = False, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + + def send_stdout(): + while True: + to_send = sproc.stdout.read(256) + logger.debug(f"Sending: {to_send}") + + if to_send: + conn.sendall(to_send) + else: + logger.debug(f"Done sending") + break + + def recv_stdin(): + remaining = buffer.read() + logger.debug(f"Received (buffered): {remaining}") + sproc.stdin.write(remaining) + + while True: + logger.debug("Waiting on input...") + ready = select([conn], [], [], 5) + if ready[0]: + resp = conn.recv(256) + logger.debug(f"Received: {resp}") + + if len(resp) <= 0: + break + + sproc.stdin.write(resp) + else: + break + logger.debug(f"Done receiving") + sproc.stdin.close() + + sleep(5) + + sproc.kill() + + send = Process(target = send_stdout) + recv = Process(target = recv_stdin) + send.start() + recv.start() + sproc_res = sproc.wait() + logger.info(f"Subprocess result: {sproc_res}") + send.join() + recv.terminate() + logger.debug(f"Handled I/O") + finally: + if conn is not None: + conn.close() -- cgit v1.2.3