11import asyncio
22from asyncio import StreamWriter , StreamReader
3- from enum import IntEnum
4- from typing import Any , Awaitable , Optional , Callable
3+ from typing import Awaitable , Optional , Callable
54
65from simulaqron .general .host_config import SocketsConfig
76
87
9- class ServingStatus (IntEnum ):
10- CONTINUE = 0
11- STOP = 1
12-
13-
14- class SimulaQronState :
15- # State of the SimulaQron simulator
16- def __init__ (self ):
17- """
18- Keeps the state of the quantum memories across multiple invocations of the message handler.
19- A handler can use this object to make a quantum memory
20- """
21- # TODO - Implement this constructor!
22- pass
23-
24- def add_return_values (self , * ret_val : Any ) -> None :
25- """
26- Adds a return value to the message handler. The returned value will be sent back to
27- the other endpoint of the connection.
28-
29- :param ret_val: The values to return.
30- :type ret_val: Any
31- """
32- # TODO - Implement this!
33- pass
34-
35- def continue_serving (self ) -> ServingStatus :
36- """
37- Creates a "continue" value used to signal the server to keep waiting for new messages.
38-
39- :return: The "continue" value of the ``ServingStatus`` class.
40- :rtype: ServingStatus
41- """
42- return ServingStatus .CONTINUE
43-
44- def stop_serving (self ) -> ServingStatus :
45- """
46- Creates a "stop" value used to signal the server to stop serving new messages.
47-
48- :return: The "stop" value of the ``ServingStatus`` class.
49- :rtype: ServingStatus
50- """
51- return ServingStatus .STOP
52-
53-
548class SimulaQronClassicalClient :
559 def __init__ (self , sockets_config : SocketsConfig ):
5610 """
57- Classical client used to send classical messages to remote nodes. The given node name
58- must exist on the given network configuration .
11+ Classical client used to send classical messages to remote nodes. The given socket configs
12+ object contains the specification of the available nodes on the network to connect to .
5913
6014 :param sockets_config: The sockets configuration for the whole network.
6115 :type sockets_config: SocketsConfig
6216 """
6317 self ._sockets_config = sockets_config
6418
6519 async def _run_client (self , hostname : str , port : int , callback : Callable [[StreamReader , StreamWriter ], Awaitable [None ]]):
20+ """
21+ Python coroutine that opens the connection and runs the function provided by the user.
22+ """
6623 reader , writer = await asyncio .open_connection (hostname , port )
6724 await callback (reader , writer )
25+ writer .close ()
6826
6927
7028 def run_client (self , node_name : str , callback : Callable [[StreamReader , StreamWriter ], Awaitable [None ]]) -> None :
7129 """
72- Connects to the node with the given name. Once the connection has been established,
73- the given callback will be executed to start the interaction with the server.
74- The given function must have the following signature::
30+ Runs a function implementing a client that connects to the node with the given name.
31+ Once the connection has been established, the given callback will be executed to start
32+ the interaction with the server.
33+ The given client function must have the following signature::
7534
76- async def connected_handler(reader: StreamReader, writer: StreamWriter):
77- # Send a message to the server
78- writer.write("Hello world!".encode("utf-8"))
79- # Afterwards, you might want to receive an answer
80- message = await reader.read(255)
81- print(message.decode("utf-8"))
35+ async def connected_handler(reader: StreamReader, writer: StreamWriter):
36+ # Send a message to the server
37+ writer.write("Hello world!".encode("utf-8"))
38+ # Afterwards, you might want to receive an answer
39+ message = await reader.read(255)
40+ print(message.decode("utf-8"))
8241
83- After calling this function, the
42+ Where ``reader`` and ``writer`` objects are the streams used to read and write
43+ messages to/from the server respectively.
44+ Once the execution of the given function, the client will close the connection to
45+ the server.
8446
8547 :param node_name: The name of the node to connect to. The name *must* exist in the
8648 configuration file given when constructing this client.
8749 :type node_name: str
88- :param callback: The function to be called when the connection is established.
50+ :param callback: The function to be called when the connection is established. This function
51+ implements the logic for interacting with the server. The passed function
52+ *must* be a python "async" function.
8953 :type callback: Callable[[StreamReader, StreamWriter], Awaitable[None]]
9054 """
9155 if node_name not in self ._sockets_config .hostDict :
9256 raise RuntimeError (f"The node with name '{ node_name } ' is not on the network configuration." )
9357 socket_config = self ._sockets_config .hostDict [node_name ]
9458 asyncio .run (self ._run_client (socket_config .hostname , socket_config .port , callback ))
9559
96- def send_message (self , message : str ) -> None :
97- """
98- Sends a message to the remote endpoint of the connection.
99-
100- :param message: The message to send.
101- :type message: str
102- """
103- pass
104-
10560
10661class SimulaQronClassicalServer :
10762 def __init__ (self , sockets_config : SocketsConfig , name : str ):
@@ -113,13 +68,15 @@ def register_client_handler(self, handler: Callable[[StreamReader, StreamWriter]
11368 """
11469 Registers the given function as a client handler. The given function must have the following signature::
11570
116- async def handler(reader: StreamReader, writer: StreamWriter):
117- reader = await reader.read(255)
118- ...
119- # Handle a new connection here
120- # E.g. send a response to the client
121- writer.write("answer".encode("utf-8"))
71+ async def handler(reader: StreamReader, writer: StreamWriter):
72+ reader = await reader.read(255)
73+ ...
74+ # Handle a new connection here
75+ # E.g. send a response to the client
76+ writer.write("answer".encode("utf-8"))
12277
78+ Where ``reader`` and ``writer`` objects are the streams used to read and write
79+ messages to/from the client respectively.
12380 The passed function will be called once a new client connects.
12481
12582 :param handler: The function to be used as a handler. This *must* be a python coroutine
0 commit comments