* Handles outbound TCP connections. * * @param {any} remoteSocket * @param {string} addressRemote The remote address to connect to. * @param {number} portRemote The remote port to connect to. * @param {Uint8Array} rawClientData The raw client data to write. * @param {import("@cloudflare
(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,)
| 345 | * @returns {Promise<void>} The remote socket. |
| 346 | */ |
| 347 | async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,) { |
| 348 | |
| 349 | /** |
| 350 | * Connects to a given address and port and writes data to the socket. |
| 351 | * @param {string} address The address to connect to. |
| 352 | * @param {number} port The port to connect to. |
| 353 | * @returns {Promise<import("@cloudflare/workers-types").Socket>} A Promise that resolves to the connected socket. |
| 354 | */ |
| 355 | async function connectAndWrite(address, port) { |
| 356 | /** @type {import("@cloudflare/workers-types").Socket} */ |
| 357 | const tcpSocket = connect({ |
| 358 | hostname: address, |
| 359 | port: port, |
| 360 | }); |
| 361 | remoteSocket.value = tcpSocket; |
| 362 | log(`connected to ${address}:${port}`); |
| 363 | const writer = tcpSocket.writable.getWriter(); |
| 364 | await writer.write(rawClientData); // first write, nomal is tls client hello |
| 365 | writer.releaseLock(); |
| 366 | return tcpSocket; |
| 367 | } |
| 368 | |
| 369 | /** |
| 370 | * Retries connecting to the remote address and port if the Cloudflare socket has no incoming data. |
| 371 | * @returns {Promise<void>} A Promise that resolves when the retry is complete. |
| 372 | */ |
| 373 | async function retry() { |
| 374 | const tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote) |
| 375 | tcpSocket.closed.catch(error => { |
| 376 | console.log('retry tcpSocket closed error', error); |
| 377 | }).finally(() => { |
| 378 | safeCloseWebSocket(webSocket); |
| 379 | }) |
| 380 | remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log); |
| 381 | } |
| 382 | |
| 383 | const tcpSocket = await connectAndWrite(addressRemote, portRemote); |
| 384 | |
| 385 | // when remoteSocket is ready, pass to websocket |
| 386 | // remote--> ws |
| 387 | remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, retry, log); |
| 388 | } |
| 389 | |
| 390 | /** |
| 391 | * Creates a readable stream from a WebSocket server, allowing for data to be read from the WebSocket. |
no test coverage detected