/
riddler_client.py
148 lines (121 loc) · 4.71 KB
/
riddler_client.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import threading
import SocketServer
import riddler_interface as interface
import socket
class client(threading.Thread):
def __init__(self, args):
super(client, self).__init__(None)
self.name = "exporter"
# Start listening threaded TCP server and wait for clients
self.server = ThreadedTCPServer((args.client_host, args.client_port), tcp_handler, bind_and_activate=False)
self.server.allow_reuse_address = True
self.server.timeout = .5
self.server.server_bind()
self.server.server_activate()
self.server.args = args
self.server.last_event = interface.STOPPED
self.server.clients = []
self.server.nodes = []
self.server.riddler = None
self.start()
# Stop the TCP server
def stop(self):
for client in self.server.clients:
client.stop()
if self.server:
print("Stopping server")
self.server.shutdown()
# Start the server in a separate thread
def run(self):
self.server.serve_forever()
def set_riddler(self, r):
self.server.riddler = r
def export_node(self, node):
self.server.nodes.append(node)
for client in self.server.clients:
client.export_nodes([node])
def export_event(self, event):
self.server.last_event = event
for client in self.server.clients:
client.export_event(event)
# Send a sample to each connected client
def export_sample(self, node, sample):
for client in self.server.clients:
client.export_sample(node, sample)
# Send a result to each connected client
def export_result(self, node, run_info, result):
for client in self.server.clients:
client.export_result(node, run_info, result)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
class tcp_handler(SocketServer.BaseRequestHandler):
# Prepare the class for a new connection
def setup(self):
self.end = threading.Event()
self.lock = threading.Lock()
self.server.clients.append(self)
self.export_args(self.server.args)
self.export_event(self.server.last_event)
self.export_nodes(self.server.nodes)
# Remove self from the list of connected clients on closed connection
def finish(self):
self.server.clients.remove(self)
self.request.close()
def stop(self):
self.end.set()
self.request.close()
def handle(self):
# self.request is the TCP socket connected to the client
while not self.end.is_set():
try:
# We currently don't expect anything from the client
obj = interface.recv(self.request)
if not obj:
break
self.handle_obj(obj)
except socket.timeout:
continue
except socket.error as e:
print("Export socket closed: {0}".format(e))
break
def handle_obj(self, obj):
if obj.cmd == interface.CLIENT_EVENT:
self.handle_event(obj.event)
elif obj.cmd == interface.CLIENT_ARGS:
self.handle_args(obj.args)
else:
print("Received unknown command")
def handle_event(self, event):
if event == interface.STARTED:
self.server.riddler.start()
elif event == interface.STOPPED:
self.server.riddler.stop_test()
elif event == interface.PAUSED:
self.server.riddler.set_pause(True)
elif event == interface.UNPAUSED:
self.server.riddler.set_pause(False)
elif event == interface.RECOVERING:
self.server.riddler.recover()
else:
print("Received unknown event: {}".format(event))
def handle_args(self, args):
self.server.args = args
self.server.riddler.set_args(args)
def send(self, cmd, **vals):
self.lock.acquire()
interface.send_client(self.request, cmd, **vals)
self.lock.release()
# Send sample to client
def export_sample(self, node, sample):
self.send(interface.CLIENT_SAMPLE, node=node, sample=sample)
# Send result to client
def export_result(self, node, run_info, result):
self.send(interface.CLIENT_RESULT, result=result, node=node, run_info=run_info)
# Send list of nodes to client
def export_nodes(self, nodes):
nodes = [{'name': node.name, 'mac': node.mesh_mac} for node in nodes]
self.send(interface.CLIENT_NODES, nodes=nodes)
def export_args(self, args):
self.send(interface.CLIENT_ARGS, args=args)
def export_event(self, event):
self.send(interface.CLIENT_EVENT, event=event)