import socket import os import subprocess import sys import threading import Queue import errno import json import struct class Driver: def __init__(self, port, use_stdin, exporter_already_running = False, use_air = False): self.port = port self.use_stdin = use_stdin self.exporter_already_running = exporter_already_running self.use_air = use_air self.stdin = None self.conn = None def make_exporter_path(self, prog_name): return os.path.join(os.path.dirname(os.path.abspath(__file__)), prog_name) def start(self): self.sock = socket.socket() self.sock.bind(("localhost", self.port)) self.sock.settimeout(0.5) self.sock.listen(0) if not self.exporter_already_running: exporter_proc_args = [self.make_exporter_path("flash/Exporter.exe")] if self.use_air: exporter_proc_args = [self.make_exporter_path("Exporter.app/Expoter.exe"), str(self.port)] self.proc = subprocess.Popen(exporter_proc_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if self.use_stdin: self.stdin = Queue.Queue() reader = threading.Thread(target=self._get_stdin) reader.daemon = True reader.start() while self.conn is None and (self.exporter_already_running or self.proc.returncode is None): try: (self.conn, _) = self.sock.accept() except socket.timeout, e: pass except e: print e self.sock.close() if not self.exporter_already_running: self.proc.wait() sys.exit(1) if not self.exporter_already_running: self.proc.poll() if self.conn: self.conn.setblocking(False) return self.conn != None def send_json(self, jsonObj): data = json.dumps(jsonObj) datalen = struct.pack(">I", len(data)) self.conn.send(datalen) self.conn.send(data) def loop(self, msg_callback, stdin_callback = None): buf = "" quit = False closed = False while self.exporter_already_running or self.proc.returncode is None: try: d = self.conn.recv(4096) if len(d): buf += d if len(buf) >= 4: buf_len = struct.unpack_from(">I", buf, 0)[0] if len(buf) >= 4 + buf_len: msg = buf[4:4+buf_len] buf = buf[4+buf_len:] if not msg_callback(msg): quit = True else: quit = True closed = True except socket.error, e: if e.args[0] == errno.EWOULDBLOCK or e.args[0] == errno.EAGAIN: pass else: print e quit = True closed = True if not quit and self.use_stdin and self.stdin.qsize(): line = self.stdin.get() if line == "": quit = True elif stdin_callback: if not stdin_callback(line): quit = True if quit: if not closed and not self.exporter_already_running: self.send_json({"command":"exit"}) self.conn.close() self.sock.close() if not self.exporter_already_running: self.proc.kill() sys.exit(1) if not self.exporter_already_running: self.proc.poll() if self.conn: self.conn.close() self.sock.close() def _get_stdin(self): while True: line = sys.stdin.readline() self.stdin.put(line) if line == "": return