<?php

require_once "Auth.php";
require_once "SmtpClient.php";


class ProxyService
{

    /**
     * 连接数
     * @var SmtpClient[]
     */
    protected static $clients = [];


    protected function push($msg){
        echo 'out '.$msg;
        return $msg;
    }

    /**
     * @author:dc
     * @time 2025/3/29 14:34
     */
    public function run()
    {
        //创建Server对象,监听 127.0.0.1:9501 端口。
        $server = new Swoole\Server(
            '0.0.0.0', 9527,
            SWOOLE_BASE,
            SWOOLE_SOCK_TCP//|SWOOLE_SSL
        );

        //监听连接进入事件。
        $server->on('Connect', function ($server, $fd) {
            $server->send($fd, $this->push("220 proxy client ok\r\n"));
        });

        //监听数据接收事件。
        $server->on('Receive', function ($server, $fd, $reactor_id, $data) {
            echo "in > ".$data;
            // 建立连接
            if (empty(self::$clients[$fd])) {

                try {
                    $auth = new Auth($data);
                }catch (Throwable $e){
                    $server->send($fd, $this->push($e->getMessage()));
                    $server->close($fd,true);
                    return;
                }
                // 创建一个客户端
                self::$clients[$fd] = new SmtpClient($auth->host);
                // 连接客户端
                try {
                    self::$clients[$fd]->open($auth->out_ip, $auth->timeOut);
                }catch (Throwable $e){
                    $server->send($fd,$this->push('500 ' . $e->getMessage()."\r\n"));
                    $server->close($fd,true);
                    return;
                }

                $line = self::$clients[$fd]->readLine(1);

                $server->send($fd,$this->push($line));

            } // 正式请求转发
            else {
                // 没有连接成功
                if(empty(self::$clients[$fd])){
                    $server->send($fd, $this->push("500 No proxy server.\r\n"));
                    $server->close($fd,true);
                    return;
                }

                $line = false;
                try {
                    // 请求数据
                    $num = self::$clients[$fd]->write($data);

                    if($num) $line = self::$clients[$fd]->readLine();

                }catch (Throwable $e){
                    $line = '500 server error '.$e->getMessage()."\r\n";
                }

//                echo 'out '.co::getCid()." => ".$line;

                if($line!==false) $server->send($fd,$this->push($line));

            }
        });

        //监听连接关闭事件。
        $server->on('Close', function ($server, $fd) {
//            echo '连接关闭了 => '.$fd."\n";
            // 关闭并释放资源
            self::$clients[$fd] = null;
            unset(self::$clients[$fd]);
        });

        //启动服务器
        $server->start();
    }

}


(new ProxyService())->run();