diff options
Diffstat (limited to 'scripts/swig_bot_lib/server.py')
-rw-r--r-- | scripts/swig_bot_lib/server.py | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/scripts/swig_bot_lib/server.py b/scripts/swig_bot_lib/server.py new file mode 100644 index 0000000000000..cc25cee4d4b1a --- /dev/null +++ b/scripts/swig_bot_lib/server.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +""" +SWIG generation server. Listens for connections from swig generation clients +and runs swig in the requested fashion, sending back the results. +""" + +# Future imports +from __future__ import absolute_import +from __future__ import print_function + +# Python modules +import argparse +import io +import logging +import os +import select +import shutil +import socket +import struct +import sys +import tempfile +import traceback + +# LLDB modules +import use_lldb_suite +from lldbsuite.support import fs +from lldbsuite.support import sockutil + +# package imports +from . import local +from . import remote + +default_port = 8537 + +def add_subparser_args(parser): + parser.add_argument( + "--port", + action="store", + default=default_port, + help=("The local port to bind to")) + + parser.add_argument( + "--swig-executable", + action="store", + default=fs.find_executable("swig"), + dest="swig_executable") + +def finalize_subparser_options(options): + pass + +def initialize_listening_socket(options): + logging.debug("Creating socket...") + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + logging.info("Binding to ip address '', port {}".format(options.port)) + s.bind(('', options.port)) + + logging.debug("Putting socket in listen mode...") + s.listen() + return s + +def accept_once(sock, options): + logging.debug("Waiting for connection...") + while True: + rlist, wlist, xlist = select.select([sock], [], [], 0.5) + if not rlist: + continue + + client, addr = sock.accept() + logging.info("Received connection from {}".format(addr)) + data_size = struct.unpack("!I", sockutil.recvall(client, 4))[0] + logging.debug("Expecting {} bytes of data from client" + .format(data_size)) + data = sockutil.recvall(client, data_size) + logging.info("Received {} bytes of data from client" + .format(len(data))) + + pack_location = None + try: + tempfolder = os.path.join(tempfile.gettempdir(), "swig-bot") + os.makedirs(tempfolder, exist_ok=True) + + pack_location = tempfile.mkdtemp(dir=tempfolder) + logging.debug("Extracting archive to {}".format(pack_location)) + + local.unpack_archive(pack_location, data) + logging.debug("Successfully unpacked archive...") + + config_file = os.path.normpath(os.path.join(pack_location, + "config.json")) + parsed_config = remote.parse_config(io.open(config_file)) + config = local.LocalConfig() + config.languages = parsed_config["languages"] + config.swig_executable = options.swig_executable + config.src_root = pack_location + config.target_dir = os.path.normpath( + os.path.join(config.src_root, "output")) + logging.info( + "Running swig. languages={}, swig={}, src_root={}, target={}" + .format(config.languages, config.swig_executable, + config.src_root, config.target_dir)) + + status = local.generate(config) + logging.debug("Finished running swig. Packaging up files {}" + .format(os.listdir(config.target_dir))) + zip_data = io.BytesIO() + zip_file = local.pack_archive(zip_data, config.target_dir, None) + response_status = remote.serialize_response_status(status) + logging.debug("Sending response status {}".format(response_status)) + logging.info("(swig output) -> swig_output.json") + zip_file.writestr("swig_output.json", response_status) + + zip_file.close() + response_data = zip_data.getvalue() + logging.info("Sending {} byte response".format(len(response_data))) + client.sendall(struct.pack("!I", len(response_data))) + client.sendall(response_data) + finally: + if pack_location is not None: + logging.debug("Removing temporary folder {}" + .format(pack_location)) + shutil.rmtree(pack_location) + +def accept_loop(sock, options): + while True: + try: + accept_once(sock, options) + except Exception as e: + error = traceback.format_exc() + logging.error("An error occurred while processing the connection.") + logging.error(error) + +def run(options): + print(options) + sock = initialize_listening_socket(options) + accept_loop(sock, options) + return options |