Search in sources :

Example 1 with VirtualChannelSelector

use of com.biglybt.core.networkmanager.VirtualChannelSelector in project BiglyBT by BiglySoftware.

the class NetworkAdminHTTPProxyImpl method getDetails.

@Override
public Details getDetails() throws NetworkAdminException {
    final int RES_CONNECT_FAILED = 0;
    final int RES_PROXY_FAILED = 1;
    final int RES_OK = 3;
    final AESemaphore sem = new AESemaphore("NetworkAdminSocksProxy:test");
    final int[] result = { RES_CONNECT_FAILED };
    final NetworkAdminException[] error = { null };
    final ProxyDetails[] details = { null };
    try {
        InetSocketAddress socks_address = new InetSocketAddress(InetAddress.getByName(http_host), Integer.parseInt(http_port));
        final InetSocketAddress target_address = new InetSocketAddress(TARGET_HOST, TARGET_PORT);
        TCPConnectionManager.ConnectListener connect_listener = new TCPConnectionManager.ConnectListener() {

            @Override
            public int connectAttemptStarted(int default_connect_timeout) {
                return (default_connect_timeout);
            }

            @Override
            public void connectSuccess(SocketChannel channel) {
                final TCPTransportImpl transport = new TCPTransportImpl((ProtocolEndpointTCP) ProtocolEndpointFactory.createEndpoint(ProtocolEndpoint.PROTOCOL_TCP, target_address), false, false, null);
                transport.setFilter(TCPTransportHelperFilterFactory.createTransparentFilter(channel));
                final long start_time = SystemTime.getCurrentTime();
                try {
                    String get_str = VersionCheckClient.getSingleton().getHTTPGetString(true, false);
                    ByteBuffer request = ByteBuffer.wrap(get_str.getBytes());
                    while (request.hasRemaining()) {
                        if (transport.write(new ByteBuffer[] { request }, 0, 1) < 1) {
                            if (SystemTime.getCurrentTime() - start_time > 30 * 1000) {
                                String error = "proxy handshake message send timed out after 30sec";
                                Debug.out(error);
                                throw new IOException(error);
                            }
                            try {
                                Thread.sleep(50);
                            } catch (Throwable t) {
                                t.printStackTrace();
                            }
                        }
                    }
                    TCPNetworkManager.getSingleton().getReadSelector().register(transport.getSocketChannel(), new VirtualChannelSelector.VirtualSelectorListener() {

                        private final byte[] reply_buffer = new byte[8192];

                        private final ByteBuffer reply = ByteBuffer.wrap(reply_buffer);

                        @Override
                        public boolean selectSuccess(VirtualChannelSelector selector, SocketChannel sc, Object attachment) {
                            try {
                                if (SystemTime.getCurrentTime() - start_time > 30 * 1000) {
                                    throw (new Exception("Timeout"));
                                }
                                long len = transport.read(new ByteBuffer[] { reply }, 0, 1);
                                if (len <= 0) {
                                    return (false);
                                }
                                String str = new String(reply_buffer, 0, reply.position());
                                if (str.contains(NL + NL)) {
                                    System.out.println(str);
                                    String server_name = "unknown";
                                    String auth = "none";
                                    String response = "unknown";
                                    StringTokenizer tok = new StringTokenizer(str, "\n");
                                    int line_num = 0;
                                    while (tok.hasMoreTokens()) {
                                        String token = tok.nextToken().trim();
                                        if (token.length() == 0) {
                                            continue;
                                        }
                                        line_num++;
                                        if (line_num == 1) {
                                            int pos = token.indexOf(' ');
                                            if (pos != -1) {
                                                response = token.substring(pos + 1).trim();
                                            }
                                        } else {
                                            int pos = token.indexOf(':');
                                            if (pos != -1) {
                                                String lhs = token.substring(0, pos).trim().toLowerCase(MessageText.LOCALE_ENGLISH);
                                                String rhs = token.substring(pos + 1).trim();
                                                if (lhs.equals("server")) {
                                                    if (!response.startsWith("200")) {
                                                        server_name = rhs;
                                                    }
                                                } else if (lhs.equals("via")) {
                                                    server_name = rhs;
                                                    int p = server_name.indexOf(' ');
                                                    if (p != -1) {
                                                        server_name = server_name.substring(p + 1).trim();
                                                    }
                                                } else if (lhs.equals("proxy-authenticate")) {
                                                    auth = rhs;
                                                }
                                            }
                                        }
                                    }
                                    details[0] = new ProxyDetails(server_name, response, auth);
                                    transport.close("Done");
                                    result[0] = RES_OK;
                                    sem.release();
                                } else {
                                    TCPNetworkManager.getSingleton().getReadSelector().resumeSelects(transport.getSocketChannel());
                                }
                                return (true);
                            } catch (Throwable t) {
                                return false;
                            }
                        }

                        @Override
                        public void selectFailure(VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) {
                            result[0] = RES_PROXY_FAILED;
                            error[0] = new NetworkAdminException("Proxy error", msg);
                            transport.close("Proxy error");
                            sem.release();
                        }
                    }, null);
                } catch (Throwable t) {
                    result[0] = RES_PROXY_FAILED;
                    error[0] = new NetworkAdminException("Proxy connect failed", t);
                    sem.release();
                }
            }

            @Override
            public void connectFailure(Throwable failure_msg) {
                result[0] = RES_CONNECT_FAILED;
                error[0] = new NetworkAdminException("Connect failed", failure_msg);
                sem.release();
            }
        };
        TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection(socks_address, connect_listener, ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM);
    } catch (Throwable e) {
        result[0] = RES_CONNECT_FAILED;
        error[0] = new NetworkAdminException("Connect failed", e);
        sem.release();
    }
    if (!sem.reserve(10000)) {
        result[0] = RES_CONNECT_FAILED;
        error[0] = new NetworkAdminException("Connect timeout");
    }
    if (result[0] == RES_OK) {
        return (details[0]);
    }
    throw (error[0]);
}
Also used : SocketChannel(java.nio.channels.SocketChannel) InetSocketAddress(java.net.InetSocketAddress) AESemaphore(com.biglybt.core.util.AESemaphore) VirtualChannelSelector(com.biglybt.core.networkmanager.VirtualChannelSelector) NetworkAdminException(com.biglybt.core.networkmanager.admin.NetworkAdminException) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) ProtocolEndpoint(com.biglybt.core.networkmanager.ProtocolEndpoint) NetworkAdminException(com.biglybt.core.networkmanager.admin.NetworkAdminException) IOException(java.io.IOException) StringTokenizer(java.util.StringTokenizer)

