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
|
# -*- coding: utf-8 -*-
# service.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import threading
from protobuf.socketrpc.server import (
SocketRpcServer,
ThreadedTCPServer,
SocketHandler,
)
from leap.common.events import (
signal_pb2 as proto,
registered_callbacks,
)
logger = logging.getLogger(__name__)
class SignalRpcServer(SocketRpcServer):
def __init__(self, port, host='localhost'):
'''port - Port this server is started on'''
self.port = port
self.host = host
self.serviceMap = {}
self.server = None
def run(self):
'''Activate the server.'''
logger.info('Running server on port %d' % self.port)
self.server = ThreadedTCPServer((self.host, self.port),
SocketHandler, self)
self.server.serve_forever()
def stop(self):
self.server.shutdown()
class SignalService(proto.SignalService):
'''
Handles signaling for LEAP components.
'''
def signal(self, controller, request, done):
logger.info('Received signal.')
# Run registered callbacks
if registered_callbacks.has_key(request.signal):
for (_, cbk) in registered_callbacks[request.signal]:
cbk(request)
# Create response message
response = proto.SignalResponse()
# TODO: change id for something meaningful
response.id = 1
response.status = proto.SignalResponse.OK
# Call provided callback with response message
done.run(response)
class SignalServiceThread(threading.Thread):
"""
Singleton class for starting a server thread
"""
# Singleton instance
_instance = None
def __init__(self, port):
super(SignalServiceThread, self).__init__()
self._service = SignalService()
self._port = port
self._server = SignalRpcServer(self._port)
self._server.registerService(self._service)
self.setDaemon(True)
@staticmethod
def start_service(port):
"""
Start the singleton instance if not already running
Will not exit until the process ends
"""
if SignalServiceThread._instance == None:
SignalServiceThread._instance = SignalServiceThread(port)
SignalServiceThread._instance.start()
elif port != SignalServiceThread._instance._port:
# TODO: make this exception more self-explanatory
raise Exception()
return SignalServiceThread._instance
def get_instance(self):
return self._instance
def run(self):
self._server.run()
def stop(self):
self._server.stop()
|