Search in sources :

Example 61 with Stanza

use of org.jivesoftware.smack.packet.Stanza in project xabber-android by redsolution.

the class AbstractChat method sendMessage.

@SuppressWarnings("WeakerAccess")
boolean sendMessage(MessageItem messageItem) {
    String text = prepareText(messageItem.getText());
    messageItem.setEncrypted(OTRManager.getInstance().isEncrypted(text));
    Long timestamp = messageItem.getTimestamp();
    Date currentTime = new Date(System.currentTimeMillis());
    Date delayTimestamp = null;
    if (timestamp != null) {
        if (currentTime.getTime() - timestamp > 60000) {
            delayTimestamp = currentTime;
        }
    }
    Message message = null;
    if (messageItem.haveAttachments()) {
        message = createFileMessagePacket(messageItem.getStanzaId(), messageItem.getAttachments(), text);
    } else if (messageItem.haveForwardedMessages()) {
        Realm realm = MessageDatabaseManager.getInstance().getNewBackgroundRealm();
        RealmResults<MessageItem> items = realm.where(MessageItem.class).in(MessageItem.Fields.UNIQUE_ID, messageItem.getForwardedIdsAsArray()).findAll();
        List<ReferenceElement> references = new ArrayList<>();
        StringBuilder builder = new StringBuilder();
        if (items != null && !items.isEmpty()) {
            for (MessageItem item : items) {
                String forward = ClipManager.createMessageTree(realm, item.getUniqueId()) + "\n";
                int begin = getSizeOfEncodedChars(builder.toString());
                builder.append(forward);
                ReferenceElement reference = ReferencesManager.createForwardReference(item, begin, getSizeOfEncodedChars(builder.toString()) - 1);
                references.add(reference);
            }
        }
        builder.append(text);
        text = builder.toString();
        message = createMessagePacket(text, messageItem.getStanzaId());
        for (ReferenceElement element : references) {
            message.addExtension(element);
        }
    } else if (text != null) {
        message = createMessagePacket(text, messageItem.getStanzaId());
    }
    if (message != null) {
        ChatStateManager.getInstance().updateOutgoingMessage(AbstractChat.this, message);
        CarbonManager.getInstance().updateOutgoingMessage(AbstractChat.this, message);
        message.addExtension(new OriginIdElement(messageItem.getStanzaId()));
        if (delayTimestamp != null) {
            message.addExtension(new DelayInformation(delayTimestamp));
        }
        final String messageId = messageItem.getUniqueId();
        try {
            StanzaSender.sendStanza(account, message, new StanzaListener() {

                @Override
                public void processStanza(Stanza packet) throws SmackException.NotConnectedException {
                    Realm realm = MessageDatabaseManager.getInstance().getNewBackgroundRealm();
                    realm.executeTransaction(new Realm.Transaction() {

                        @Override
                        public void execute(Realm realm) {
                            MessageItem acknowledgedMessage = realm.where(MessageItem.class).equalTo(MessageItem.Fields.UNIQUE_ID, messageId).findFirst();
                            if (acknowledgedMessage != null) {
                                acknowledgedMessage.setAcknowledged(true);
                            }
                        }
                    });
                    realm.close();
                }
            });
        } catch (NetworkException e) {
            return false;
        }
    }
    if (message == null) {
        messageItem.setError(true);
        messageItem.setErrorDescription("Internal error: message is null");
    } else {
        message.setFrom(account.getFullJid());
        messageItem.setOriginalStanza(message.toXML().toString());
    }
    if (delayTimestamp != null) {
        messageItem.setDelayTimestamp(delayTimestamp.getTime());
    }
    if (messageItem.getTimestamp() == null) {
        messageItem.setTimestamp(currentTime.getTime());
    }
    messageItem.setSent(true);
    return true;
}
Also used : MessageItem(com.xabber.android.data.database.messagerealm.MessageItem) Message(org.jivesoftware.smack.packet.Message) Stanza(org.jivesoftware.smack.packet.Stanza) StanzaListener(org.jivesoftware.smack.StanzaListener) Date(java.util.Date) DelayInformation(org.jivesoftware.smackx.delay.packet.DelayInformation) ReferenceElement(com.xabber.android.data.extension.references.ReferenceElement) List(java.util.List) RealmList(io.realm.RealmList) ArrayList(java.util.ArrayList) OriginIdElement(com.xabber.xmpp.sid.OriginIdElement) Realm(io.realm.Realm) NetworkException(com.xabber.android.data.NetworkException) RealmResults(io.realm.RealmResults)

