001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.jivesoftware.smackx.jingleold.nat;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.io.OutputStream;
023import java.net.DatagramPacket;
024import java.net.DatagramSocket;
025import java.net.InetAddress;
026import java.net.ServerSocket;
027import java.net.Socket;
028import java.util.logging.Level;
029import java.util.logging.Logger;
030
031/**
032 * A Simple and Experimental Bridge.
033 * It Creates a TCP Socket Listeners for Connections and forwards every packets received to an UDP Listener.
034 * And forwards every packets received in UDP Socket, to the TCP Client
035 */
036@SuppressWarnings("UnusedVariable")
037public class TcpUdpBridgeServer {
038
039    private static final Logger LOGGER = Logger.getLogger(TcpUdpBridgeServer.class.getName());
040
041    private String remoteTcpHost = null;
042    private String remoteUdpHost = null;
043    private int remoteTcpPort = -1;
044    private int remoteUdpPort = -1;
045    private int localUdpPort = -1;
046
047    private DatagramSocket localUdpSocket;
048    private Socket localTcpSocket;
049    private ServerSocket serverTcpSocket;
050
051    @SuppressWarnings("this-escape")
052    public TcpUdpBridgeServer(String remoteTcpHost, String remoteUdpHost, int remoteTcpPort, int remoteUdpPort) {
053        this.remoteTcpHost = remoteTcpHost;
054        this.remoteUdpHost = remoteUdpHost;
055        this.remoteTcpPort = remoteTcpPort;
056        this.remoteUdpPort = remoteUdpPort;
057
058        try {
059            serverTcpSocket = new ServerSocket(remoteTcpPort);
060            localUdpSocket = new DatagramSocket(0);
061            localUdpPort = localUdpSocket.getLocalPort();
062            LOGGER.fine("UDP: " + localUdpSocket.getLocalPort());
063        }
064        catch (IOException e) {
065            LOGGER.log(Level.WARNING, "exception", e);
066        }
067        startBridge();
068    }
069
070    public void startBridge() {
071
072        final Thread process = new Thread(new Runnable() {
073
074            @Override
075            public void run() {
076                try {
077                    OutputStream out = localTcpSocket.getOutputStream();
078
079                    while (true) {
080
081                        byte[] b = new byte[500];
082                        DatagramPacket p = new DatagramPacket(b, 500);
083
084                        localUdpSocket.receive(p);
085                        if (p.getLength() == 0) continue;
086
087                        LOGGER.fine("UDP Server Received and Sending to TCP Client:" + new String(p.getData(), 0, p.getLength(), "UTF-8"));
088
089                        out.write(p.getData(), 0, p.getLength());
090                        out.flush();
091                        LOGGER.fine("Server Flush");
092                    }
093
094                }
095                catch (IOException e) {
096                    LOGGER.log(Level.WARNING, "exception", e);
097                }
098            }
099
100        });
101
102        new Thread(new Runnable() {
103
104            @Override
105            public void run() {
106                try {
107
108                    localTcpSocket = serverTcpSocket.accept();
109                    process.start();
110                    InputStream in = localTcpSocket.getInputStream();
111                    InetAddress remoteHost = InetAddress.getByName(remoteUdpHost);
112
113                    while (true) {
114                        byte[] b = new byte[500];
115
116                        int s = in.read(b);
117                        // if (s == -1) continue;
118
119                        LOGGER.fine("TCP Server:" + new String(b, 0, s, "UTF-8"));
120
121                        DatagramPacket udpPacket = new DatagramPacket(b, s);
122
123                        udpPacket.setAddress(remoteHost);
124                        udpPacket.setPort(remoteUdpPort);
125
126                        localUdpSocket.send(udpPacket);
127
128                    }
129
130                }
131                catch (IOException e) {
132                    LOGGER.log(Level.WARNING, "exception", e);
133                }
134            }
135
136        }).start();
137    }
138
139    public Socket getLocalTcpSocket() {
140        return localTcpSocket;
141    }
142
143    public DatagramSocket getLocalUdpSocket() {
144        return localUdpSocket;
145    }
146}