Search in sources :

Example 96 with Element

use of de.pixart.messenger.xml.Element in project Pix-Art-Messenger by kriztan.

the class XmppConnectionService method sendPresence.

public void sendPresence(final Account account, final boolean includeIdleTimestamp) {
    Presence.Status status;
    if (manuallyChangePresence()) {
        status = account.getPresenceStatus();
    } else {
        status = getTargetPresence();
    }
    PresencePacket packet = mPresenceGenerator.selfPresence(account, status);
    String message = account.getPresenceStatusMessage();
    if (message != null && !message.isEmpty()) {
        packet.addChild(new Element("status").setContent(message));
    }
    if (mLastActivity > 0 && includeIdleTimestamp) {
        // don't send future dates
        long since = Math.min(mLastActivity, System.currentTimeMillis());
        packet.addChild("idle", Namespace.IDLE).setAttribute("since", AbstractGenerator.getTimestamp(since));
    }
    sendPresencePacket(account, packet);
}
Also used : Element(de.pixart.messenger.xml.Element) Presence(de.pixart.messenger.entities.Presence) PresencePacket(de.pixart.messenger.xmpp.stanzas.PresencePacket)

Example 97 with Element

use of de.pixart.messenger.xml.Element in project Pix-Art-Messenger by kriztan.

the class XmppConnection method processStream.