Example 62 with Stanza

use of org.jivesoftware.smack.packet.Stanza in project xabber-android by redsolution.

the class XMPPTCPConnection method loginInternal.

@Override
protected synchronized void loginInternal(String username, String password, Resourcepart resource) throws XMPPException, SmackException, IOException, InterruptedException {
    // Authenticate using SASL
    SSLSession sslSession = secureSocket != null ? secureSocket.getSession() : null;
    saslAuthentication.authenticate(username, password, config.getAuthzid(), sslSession);
    // If compression is enabled then request the server to use stream compression. XEP-170
    // recommends to perform stream compression before resource binding.
    maybeEnableCompression();
    if (isSmResumptionPossible()) {
        smResumedSyncPoint.sendAndWaitForResponse(new Resume(clientHandledStanzasCount, smSessionId));
        if (smResumedSyncPoint.wasSuccessful()) {
            // We successfully resumed the stream, be done here
            afterSuccessfulLogin(true);
            return;
        }
        // SM resumption failed, what Smack does here is to report success of
        // lastFeaturesReceived in case of sm resumption was answered with 'failed' so that
        // normal resource binding can be tried.
        LOGGER.fine("Stream resumption failed, continuing with normal stream establishment process");
    }
    List<Stanza> previouslyUnackedStanzas = new LinkedList<Stanza>();
    if (unacknowledgedStanzas != null) {
        // There was a previous connection with SM enabled but that was either not resumable or
        // failed to resume. Make sure that we (re-)send the unacknowledged stanzas.
        unacknowledgedStanzas.drainTo(previouslyUnackedStanzas);
        // Reset unacknowledged stanzas to 'null' to signal that we never send 'enable' in this
        // XMPP session (There maybe was an enabled in a previous XMPP session of this
        // connection instance though). This is used in writePackets to decide if stanzas should
        // be added to the unacknowledged stanzas queue, because they have to be added right
        // after the 'enable' stream element has been sent.
        dropSmState();
    }
    // X-TOKEN
    Mechanisms mechanisms = getFeature(Mechanisms.ELEMENT, Mechanisms.NAMESPACE);
    List<String> mechanismsList = mechanisms.getMechanisms();
    if (mechanismsList.contains(SASLXTOKENMechanism.NAME) && !getUsedSaslMechansism().equals(SASLXTOKENMechanism.NAME)) {
        XTokenManager.getInstance().sendXTokenRequest(this);
    }
    // Now bind the resource. It is important to do this *after* we dropped an eventually
    // existing Stream Management state. As otherwise <bind/> and <session/> may end up in
    // unacknowledgedStanzas and become duplicated on reconnect. See SMACK-706.
    bindResourceAndEstablishSession(resource);
    if (isSmAvailable() && useSm) {
        // Remove what is maybe left from previously stream managed sessions
        serverHandledStanzasCount = 0;
        // XEP-198 3. Enabling Stream Management. If the server response to 'Enable' is 'Failed'
        // then this is a non recoverable error and we therefore throw an exception.
        smEnabledSyncPoint.sendAndWaitForResponseOrThrow(new Enable(useSmResumption, smClientMaxResumptionTime));
        synchronized (requestAckPredicates) {
            if (requestAckPredicates.isEmpty()) {
                // Assure that we have at lest one predicate set up that so that we request acks
                // for the server and eventually flush some stanzas from the unacknowledged
                // stanza queue
                requestAckPredicates.add(Predicate.forMessagesOrAfter5Stanzas());
            }
        }
    }
    // (Re-)send the stanzas *after* we tried to enable SM
    for (Stanza stanza : previouslyUnackedStanzas) {
        sendStanzaInternal(stanza);
    }
    afterSuccessfulLogin(false);
}
Also used : Mechanisms(org.jivesoftware.smack.packet.Mechanisms) Stanza(org.jivesoftware.smack.packet.Stanza) SSLSession(javax.net.ssl.SSLSession) Enable(org.jivesoftware.smack.sm.packet.StreamManagement.Enable) LinkedList(java.util.LinkedList) Resume(org.jivesoftware.smack.sm.packet.StreamManagement.Resume)

Example 63 with Stanza

