All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rnorth.tcpunixsocketproxy.ProxyThread Maven / Gradle / Ivy

package org.rnorth.tcpunixsocketproxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * General purpose proxy between two {@link Socket}s. Blocking I/O for raw simplicity; not intended to
 * be particularly performant.
 */
class ProxyThread extends Thread {

    private static final Logger logger = LoggerFactory.getLogger(ProxyThread.class);
    private static final int COPY_BUFFER_SIZE = 4096;

    /**
     * Proxy incoming traffic from the client socket to the server socket (and responses
     * back).
     * @param clientSocket the socket the client is connecting to (e.g. a local {@link java.net.ServerSocket})
     * @param serverSocket the socket for connections to the (remote) server
     * @throws IOException if sockets cannot be streamed to/from
     */
    public ProxyThread(final Socket clientSocket, final Socket serverSocket) throws IOException {

        InputStream fromClient = clientSocket.getInputStream();
        OutputStream toClient = clientSocket.getOutputStream();
        InputStream fromServer = serverSocket.getInputStream();
        OutputStream toServer = serverSocket.getOutputStream();

        // Create a thread to copy data from client to server
        Thread clientToServerThread = new Thread(() -> {
            copyUntilFailure(fromClient, toServer);
            logger.trace("C->S died, closing sockets");
            quietlyClose(serverSocket);
            quietlyClose(clientSocket);
        });
        clientToServerThread.start();

        // Create a thread to copy data back from server to client
        Thread serverToClientThread = new Thread(() -> {
            copyUntilFailure(fromServer, toClient);
            logger.trace("S->C died, closing sockets");
            quietlyClose(serverSocket);
            quietlyClose(clientSocket);
        });
        serverToClientThread.start();

    }

    /*
     * Copy data from a from stream to a to stream, until the from stream ends.
     */
    private void copyUntilFailure(InputStream from, OutputStream to) {
        byte[] buffer = new byte[COPY_BUFFER_SIZE];

        int read;
        try {
            while ((read = from.read(buffer)) != -1) {
                to.write(buffer, 0, read);
                to.flush();
            }
        } catch (IOException ignored) {
            // just return
        }
    }

    /*
     * Close a socket without handling exceptions, which also closes its streams.
     */
    private void quietlyClose(Socket socket) {
        if (socket != null && !socket.isClosed()) {
            try {
                socket.close();
            } catch (IOException ignored) {
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy