11import asyncio
2+ import datetime
23import logging
3- import os
4- import socket
5- import sys
4+ import uuid
65
7- from . import protocol
86from .ws import WSServer
7+ from .protocol import BasicProtocol , create_peer
8+ from .receptor import Receptor
9+ from .messages import envelope
910
1011logger = logging .getLogger (__name__ )
1112
@@ -16,47 +17,64 @@ def connect_to_socket(socket_path):
1617 return sock
1718
1819
19- def send_directive (directive , recipient , payload , sock ):
20- if payload == '-' :
21- payload = sys .stdin .read ()
22- sock .sendall (f"{ recipient } \n { directive } \n { payload } " .encode ('utf-8' ) + protocol .DELIM )
23- response = b''
24- while True :
25- received = sock .recv (1024 )
26- done = protocol .DELIM in received
27- response += received .rstrip (protocol .DELIM )
28- if done :
29- break
30-
31- return response
32-
33-
34- # FIXME: the socket path is in the config, it shouldn't need to be passed as an arg here
35- def mainloop (receptor , socket_path , loop = asyncio .get_event_loop ()):
36- config = receptor .config
37- listener = loop .create_server (
38- lambda : protocol .BasicProtocol (receptor , loop ),
39- config .controller_listen_address , config .controller_listen_port , ssl = config .get_server_ssl_context ())
40- logger .info ("Serving on %s:%s" , config .controller_listen_address , config .controller_listen_port )
41- loop .create_task (listener )
42-
43- ws_server = WSServer (receptor , loop )
44- ws_listener = loop .create_server (ws_server .app ().make_handler (),
45- config .node_listen_address , config .node_listen_port + 1 , ssl = config .get_server_ssl_context ())
46- loop .create_task (ws_listener )
47- logger .info ("Serving ws on %s:%s" , config .node_listen_address , config .node_listen_port + 1 )
48-
49- control_listener = loop .create_unix_server (
50- lambda : protocol .BasicControllerProtocol (receptor , loop ),
51- path = socket_path
52- )
53- logger .info (f'Opening control socket on { socket_path } ' )
54- loop .create_task (control_listener )
55- loop .create_task (receptor .watch_expire ())
56- try :
57- loop .run_forever ()
58- except KeyboardInterrupt :
59- pass
60- finally :
61- loop .stop ()
62- os .remove (socket_path )
20+ # TODO: track stats
21+ class Controller :
22+
23+ def __init__ (self , config , loop = asyncio .get_event_loop (), queue = None ):
24+ self .receptor = Receptor (config )
25+ self .loop = loop
26+ self .queue = queue
27+ if self .queue is None :
28+ self .queue = asyncio .Queue (loop = loop )
29+ self .receptor .response_queue = self .queue
30+
31+ def enable_server (self , listen_address , listen_port ):
32+ listener = self .loop .create_server (
33+ lambda : BasicProtocol (self .receptor , self .loop ),
34+ listen_address , listen_port ,
35+ ssl = self .receptor .config .get_server_ssl_context ())
36+ logger .info ("Serving on {}:{}" .format (listen_address , listen_port ))
37+ # TODO: Enable stats?
38+ self .loop .create_task (listener )
39+
40+ def enable_websocket_server (self , listen_address , listen_port ):
41+ listener = self .loop .create_server (
42+ WSServer (self .receptor , self .loop ).app ().make_handler (),
43+ listen_address , listen_port ,
44+ ssl = self .receptor .config .get_server_ssl_context ())
45+ logger .info ("Server ws on {}:{}" .format (listen_address , listen_port ))
46+ self .loop .create_task (listener )
47+
48+ def add_peer (self , peer ):
49+ # NOTE: Not signing or serializing
50+ logger .info ("Connecting to peer {}" .format (peer ))
51+ self .loop .create_task (create_peer (self .receptor , self .loop ,
52+ * peer .strip ().split (":" , 1 )))
53+
54+ async def recv (self ):
55+ inner = await self .receptor .response_queue .get ()
56+ return inner .raw_payload
57+
58+ async def send (self , message ):
59+ inner_env = envelope .Inner (
60+ receptor = self .receptor ,
61+ messageid = str (uuid .uuid4 ()),
62+ sender = self .receptor .node_id ,
63+ recipient = message .recipient ,
64+ message_type = "directive" ,
65+ directive = message .directive ,
66+ timestamp = datetime .datetime .utcnow ().isoformat (),
67+ raw_payload = message .fd .read (),
68+ )
69+ await self .receptor .router .send (inner_env , expected_response = True )
70+
71+ async def ping (self , destination ):
72+ await self .receptor .router .ping_node (destination )
73+
74+ def run (self ):
75+ try :
76+ self .loop .run_until_complete (self .receptor .shutdown_handler ())
77+ except KeyboardInterrupt :
78+ pass
79+ finally :
80+ self .loop .stop ()
0 commit comments