use of org.jivesoftware.smack.packet.Stanza in project Smack by igniterealtime.

the class Socks5BytestreamManager method establishSession.

/**
 * Establishes a SOCKS5 Bytestream with the given user using the given session ID and returns
 * the Socket to send/receive data to/from the user.
 *
 * @param targetJID the JID of the user a SOCKS5 Bytestream should be established
 * @param sessionID the session ID for the SOCKS5 Bytestream request
 * @return the Socket to send/receive data to/from the user
 * @throws IOException if the bytestream could not be established
 * @throws InterruptedException if the current thread was interrupted while waiting
 * @throws XMPPException if an XMPP protocol error was received.
 * @throws NotConnectedException if the XMPP connection is not connected.
 * @throws NoResponseException if there was no response from the remote entity.
 * @throws SmackMessageException if there was an error.
 * @throws FeatureNotSupportedException if a requested feature is not supported by the remote entity.
 */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID) throws IOException, InterruptedException, XMPPException, NoResponseException, NotConnectedException, SmackMessageException, FeatureNotSupportedException {
    XMPPConnection connection = connection();
    XMPPErrorException discoveryException = null;
    // check if target supports SOCKS5 Bytestream
    if (!supportsSocks5(targetJID)) {
        throw new FeatureNotSupportedException("SOCKS5 Bytestream", targetJID);
    }
    List<Jid> proxies = new ArrayList<>();
    // determine SOCKS5 proxies from XMPP-server
    try {
        proxies.addAll(determineProxies());
    } catch (XMPPErrorException e) {
        // don't abort here, just remember the exception thrown by determineProxies()
        // determineStreamHostInfos() will at least add the local Socks5 proxy (if enabled)
        discoveryException = e;
    }
    // determine address and port of each proxy
    List<StreamHost> streamHosts = determineStreamHostInfos(proxies);
    if (streamHosts.isEmpty()) {
        if (discoveryException != null) {
            throw discoveryException;
        } else {
            throw new SmackException.SmackMessageException("no SOCKS5 proxies available");
        }
    }
    // compute digest
    String digest = Socks5Utils.createDigest(sessionID, connection.getUser(), targetJID);
    // prioritize last working SOCKS5 proxy if exists
    if (this.proxyPrioritizationEnabled && this.lastWorkingProxy != null) {
        StreamHost selectedStreamHost = null;
        for (StreamHost streamHost : streamHosts) {
            if (streamHost.getJID().equals(this.lastWorkingProxy)) {
                selectedStreamHost = streamHost;
                break;
            }
        }
        if (selectedStreamHost != null) {
            streamHosts.remove(selectedStreamHost);
            streamHosts.add(0, selectedStreamHost);
        }
    }
    Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
    try {
        // add transfer digest to local proxy to make transfer valid
        socks5Proxy.addTransfer(digest);
        // create initiation packet
        Bytestream initiation = createBytestreamInitiation(sessionID, targetJID, streamHosts);
        // send initiation packet
        Stanza response = connection.createStanzaCollectorAndSend(initiation).nextResultOrThrow(getTargetResponseTimeout());
        // extract used stream host from response
        StreamHostUsed streamHostUsed = ((Bytestream) response).getUsedHost();
        StreamHost usedStreamHost = initiation.getStreamHost(streamHostUsed.getJID());
        if (usedStreamHost == null) {
            throw new SmackException.SmackMessageException("Remote user responded with unknown host");
        }
        // build SOCKS5 client
        Socks5Client socks5Client = new Socks5ClientForInitiator(usedStreamHost, digest, connection, sessionID, targetJID);
        // establish connection to proxy
        Socket socket = socks5Client.getSocket(getProxyConnectionTimeout());
        // remember last working SOCKS5 proxy to prioritize it for next request
        this.lastWorkingProxy = usedStreamHost.getJID();
        // negotiation successful, return the output stream
        return new Socks5BytestreamSession(socket, usedStreamHost.getJID().equals(connection.getUser()));
    } catch (TimeoutException e) {
        throw new IOException("Timeout while connecting to SOCKS5 proxy", e);
    } finally {
        // remove transfer digest if output stream is returned or an exception
        // occurred
        socks5Proxy.removeTransfer(digest);
    }
}
Also used : StreamHostUsed(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHostUsed) SmackMessageException(org.jivesoftware.smack.SmackException.SmackMessageException) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) Jid(org.jxmpp.jid.Jid) EntityFullJid(org.jxmpp.jid.EntityFullJid) Stanza(org.jivesoftware.smack.packet.Stanza) FeatureNotSupportedException(org.jivesoftware.smack.SmackException.FeatureNotSupportedException) ArrayList(java.util.ArrayList) XMPPConnection(org.jivesoftware.smack.XMPPConnection) IOException(java.io.IOException) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 64 with Stanza

