📄 vpnudptunnel.java
字号:
/*
* SSL-Explorer
*
* Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package com.sslexplorer.vpn.base;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Vector;
import com.sslexplorer.vpn.util.IOStreamConnector;
import com.sslexplorer.vpn.util.IOStreamConnectorListener;
public class VPNUDPTunnel implements VPNTunnel {
Socket tunnel;
DatagramSocket socket;
String destinationHost;
int destinationPort;
IOStreamConnector tx;
IOStreamListener listener = new IOStreamListener();
Vector listeners;
IOStreamConnectorListener txListener;
IOStreamConnectorListener rxListener;
boolean listening;
int packetSize = 65536;
AbstractVPNClient vpn;
// DatagramOutputStream datagramOut = null;
int listeningPort;
VPNConnectionListener vpnConnectionListener;
/* DEBUG */org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(VPNUDPTunnel.class);
VPNUDPTunnel(VPNConnectionListener vpnConnectionListener, AbstractVPNClient vpn, int listeningPort, Socket tunnel,
DatagramSocket socket, String destinationHost, int destinationPort, IOStreamConnectorListener txListener,
IOStreamConnectorListener rxListener) {
this.listeningPort = listeningPort;
this.vpnConnectionListener = vpnConnectionListener;
this.tunnel = tunnel;
this.vpn = vpn;
this.destinationHost = destinationHost;
this.socket = socket;
this.destinationPort = destinationPort;
this.txListener = txListener;
this.rxListener = rxListener;
this.listeners = new Vector();
}
public String getDestinationHost() {
return destinationHost;
}
public int getDestinationPort() {
return destinationPort;
}
public String getClientHost() {
// TODO we do not know the client address and a packet has been received
// -
// is there a better way?
return socket.getLocalAddress() == null ? "localhost" : socket.getLocalAddress().getHostName();
}
public void addListener(VPNTunnelListener listener) {
if (listener != null)
listeners.addElement(listener);
}
public void start() throws IOException {
try {
if (tunnel == null) {
throw new IOException("No tunnel has been initialised.");
}
if (socket == null) {
throw new IOException("No UPD socket has been initialised.");
}
InputStream tunnelIn = tunnel.getInputStream();
OutputStream tunnelOut = tunnel.getOutputStream();
if (tunnelIn == null || tunnelOut == null) {
throw new IOException("Either the input or output tunnel streams could not be obtained.");
}
DataOutputStream datagramDataOutStream = new DataOutputStream(tunnelOut);
final DataInputStream datagramDataInStream = new DataInputStream(tunnelIn);
Thread tunnelInThread = new Thread() {
public void run() {
try {
int size = -1;
int read;
while (true) {
/* DEBUG */log.info("Waiting for source address / port from tunnel");
byte[] srcAddrBytes = new byte[4];
datagramDataInStream.read(srcAddrBytes);
InetAddress srcAddr = InetAddress.getByName(new Byte(srcAddrBytes[0]).intValue() + "."
+ new Byte(srcAddrBytes[1]).intValue() + "." + new Byte(srcAddrBytes[2]).intValue()
+ "." + new Byte(srcAddrBytes[3]).intValue());
int srcPort = datagramDataInStream.readInt();
int packetPort = datagramDataInStream.readInt();
/* DEBUG */log.info("Source is " + srcAddr + ":" + srcPort + " packet port:" + packetPort);
/* DEBUG */log.info("Waiting for packet size from tunnel");
size = datagramDataInStream.readInt();
/* DEBUG */log.info("Got packet size - expecting " + size + " bytes");
byte[] buf = new byte[size];
datagramDataInStream.readFully(buf);
DatagramPacket packet = new DatagramPacket(buf, size, srcAddr, srcPort);
/* DEBUG */log.info("Tunneling " + size + " UDP bytes to " + srcAddr + " / " + srcPort + " ["
/* DEBUG */ + new String(buf));
socket.send(packet);
listener.dataTransfered(buf, size);
if (rxListener != null) {
rxListener.dataTransfered(buf, size);
}
}
} catch (EOFException e) {
} catch (Exception e) {
/* DEBUG */log.error("Error reading tunnel.", e);
} finally {
listener.connectorClosed(null);
if (rxListener != null) {
rxListener.connectorClosed(null);
}
}
}
};
tunnelInThread.start();
for (int i = 0; i < listeners.size(); i++)
((VPNTunnelListener) listeners.elementAt(i)).started(this);
listening = true;
byte[] buffer = new byte[packetSize];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (listening) {
packet.setData(buffer);
packet.setLength(buffer.length);
/* DEBUG */log.info("Waiting for UDP packet");
socket.receive(packet);
/* DEBUG */log.info("Got UDP packet of " + packet.getLength());
InetAddress srcAddress = packet.getAddress();
int srcPort = packet.getPort();
/* DEBUG */log.info("Address is " + srcAddress + ":" + srcPort);
datagramDataOutStream.write(srcAddress.getAddress());
datagramDataOutStream.writeInt(srcPort);
datagramDataOutStream.writeInt(packet.getLength());
/* DEBUG */log.info("Writing UDP packet of " + packet.getLength() + " bytes back to the tunnel ["
/* DEBUG */+ new String(packet.getData(), 0, packet.getLength()));
datagramDataOutStream.write(packet.getData(), 0, packet.getLength());
/* DEBUG */log.info("Flushed");
datagramDataOutStream.flush();
listener.dataTransfered(buffer, packet.getLength());
if (rxListener != null) {
rxListener.dataTransfered(buffer, packet.getLength());
}
}
} catch (Throwable ex) {
/* DEBUG */log.error("Failed to start UDP tunnel.", ex);
throw new IOException("The tunnel failed to start: " + ex.getMessage());
} finally {
try {
/* DEBUG */log.info("Closing UDP socket");
socket.close();
} catch (Exception e) {
}
try {
/* DEBUG */log.info("Closing UDP tunnel");
tunnel.close();
} catch (Exception e) {
}
// if(datagramOut != null) {
// try {
// datagramOut.close();
// }
// catch(IOException ioe) {
// }
// }
listener.connectorClosed(null);
if (txListener != null) {
txListener.connectorClosed(null);
}
}
}
/**
* Stop's the tunnel from transfering data, closing the channel and the
* attached socket.
*/
public void stop() {
listening = false;
if (socket != null) {
socket.close();
}
if (tx != null && !tx.isClosed()) {
tx.close();
}
for (int i = 0; i < listeners.size(); i++)
((VPNTunnelListener) listeners.elementAt(i)).stopped(this);
}
class IOStreamListener implements IOStreamConnectorListener {
boolean hasStopped = false;
public synchronized void connectorClosed(IOStreamConnector connector) {
/* DEBUG */log.info("Connector closed");
socket.close();
try {
tunnel.close();
} catch (Exception ex1) {
}
if (!hasStopped) {
stop();
hasStopped = true;
}
}
public void dataTransfered(byte[] buffer, int count) {
for (int i = listeners.size() - 1; i >= 0; i--)
((VPNTunnelListener) listeners.elementAt(i)).dataTransferred(VPNUDPTunnel.this, buffer, count);
}
}
public VPNConnectionListener getVPNConnectionListener() {
return vpnConnectionListener;
}
// class DatagramOutputStream extends OutputStream {
//
// DatagramOutputStream() {
// }
//
// public void write(int b) throws IOException {
// write(new byte[] { (byte)b });
// }
//
// public void write(byte[] b, int off, int len) throws IOException {
// if(remoteAddress != null) {
// if(off > 0) {
// byte[] tmp = new byte[len];
// System.arraycopy(b, off, tmp, 0, len);
// b = tmp;
// }
// DatagramPacket packet = new DatagramPacket(b, len, remoteAddress,
// remotePort);
// /* DEBUG */ log.info("Tunneling " + len + " UDP bytes to " +
// remoteAddress
// + " / " + remotePort + " [" + new String(b, off,len) );
// socket.send(packet);
// }
// else {
// /* DEBUG */ log.warn("The remote address is not yet known. UDP packets
// have
// been dropped.");
// }
// }
//
// public void write(byte[] b) throws IOException {
// write(b, 0, b.length);
// }
//
// public void close() throws IOException {
// if(socket != null) {
// socket.close();
// }
// }
// }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -