#!/usr/bin/env node
const net = require('node:net');
const [proxyHost, proxyPortRaw, targetHost, targetPortRaw] = process.argv.slice(2);
const proxyPort = Number.parseInt(proxyPortRaw || '', 10);
const targetPort = Number.parseInt(targetPortRaw || '', 10);
if (!proxyHost || !Number.isInteger(proxyPort) || !targetHost || !Number.isInteger(targetPort)) {
  console.error('hwlab git-mirror proxy-connect: invalid ProxyCommand arguments');
  process.exit(64);
}
let settled = false;
let tunnelEstablished = false;
function finish(code, message) {
  if (settled) return;
  settled = true;
  if (message) console.error('hwlab git-mirror proxy-connect: ' + message);
  process.exit(code);
}
const socket = net.createConnection({ host: proxyHost, port: proxyPort });
let buffer = Buffer.alloc(0);
socket.setTimeout(15000, () => { socket.destroy(); finish(65, 'timeout connecting via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); });
socket.on('connect', () => socket.write('CONNECT ' + targetHost + ':' + targetPort + ' HTTP/1.1\r\nHost: ' + targetHost + ':' + targetPort + '\r\nProxy-Connection: Keep-Alive\r\n\r\n'));
socket.on('error', (error) => finish(tunnelEstablished ? 69 : 66, (tunnelEstablished ? 'tunnel socket error: ' : 'tcp error connecting to proxy: ') + (error && error.message ? error.message : String(error))));
socket.on('close', () => { if (!tunnelEstablished) finish(68, 'proxy closed before CONNECT completed via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); else finish(0); });
function onData(chunk) {
  buffer = Buffer.concat([buffer, chunk]);
  const headerEnd = buffer.indexOf('\r\n\r\n');
  if (headerEnd === -1 && buffer.length < 8192) return;
  if (headerEnd === -1) { socket.destroy(); finish(68, 'proxy response header exceeded 8192 bytes before CONNECT status via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); return; }
  const head = buffer.slice(0, headerEnd + 4).toString('latin1');
  const statusLine = head.split('\r\n', 1)[0] || '';
  const statusCode = Number.parseInt(statusLine.split(' ')[1] || '', 10);
  if (!statusLine.startsWith('HTTP/1.') || !Number.isInteger(statusCode) || statusCode < 200 || statusCode > 299) {
    const safeStatus = statusLine.replace(/[^\x20-\x7e]/g, '?').slice(0, 160);
    socket.destroy();
    finish(67, 'proxy CONNECT failed via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort + ': ' + safeStatus);
    return;
  }
  socket.off('data', onData);
  socket.setTimeout(0);
  tunnelEstablished = true;
  const rest = buffer.slice(headerEnd + 4);
  if (rest.length) process.stdout.write(rest);
  process.stdin.on('error', () => {});
  process.stdout.on('error', () => {});
  process.stdin.pipe(socket);
  socket.pipe(process.stdout);
}
socket.on('data', onData);