Example 2 with VirtualChannelSelector

use of com.biglybt.core.networkmanager.VirtualChannelSelector in project BiglyBT by BiglySoftware.

the class ProxyLoginHandler method doSocks5Login.

private void doSocks5Login() {
    try {
        final ArrayList data = new ArrayList(2);
        ByteBuffer[] header = createSocks5Message();
        // message
        data.add(header[0]);
        // reply buff
        data.add(header[1]);
        // send initial handshake to get things started
        sendMessage((ByteBuffer) data.get(0));
        // register for read ops
        TCPNetworkManager.getSingleton().getReadSelector().register(proxy_connection.getSocketChannel(), new VirtualChannelSelector.VirtualSelectorListener() {

            @Override
            public boolean selectSuccess(VirtualChannelSelector selector, SocketChannel sc, Object attachment) {
                try {
                    int result = readMessage((ByteBuffer) data.get(1));
                    if (result == READ_DONE) {
                        // will throw exception on error
                        boolean done = parseSocks5Reply((ByteBuffer) data.get(1));
                        if (done) {
                            TCPNetworkManager.getSingleton().getReadSelector().cancel(proxy_connection.getSocketChannel());
                            proxy_listener.connectSuccess();
                        } else {
                            ByteBuffer[] raw = createSocks5Message();
                            data.set(0, raw[0]);
                            data.set(1, raw[1]);
                            if (raw[0] != null)
                                sendMessage(raw[0]);
                            // resume read ops
                            TCPNetworkManager.getSingleton().getReadSelector().resumeSelects(proxy_connection.getSocketChannel());
                        }
                    } else {
                        // resume read ops
                        TCPNetworkManager.getSingleton().getReadSelector().resumeSelects(proxy_connection.getSocketChannel());
                    }
                    return (result != READ_NO_PROGRESS);
                } catch (Throwable t) {
                    // Debug.out( t );
                    TCPNetworkManager.getSingleton().getReadSelector().cancel(proxy_connection.getSocketChannel());
                    proxy_listener.connectFailure(t);
                    return false;
                }
            }

            @Override
            public void selectFailure(VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) {
                // Debug.out( msg );
                TCPNetworkManager.getSingleton().getReadSelector().cancel(proxy_connection.getSocketChannel());
                proxy_listener.connectFailure(msg);
            }
        }, null);
    } catch (Throwable t) {
        // Debug.out( t );
        SocketChannel chan = proxy_connection.getSocketChannel();
        if (chan != null) {
            TCPNetworkManager.getSingleton().getReadSelector().cancel(chan);
        }
        proxy_listener.connectFailure(t);
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) VirtualChannelSelector(com.biglybt.core.networkmanager.VirtualChannelSelector) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer)

