blob: 33367c0b345fb0760cdc842e0a01aebce6e6b961 [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab
package org.mariadb.jdbc.integration.tools;
import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import org.mariadb.jdbc.util.log.Logger;
import org.mariadb.jdbc.util.log.Loggers;
public class TcpProxySocket implements Runnable {
private static final Logger logger = Loggers.getLogger(TcpProxySocket.class);
private final String host;
private final int remoteport;
private final int localport;
private boolean stop = false;
private Socket client = null;
private Socket server = null;
private ServerSocket ss;
private int delay;
/**
* Creation of proxy.
*
* @param host database host
* @param remoteport database port
* @throws IOException exception
*/
public TcpProxySocket(String host, int remoteport) throws IOException {
this.host = host;
this.remoteport = remoteport;
ss = new ServerSocket(0);
this.localport = ss.getLocalPort();
}
public int getLocalPort() {
return ss.getLocalPort();
}
public boolean isClosed() {
return ss.isClosed();
}
public void setDelay(int delay) {
this.delay = delay;
}
/** Kill proxy. */
public void kill() {
stop = true;
try {
if (server != null) {
server.close();
}
} catch (IOException e) {
// eat Exception
}
try {
if (client != null) {
client.close();
}
} catch (IOException e) {
// eat Exception
}
try {
ss.close();
} catch (IOException e) {
// eat Exception
}
}
public void sendRst() {
try {
if (client != null) {
// send an RST, not FIN
client.setSoLinger(true, 0);
client.close();
}
} catch (IOException e) {
// eat Exception
}
try {
if (server != null) {
server.close();
}
} catch (IOException e) {
// eat Exception
}
try {
ss.close();
} catch (IOException e) {
// eat Exception
}
}
@Override
public void run() {
logger.trace("host proxy port " + this.localport + " for " + host + " started");
stop = false;
try {
try {
if (ss.isClosed()) {
ss = new ServerSocket(localport);
}
} catch (BindException b) {
// in case for testing crash and reopen too quickly
try {
Thread.sleep(100);
} catch (InterruptedException i) {
// eat Exception
}
if (ss.isClosed()) {
ss = new ServerSocket(localport);
}
}
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
while (!stop) {
try {
client = ss.accept();
final InputStream fromClient = client.getInputStream();
final OutputStream toClient = client.getOutputStream();
try {
server = new Socket(host, remoteport);
} catch (IOException e) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(toClient));
out.println("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e);
out.flush();
client.close();
continue;
}
final InputStream fromServer = server.getInputStream();
final OutputStream toServer = server.getOutputStream();
new Thread(
() -> {
int bytesRead;
try {
while ((bytesRead = fromClient.read(request)) != -1) {
if (delay > 0) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
toServer.write(request, 0, bytesRead);
toServer.flush();
}
} catch (IOException e) {
// eat exception
}
try {
toServer.close();
} catch (IOException e) {
// eat exception
}
})
.start();
int bytesRead;
try {
while ((bytesRead = fromServer.read(reply)) != -1) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
toClient.write(reply, 0, bytesRead);
toClient.flush();
}
} catch (IOException e) {
// eat exception
}
toClient.close();
} catch (IOException e) {
// System.err.println("ERROR socket : "+e);
} finally {
try {
if (server != null) {
server.close();
}
if (client != null) {
client.close();
}
} catch (IOException e) {
// eat exception
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public int getLocalport() {
return localport;
}
}