All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jivesoftware.smack.proxy.Socks4ProxySocketFactory Maven / Gradle / Ivy

/**
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jivesoftware.smack.proxy;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.SocketFactory;

/**
 * Socket factory for socks4 proxy
 * 
 * @author Atul Aggarwal
 */
public class Socks4ProxySocketFactory extends SocketFactory {
    private ProxyInfo proxy;

    public Socks4ProxySocketFactory(ProxyInfo proxy) {
        this.proxy = proxy;
    }

    public Socket createSocket(String host, int port) throws IOException,
            UnknownHostException {
        return socks4ProxifiedSocket(host, port);

    }

    public Socket createSocket(String host, int port, InetAddress localHost,
            int localPort) throws IOException, UnknownHostException {
        return socks4ProxifiedSocket(host, port);
    }

    public Socket createSocket(InetAddress host, int port) throws IOException {
        return socks4ProxifiedSocket(host.getHostAddress(), port);
    }

    public Socket createSocket(InetAddress address, int port,
            InetAddress localAddress, int localPort) throws IOException {
        return socks4ProxifiedSocket(address.getHostAddress(), port);

    }

    private Socket socks4ProxifiedSocket(String host, int port)
            throws IOException {
        Socket socket = null;
        InputStream in = null;
        OutputStream out = null;
        String proxy_host = proxy.getProxyAddress();
        int proxy_port = proxy.getProxyPort();
        String user = proxy.getProxyUsername();
        String passwd = proxy.getProxyPassword();

        try {
            socket = new Socket(proxy_host, proxy_port);
            in = socket.getInputStream();
            out = socket.getOutputStream();
            socket.setTcpNoDelay(true);

            byte[] buf = new byte[1024];
            int index = 0;

            /*
             * 1) CONNECT
             * 
             * The client connects to the SOCKS server and sends a CONNECT
             * request when it wants to establish a connection to an application
             * server. The client includes in the request packet the IP address
             * and the port number of the destination host, and userid, in the
             * following format.
             * 
             * +----+----+----+----+----+----+----+----+----+----+....+----+ |
             * VN | CD | DSTPORT | DSTIP | USERID |NULL|
             * +----+----+----+----+----+----+----+----+----+----+....+----+ #
             * of bytes: 1 1 2 4 variable 1
             * 
             * VN is the SOCKS protocol version number and should be 4. CD is
             * the SOCKS command code and should be 1 for CONNECT request. NULL
             * is a byte of all zero bits.
             */

            index = 0;
            buf[index++] = 4;
            buf[index++] = 1;

            buf[index++] = (byte) (port >>> 8);
            buf[index++] = (byte) (port & 0xff);

            try {
                InetAddress addr = InetAddress.getByName(host);
                byte[] byteAddress = addr.getAddress();
                for (int i = 0; i < byteAddress.length; i++) {
                    buf[index++] = byteAddress[i];
                }
            } catch (UnknownHostException uhe) {
                throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
                        uhe.toString(), uhe);
            }

            if (user != null) {
                System.arraycopy(user.getBytes(), 0, buf, index, user.length());
                index += user.length();
            }
            buf[index++] = 0;
            out.write(buf, 0, index);

            /*
             * The SOCKS server checks to see whether such a request should be
             * granted based on any combination of source IP address,
             * destination IP address, destination port number, the userid, and
             * information it may obtain by consulting IDENT, cf. RFC 1413. If
             * the request is granted, the SOCKS server makes a connection to
             * the specified port of the destination host. A reply packet is
             * sent to the client when this connection is established, or when
             * the request is rejected or the operation fails.
             * 
             * +----+----+----+----+----+----+----+----+ | VN | CD | DSTPORT |
             * DSTIP | +----+----+----+----+----+----+----+----+ # of bytes: 1 1
             * 2 4
             * 
             * VN is the version of the reply code and should be 0. CD is the
             * result code with one of the following values:
             * 
             * 90: request granted 91: request rejected or failed 92: request
             * rejected becasue SOCKS server cannot connect to identd on the
             * client 93: request rejected because the client program and identd
             * report different user-ids
             * 
             * The remaining fields are ignored.
             */

            int len = 6;
            int s = 0;
            while (s < len) {
                int i = in.read(buf, s, len - s);
                if (i <= 0) {
                    throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
                            "stream is closed");
                }
                s += i;
            }
            if (buf[0] != 0) {
                throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
                        "server returns VN " + buf[0]);
            }
            if (buf[1] != 90) {
                try {
                    socket.close();
                } catch (Exception eee) {
                }
                String message = "ProxySOCKS4: server returns CD " + buf[1];
                throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, message);
            }
            byte[] temp = new byte[2];
            in.read(temp, 0, 2);
            return socket;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            try {
                if (socket != null)
                    socket.close();
            } catch (Exception eee) {
            }
            throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, e.toString());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy