conn : null; } public function stream_open(string $path, string $mode, int $options, ?string &$opened): bool { $id = (int)substr($path, strlen(self::SCHEME) + 3); $this->conn = self::$pending[$id] ?? null; return $this->conn !== null; } public function stream_read(int $count): string|false { return $this->conn->read($count); } public function stream_write(string $data): int { try { return $this->conn->write($data); } catch (TlsException $e) { return 0; } } public function stream_eof(): bool { return $this->conn->eof(); } public function stream_close(): void { $this->conn?->close(); } public function stream_flush(): bool { return true; } public function stream_set_option(int $option, int $arg1, ?int $arg2): bool { if ($option === STREAM_OPTION_READ_TIMEOUT) return stream_set_timeout($this->conn->socket(), $arg1, (int)$arg2); if ($option === STREAM_OPTION_BLOCKING) return $arg1 === 1; // ブロッキングのみ return false; } /** stream_select()用に下のソケットを返す */ public function stream_cast(int $castAs) { return $this->conn->socket(); } public function stream_stat(): array { return []; } }