|
|
|
/*
|
|
|
|
* Copyright (C) 2022 jimj316
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
package moe.nekojimi.chords;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.net.*;
|
|
|
|
import javax.net.SocketFactory;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @author jimj316
|
|
|
|
*/
|
|
|
|
public class LocalBindSocketFactory extends SocketFactory
|
|
|
|
{
|
|
|
|
|
|
|
|
private InetAddress localAddress;
|
|
|
|
|
|
|
|
public InetAddress getLocalAddress()
|
|
|
|
{
|
|
|
|
return localAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLocalAddress(InetAddress localAddress)
|
|
|
|
{
|
|
|
|
this.localAddress = localAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Socket createSocket() throws IOException
|
|
|
|
{
|
|
|
|
return new LocalBoundSocket();
|
|
|
|
// throw new RuntimeException("Trying to create an empty socket!");
|
|
|
|
}
|
|
|
|
|
|
|
|
private InetSocketAddress findFreeSocketAddress()
|
|
|
|
{
|
|
|
|
return new InetSocketAddress(localAddress, findFreePort(localAddress));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Socket createSocket(String remoteAddr, int remotePort) throws IOException, UnknownHostException
|
|
|
|
{
|
|
|
|
return createSocket(remoteAddr, remotePort, localAddress, findFreePort(localAddress));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Socket createSocket(String remoteAddr, int remotePort, InetAddress x, int localPort) throws IOException, UnknownHostException
|
|
|
|
{
|
|
|
|
return createSocket(InetAddress.getByName(remoteAddr), remotePort, localAddress, localPort);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Socket createSocket(InetAddress remoteAddr, int remotePort) throws IOException
|
|
|
|
{
|
|
|
|
return createSocket(remoteAddr, remotePort, localAddress, findFreePort(localAddress));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Socket createSocket(InetAddress remoteAddr, int remotePort, InetAddress x, int localPort) throws IOException
|
|
|
|
{
|
|
|
|
System.out.println("Requested socket; " + localAddress + ":" + localPort + " -> " + remoteAddr + ":" + remotePort);
|
|
|
|
Socket socket = new Socket(remoteAddr, remotePort, localAddress, localPort);
|
|
|
|
System.out.println("Returned socket; " + socket.getLocalSocketAddress() + ":" + socket.getLocalPort() + " -> " + socket.getRemoteSocketAddress() + ":" + socket.getPort());
|
|
|
|
return socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int findFreePort(InetAddress localAddr)
|
|
|
|
{
|
|
|
|
int port = 0;
|
|
|
|
// For ServerSocket port number 0 means that the port number is automatically allocated.
|
|
|
|
try (ServerSocket socket = new ServerSocket(0, 0, localAddr))
|
|
|
|
{
|
|
|
|
// Disable timeout and reuse address after closing the socket.
|
|
|
|
socket.setReuseAddress(true);
|
|
|
|
port = socket.getLocalPort();
|
|
|
|
} catch (IOException ignored)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
if (port > 0)
|
|
|
|
{
|
|
|
|
return port;
|
|
|
|
}
|
|
|
|
throw new RuntimeException("Could not find a free port");
|
|
|
|
}
|
|
|
|
|
|
|
|
private class LocalBoundSocket extends Socket
|
|
|
|
{
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void bind(SocketAddress bindpoint) throws IOException
|
|
|
|
{
|
|
|
|
InetSocketAddress localAddress = findFreeSocketAddress();
|
|
|
|
System.err.println("LocalBoundSocket NOT binding to " + bindpoint + ", using " + localAddress + " instead!");
|
|
|
|
super.bind(localAddress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|