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