* Handle CONNECT response
()
| 316 | * Handle CONNECT response |
| 317 | */ |
| 318 | handleConnectResponse () { |
| 319 | if (this.buffer.length < 4) { |
| 320 | return // Not enough data for header |
| 321 | } |
| 322 | |
| 323 | const version = this.buffer[0] |
| 324 | const reply = this.buffer[1] |
| 325 | const addressType = this.buffer[3] |
| 326 | |
| 327 | if (version !== SOCKS_VERSION) { |
| 328 | throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, 'UND_ERR_SOCKS5_REPLY_VERSION') |
| 329 | } |
| 330 | |
| 331 | // Calculate the expected response length |
| 332 | let responseLength = 4 // VER + REP + RSV + ATYP |
| 333 | if (addressType === ADDRESS_TYPES.IPV4) { |
| 334 | responseLength += 4 + 2 // IPv4 + port |
| 335 | } else if (addressType === ADDRESS_TYPES.DOMAIN) { |
| 336 | if (this.buffer.length < 5) { |
| 337 | return // Need domain length byte |
| 338 | } |
| 339 | responseLength += 1 + this.buffer[4] + 2 // length byte + domain + port |
| 340 | } else if (addressType === ADDRESS_TYPES.IPV6) { |
| 341 | responseLength += 16 + 2 // IPv6 + port |
| 342 | } else { |
| 343 | throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, 'UND_ERR_SOCKS5_ADDR_TYPE') |
| 344 | } |
| 345 | |
| 346 | if (this.buffer.length < responseLength) { |
| 347 | return // Not enough data for full response |
| 348 | } |
| 349 | |
| 350 | if (reply !== REPLY_CODES.SUCCEEDED) { |
| 351 | const errorMessage = this.getReplyErrorMessage(reply) |
| 352 | throw new Socks5ProxyError(`SOCKS5 connection failed: ${errorMessage}`, `UND_ERR_SOCKS5_REPLY_${reply}`) |
| 353 | } |
| 354 | |
| 355 | // Parse bound address and port |
| 356 | let boundAddress |
| 357 | let offset = 4 |
| 358 | |
| 359 | if (addressType === ADDRESS_TYPES.IPV4) { |
| 360 | boundAddress = Array.from(this.buffer.subarray(offset, offset + 4)).join('.') |
| 361 | offset += 4 |
| 362 | } else if (addressType === ADDRESS_TYPES.DOMAIN) { |
| 363 | const domainLength = this.buffer[offset] |
| 364 | offset += 1 |
| 365 | boundAddress = this.buffer.subarray(offset, offset + domainLength).toString() |
| 366 | offset += domainLength |
| 367 | } else if (addressType === ADDRESS_TYPES.IPV6) { |
| 368 | // Parse IPv6 address from 16-byte buffer |
| 369 | const parts = [] |
| 370 | for (let i = 0; i < 8; i++) { |
| 371 | const value = this.buffer.readUInt16BE(offset + i * 2) |
| 372 | parts.push(value.toString(16)) |
| 373 | } |
| 374 | boundAddress = parts.join(':') |
| 375 | offset += 16 |
no test coverage detected