private void processStream() throws XmlPullParserException, IOException, NoSuchAlgorithmException {
    final CountDownLatch streamCountDownLatch = new CountDownLatch(1);
    this.mStreamCountDownLatch = streamCountDownLatch;
    Tag nextTag = tagReader.readTag();
    while (nextTag != null && !nextTag.isEnd("stream")) {
        if (nextTag.isStart("error")) {
            processStreamError(nextTag);
        } else if (nextTag.isStart("features")) {
            processStreamFeatures(nextTag);
        } else if (nextTag.isStart("proceed")) {
            switchOverToTls(nextTag);
        } else if (nextTag.isStart("success")) {
            final String challenge = tagReader.readElement(nextTag).getContent();
            try {
                saslMechanism.getResponse(challenge);
            } catch (final SaslMechanism.AuthenticationException e) {
                Log.e(Config.LOGTAG, String.valueOf(e));
                throw new StateChangingException(Account.State.UNAUTHORIZED);
            }
            Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": logged in");
            account.setKey(Account.PINNED_MECHANISM_KEY, String.valueOf(saslMechanism.getPriority()));
            tagReader.reset();
            sendStartStream();
            final Tag tag = tagReader.readTag();
            if (tag != null && tag.isStart("stream")) {
                processStream();
            } else {
                throw new IOException("server didn't restart stream after successful auth");
            }
            break;
        } else if (nextTag.isStart("failure")) {
            final Element failure = tagReader.readElement(nextTag);
            if (Namespace.SASL.equals(failure.getNamespace())) {
                final String text = failure.findChildContent("text");
                if (failure.hasChild("account-disabled") && text != null) {
                    Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(text);
                    if (matcher.find()) {
                        try {
                            URL url = new URL(text.substring(matcher.start(), matcher.end()));
                            if (url.getProtocol().equals("https")) {
                                this.redirectionUrl = url;
                                throw new StateChangingException(Account.State.PAYMENT_REQUIRED);
                            }
                        } catch (MalformedURLException e) {
                            throw new StateChangingException(Account.State.UNAUTHORIZED);
                        }
                    }
                }
                throw new StateChangingException(Account.State.UNAUTHORIZED);
            } else if (Namespace.TLS.equals(failure.getNamespace())) {
                throw new StateChangingException(Account.State.TLS_ERROR);
            } else {
                throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
            }
        } else if (nextTag.isStart("challenge")) {
            final String challenge = tagReader.readElement(nextTag).getContent();
            final Element response = new Element("response", Namespace.SASL);
            try {
                response.setContent(saslMechanism.getResponse(challenge));
            } catch (final SaslMechanism.AuthenticationException e) {
                // TODO: Send auth abort tag.
                Log.e(Config.LOGTAG, e.toString());
            }
            tagWriter.writeElement(response);
        } else if (nextTag.isStart("enabled")) {
            final Element enabled = tagReader.readElement(nextTag);
            if ("true".equals(enabled.getAttribute("resume"))) {
                this.streamId = enabled.getAttribute("id");
                Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": stream management(" + smVersion + ") enabled (resumable)");
            } else {
                Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": stream management(" + smVersion + ") enabled");
            }
            this.stanzasReceived = 0;
            this.inSmacksSession = true;
            final RequestPacket r = new RequestPacket(smVersion);
            tagWriter.writeStanzaAsync(r);
        } else if (nextTag.isStart("resumed")) {
            this.inSmacksSession = true;
            this.isBound = true;
            this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
            lastPacketReceived = SystemClock.elapsedRealtime();
            final Element resumed = tagReader.readElement(nextTag);
            final String h = resumed.getAttribute("h");
            try {
                ArrayList<AbstractAcknowledgeableStanza> failedStanzas = new ArrayList<>();
                synchronized (this.mStanzaQueue) {
                    final int serverCount = Integer.parseInt(h);
                    if (serverCount < stanzasSent) {
                        Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": session resumed with lost packages");
                        stanzasSent = serverCount;
                    } else {
                        Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": session resumed");
                    }
                    acknowledgeStanzaUpTo(serverCount);
                    for (int i = 0; i < this.mStanzaQueue.size(); ++i) {
                        failedStanzas.add(mStanzaQueue.valueAt(i));
                    }
                    mStanzaQueue.clear();
                }
                Log.d(Config.LOGTAG, "resending " + failedStanzas.size() + " stanzas");
                for (AbstractAcknowledgeableStanza packet : failedStanzas) {
                    if (packet instanceof MessagePacket) {
                        MessagePacket message = (MessagePacket) packet;
                        mXmppConnectionService.markMessage(account, message.getTo().toBareJid(), message.getId(), Message.STATUS_UNSEND);
                    }
                    sendPacket(packet);
                }
            } catch (final NumberFormatException ignored) {
            }
            Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": online with resource " + account.getResource());
            changeStatus(Account.State.ONLINE);
        } else if (nextTag.isStart("r")) {
            tagReader.readElement(nextTag);
            if (Config.EXTENDED_SM_LOGGING) {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": acknowledging stanza #" + this.stanzasReceived);
            }
            final AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
            tagWriter.writeStanzaAsync(ack);
        } else if (nextTag.isStart("a")) {
            boolean accountUiNeedsRefresh = false;
            synchronized (NotificationService.CATCHUP_LOCK) {
                if (mWaitingForSmCatchup.compareAndSet(true, false)) {
                    int count = mSmCatchupMessageCounter.get();
                    Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": SM catchup complete (" + count + ")");
                    accountUiNeedsRefresh = true;
                    if (count > 0) {
                        mXmppConnectionService.getNotificationService().finishBacklog(true, account);
                    }
                }
            }
            if (accountUiNeedsRefresh) {
                mXmppConnectionService.updateAccountUi();
            }
            final Element ack = tagReader.readElement(nextTag);
            lastPacketReceived = SystemClock.elapsedRealtime();
            try {
                synchronized (this.mStanzaQueue) {
                    final int serverSequence = Integer.parseInt(ack.getAttribute("h"));
                    acknowledgeStanzaUpTo(serverSequence);
                }
            } catch (NumberFormatException | NullPointerException e) {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server send ack without sequence number");
            }
        } else if (nextTag.isStart("failed")) {
            Element failed = tagReader.readElement(nextTag);
            try {
                final int serverCount = Integer.parseInt(failed.getAttribute("h"));
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed but server acknowledged stanza #" + serverCount);
                synchronized (this.mStanzaQueue) {
                    acknowledgeStanzaUpTo(serverCount);
                }
            } catch (NumberFormatException | NullPointerException e) {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed");
            }
            resetStreamId();
            sendBindRequest();
        } else if (nextTag.isStart("iq")) {
            processIq(nextTag);
        } else if (nextTag.isStart("message")) {
            processMessage(nextTag);
        } else if (nextTag.isStart("presence")) {
            processPresence(nextTag);
        }
        nextTag = tagReader.readTag();
    }
    if (nextTag != null && nextTag.isEnd("stream")) {
        streamCountDownLatch.countDown();
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) RequestPacket(de.pixart.messenger.xmpp.stanzas.streammgmt.RequestPacket) Matcher(java.util.regex.Matcher) Element(de.pixart.messenger.xml.Element) ArrayList(java.util.ArrayList) AckPacket(de.pixart.messenger.xmpp.stanzas.streammgmt.AckPacket) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) URL(java.net.URL) MessagePacket(de.pixart.messenger.xmpp.stanzas.MessagePacket) AbstractAcknowledgeableStanza(de.pixart.messenger.xmpp.stanzas.AbstractAcknowledgeableStanza) Tag(de.pixart.messenger.xml.Tag)

Example 98 with Element

use of de.pixart.messenger.xml.Element in project Pix-Art-Messenger by kriztan.

the class XmppConnection method authenticate.