Example 3 with VirtualChannelSelector

use of com.biglybt.core.networkmanager.VirtualChannelSelector in project BiglyBT by BiglySoftware.

the class TCPConnectionManager method addNewRequest.

private void addNewRequest(final ConnectionRequest request) {
    request.setConnectTimeout(request.listener.connectAttemptStarted(request.getConnectTimeout()));
    boolean ipv6problem = false;
    boolean bind_failed = false;
    try {
        request.channel = SocketChannel.open();
        InetAddress bindIP = null;
        try {
            // advanced socket options
            if (rcv_size > 0) {
                if (Logger.isEnabled())
                    Logger.log(new LogEvent(LOGID, "Setting socket receive buffer size" + " for outgoing connection [" + request.address + "] to: " + rcv_size));
                request.channel.socket().setReceiveBufferSize(rcv_size);
            }
            if (snd_size > 0) {
                if (Logger.isEnabled())
                    Logger.log(new LogEvent(LOGID, "Setting socket send buffer size " + "for outgoing connection [" + request.address + "] to: " + snd_size));
                request.channel.socket().setSendBufferSize(snd_size);
            }
            if (ip_tos.length() > 0) {
                if (Logger.isEnabled())
                    Logger.log(new LogEvent(LOGID, "Setting socket TOS field " + "for outgoing connection [" + request.address + "] to: " + ip_tos));
                request.channel.socket().setTrafficClass(Integer.decode(ip_tos).intValue());
            }
            if (local_bind_port > 0) {
                request.channel.socket().setReuseAddress(true);
            }
            try {
                bindIP = NetworkAdmin.getSingleton().getMultiHomedOutgoingRoundRobinBindAddress(request.address.getAddress());
                if (bindIP != null) {
                    if (bindIP.isAnyLocalAddress() || !AEProxyFactory.isPluginProxy(request.address)) {
                        if (Logger.isEnabled())
                            Logger.log(new LogEvent(LOGID, "Binding outgoing connection [" + request.address + "] to local IP address: " + bindIP + ":" + local_bind_port));
                        request.channel.socket().bind(new InetSocketAddress(bindIP, local_bind_port));
                    }
                } else if (local_bind_port > 0) {
                    if (Logger.isEnabled())
                        Logger.log(new LogEvent(LOGID, "Binding outgoing connection [" + request.address + "] to local port #: " + local_bind_port));
                    request.channel.socket().bind(new InetSocketAddress(local_bind_port));
                }
            } catch (SocketException e) {
                bind_failed = true;
                String msg = e.getMessage().toLowerCase();
                if ((msg.contains("address family not supported by protocol family") || msg.contains("protocol family unavailable")) && !NetworkAdmin.getSingleton().hasIPV6Potential(true)) {
                    ipv6problem = true;
                }
                throw e;
            }
        } catch (Throwable t) {
            if (bind_failed && NetworkAdmin.getSingleton().mustBind()) {
                throw (t);
            } else if (!ipv6problem) {
                // dont pass the exception outwards, so we will continue processing connection without advanced options set
                String msg = "Error while processing advanced socket options (rcv=" + rcv_size + ", snd=" + snd_size + ", tos=" + ip_tos + ", port=" + local_bind_port + ", bind=" + bindIP + ")";
                // Debug.out( msg, t );
                Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, t));
            } else {
                throw (t);
            }
        }
        request.channel.configureBlocking(false);
        request.connect_start_time = SystemTime.getMonotonousTime();
        if (request.channel.connect(request.address)) {
            // already connected
            finishConnect(request);
        } else {
            try {
                new_canceled_mon.enter();
                pending_attempts.put(request, null);
            } finally {
                new_canceled_mon.exit();
            }
            connect_selector.register(request.channel, new VirtualChannelSelector.VirtualSelectorListener() {

                @Override
                public boolean selectSuccess(VirtualChannelSelector selector, SocketChannel sc, Object attachment) {
                    try {
                        new_canceled_mon.enter();
                        pending_attempts.remove(request);
                    } finally {
                        new_canceled_mon.exit();
                    }
                    finishConnect(request);
                    return true;
                }

                @Override
                public void selectFailure(VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) {
                    try {
                        new_canceled_mon.enter();
                        pending_attempts.remove(request);
                    } finally {
                        new_canceled_mon.exit();
                    }
                    closeConnection(request.channel);
                    request.listener.connectFailure(msg);
                }
            }, null);
        }
    } catch (Throwable t) {
        String full = request.address.toString();
        String hostname = request.address.getHostName();
        int port = request.address.getPort();
        boolean unresolved = request.address.isUnresolved();
        InetAddress inet_address = request.address.getAddress();
        String full_sub = inet_address == null ? request.address.toString() : inet_address.toString();
        String host_address = inet_address == null ? request.address.toString() : inet_address.getHostAddress();
        String msg = "ConnectDisconnectManager::address exception: full=" + full + ", hostname=" + hostname + ", port=" + port + ", unresolved=" + unresolved + ", full_sub=" + full_sub + ", host_address=" + host_address;
        if (request.channel != null) {
            String channel = request.channel.toString();
            Socket socket = request.channel.socket();
            String socket_string = socket.toString();
            InetAddress local_address = socket.getLocalAddress();
            String local_address_string = local_address == null ? "<null>" : local_address.toString();
            int local_port = socket.getLocalPort();
            SocketAddress ra = socket.getRemoteSocketAddress();
            String remote_address;
            if (ra != null)
                remote_address = ra.toString();
            else
                remote_address = "<null>";
            int remote_port = socket.getPort();
            msg += "\n channel=" + channel + ", socket=" + socket_string + ", local_address=" + local_address_string + ", local_port=" + local_port + ", remote_address=" + remote_address + ", remote_port=" + remote_port;
        } else {
            msg += "\n channel=<null>";
        }
        if (ipv6problem || t instanceof UnresolvedAddressException || t instanceof NoRouteToHostException) {
            Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, msg));
        } else {
            Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, msg, t));
        }
        if (request.channel != null) {
            closeConnection(request.channel);
        }
        request.listener.connectFailure(t);
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) LogEvent(com.biglybt.core.logging.LogEvent) LogAlert(com.biglybt.core.logging.LogAlert) VirtualChannelSelector(com.biglybt.core.networkmanager.VirtualChannelSelector) UnresolvedAddressException(java.nio.channels.UnresolvedAddressException)

Aggregations

VirtualChannelSelector (com.biglybt.core.networkmanager.VirtualChannelSelector)3 SocketChannel (java.nio.channels.SocketChannel)3 ByteBuffer (java.nio.ByteBuffer)2 LogAlert (com.biglybt.core.logging.LogAlert)1 LogEvent (com.biglybt.core.logging.LogEvent)1 ProtocolEndpoint (com.biglybt.core.networkmanager.ProtocolEndpoint)1 NetworkAdminException (com.biglybt.core.networkmanager.admin.NetworkAdminException)1 AESemaphore (com.biglybt.core.util.AESemaphore)1 IOException (java.io.IOException)1 InetSocketAddress (java.net.InetSocketAddress)1 UnresolvedAddressException (java.nio.channels.UnresolvedAddressException)1 ArrayList (java.util.ArrayList)1 StringTokenizer (java.util.StringTokenizer)1