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;
}
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);
}
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);
}
}
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);
}
}
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);
}
Aggregations