webstation-broker
DeveloperPython referenceemulators

emulators.pine

The PINE wire protocol, shared by PCSX2 and RPCS3.

The PINE wire protocol, shared by PCSX2 and RPCS3.

Both emulators speak the same framing over a Unix socket; RPCS3 just implements a smaller opcode set (no save/load-state). Each request opens its own connection, so callers pass the socket path every time and a test can point a module's PINE_SOCKET elsewhere.

attributelog
= logging.getLogger(__name__)
attributeMAX_REPLY_BYTES
= 64 * 1024

Largest reply the broker will read off a PINE socket.

The opcodes the broker sends answer in a handful of bytes. The declared size is a u32 read straight off the wire, so without a ceiling a bogus one has the broker buying 4 GiB of memory on the word of whatever is on the socket.

funcrecv_exact(sock, n, deadline, socket_path) -> Optional[bytes]

Read exactly n bytes from a PINE socket, on one shared deadline.

paramsock_socket.socket

A connected PINE socket.

paramnint

Number of bytes to read.

paramdeadlinefloat

time.monotonic value the whole read must finish by. A per-recv timeout alone never expires against a peer that dribbles one byte at a time, so the budget is spent, not restarted.

paramsocket_pathPath

The socket's path, for the timeout warning.

Returns

typing.Optional

The bytes read, or None if the peer closed the connection or the deadline passed.

funcrequest(socket_path, opcode, payload=b'', timeout=5.0) -> Optional[bytes]

Send one PINE request and return the reply body.

Wire format (little endian): u32 total size, u8 opcode, payload; the reply is u32 size, u8 result (0 = OK), payload.

paramsocket_pathPath

The emulator's PINE Unix socket.

paramopcodeint

The PINE message opcode.

parampayloadbytes
= b''

Bytes following the opcode.

paramtimeoutfloat
= 5.0

Seconds the whole exchange gets, connect through reply.

Returns

typing.Optional

The reply payload (possibly empty), or None when the socket is down, the peer hangs up,