⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vpnudptunnel.java

📁 这是linux下ssl vpn的实现程序
💻 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 + -