<?php


namespace Mainto\RpcServer\Util\Net\Listener;


use Mainto\RpcServer\Util\Net\Address;
use Mainto\RpcServer\Util\Net\Conn;
use Mainto\RpcServer\Util\Net\Listener;
use RuntimeException;

class TcpListener implements Listener {
    private Address\TcpAddress $address;
    /**
     * @var false|resource
     */
    private $listenSocket;

    public function __construct (string $address) {
        $listenSocket = @socket_create( AF_INET, SOCK_STREAM, SOL_TCP);

        if ($listenSocket === false) {
            throw new RuntimeException("create server [$address] error socket is false");
        }

        ["host" => $host, "port" => $port] = parse_url($address);

        if (!@socket_bind($listenSocket, $host, $port)) {
            throw new RuntimeException("bind server [$address] error: ". socket_last_error($listenSocket));
        }

        @socket_listen($listenSocket);

        $this->address = new Address\TcpAddress($address);
        $this->listenSocket = $listenSocket;
    }

    public function close () {
        @socket_close($this->listenSocket);
    }

    public function accept (): Conn {
        $socket = socket_accept($this->listenSocket);

        return new Conn\TcpConn($socket);
    }

    public function address (): Address {
        return $this->address;
    }
}