From 4e36524778eac2441c306e94c1eb938c4be11a60 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 16 Dec 2023 12:46:57 -0500 Subject: [PATCH] windows named pipe support for python --- veilid-python/tests/api.py | 23 +++++++++++++++-------- veilid-python/veilid/json_api.py | 23 +++++++++++++++++++++-- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/veilid-python/tests/api.py b/veilid-python/tests/api.py index a6855375..d3ad9a57 100644 --- a/veilid-python/tests/api.py +++ b/veilid-python/tests/api.py @@ -32,6 +32,15 @@ def server_info() -> tuple[str, int]: return hostname, int(rest[0]) return hostname, 5959 +def ipc_path_exists(path: str) -> bool: + """Determine if an IPC socket exists in a platform independent way.""" + if os.name == 'nt': + if not path.upper().startswith("\\\\.\\PIPE\\"): + return False + return path[9:] in os.listdir("\\\\.\\PIPE") + else: + return os.path.exists(path) + @cache def ipc_info() -> str: """Return the path of the ipc socket of the test server.""" @@ -40,12 +49,11 @@ def ipc_info() -> str: return VEILID_SERVER_IPC if os.name == 'nt': - return '\\\\.\\PIPE\\veilid-server\\ipc\\0' - - if os.name == 'posix': - ipc_0_path = "/var/db/veilid-server/ipc/0" - if os.path.exists(ipc_0_path): - return ipc_0_path + return '\\\\.\\PIPE\\veilid-server\\0' + + ipc_0_path = "/var/db/veilid-server/ipc/0" + if os.path.exists(ipc_0_path): + return ipc_0_path # hack to deal with rust's 'directories' crate case-inconsistency if sys.platform.startswith('darwin'): @@ -67,8 +75,7 @@ async def api_connector(callback: Callable) -> _JsonVeilidAPI: hostname, port = server_info() try: - print(f"ipc_path: {ipc_path}") - if os.path.exists(ipc_path): + if ipc_path_exists(ipc_path): return await veilid.json_api_connect_ipc(ipc_path, callback) else: return await veilid.json_api_connect(hostname, port, callback) diff --git a/veilid-python/veilid/json_api.py b/veilid-python/veilid/json_api.py index 16cb20be..045fd60d 100644 --- a/veilid-python/veilid/json_api.py +++ b/veilid-python/veilid/json_api.py @@ -155,11 +155,30 @@ class _JsonVeilidAPI(VeilidAPI): async def connect_ipc( cls, ipc_path: str, update_callback: Callable[[VeilidUpdate], Awaitable] ) -> Self: - reader, writer = await asyncio.open_unix_connection(ipc_path) + print("opening pipe") + + if os.name=='nt': + async def open_windows_pipe(path=None, *, + limit=65536, **kwds): + """Similar to `open_unix_connection` but works with Windows Named Pipes.""" + loop = asyncio.events.get_running_loop() + + reader = asyncio.StreamReader(limit=limit, loop=loop) + protocol = asyncio.StreamReaderProtocol(reader, loop=loop) + transport, _ = await loop.create_pipe_connection( + lambda: protocol, path, **kwds) + writer = asyncio.StreamWriter(transport, protocol, reader, loop) + return reader, writer + reader, writer = await open_windows_pipe(ipc_path) + else: + reader, writer = await asyncio.open_unix_connection(ipc_path) + + print(f"reader: {vars(reader)}\nwriter: {vars(writer)}\n") + veilid_api = cls(reader, writer, update_callback) veilid_api.handle_recv_messages_task = asyncio.create_task( veilid_api.handle_recv_messages(), name="JsonVeilidAPI.handle_recv_messages" - ) + ) return veilid_api async def handle_recv_message_response(self, j: dict):