}; // 当shadowsocks客户端连接上有错误时,关闭远程服务端连接 $connection->onError = function ($connection, $code, $msg) { echo "connection err code:{$code} msg:{$msg}\n"; $connection->close(); if (isset($connection->opposite)) { $connection->opposite->close(); } }; // 执行远程连接 $remote_connection->connect(); // 改变当前连接的状态为STAGE_STREAM,即开始转发数据流 $connection->state = STAGE_STREAM; // shadowsocks客户端第一次发来的数据超过头部,则要把头部后面的数据发给远程服务端 if (strlen($buffer) > $header_len) { $remote_connection->send(substr($buffer, $header_len)); } } }; /** * 解析shadowsocks客户端发来的socket5头部数据 * @param string $buffer */ function parse_socket5_header($buffer) { $addr_type = ord($buffer[0]); switch ($addr_type) { case ADDRTYPE_IPV4: $dest_addr = ord($buffer[1]) . '.' . ord($buffer[2]) . '.' . ord($buffer[3]) . '.' . ord($buffer[4]); $port_data = unpack('n', substr($buffer, 5, 2)); $dest_port = $port_data[1];
// 当客户端发来数据时,加密数据,并发给远程服务端 $connection->onMessage = function ($connection, $data) { $connection->opposite->send($connection->encryptor->encrypt($data)); }; // 当客户端关闭连接时,关闭远程服务端的连接 $connection->onClose = function ($connection) { $connection->opposite->close(); $connection->opposite = null; }; // 当客户端连接上有错误时,关闭远程服务端连接 $connection->onError = function ($connection, $code, $msg) { echo "connection err code:{$code} msg:{$msg}\n"; $connection->close(); if (isset($connection->opposite)) { $connection->opposite->close(); } }; // 执行远程连接 $remote_connection->connect(); // 改变当前连接的状态为STAGE_STREAM,即开始转发数据流 $connection->state = STAGE_STREAM; //转发首个数据包,包含由客户端封装的目标地址,端口号等信息 $buffer = substr($buffer, 3); $buffer = $connection->encryptor->encrypt($buffer); $remote_connection->send($buffer); } }; // 如果不是在根目录启动,则运行runAll方法 if (!defined('GLOBAL_START')) { Worker::runAll(); }
/** * 尝试连接Gateway内部通讯地址 * @return void */ public function tryToConnectGateway($addr) { if (!isset($this->gatewayConnections[$addr]) && !isset($this->_connectingGatewayAddresses[$addr]) && isset($this->_gatewayAddresses[$addr])) { $gateway_connection = new AsyncTcpConnection("GatewayProtocol://{$addr}"); $gateway_connection->remoteAddress = $addr; $gateway_connection->onConnect = array($this, 'onConnectGateway'); $gateway_connection->onMessage = array($this, 'onGatewayMessage'); $gateway_connection->onClose = array($this, 'onGatewayClose'); $gateway_connection->onError = array($this, 'onGatewayError'); if (TcpConnection::$defaultMaxSendBufferSize == $gateway_connection->maxSendBufferSize) { $gateway_connection->maxSendBufferSize = 50 * 1024 * 1024; } $gateway_data = GatewayProtocol::$empty; $gateway_data['cmd'] = GatewayProtocol::CMD_WORKER_CONNECT; $gateway_connection->send($gateway_data); $gateway_connection->connect(); $this->_connectingGatewayAddresses[$addr] = $addr; } unset($this->_waitingConnectGatewayAddresses[$addr]); }