-
Notifications
You must be signed in to change notification settings - Fork 0
/
RunnerServer.py
126 lines (107 loc) · 4.2 KB
/
RunnerServer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import select
import socket
import threading
import atexit
import time
import psutil
import logging
from queue import Queue
from AppCtx import AppContext
class Message:
def __init__(self, cmd, args):
self.command = cmd
self.args = args
class ServerThread(threading.Thread):
lock = threading.Lock()
def run(self) -> None:
self.name = "RunnerServer"
return super().run()
class RunnerServer:
def __init__(self,ctx:AppContext=None, ip='127.0.0.1', port=9897):
self.queue = Queue()
self.callbackQueue = Queue()
self.logger = logging.getLogger("SRV")
self.logger.setLevel(logging.DEBUG if ctx.verbose else logging.INFO)
if ctx.args.logToFile:
self.logger.addHandler(ctx.fileHandler)
self.server_ip = ip
self.server_port = port
self.server_socket = None
self.client_socket = None
self.active = False
self.clientConnected = False
self.thread = ServerThread(target=self.handle_client)
def isClientConnected(self):
with self.thread.lock:
return self.clientConnected
def setClientConnected(self,value):
with self.thread.lock:
self.clientConnected = value
def addCallback(self, callback:str):
self.callbackQueue.put(callback)
def start(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.server_ip, self.server_port))
self.server_socket.listen(1)
self.active = True
self.logger.debug("Started")
self.thread.start()
def stop(self):
with self.thread.lock:
if self.active:
self.active = False
self.server_socket.close()
self.clientConnected = False
self.logger.debug("Stopped")
def handle_client(self):
try:
while self.active:
self.client_socket, client_address = self.server_socket.accept()
self.client_socket.setblocking(False)
self.setClientConnected(True)
buff = b''
while self.active and not self.client_socket._closed:
try:
rread, wwrite, _ = select.select([self.client_socket], [self.client_socket], [], 0)
if rread:
dat = self.client_socket.recv(1024)
if not dat:
break
buff += dat
while b'\0' in buff:
dt,buff = buff.split(b'\0', 1)
self.handle_client_message(dt.decode('utf-8'))
if wwrite:
if not self.callbackQueue.empty():
dt = self.callbackQueue.get()
self.client_socket.sendall(dt.encode('utf-8'))
except BlockingIOError:
pass
except ConnectionResetError:
break
self.client_socket.close()
self.setClientConnected(False)
except OSError:
#print("server closed")
pass
except Exception as e:
print(f"UNKNOWN SERVER ERROR <{e.__class__.__name__}>: {e}")
def handle_client_message(self, message):
if not message.startswith('m:'):
return
message = message[2:]
cmd,args = message.split(';',1)
if (cmd == "print"):
_astr = args.replace('',";")
if (_astr == "$auto_reload_request$"):
self.logger.info("Auto reload request")
v = input("Type exit to exit from VM. Otherwise press any key for reload")
if (v == "exit"):
self.addCallback(v)
else:
self.addCallback(v)
return
self.logger.info(_astr)
return
self.queue.put(Message(cmd,args))
self.logger.debug("Received: {} with args: {}".format(cmd,args))