private void authenticate() throws IOException {
    final List<String> mechanisms = extractMechanisms(streamFeatures.findChild("mechanisms"));
    final Element auth = new Element("auth", Namespace.SASL);
    if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) {
        saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG());
    } else if (mechanisms.contains("SCRAM-SHA-256")) {
        saslMechanism = new ScramSha256(tagWriter, account, mXmppConnectionService.getRNG());
    } else if (mechanisms.contains("SCRAM-SHA-1")) {
        saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
    } else if (mechanisms.contains("PLAIN") && !account.getJid().getDomainpart().equals("nimbuzz.com")) {
        saslMechanism = new Plain(tagWriter, account);
    } else if (mechanisms.contains("DIGEST-MD5")) {
        saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
    } else if (mechanisms.contains("ANONYMOUS")) {
        saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG());
    }
    if (saslMechanism != null) {
        final int pinnedMechanism = account.getKeyAsInt(Account.PINNED_MECHANISM_KEY, -1);
        if (pinnedMechanism > saslMechanism.getPriority()) {
            Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() + " has lower priority (" + String.valueOf(saslMechanism.getPriority()) + ") than pinned priority (" + pinnedMechanism + "). Possible downgrade attack?");
            throw new StateChangingException(Account.State.DOWNGRADE_ATTACK);
        }
        Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism());
        auth.setAttribute("mechanism", saslMechanism.getMechanism());
        if (!saslMechanism.getClientFirstMessage().isEmpty()) {
            auth.setContent(saslMechanism.getClientFirstMessage());
        }
        tagWriter.writeElement(auth);
    } else {
        throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
    }
}
Also used : ScramSha256(de.pixart.messenger.crypto.sasl.ScramSha256) Plain(de.pixart.messenger.crypto.sasl.Plain) DigestMd5(de.pixart.messenger.crypto.sasl.DigestMd5) Element(de.pixart.messenger.xml.Element) External(de.pixart.messenger.crypto.sasl.External) ScramSha1(de.pixart.messenger.crypto.sasl.ScramSha1) Anonymous(de.pixart.messenger.crypto.sasl.Anonymous)

Example 99 with Element

use of de.pixart.messenger.xml.Element in project Pix-Art-Messenger by kriztan.

the class XmppConnection method sendServiceDiscoveryItems.

private void sendServiceDiscoveryItems(final Jid server) {
    mPendingServiceDiscoveries.incrementAndGet();
    final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
    iq.setTo(server.toDomainJid());
    iq.query("http://jabber.org/protocol/disco#items");
    this.sendIqPacket(iq, new OnIqPacketReceived() {

        @Override
        public void onIqPacketReceived(final Account account, final IqPacket packet) {
            if (packet.getType() == IqPacket.TYPE.RESULT) {
                HashSet<Jid> items = new HashSet<Jid>();
                final List<Element> elements = packet.query().getChildren();
                for (final Element element : elements) {
                    if (element.getName().equals("item")) {
                        final Jid jid = element.getAttributeAsJid("jid");
                        if (jid != null && !jid.equals(account.getServer())) {
                            items.add(jid);
                        }
                    }
                }
                for (Jid jid : items) {
                    sendServiceDiscoveryInfo(jid);
                }
            } else {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco items of " + server);
            }
            if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
                if (mPendingServiceDiscoveries.decrementAndGet() == 0 && mWaitForDisco.compareAndSet(true, false)) {
                    finalizeBind();
                }
            }
        }
    });
}
Also used : Account(de.pixart.messenger.entities.Account) Jid(de.pixart.messenger.xmpp.jid.Jid) Element(de.pixart.messenger.xml.Element) List(java.util.List) ArrayList(java.util.ArrayList) IqPacket(de.pixart.messenger.xmpp.stanzas.IqPacket) HashSet(java.util.HashSet)

Example 100 with Element

use of de.pixart.messenger.xml.Element in project Pix-Art-Messenger by kriztan.

the class XmppConnection method processStreamError.

private void processStreamError(final Tag currentTag) throws XmlPullParserException, IOException {
    final Element streamError = tagReader.readElement(currentTag);
    if (streamError == null) {
        return;
    }
    if (streamError.hasChild("conflict")) {
        account.setResource(createNewResource());
        Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": switching resource due to conflict (" + account.getResource() + ")");
        throw new IOException();
    } else if (streamError.hasChild("host-unknown")) {
        throw new StateChangingException(Account.State.HOST_UNKNOWN);
    } else if (streamError.hasChild("policy-violation")) {
        throw new StateChangingException(Account.State.POLICY_VIOLATION);
    } else {
        Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": stream error " + streamError.toString());
        throw new StateChangingException(Account.State.STREAM_ERROR);
    }
}
Also used : Element(de.pixart.messenger.xml.Element) IOException(java.io.IOException)

Aggregations

Element (de.pixart.messenger.xml.Element)100 IqPacket (de.pixart.messenger.xmpp.stanzas.IqPacket)48 Account (de.pixart.messenger.entities.Account)23 Jid (de.pixart.messenger.xmpp.jid.Jid)19 OnIqPacketReceived (de.pixart.messenger.xmpp.OnIqPacketReceived)17 Contact (de.pixart.messenger.entities.Contact)9 MessagePacket (de.pixart.messenger.xmpp.stanzas.MessagePacket)8 ArrayList (java.util.ArrayList)7 Conversation (de.pixart.messenger.entities.Conversation)6 IOException (java.io.IOException)6 Data (de.pixart.messenger.xmpp.forms.Data)5 Avatar (de.pixart.messenger.xmpp.pep.Avatar)5 HashSet (java.util.HashSet)5 AxolotlService (de.pixart.messenger.crypto.axolotl.AxolotlService)4 MucOptions (de.pixart.messenger.entities.MucOptions)4 ECPublicKey (org.whispersystems.libsignal.ecc.ECPublicKey)4 PreKeyBundle (org.whispersystems.libsignal.state.PreKeyBundle)4 Pair (android.util.Pair)3 Bookmark (de.pixart.messenger.entities.Bookmark)3 Message (de.pixart.messenger.entities.Message)3