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 * 1024Largest 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.socketA connected PINE socket.
paramnintNumber of bytes to read.
paramdeadlinefloattime.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_pathPathThe socket's path, for the timeout warning.
Returns
typing.OptionalThe 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_pathPathThe emulator's PINE Unix socket.
paramopcodeintThe PINE message opcode.
parampayloadbytes= b''Bytes following the opcode.
paramtimeoutfloat= 5.0Seconds the whole exchange gets, connect through reply.
Returns
typing.OptionalThe reply payload (possibly empty), or None when the socket is down, the peer hangs up,