Search in sources :

Example 1 with Resolver

use of eu.siacs.conversations.utils.Resolver in project Conversations by siacs.

the class DatabaseBackend method findResolverResult.

public synchronized Resolver.Result findResolverResult(String domain) {
    SQLiteDatabase db = this.getReadableDatabase();
    String where = Resolver.Result.DOMAIN + "=?";
    String[] whereArgs = { domain };
    final Cursor cursor = db.query(RESOLVER_RESULTS_TABLENAME, null, where, whereArgs, null, null, null);
    Resolver.Result result = null;
    if (cursor != null) {
        try {
            if (cursor.moveToFirst()) {
                result = Resolver.Result.fromCursor(cursor);
            }
        } catch (Exception e) {
            Log.d(Config.LOGTAG, "unable to find cached resolver result in database " + e.getMessage());
            return null;
        } finally {
            cursor.close();
        }
    }
    return result;
}
Also used : Resolver(eu.siacs.conversations.utils.Resolver) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Cursor(android.database.Cursor) JSONException(org.json.JSONException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException)

Example 2 with Resolver

use of eu.siacs.conversations.utils.Resolver in project Conversations by siacs.

the class XmppConnection method connect.

protected void connect() {
    if (mXmppConnectionService.areMessagesInitialized()) {
        mXmppConnectionService.resetSendingToWaiting(account);
    }
    Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": connecting");
    features.encryptionEnabled = false;
    inSmacksSession = false;
    isBound = false;
    this.attempt++;
    // will be set if user entered hostname is being used or hostname was verified with dnssec
    this.verifiedHostname = null;
    try {
        Socket localSocket;
        shouldAuthenticate = !account.isOptionSet(Account.OPTION_REGISTER);
        this.changeStatus(Account.State.CONNECTING);
        final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion();
        final boolean extended = mXmppConnectionService.showExtendedConnectionOptions();
        if (useTor) {
            String destination;
            if (account.getHostname().isEmpty() || account.isOnion()) {
                destination = account.getServer();
            } else {
                destination = account.getHostname();
                this.verifiedHostname = destination;
            }
            final int port = account.getPort();
            final boolean directTls = Resolver.useDirectTls(port);
            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor. directTls=" + directTls);
            localSocket = SocksSocketFactory.createSocketOverTor(destination, port);
            if (directTls) {
                localSocket = upgradeSocketToTls(localSocket);
                features.encryptionEnabled = true;
            }
            try {
                startXmpp(localSocket);
            } catch (InterruptedException e) {
                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream");
                return;
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        } else {
            final String domain = account.getServer();
            final List<Resolver.Result> results;
            final boolean hardcoded = extended && !account.getHostname().isEmpty();
            if (hardcoded) {
                results = Resolver.fromHardCoded(account.getHostname(), account.getPort());
            } else {
                results = Resolver.resolve(domain);
            }
            if (Thread.currentThread().isInterrupted()) {
                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
                return;
            }
            if (results.size() == 0) {
                Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": Resolver results were empty");
                return;
            }
            final Resolver.Result storedBackupResult;
            if (hardcoded) {
                storedBackupResult = null;
            } else {
                storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
                if (storedBackupResult != null && !results.contains(storedBackupResult)) {
                    results.add(storedBackupResult);
                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
                }
            }
            for (Iterator<Resolver.Result> iterator = results.iterator(); iterator.hasNext(); ) {
                final Resolver.Result result = iterator.next();
                if (Thread.currentThread().isInterrupted()) {
                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
                    return;
                }
                try {
                    // if tls is true, encryption is implied and must not be started
                    features.encryptionEnabled = result.isDirectTls();
                    verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null;
                    Log.d(Config.LOGTAG, "verified hostname " + verifiedHostname);
                    final InetSocketAddress addr;
                    if (result.getIp() != null) {
                        addr = new InetSocketAddress(result.getIp(), result.getPort());
                        Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": using values from resolver " + (result.getHostname() == null ? "" : result.getHostname().toString() + "/") + result.getIp().getHostAddress() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
                    } else {
                        addr = new InetSocketAddress(IDN.toASCII(result.getHostname().toString()), result.getPort());
                        Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": using values from resolver " + result.getHostname().toString() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
                    }
                    localSocket = new Socket();
                    localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
                    if (features.encryptionEnabled) {
                        localSocket = upgradeSocketToTls(localSocket);
                    }
                    localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
                    if (startXmpp(localSocket)) {
                        // reset to 0; once the connection is established we don’t want this
                        localSocket.setSoTimeout(0);
                        if (!hardcoded && !result.equals(storedBackupResult)) {
                            mXmppConnectionService.databaseBackend.saveResolverResult(domain, result);
                        }
                        // successfully connected to server that speaks xmpp
                        break;
                    } else {
                        FileBackend.close(localSocket);
                        throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
                    }
                } catch (final StateChangingException e) {
                    if (!iterator.hasNext()) {
                        throw e;
                    }
                } catch (InterruptedException e) {
                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream");
                    return;
                } catch (final Throwable e) {
                    Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage() + "(" + e.getClass().getName() + ")");
                    if (!iterator.hasNext()) {
                        throw new UnknownHostException();
                    }
                }
            }
        }
        processStream();
    } catch (final SecurityException e) {
        this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION);
    } catch (final StateChangingException e) {
        this.changeStatus(e.state);
    } catch (final UnknownHostException | ConnectException | SocksSocketFactory.HostNotFoundException e) {
        this.changeStatus(Account.State.SERVER_NOT_FOUND);
    } catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
        this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
    } catch (final IOException | XmlPullParserException e) {
        Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage());
        this.changeStatus(Account.State.OFFLINE);
        this.attempt = Math.max(0, this.attempt - 1);
    } finally {
        if (!Thread.currentThread().isInterrupted()) {
            forceCloseSocket();
        } else {
            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": not force closing socket because thread was interrupted");
        }
    }
}
Also used : Resolver(eu.siacs.conversations.utils.Resolver) UnknownHostException(java.net.UnknownHostException) InetSocketAddress(java.net.InetSocketAddress) IOException(java.io.IOException) SocksSocketFactory(eu.siacs.conversations.utils.SocksSocketFactory) KeyManagementException(java.security.KeyManagementException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ConnectException(java.net.ConnectException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) SSLPeerUnverifiedException(javax.net.ssl.SSLPeerUnverifiedException) ServiceDiscoveryResult(eu.siacs.conversations.entities.ServiceDiscoveryResult) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) SSLSocket(javax.net.ssl.SSLSocket) Socket(java.net.Socket) ConnectException(java.net.ConnectException)

Aggregations

Resolver (eu.siacs.conversations.utils.Resolver)2 IOException (java.io.IOException)2 Cursor (android.database.Cursor)1 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)1 ServiceDiscoveryResult (eu.siacs.conversations.entities.ServiceDiscoveryResult)1 SocksSocketFactory (eu.siacs.conversations.utils.SocksSocketFactory)1 ConnectException (java.net.ConnectException)1 InetSocketAddress (java.net.InetSocketAddress)1 Socket (java.net.Socket)1 UnknownHostException (java.net.UnknownHostException)1 KeyManagementException (java.security.KeyManagementException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 CertificateEncodingException (java.security.cert.CertificateEncodingException)1 CertificateException (java.security.cert.CertificateException)1 SSLPeerUnverifiedException (javax.net.ssl.SSLPeerUnverifiedException)1 SSLSocket (javax.net.ssl.SSLSocket)1 JSONException (org.json.JSONException)1 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)1 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)1