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.jingle.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.Logger;
029
030/**
031 * A Simple and Experimental Bridge.
032 * It Creates a TCP Socket Listeners for Connections and forwards every packets received to an UDP Listener.
033 * And forwards every packets received in UDP Socket, to the TCP Client
034 */
035public class TcpUdpBridgeServer {
036
037        private static final Logger LOGGER = Logger.getLogger(TcpUdpBridgeServer.class.getName());
038
039        private String remoteTcpHost = null;
040    private String remoteUdpHost = null;
041    private int remoteTcpPort = -1;
042    private int remoteUdpPort = -1;
043    private int localUdpPort = -1;
044
045    private DatagramSocket localUdpSocket;
046    private Socket localTcpSocket;
047    private ServerSocket serverTcpSocket;
048
049    public TcpUdpBridgeServer(String remoteTcpHost, String remoteUdpHost, int remoteTcpPort, int remoteUdpPort) {
050        this.remoteTcpHost = remoteTcpHost;
051        this.remoteUdpHost = remoteUdpHost;
052        this.remoteTcpPort = remoteTcpPort;
053        this.remoteUdpPort = remoteUdpPort;
054
055        try {
056            serverTcpSocket = new ServerSocket(remoteTcpPort);
057            localUdpSocket = new DatagramSocket(0);
058            localUdpPort = localUdpSocket.getLocalPort();
059            LOGGER.fine("UDP: " + localUdpSocket.getLocalPort());
060        }
061        catch (IOException e) {
062            e.printStackTrace();
063        }
064        startBridge();
065    }
066
067    public void startBridge() {
068
069        final Thread process = new Thread(new Runnable() {
070
071            public void run() {
072                try {
073                    OutputStream out = localTcpSocket.getOutputStream();
074
075                    while (true) {
076
077                        byte b[] = new byte[500];
078                        DatagramPacket p = new DatagramPacket(b, 500);
079
080                        localUdpSocket.receive(p);
081                        if (p.getLength() == 0) continue;
082
083                        LOGGER.fine("UDP Server Received and Sending to TCP Client:" + new String(p.getData(), 0, p.getLength(), "UTF-8"));
084
085                        out.write(p.getData(), 0, p.getLength());
086                        out.flush();
087                        LOGGER.fine("Server Flush");
088                    }
089
090                }
091                catch (IOException e) {
092                    e.printStackTrace();
093                }
094            }
095
096        });
097
098        new Thread(new Runnable() {
099
100            public void run() {
101                try {
102
103                    localTcpSocket = serverTcpSocket.accept();
104                    process.start();
105                    InputStream in = localTcpSocket.getInputStream();
106                    InetAddress remoteHost = InetAddress.getByName(remoteUdpHost);
107
108                    while (true) {
109                        byte b[] = new byte[500];
110
111                        int s = in.read(b);
112                        //if (s == -1) continue;
113
114                        LOGGER.fine("TCP Server:" + new String(b, 0, s, "UTF-8"));
115
116                        DatagramPacket udpPacket = new DatagramPacket(b, s);
117
118                        udpPacket.setAddress(remoteHost);
119                        udpPacket.setPort(remoteUdpPort);
120
121                        localUdpSocket.send(udpPacket);
122
123                    }
124
125                }
126                catch (IOException e) {
127                    e.printStackTrace();
128                }
129            }
130
131        }).start();
132    }
133
134    public Socket getLocalTcpSocket() {
135        return localTcpSocket;
136    }
137
138    public DatagramSocket getLocalUdpSocket() {
139        return localUdpSocket;
140    }
141}