use of org.jivesoftware.smack.packet.Stanza in project Smack by igniterealtime.

the class AbstractXMPPConnection method parseAndProcessStanza.

protected void parseAndProcessStanza(XmlPullParser parser) throws XmlPullParserException, IOException, InterruptedException {
    ParserUtils.assertAtStartTag(parser);
    int parserDepth = parser.getDepth();
    Stanza stanza = null;
    try {
        stanza = PacketParserUtils.parseStanza(parser, incomingStreamXmlEnvironment);
    } catch (XmlPullParserException | SmackParsingException | IOException | IllegalArgumentException e) {
        CharSequence content = PacketParserUtils.parseContentDepth(parser, parserDepth);
        UnparseableStanza message = new UnparseableStanza(content, e);
        ParsingExceptionCallback callback = getParsingExceptionCallback();
        if (callback != null) {
            callback.handleUnparsableStanza(message);
        }
    }
    ParserUtils.assertAtEndTag(parser);
    if (stanza != null) {
        processStanza(stanza);
    }
}
Also used : Stanza(org.jivesoftware.smack.packet.Stanza) ParsingExceptionCallback(org.jivesoftware.smack.parsing.ParsingExceptionCallback) XmlPullParserException(org.jivesoftware.smack.xml.XmlPullParserException) IOException(java.io.IOException) SmackParsingException(org.jivesoftware.smack.parsing.SmackParsingException)

Example 65 with Stanza

use of org.jivesoftware.smack.packet.Stanza in project Smack by igniterealtime.

the class AbstractXMPPConnection method sendStanza.

@Override
public final void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException {
    Objects.requireNonNull(stanza, "Stanza must not be null");
    assert stanza instanceof Message || stanza instanceof Presence || stanza instanceof IQ;
    throwNotConnectedExceptionIfAppropriate();
    switch(fromMode) {
        case OMITTED:
            stanza.setFrom((Jid) null);
            break;
        case USER:
            stanza.setFrom(getUser());
            break;
        case UNCHANGED:
        default:
            break;
    }
    // Invoke interceptors for the new stanza that is about to be sent. Interceptors may modify
    // the content of the stanza.
    Stanza stanzaAfterInterceptors = firePacketInterceptors(stanza);
    sendStanzaInternal(stanzaAfterInterceptors);
}
Also used : Message(org.jivesoftware.smack.packet.Message) Stanza(org.jivesoftware.smack.packet.Stanza) IQ(org.jivesoftware.smack.packet.IQ) ErrorIQ(org.jivesoftware.smack.packet.ErrorIQ) Presence(org.jivesoftware.smack.packet.Presence) MessageOrPresence(org.jivesoftware.smack.packet.MessageOrPresence)

Aggregations

Stanza (org.jivesoftware.smack.packet.Stanza)101 StanzaListener (org.jivesoftware.smack.StanzaListener)24 Test (org.junit.Test)22 IQ (org.jivesoftware.smack.packet.IQ)20 Test (org.junit.jupiter.api.Test)18 XMPPConnection (org.jivesoftware.smack.XMPPConnection)14 Message (org.jivesoftware.smack.packet.Message)14 ArrayList (java.util.ArrayList)11 SmackException (org.jivesoftware.smack.SmackException)11 Jid (org.jxmpp.jid.Jid)11 IOException (java.io.IOException)9 NotConnectedException (org.jivesoftware.smack.SmackException.NotConnectedException)8 StanzaFilter (org.jivesoftware.smack.filter.StanzaFilter)8 Bytestream (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream)7 DelayInformation (org.jivesoftware.smackx.delay.packet.DelayInformation)7 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)6 StanzaTypeFilter (org.jivesoftware.smack.filter.StanzaTypeFilter)6 Protocol (org.jivesoftware.util.Protocol)6 EntityFullJid (org.jxmpp.jid.EntityFullJid)6 LinkedList (java.util.LinkedList)5