Add macOS compatibility for Unix socket credential passing
Make socket credential imports platform-conditional in `.ipc._uds`. - Linux: use `SO_PASSCRED`/`SO_PEERCRED` from socket module - macOS: use `LOCAL_PEERCRED` (0x0001) instead, no need for `SO_PASSCRED` - Conditionally call `setsockopt(SO_PASSCRED)` only on Linux Fixes AttributeError on macOS where SO_PASSCRED doesn't exist. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>macos_fixed_2025
parent
e232d9dd06
commit
356b55701c
|
@ -23,14 +23,29 @@ from contextlib import (
|
||||||
)
|
)
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from socket import (
|
from socket import (
|
||||||
AF_UNIX,
|
AF_UNIX,
|
||||||
SOCK_STREAM,
|
SOCK_STREAM,
|
||||||
SO_PASSCRED,
|
|
||||||
SO_PEERCRED,
|
|
||||||
SOL_SOCKET,
|
SOL_SOCKET,
|
||||||
)
|
)
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
# Platform-specific credential passing constants
|
||||||
|
# See: https://stackoverflow.com/a/7982749
|
||||||
|
if sys.platform == 'linux':
|
||||||
|
from socket import SO_PASSCRED, SO_PEERCRED
|
||||||
|
elif sys.platform == 'darwin': # macOS
|
||||||
|
# macOS uses LOCAL_PEERCRED instead of SO_PEERCRED
|
||||||
|
# and doesn't need SO_PASSCRED (credential passing is always enabled)
|
||||||
|
# Value from <sys/un.h>: #define LOCAL_PEERCRED 0x001
|
||||||
|
LOCAL_PEERCRED = 0x0001
|
||||||
|
SO_PEERCRED = LOCAL_PEERCRED # Alias for compatibility
|
||||||
|
SO_PASSCRED = None # Not needed/available on macOS
|
||||||
|
else:
|
||||||
|
# Other Unix platforms - may need additional handling
|
||||||
|
SO_PASSCRED = None
|
||||||
|
SO_PEERCRED = None
|
||||||
from typing import (
|
from typing import (
|
||||||
Type,
|
Type,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
|
@ -306,7 +321,11 @@ async def open_unix_socket_w_passcred(
|
||||||
# much more simplified logic vs tcp sockets - one socket type and only one
|
# much more simplified logic vs tcp sockets - one socket type and only one
|
||||||
# possible location to connect to
|
# possible location to connect to
|
||||||
sock = trio.socket.socket(AF_UNIX, SOCK_STREAM)
|
sock = trio.socket.socket(AF_UNIX, SOCK_STREAM)
|
||||||
sock.setsockopt(SOL_SOCKET, SO_PASSCRED, 1)
|
|
||||||
|
# Only set SO_PASSCRED on Linux (not needed/available on macOS)
|
||||||
|
if SO_PASSCRED is not None:
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_PASSCRED, 1)
|
||||||
|
|
||||||
with close_on_error(sock):
|
with close_on_error(sock):
|
||||||
await sock.connect(os.fspath(filename))
|
await sock.connect(os.fspath(filename))
|
||||||
|
|
||||||
|
@ -320,7 +339,10 @@ def get_peer_info(sock: trio.socket.socket) -> tuple[
|
||||||
]:
|
]:
|
||||||
'''
|
'''
|
||||||
Deliver the connecting peer's "credentials"-info as defined in
|
Deliver the connecting peer's "credentials"-info as defined in
|
||||||
a very Linux specific way..
|
a platform-specific way.
|
||||||
|
|
||||||
|
On Linux, uses SO_PEERCRED.
|
||||||
|
On macOS, uses LOCAL_PEERCRED.
|
||||||
|
|
||||||
For more deats see,
|
For more deats see,
|
||||||
- `man accept`,
|
- `man accept`,
|
||||||
|
@ -333,6 +355,11 @@ def get_peer_info(sock: trio.socket.socket) -> tuple[
|
||||||
- https://stackoverflow.com/a/7982749
|
- https://stackoverflow.com/a/7982749
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
if SO_PEERCRED is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
f'Peer credential retrieval not supported on {sys.platform}!'
|
||||||
|
)
|
||||||
|
|
||||||
creds: bytes = sock.getsockopt(
|
creds: bytes = sock.getsockopt(
|
||||||
SOL_SOCKET,
|
SOL_SOCKET,
|
||||||
SO_PEERCRED,
|
SO_PEERCRED,
|
||||||
|
|
Loading…
Reference in New Issue