Core AIP protocol implementation. This class provides the foundation for all AIP communication: - Message serialization and deserialization - Middleware pipeline for extensibility - Message routing and handler registration - Error handling and logging The protocol is t
| 20 | |
| 21 | |
| 22 | class AIPProtocol: |
| 23 | """ |
| 24 | Core AIP protocol implementation. |
| 25 | |
| 26 | This class provides the foundation for all AIP communication: |
| 27 | - Message serialization and deserialization |
| 28 | - Middleware pipeline for extensibility |
| 29 | - Message routing and handler registration |
| 30 | - Error handling and logging |
| 31 | |
| 32 | The protocol is transport-agnostic and works with any Transport implementation. |
| 33 | |
| 34 | Usage: |
| 35 | transport = WebSocketTransport() |
| 36 | protocol = AIPProtocol(transport) |
| 37 | await protocol.send_message(ClientMessage(...)) |
| 38 | message = await protocol.receive_message() |
| 39 | """ |
| 40 | |
| 41 | def __init__(self, transport: Transport): |
| 42 | """ |
| 43 | Initialize AIP protocol. |
| 44 | |
| 45 | :param transport: Transport layer for sending/receiving messages |
| 46 | """ |
| 47 | self.transport = transport |
| 48 | self.message_handlers: Dict[str, List[MessageHandler]] = {} |
| 49 | self.middleware_chain: List["ProtocolMiddleware"] = [] |
| 50 | self.logger = logging.getLogger(f"{__name__}.AIPProtocol") |
| 51 | |
| 52 | async def send_message(self, msg: Any) -> None: |
| 53 | """ |
| 54 | Send a message through the protocol. |
| 55 | |
| 56 | Applies outgoing middleware, serializes the message, and sends via transport. |
| 57 | |
| 58 | :param msg: Message to send (ClientMessage or ServerMessage) |
| 59 | :raises: ConnectionError if transport not connected |
| 60 | :raises: IOError if send fails |
| 61 | """ |
| 62 | try: |
| 63 | # Apply outgoing middleware |
| 64 | for middleware in self.middleware_chain: |
| 65 | msg = await middleware.process_outgoing(msg) |
| 66 | |
| 67 | # Serialize message |
| 68 | if hasattr(msg, "model_dump_json"): |
| 69 | # Pydantic model |
| 70 | serialized = msg.model_dump_json().encode("utf-8") |
| 71 | elif isinstance(msg, str): |
| 72 | serialized = msg.encode("utf-8") |
| 73 | elif isinstance(msg, bytes): |
| 74 | serialized = msg |
| 75 | else: |
| 76 | raise ValueError(f"Unsupported message type: {type(msg)}") |
| 77 | |
| 78 | # Send via transport |
| 79 | await self.transport.send(serialized) |
no outgoing calls