genai-protocol-lite 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AIConnector/__init__.py +0 -0
- AIConnector/common/__init__.py +0 -0
- AIConnector/common/exceptions.py +13 -0
- AIConnector/common/logger.py +57 -0
- AIConnector/common/message.py +14 -0
- AIConnector/common/network.py +146 -0
- AIConnector/connector/__init__.py +0 -0
- AIConnector/connector/azure_connector.py +205 -0
- AIConnector/connector/base_connector.py +51 -0
- AIConnector/connector/peer_connection_manager.py +260 -0
- AIConnector/connector/ws_connector.py +213 -0
- AIConnector/core/__init__.py +0 -0
- AIConnector/core/chat_client.py +505 -0
- AIConnector/core/job.py +48 -0
- AIConnector/core/job_manager.py +219 -0
- AIConnector/core/message_factory.py +44 -0
- AIConnector/discovery/__init__.py +0 -0
- AIConnector/discovery/azure_discovery_service.py +206 -0
- AIConnector/discovery/base_discovery_service.py +27 -0
- AIConnector/discovery/discovery_service.py +226 -0
- AIConnector/session.py +274 -0
- genai_protocol_lite-1.0.0.dist-info/METADATA +186 -0
- genai_protocol_lite-1.0.0.dist-info/RECORD +26 -0
- genai_protocol_lite-1.0.0.dist-info/WHEEL +5 -0
- genai_protocol_lite-1.0.0.dist-info/licenses/LICENSE +201 -0
- genai_protocol_lite-1.0.0.dist-info/top_level.txt +1 -0
AIConnector/__init__.py
ADDED
File without changes
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ParameterException(ValueError):
|
2
|
+
"""Exception raised for errors in the input parameters."""
|
3
|
+
pass
|
4
|
+
|
5
|
+
|
6
|
+
class PeerDisconnectedException(Exception):
|
7
|
+
"""Exception indicating that the peer has disconnected."""
|
8
|
+
pass
|
9
|
+
|
10
|
+
|
11
|
+
class AgentConnectionError(Exception):
|
12
|
+
"""Exception indicating that we couldn't connect to agent."""
|
13
|
+
pass
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import logging
|
2
|
+
from colorlog import ColoredFormatter
|
3
|
+
|
4
|
+
|
5
|
+
class Logger:
|
6
|
+
LOG_LEVEL = {
|
7
|
+
"critical": (logging.CRITICAL, "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"),
|
8
|
+
"error": (logging.ERROR, "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"),
|
9
|
+
"warning": (logging.WARNING, "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"),
|
10
|
+
"info": (logging.INFO, "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"),
|
11
|
+
"debug": (logging.DEBUG, f"%(pathname)s:%(lineno)d:\n%(asctime)s %(levelname)-8s [%(name)s] %(message)s"),
|
12
|
+
"notset": (logging.NOTSET, "%(asctime)s %(levelname)-8s [%(name)s] %(message)s")
|
13
|
+
}
|
14
|
+
|
15
|
+
def __init__(self, log_level):
|
16
|
+
self._date_fmt = "%d-%m-%Y:%H:%M:%S"
|
17
|
+
self.log_level = self._get_log_level(log_level)
|
18
|
+
self.log_format = self._get_log_format(log_level)
|
19
|
+
self._config()
|
20
|
+
|
21
|
+
def _get_log_level(self, log_level):
|
22
|
+
return self.LOG_LEVEL[log_level][0]
|
23
|
+
|
24
|
+
def _get_log_format(self, log_level):
|
25
|
+
return self.LOG_LEVEL[log_level][1]
|
26
|
+
|
27
|
+
def _config(self):
|
28
|
+
"""
|
29
|
+
Configures logging using a colored formatter.
|
30
|
+
"""
|
31
|
+
# Get the root logger
|
32
|
+
root_logger = logging.getLogger()
|
33
|
+
|
34
|
+
# Remove existing handlers, if any
|
35
|
+
for handler in root_logger.handlers[:]:
|
36
|
+
root_logger.removeHandler(handler)
|
37
|
+
|
38
|
+
# Create a console handler
|
39
|
+
stream_handler = logging.StreamHandler()
|
40
|
+
|
41
|
+
# Define the color scheme for different logging levels
|
42
|
+
formatter = ColoredFormatter(
|
43
|
+
"%(log_color)s" + self.log_format,
|
44
|
+
datefmt=self._date_fmt,
|
45
|
+
log_colors={
|
46
|
+
'DEBUG': 'blue',
|
47
|
+
'INFO': 'green',
|
48
|
+
'WARNING': 'yellow',
|
49
|
+
'ERROR': 'red',
|
50
|
+
'CRITICAL': 'red,bg_white',
|
51
|
+
}
|
52
|
+
)
|
53
|
+
stream_handler.setFormatter(formatter)
|
54
|
+
|
55
|
+
# Configure the root logger
|
56
|
+
root_logger.setLevel(self.log_level)
|
57
|
+
root_logger.addHandler(stream_handler)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
|
4
|
+
class MessageTypes(Enum):
|
5
|
+
"""
|
6
|
+
Enum representing different types of messages exchanged between peers.
|
7
|
+
"""
|
8
|
+
HELLO = "hello"
|
9
|
+
TEXT = "text"
|
10
|
+
SYSTEM_MESSAGE = "system_message"
|
11
|
+
HEARTBEAT = "heartbeat"
|
12
|
+
FINAL_MESSAGE = "final_message"
|
13
|
+
ERROR = "error"
|
14
|
+
JOB_LIST = "job_list"
|
@@ -0,0 +1,146 @@
|
|
1
|
+
import socket
|
2
|
+
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from AIConnector.common.exceptions import ParameterException
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass
|
10
|
+
class Config:
|
11
|
+
"""
|
12
|
+
Data class representing the Class network configuration settings.
|
13
|
+
|
14
|
+
Attributes:
|
15
|
+
webserver_port (Optional[int]): Port number for the webserver.
|
16
|
+
If not provided, an available port within the autodiscovery range will be used.
|
17
|
+
Required in: 'local' and 'remote'.
|
18
|
+
azure_endpoint_url (Optional[str]): URL endpoint for Azure connectivity.
|
19
|
+
Required in: 'remote'.
|
20
|
+
azure_access_key (Optional[str]): Access key for Azure services.
|
21
|
+
Required in: 'remote'.
|
22
|
+
advertisement_port (int): Port used for network advertisement. Defaults to 9999.
|
23
|
+
Required in: 'local' and 'remote'.
|
24
|
+
advertisement_ip (str): IP address for network advertisement. Defaults to "224.1.1.1".
|
25
|
+
Required in: 'local' and 'remote'.
|
26
|
+
advertisement_interval (float): Interval (in seconds) for sending advertisements. Defaults to 15.0.
|
27
|
+
Required in: 'local' and 'remote'.
|
28
|
+
heartbeat_delay (float): Delay (in seconds) between heartbeat messages. Defaults to 5.0.
|
29
|
+
Required in: 'local' and 'remote'.
|
30
|
+
webserver_port_min (int): Minimum port number for autodiscovery. Defaults to 5000.
|
31
|
+
Required in: 'local'.
|
32
|
+
webserver_port_max (int): Maximum port number for autodiscovery. Defaults to 7000.
|
33
|
+
Required in: 'local'.
|
34
|
+
peer_discovery_timeout (float): Timeout (in seconds) for peer discovery. Defaults to 30.0.
|
35
|
+
Required in: 'local' and 'remote'.
|
36
|
+
peer_ping_interval (float): Interval (in seconds) for pinging peers. Defaults to 5.0.
|
37
|
+
Required in: 'local' and 'remote'.
|
38
|
+
azure_api_version (str): API version for Azure communications. Defaults to "1.0".
|
39
|
+
Required in: 'remote'.
|
40
|
+
connection_type (str): Type of connection, either "local" or "remote". Defaults to "local".
|
41
|
+
Required in: 'local' and 'remote'.
|
42
|
+
"""
|
43
|
+
webserver_port: Optional[int] = None
|
44
|
+
|
45
|
+
azure_endpoint_url: Optional[str] = None
|
46
|
+
azure_access_key: Optional[str] = None
|
47
|
+
|
48
|
+
advertisement_port: int = 9999
|
49
|
+
advertisement_ip: str = "224.1.1.1"
|
50
|
+
advertisement_interval: float = 15.0
|
51
|
+
heartbeat_delay: float = 15.0
|
52
|
+
webserver_port_min: int = 5000
|
53
|
+
webserver_port_max: int = 65000
|
54
|
+
peer_discovery_timeout: float = 30.0
|
55
|
+
peer_ping_interval: float = 5.0
|
56
|
+
azure_api_version: str = "1.0"
|
57
|
+
connection_type: str = "local"
|
58
|
+
|
59
|
+
def __post_init__(self):
|
60
|
+
"""
|
61
|
+
Validate the network configuration parameters immediately after initialization.
|
62
|
+
|
63
|
+
Raises:
|
64
|
+
ParameterException: If any parameter is invalid.
|
65
|
+
"""
|
66
|
+
# Validate connection type
|
67
|
+
if self.connection_type not in ("local", "remote"):
|
68
|
+
raise ParameterException("Invalid connection type. Only 'local' and 'remote' are allowed.")
|
69
|
+
|
70
|
+
# For remote connections, ensure Azure settings are provided
|
71
|
+
if self.connection_type == "remote":
|
72
|
+
if not (self.azure_endpoint_url and self.azure_access_key):
|
73
|
+
raise ParameterException(
|
74
|
+
"Azure endpoint URL and access key must be provided for 'remote' sessions."
|
75
|
+
)
|
76
|
+
|
77
|
+
# Define a list of fields to validate (field name, value, expected type)
|
78
|
+
fields_to_validate = (
|
79
|
+
("advertisement_port", self.advertisement_port, int),
|
80
|
+
("webserver_port_min", self.webserver_port_min, int),
|
81
|
+
("webserver_port_max", self.webserver_port_max, int),
|
82
|
+
("advertisement_interval", self.advertisement_interval, float),
|
83
|
+
("heartbeat_delay", self.heartbeat_delay, float),
|
84
|
+
("peer_discovery_timeout", self.peer_discovery_timeout, float),
|
85
|
+
("peer_ping_interval", self.peer_ping_interval, float),
|
86
|
+
)
|
87
|
+
|
88
|
+
# Check each field for correct type and positive value
|
89
|
+
for field_name, value, expected_type in fields_to_validate:
|
90
|
+
if not isinstance(value, expected_type):
|
91
|
+
raise ParameterException(f"Parameter '{field_name}' must be of type {expected_type.__name__}.")
|
92
|
+
if value <= 0:
|
93
|
+
raise ParameterException(f"Parameter '{field_name}' must be greater than 0.")
|
94
|
+
|
95
|
+
# Ensure autodiscovery port range is valid
|
96
|
+
if self.webserver_port_min > self.webserver_port_max:
|
97
|
+
raise ParameterException(
|
98
|
+
"webserver_port_min cannot be greater than webserver_port_max."
|
99
|
+
)
|
100
|
+
|
101
|
+
# If webserver_port is not set, determine an available port from the autodiscovery range
|
102
|
+
if not self.webserver_port:
|
103
|
+
self.webserver_port = get_available_port(
|
104
|
+
self.webserver_port_min,
|
105
|
+
self.webserver_port_max
|
106
|
+
)
|
107
|
+
|
108
|
+
|
109
|
+
@dataclass
|
110
|
+
class NetworkConfig(Config):
|
111
|
+
"""
|
112
|
+
Data class representing the App network configuration settings.
|
113
|
+
|
114
|
+
Attributes:
|
115
|
+
client_id (Optional[str]): Identifier for the client.
|
116
|
+
Required in: 'local' and 'remote'.
|
117
|
+
"""
|
118
|
+
client_id: Optional[str] = None
|
119
|
+
|
120
|
+
|
121
|
+
def get_available_port(start_port: int = 5000, end_port: int = 7000) -> Optional[int]:
|
122
|
+
"""
|
123
|
+
Find and return the first available network port in the given range (inclusive).
|
124
|
+
|
125
|
+
The function iterates through the port range and attempts to bind a temporary
|
126
|
+
socket to each port. If the bind is successful, the port is considered available.
|
127
|
+
|
128
|
+
Args:
|
129
|
+
start_port (int): The beginning of the port range to check. Defaults to 5000.
|
130
|
+
end_port (int): The end of the port range to check. Defaults to 7000.
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
Optional[int]: The first available port number, or None if no port is available.
|
134
|
+
"""
|
135
|
+
for port in range(start_port, end_port + 1):
|
136
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
137
|
+
try:
|
138
|
+
# Attempt to bind the socket to the current port on all interfaces.
|
139
|
+
sock.bind(("0.0.0.0", port))
|
140
|
+
# Successful bind indicates the port is free.
|
141
|
+
return port
|
142
|
+
except OSError:
|
143
|
+
# Port is already in use; try the next one.
|
144
|
+
continue
|
145
|
+
# Return None if no available port is found in the specified range.
|
146
|
+
return None
|
File without changes
|
@@ -0,0 +1,205 @@
|
|
1
|
+
import asyncio
|
2
|
+
import json
|
3
|
+
import logging
|
4
|
+
import time
|
5
|
+
from typing import Callable, Optional, Dict, Any
|
6
|
+
|
7
|
+
import websockets
|
8
|
+
|
9
|
+
from azure.messaging.webpubsubservice import WebPubSubServiceClient
|
10
|
+
from AIConnector.connector.base_connector import BaseConnector
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
class AzureConnector(BaseConnector):
|
16
|
+
"""
|
17
|
+
AzureConnector implements message exchange via Azure Web PubSub,
|
18
|
+
similar to how WsConnector operates for local connections.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
client_id: str,
|
24
|
+
on_message_callback: Callable[[Dict[str, Any]], Any],
|
25
|
+
azure_endpoint_url: str,
|
26
|
+
azure_access_key: str,
|
27
|
+
azure_api_version: str,
|
28
|
+
messaging_hub: str = "messaging_demo",
|
29
|
+
reconnect_attempts: int = 2,
|
30
|
+
client_name: Optional[str] = None,
|
31
|
+
on_peer_disconnected: Optional[Callable[[str], Any]] = None,
|
32
|
+
on_peer_connected: Optional[Callable[[str], Any]] = None,
|
33
|
+
) -> None:
|
34
|
+
"""
|
35
|
+
Initialize the AzureConnector.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
client_id (str): Identifier for the client.
|
39
|
+
on_message_callback (Callable[[Dict[str, Any]], Any]): Callback function to handle incoming messages.
|
40
|
+
azure_endpoint_url (str): Azure Web PubSub endpoint URL.
|
41
|
+
azure_access_key (str): Access key for Azure Web PubSub.
|
42
|
+
azure_api_version (str): API version for Azure services.
|
43
|
+
messaging_hub (str, optional): Name of the messaging hub. Defaults to "messaging_demo".
|
44
|
+
reconnect_attempts (int, optional): Number of reconnection attempts on failure. Defaults to 2.
|
45
|
+
client_name (Optional[str], optional): Name of the client. Defaults to None.
|
46
|
+
on_peer_disconnected (Optional[Callable[[str], Any]], optional): Callback when a peer disconnects. Defaults to None.
|
47
|
+
on_peer_connected (Optional[Callable[[str], Any]], optional): Callback when a peer connects. Defaults to None.
|
48
|
+
"""
|
49
|
+
self.client_id = client_id
|
50
|
+
self.on_message_callback = on_message_callback
|
51
|
+
self.on_peer_disconnected = on_peer_disconnected
|
52
|
+
self.on_peer_connected = on_peer_connected
|
53
|
+
self.client_name = client_name
|
54
|
+
self.reconnect_attempts = reconnect_attempts
|
55
|
+
self.messaging_hub = messaging_hub
|
56
|
+
|
57
|
+
self.is_connected = False
|
58
|
+
self.running = False
|
59
|
+
self.active_connections: Dict[str, websockets.WebSocketClientProtocol] = {}
|
60
|
+
|
61
|
+
# Initialize the service client for the messaging hub.
|
62
|
+
connection_string = f"Endpoint={azure_endpoint_url};AccessKey={azure_access_key};ApiVersion={azure_api_version}"
|
63
|
+
self.service_client = WebPubSubServiceClient.from_connection_string(
|
64
|
+
connection_string,
|
65
|
+
hub=messaging_hub,
|
66
|
+
)
|
67
|
+
self.websocket = None
|
68
|
+
|
69
|
+
async def start_server(self, host: str = None, port: int = None, allow_discovery: bool = False) -> None:
|
70
|
+
"""
|
71
|
+
Establish a WebSocket connection with the messaging hub.
|
72
|
+
|
73
|
+
The host and port parameters are provided for interface compatibility,
|
74
|
+
but they are not used in AzureConnector.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
host (str, optional): Not used in AzureConnector.
|
78
|
+
port (int, optional): Not used in AzureConnector.
|
79
|
+
allow_discovery (bool, optional): Not used in AzureConnector.
|
80
|
+
"""
|
81
|
+
self.running = True
|
82
|
+
try:
|
83
|
+
logger.info(f"Client ID: {self.client_id}")
|
84
|
+
token = self.service_client.get_client_access_token(user_id=self.client_id)
|
85
|
+
self.websocket = await websockets.connect(token["url"])
|
86
|
+
self.is_connected = True
|
87
|
+
logger.info(f"[AzureConnector] Connected to Azure Web PubSub messaging hub: {self.messaging_hub}")
|
88
|
+
|
89
|
+
# Start receiving messages asynchronously.
|
90
|
+
asyncio.create_task(self._receive_messages())
|
91
|
+
|
92
|
+
except Exception as e:
|
93
|
+
logger.error(f"[AzureConnector] Connection failed: {e}")
|
94
|
+
await self._attempt_reconnect()
|
95
|
+
|
96
|
+
async def stop_server(self) -> None:
|
97
|
+
"""
|
98
|
+
Stop the WebSocket connection with the messaging hub.
|
99
|
+
"""
|
100
|
+
self.running = False
|
101
|
+
self.is_connected = False
|
102
|
+
if self.websocket:
|
103
|
+
await self.websocket.close()
|
104
|
+
logger.info("[AzureConnector] Messaging WebSocket connection closed")
|
105
|
+
|
106
|
+
async def send_message(self, peer_id: str, msg: Dict[str, Any]) -> None:
|
107
|
+
"""
|
108
|
+
Send a message to a specific peer via the messaging hub.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
peer_id (str): The identifier of the target peer.
|
112
|
+
msg (Dict[str, Any]): The message payload to send.
|
113
|
+
"""
|
114
|
+
if not self.is_connected:
|
115
|
+
logger.error("[AzureConnector] Cannot send message: not connected")
|
116
|
+
return
|
117
|
+
|
118
|
+
try:
|
119
|
+
message = {
|
120
|
+
"type": "MESSAGE",
|
121
|
+
"from_id": self.client_id,
|
122
|
+
"from_name": self.client_name or "Unknown",
|
123
|
+
"to_id": peer_id,
|
124
|
+
"timestamp": time.time(),
|
125
|
+
"payload": msg,
|
126
|
+
}
|
127
|
+
# Send the message as a JSON string.
|
128
|
+
self.service_client.send_to_user(peer_id, json.dumps(message))
|
129
|
+
except Exception as e:
|
130
|
+
logger.error(f"[AzureConnector] Error sending message to {peer_id}: {e}")
|
131
|
+
else:
|
132
|
+
logger.info(f"[AzureConnector] Message sent to {peer_id}")
|
133
|
+
|
134
|
+
async def connect_to_peer(self, ip: str, port: int, peer_id: str) -> None:
|
135
|
+
"""
|
136
|
+
For Azure, a direct connection to peers is not required.
|
137
|
+
Instead, a HELLO message is sent to simulate a handshake.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
ip (str): Not used in AzureConnector.
|
141
|
+
port (int): Not used in AzureConnector.
|
142
|
+
peer_id (str): The identifier of the peer to connect to.
|
143
|
+
"""
|
144
|
+
hello_msg = {
|
145
|
+
"type": "HELLO",
|
146
|
+
"from_id": self.client_id,
|
147
|
+
"from_name": self.client_name or "Unknown",
|
148
|
+
"timestamp": time.time(),
|
149
|
+
}
|
150
|
+
await self.send_message(peer_id, hello_msg)
|
151
|
+
|
152
|
+
async def _receive_messages(self) -> None:
|
153
|
+
"""
|
154
|
+
Receive incoming messages via the messaging hub.
|
155
|
+
"""
|
156
|
+
while self.running and self.websocket:
|
157
|
+
try:
|
158
|
+
message = await self.websocket.recv()
|
159
|
+
msg = json.loads(message)
|
160
|
+
# If the received message is a string, try to parse it again.
|
161
|
+
if isinstance(msg, str):
|
162
|
+
msg = json.loads(msg)
|
163
|
+
payload = msg["payload"]
|
164
|
+
# If a HELLO message is received, update active connections and trigger callback.
|
165
|
+
if payload.get("type").lower() == "hello":
|
166
|
+
peer_id = payload.get("from_id")
|
167
|
+
if peer_id:
|
168
|
+
self.active_connections[peer_id] = self.websocket
|
169
|
+
if self.on_peer_connected:
|
170
|
+
await self.on_peer_connected(peer_id)
|
171
|
+
|
172
|
+
# Process the incoming message with the provided callback.
|
173
|
+
await self.on_message_callback(payload)
|
174
|
+
except websockets.exceptions.ConnectionClosed:
|
175
|
+
logger.error("[AzureConnector] Messaging WebSocket connection closed")
|
176
|
+
await self._attempt_reconnect()
|
177
|
+
break
|
178
|
+
except Exception as e:
|
179
|
+
logger.error(f"[AzureConnector] Error processing message: {e}")
|
180
|
+
|
181
|
+
async def _attempt_reconnect(self) -> None:
|
182
|
+
"""
|
183
|
+
Attempt to reconnect to Azure Web PubSub after a connection loss.
|
184
|
+
"""
|
185
|
+
for attempt in range(self.reconnect_attempts):
|
186
|
+
try:
|
187
|
+
logger.info(f"[AzureConnector] Reconnection attempt {attempt + 1}/{self.reconnect_attempts}")
|
188
|
+
await self.start_server()
|
189
|
+
if self.is_connected:
|
190
|
+
return
|
191
|
+
except Exception as e:
|
192
|
+
logger.error(f"[AzureConnector] Reconnection attempt failed: {e}")
|
193
|
+
# Exponential backoff before the next attempt.
|
194
|
+
await asyncio.sleep(2 ** attempt)
|
195
|
+
logger.error("[AzureConnector] Failed to reconnect after multiple attempts")
|
196
|
+
|
197
|
+
|
198
|
+
async def disconnect_from_peer(self, peer_id: str) -> None:
|
199
|
+
"""
|
200
|
+
Close connection
|
201
|
+
|
202
|
+
Args:
|
203
|
+
peer_id (str): Unique identifier of the lost peer.
|
204
|
+
"""
|
205
|
+
pass
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
|
5
|
+
class BaseConnector(ABC):
|
6
|
+
"""
|
7
|
+
Abstract base class for network connectors.
|
8
|
+
|
9
|
+
Classes inheriting from BaseConnector must implement the methods
|
10
|
+
to start and stop the server, as well as to send messages.
|
11
|
+
"""
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
async def start_server(self, host: str, port: int, allow_discovery: bool) -> None:
|
15
|
+
"""
|
16
|
+
Start the server and establish necessary connections.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
host (str): The host address to bind the server.
|
20
|
+
port (int): The port number to bind the server.
|
21
|
+
allow_discovery (bool): Flag indicating if discovery is allowed.
|
22
|
+
"""
|
23
|
+
pass
|
24
|
+
|
25
|
+
@abstractmethod
|
26
|
+
async def stop_server(self) -> None:
|
27
|
+
"""
|
28
|
+
Stop the server and close all active connections.
|
29
|
+
"""
|
30
|
+
pass
|
31
|
+
|
32
|
+
@abstractmethod
|
33
|
+
async def send_message(self, peer_id: str, msg: Dict[str, Any]) -> None:
|
34
|
+
"""
|
35
|
+
Send a message to a specified peer.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
peer_id (str): Identifier of the target peer.
|
39
|
+
msg (Dict[str, Any]): The message payload to be sent.
|
40
|
+
"""
|
41
|
+
pass
|
42
|
+
|
43
|
+
@abstractmethod
|
44
|
+
async def disconnect_from_peer(self, peer_id: str) -> None:
|
45
|
+
"""
|
46
|
+
Disconnect from peer by peer id
|
47
|
+
|
48
|
+
Args:
|
49
|
+
peer_id (str): Identifier of the target peer.
|
50
|
+
"""
|
51
|
+
pass
|