/** * 检查gateway的通信端口是否都已经连 * 如果有未连接的端口,则尝试连接 * @return void */ public function checkGatewayConnections() { $key = 'GLOBAL_GATEWAY_ADDRESS'; $addresses_list = Store::instance('gateway')->get($key); if (empty($addresses_list)) { return; } foreach ($addresses_list as $addr) { if (!isset($this->gatewayConnections[$addr]) && !isset($this->_connectingGatewayAddress[$addr]) && !isset($this->_badGatewayAddress[$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, 'onClose'); $gateway_connection->onError = array($this, 'onError'); if (TcpConnection::$defaultMaxSendBufferSize == $gateway_connection->maxSendBufferSize) { $gateway_connection->maxSendBufferSize = 10 * 1024 * 1024; } $gateway_connection->connect(); $this->_connectingGatewayAddress[$addr] = 1; } } }
$buffer = $connection->encryptor->decrypt($buffer); // 解析socket5头 $header_data = parse_socket5_header($buffer); // 头部长度 $header_len = $header_data[3]; // 解析头部出错,则关闭连接 if (!$header_data) { $connection->close(); return; } // 解析得到实际请求地址及端口 $host = $header_data[1]; $port = $header_data[2]; $address = "tcp://{$host}:{$port}"; // 异步建立与实际服务器的远程连接 $remote_connection = new AsyncTcpConnection($address); $connection->opposite = $remote_connection; $remote_connection->opposite = $connection; // 流量控制,远程连接的发送缓冲区满,则停止读取shadowsocks客户端发来的数据 // 避免由于读取速度大于发送速导致发送缓冲区爆掉 $remote_connection->onBufferFull = function ($remote_connection) { $remote_connection->opposite->pauseRecv(); }; // 流量控制,远程连接的发送缓冲区发送完毕后,则恢复读取shadowsocks客户端发来的数据 $remote_connection->onBufferDrain = function ($remote_connection) { $remote_connection->opposite->resumeRecv(); }; // 远程连接发来消息时,进行加密,转发给shadowsocks客户端,shadowsocks客户端会解密转发给浏览器 $remote_connection->onMessage = function ($remote_connection, $buffer) { $remote_connection->opposite->send($remote_connection->opposite->encryptor->encrypt($buffer)); };
$connection->send(""); $connection->stage = STAGE_ADDR; return; case STAGE_ADDR: $cmd = ord($buffer[1]); //仅处理客户端的TCP连接请求 if ($cmd != CMD_CONNECT) { echo "unsupport cmd\n"; $connection->send(""); return $connection->close(); } $connection->stage = STAGE_CONNECTING; $buf_replies = "" . pack('n', $LOCAL_PORT); $connection->send($buf_replies); $address = "tcp://{$SERVER}:{$PORT}"; $remote_connection = new AsyncTcpConnection($address); $connection->opposite = $remote_connection; $remote_connection->opposite = $connection; // 流量控制 $remote_connection->onBufferFull = function ($remote_connection) { $remote_connection->opposite->pauseRecv(); }; $remote_connection->onBufferDrain = function ($remote_connection) { $remote_connection->opposite->resumeRecv(); }; // 远程连接发来消息时,进行解密,转发给客户端 $remote_connection->onMessage = function ($remote_connection, $buffer) { $remote_connection->opposite->send($remote_connection->opposite->encryptor->decrypt($buffer)); }; // 远程连接断开时,则断开客户端的连接 $remote_connection->onClose = function ($remote_connection) {
/** * 尝试连接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]); }