blob: fffd707f001fa6379617900a5e9bbe93f85ef218 (
plain) (
tree)
|
|
package org.openslx.taskmanager.tasks;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.security.cert.X509Certificate;
import java.util.Date;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.openslx.taskmanager.api.AbstractTask;
import com.google.gson.annotations.Expose;
public class DirectedRelay extends AbstractTask
{
protected Output status = new Output();
@Expose
public String ip;
@Expose
public int port;
@Override
protected boolean execute()
{
SSLContext ctx = getSSLContext();
if ( ctx == null )
return false;
try ( SSLSocket dbgSock = getDbgSock( ctx );
SSLServerSocket srvSock = getSrvSock( ctx ) ) {
connectToDbg( dbgSock );
bindToPort( srvSock );
try ( SSLSocket poolSock = ( SSLSocket ) srvSock.accept() ) {
status.addMessage( "INFO: Connection from pool client established." );
relay( dbgSock, poolSock );
} catch ( Exception ex ) {
throw( ex );
}
} catch ( Exception e ) {
status.addMessage( "ERROR: " + e.getMessage() );
return false;
}
return true;
}
protected void connectToDbg ( SSLSocket dbgSock ) throws IOException {
InetSocketAddress addr = new InetSocketAddress( ip, port );
dbgSock.connect( addr );
status.addMessage( "INFO: Connected to debug server at " + ip + ":" + port + "." );
status.setDbgAddr( addr );
}
protected void bindToPort ( SSLServerSocket srvSock ) throws IOException {
srvSock.bind( null );
status.setListenPort( srvSock.getLocalPort() );
status.addMessage( "INFO: Listening on localhost:" + status.getListenPort() + "." );
}
protected SSLContext getSSLContext() {
SSLContext ctx = null;
try {
ctx = trustAll();
status.addMessage( "INFO: SSLContext created." );
} catch ( Exception e ) {
status.addMessage( "ERROR: Failed to create SSLContext." );
}
return ctx;
}
private boolean relay( SSLSocket dbgSock, SSLSocket poolSock ) {
Relay toDbg = new Relay( poolSock, dbgSock, status );
Relay toPool = new Relay( dbgSock, poolSock, status );
toDbg.setName( "PoolToDebug" );
toPool.setName( "DebugToPool" );
toDbg.start();
toPool.start();
try {
for ( Relay r : new Relay[]{ toDbg, toPool })
r.join();
} catch ( InterruptedException ix ) {
status.addMessage( "INFO: Relay closed: " + Thread.currentThread().getName() );
}
return true;
}
protected SSLContext trustAll () throws Exception
{
TrustManager[] trustAllMgr = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted( X509Certificate[] certs, String authType ) {}
public void checkServerTrusted( X509Certificate[] certs, String authType ) {}
}
};
SSLContext ctx = SSLContext.getInstance( "SSL" );
ctx.init( null, trustAllMgr, new java.security.SecureRandom() );
return ctx;
}
private SSLServerSocket getSrvSock( SSLContext ctx ) throws IOException
{
SSLServerSocketFactory sssf = ctx.getServerSocketFactory();
return ( SSLServerSocket ) sssf.createServerSocket();
}
private SSLSocket getDbgSock( SSLContext ctx ) throws IOException
{
SSLSocketFactory ssf = ctx.getSocketFactory();
return ( SSLSocket ) ssf.createSocket();
}
@Override
protected boolean initTask()
{
this.setStatusObject( this.status );
status.addMessage( "INFO: Initiating directed relay to debug server at: " + ip + ":" + port + "." );
return true;
}
public static class Output
{
protected String messages = null;
protected Date d = null;
protected InetSocketAddress dbgAddr = null;
protected int listenPort;
public void setListenPort ( int port ) { listenPort = port; }
public int getListenPort () { return listenPort; }
public void setDbgAddr ( InetSocketAddress addr ) { dbgAddr = addr; }
public void addMessage( String str )
{
d = new Date();
if ( messages == null ) {
messages = d.toString() + "-" + str;
} else {
messages += "\n" + d.toString() + "-" + str;
}
}
}
private class Relay extends Thread
{
boolean active = true;
private byte[] buffer = new byte[16384];
private SSLSocket srcSock;
private SSLSocket destSock;
private Output status;
public Relay ( SSLSocket srcSock, SSLSocket destSock, Output status ) {
this.srcSock = srcSock;
this.destSock = destSock;
this.status = status;
}
@Override
public void run() {
boolean first = true;
int readBytes;
try ( InputStream in = srcSock.getInputStream();
OutputStream out = destSock.getOutputStream() ) {
while( active ) {
readBytes = in.read( buffer );
out.write( buffer, 0, readBytes );
if ( first )
status.addMessage( "INFO: Relay operating: " + this.getName() );
}
} catch ( Exception e ) {
active = false;
return;
}
}
}
}
|