package com.dragonssh.xhttpdemo.core.tunnel;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * A virtual duplex {@link Socket} handed to the Trilead SSH client by
 * {@link XHttpProxy}. Its input stream is the XHTTP downlink (the HTTP/2 GET
 * response body) and its output stream is the XHTTP uplink (fed into the HTTP/2
 * POST request body). The underlying HTTP/2 connection is managed by OkHttp, so
 * this class only bridges the two streams and cleans up on close.
 *
 * <p>Trilead's {@code TransportManager} only calls {@link #getInputStream()},
 * {@link #getOutputStream()}, {@link #close()} and — via {@code Connection} —
 * {@link #setTcpNoDelay(boolean)} / {@link #setSoTimeout(int)}. The latter two
 * are no-ops here because OkHttp owns the real sockets (read timeout is disabled
 * for the streaming tunnel; a stalled SSH handshake is aborted by Trilead's own
 * kex-timeout watchdog, which closes this socket).</p>
 */
final class XHttpBridgeSocket extends Socket {

	private final InputStream in;
	private final OutputStream out;
	private final Runnable onClose;
	private volatile boolean closed = false;

	XHttpBridgeSocket(InputStream in, OutputStream out, Runnable onClose) {
		this.in = in;
		this.out = out;
		this.onClose = onClose;
	}

	@Override
	public InputStream getInputStream() {
		return in;
	}

	@Override
	public OutputStream getOutputStream() {
		return out;
	}

	@Override
	public void setTcpNoDelay(boolean on) { /* managed by OkHttp */ }

	@Override
	public void setSoTimeout(int timeout) { /* streaming tunnel: no read timeout */ }

	@Override
	public boolean isConnected() {
		return !closed;
	}

	@Override
	public boolean isClosed() {
		return closed;
	}

	@Override
	public synchronized void close() throws IOException {
		if (closed) {
			return;
		}
		closed = true;
		try { out.close(); } catch (Exception ignored) {}
		try { in.close(); } catch (Exception ignored) {}
		if (onClose != null) {
			try { onClose.run(); } catch (Exception ignored) {}
		}
	}
}
