Proxy-side IPC server — receives requests, executes real syscalls.
| 200 | |
| 201 | |
| 202 | class ProxyServer: |
| 203 | """Proxy-side IPC server — receives requests, executes real syscalls.""" |
| 204 | |
| 205 | def __init__(self, sock: socket.socket): |
| 206 | self._sock = sock |
| 207 | |
| 208 | def recv_request(self) -> tuple: |
| 209 | """Receive one request. Returns (msg_type, parsed_fields).""" |
| 210 | header = _recvall(self._sock, HEADER_SIZE) |
| 211 | msg_type, payload_len = struct.unpack(HEADER_FMT, header) |
| 212 | |
| 213 | payload = _recvall(self._sock, payload_len) |
| 214 | |
| 215 | if msg_type == MsgType.SYSCALL: |
| 216 | fields = struct.unpack(SYSCALL_REQ_FMT, payload) |
| 217 | return MsgType.SYSCALL, fields # (nr, a0, a1, a2, a3, a4, a5) |
| 218 | |
| 219 | elif msg_type == MsgType.SYSCALL_EX: |
| 220 | offset = SYSCALL_REQ_SIZE |
| 221 | fixed = struct.unpack(SYSCALL_REQ_FMT, payload[:offset]) |
| 222 | nr = fixed[0] |
| 223 | args = list(fixed[1:]) |
| 224 | |
| 225 | num_in = payload[offset] |
| 226 | offset += 1 |
| 227 | in_bufs: List[Tuple[int, bytes]] = [] |
| 228 | for _ in range(num_in): |
| 229 | arg_idx, length = struct.unpack('!BI', payload[offset:offset + 5]) |
| 230 | offset += 5 |
| 231 | in_bufs.append((arg_idx, payload[offset:offset + length])) |
| 232 | offset += length |
| 233 | |
| 234 | num_out = payload[offset] |
| 235 | offset += 1 |
| 236 | out_specs: List[Tuple[int, int]] = [] |
| 237 | for _ in range(num_out): |
| 238 | arg_idx, length = struct.unpack('!BI', payload[offset:offset + 5]) |
| 239 | offset += 5 |
| 240 | out_specs.append((arg_idx, length)) |
| 241 | |
| 242 | return MsgType.SYSCALL_EX, (nr, args, in_bufs, out_specs) |
| 243 | |
| 244 | elif msg_type == MsgType.FD_OP: |
| 245 | fixed = struct.unpack(FD_OP_REQ_FMT, payload[:FD_OP_REQ_SIZE]) |
| 246 | op, proxy_fd, arg1, arg2, data_len = fixed |
| 247 | data = payload[FD_OP_REQ_SIZE:FD_OP_REQ_SIZE + data_len] |
| 248 | return MsgType.FD_OP, (FdOp(op), proxy_fd, arg1, arg2, data) |
| 249 | |
| 250 | else: |
| 251 | raise QlProxyConnectionError(f"unknown message type: {msg_type}") |
| 252 | |
| 253 | def send_syscall_response(self, retval: int, errno_val: int): |
| 254 | payload = struct.pack(SYSCALL_RESP_FMT, retval, errno_val) |
| 255 | header = struct.pack(HEADER_FMT, 0, len(payload)) |
| 256 | self._sock.sendall(header + payload) |
| 257 | |
| 258 | def send_syscall_ex_response(self, retval: int, errno_val: int, out_bufs: Sequence[bytes]): |
| 259 | payload = bytearray(struct.pack(SYSCALL_EX_RESP_HEAD_FMT, retval, errno_val, len(out_bufs))) |