Index
pyvider.rpcplugin.handshake
¶
RPC Plugin handshake functionality.
This package provides handshake configuration, validation, building, parsing, and negotiation capabilities for the RPC plugin system.
Classes¶
HandshakeConfig
¶
Attributes:
| Name | Type | Description |
|---|---|---|
magic_cookie_key |
str
|
The expected environment key for the handshake cookie. |
magic_cookie_value |
str
|
The expected handshake cookie value. |
protocol_versions |
list[int]
|
A list of protocol versions supported by the server. |
supported_transports |
list[str]
|
A list of supported transport types (e.g. "tcp", "unix"). |
Functions¶
build_handshake_response
async
¶
build_handshake_response(
plugin_version: int,
transport_name: str,
transport: TransportT,
server_cert: Certificate | None = None,
port: int | None = None,
) -> str
CORE_VERSION|PLUGIN_VERSION|NETWORK|ADDRESS|PROTOCOL|TLS_CERT
Note: For TCP transport, the ADDRESS 127.0.0.1 is standard for same-host
plugin communication, ensuring the plugin host connects to the plugin
locally. The actual listening interface might be broader (e.g., 0.0.0.0),
but the handshake communicates 127.0.0.1 for the host to connect to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plugin_version
|
int
|
The version of the plugin. |
required |
transport_name
|
str
|
The name of the transport ("tcp" or "unix"). |
required |
transport
|
TransportT
|
The transport instance. |
required |
server_cert
|
Certificate | None
|
Optional server certificate for TLS. |
None
|
port
|
int | None
|
Optional port number, required for TCP transport. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The constructed handshake response string. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If required parameters are missing (e.g., port for TCP). |
TransportError
|
If an unsupported transport type is given. |
Exception
|
Propagates exceptions from underlying operations. |
Source code in pyvider/rpcplugin/handshake/core.py
create_stderr_relay
async
¶
Creates a background task that continuously reads and logs stderr from the plugin process. Essential for debugging handshake issues, especially with Go plugins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
process
|
Popen[bytes]
|
The subprocess.Popen instance with stderr pipe. |
required |
Returns:
| Type | Description |
|---|---|
Task[None] | None
|
The asyncio.Task managing the stderr relay, or None if stderr is not available. |
Source code in pyvider/rpcplugin/handshake/negotiation.py
is_valid_handshake_parts
¶
Ensures it contains exactly 6 parts and the first two parts are digits.
negotiate_protocol_version
¶
🤝🔄 Selects the highest mutually supported protocol version.
Compares the server-provided versions against the client's supported versions from the configuration.
Returns:
| Type | Description |
|---|---|
int
|
The highest mutually supported protocol version. |
Raises:
| Type | Description |
|---|---|
ProtocolError
|
If no mutually supported version is found. |
Source code in pyvider/rpcplugin/handshake/negotiation.py
negotiate_transport
async
¶
(🗣️🚊 Transport Negotiation) Negotiates the transport type with the server and creates the appropriate transport instance.
Returns:
| Type | Description |
|---|---|
tuple[str, TransportT]
|
A tuple of (transport_name, transport_instance). |
Raises:
| Type | Description |
|---|---|
TransportError
|
If no compatible transport can be negotiated or an error occurs during negotiation. |
Source code in pyvider/rpcplugin/handshake/negotiation.py
parse_handshake_response
¶
(📡🔍 Handshake Parsing) Parses the handshake response string. Expected Format: CORE_VERSION|PLUGIN_VERSION|NETWORK|ADDRESS|PROTOCOL|TLS_CERT
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
str
|
The handshake response string to parse. |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, str, str, str, str | None]
|
A tuple containing: - core_version (int) - plugin_version (int) - network (str) - address (str) - protocol (str) - server_cert (str | None) |
Raises:
| Type | Description |
|---|---|
HandshakeError
|
If parsing fails or the format is invalid. |
ValueError
|
If parts of the handshake string are invalid (e.g., non-integer versions). |
Source code in pyvider/rpcplugin/handshake/core.py
read_handshake_response
async
¶
Robust handshake response reader with multiple strategies to handle different Go-Python interop challenges.
The handshake response is a pipe-delimited string with format: CORE_VERSION|PLUGIN_VERSION|NETWORK|ADDRESS|PROTOCOL|TLS_CERT
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
process
|
Popen[bytes]
|
The subprocess.Popen instance representing the plugin. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The complete handshake response string. |
Raises:
| Type | Description |
|---|---|
HandshakeError
|
If handshake fails (e.g. process exits early) or times out. |
Source code in pyvider/rpcplugin/handshake/negotiation.py
validate_magic_cookie
¶
validate_magic_cookie(
magic_cookie_key: (
str | None | _SentinelType
) = _SENTINEL_INSTANCE,
magic_cookie_value: (
str | None | _SentinelType
) = _SENTINEL_INSTANCE,
magic_cookie: (
str | None | _SentinelType
) = _SENTINEL_INSTANCE,
) -> None
Validates the magic cookie.
If a parameter is omitted (i.e. remains as the sentinel), its value is read from rpcplugin_config. However, if the caller explicitly passes None, that is treated as missing and an error is raised.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
magic_cookie_key
|
str | None | _SentinelType
|
The environment key for the magic cookie. |
_SENTINEL_INSTANCE
|
magic_cookie_value
|
str | None | _SentinelType
|
The expected value of the magic cookie. |
_SENTINEL_INSTANCE
|
magic_cookie
|
str | None | _SentinelType
|
The actual cookie value provided. |
_SENTINEL_INSTANCE
|
Raises:
| Type | Description |
|---|---|
HandshakeError
|
If cookie validation fails. |