mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-25 15:52:06 +01:00
Smack 4.2.0-rc2
-----BEGIN PGP SIGNATURE----- iQF8BAABCgBmBQJYe7kjXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQ5Nzc1MDU5RjNBMjFEQ0UxNkJFNEZCQUUy MjM5QTdFOEY1ODUyMDUyAAoJECI5p+j1hSBSuGkH/1mU66MNR0/ywbdZ2RKcb9MK WTHBBOuD/KaqkQOQQ5Fud+ktyahmDd9Nk4TbchIJ56PlEPqJbhnwP8txh1gU+8Zz jpRHYYQiTEuLSblToVL3afrfd/IQnOrh7VbwkG7S1wkWmOFKCv94wlv/OgZFaICc RHHJyJbJ0TTuavEkJ141ruNYmq/qYjUjdLmFrqhT3hv3iuiHCT1PK1787wEB0EWS ciwkw2j/j/2i27XNQRwu7QaLsmUGk8rLnr2/AsYpmsBsjAMqMbNEQEPbIgO9MVef 7dt/GWoqHjH1opVcOw+rRz/cynMii2sSTXiqRVTEZsWlx3uYYz5eKsuiuckZcBs= =yqh1 -----END PGP SIGNATURE----- Merge tag '4.2.0-rc2' Smack 4.2.0-rc2
This commit is contained in:
commit
382ed9d871
53 changed files with 797 additions and 182 deletions
|
@ -69,6 +69,7 @@ Smack Extensions and currently supported XEPs of smack-extensions
|
||||||
| XMPP Over BOSH | [XEP-0206](http://xmpp.org/extensions/xep-0206.html) | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. |
|
| XMPP Over BOSH | [XEP-0206](http://xmpp.org/extensions/xep-0206.html) | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. |
|
||||||
| Attention | [XEP-0224](http://xmpp.org/extensions/xep-0224.html) | Getting attention of another user. |
|
| Attention | [XEP-0224](http://xmpp.org/extensions/xep-0224.html) | Getting attention of another user. |
|
||||||
| Bits of Binary | [XEP-0231](http://xmpp.org/extensions/xep-0231.html) | Including or referring to small bits of binary data in an XML stanza. |
|
| Bits of Binary | [XEP-0231](http://xmpp.org/extensions/xep-0231.html) | Including or referring to small bits of binary data in an XML stanza. |
|
||||||
|
| Best Practices for Resource Locking | [XEP-0296](https://xmpp.org/extensions/xep-0296.html) | Specifies best practices to be followed by Jabber/XMPP clients about when to lock into, and unlock away from, resources. |
|
||||||
| Last Message Correction | [XEP-0308](http://xmpp.org/extensions/xep-0308.html) | Provides a method for indicating that a message is a correction of the last sent message. |
|
| Last Message Correction | [XEP-0308](http://xmpp.org/extensions/xep-0308.html) | Provides a method for indicating that a message is a correction of the last sent message. |
|
||||||
| [Group Chat Invitations](invitation.md) | n/a | Send invitations to other users to join a group chat room. |
|
| [Group Chat Invitations](invitation.md) | n/a | Send invitations to other users to join a group chat room. |
|
||||||
| [Jive Properties](properties.md) | n/a | TODO |
|
| [Jive Properties](properties.md) | n/a | TODO |
|
||||||
|
|
|
@ -97,8 +97,8 @@ done. The last step is to send the message as you do with any other message.
|
||||||
|
|
||||||
An XHTML message is like any regular message, therefore to send the message
|
An XHTML message is like any regular message, therefore to send the message
|
||||||
you can follow the usual steps you do in order to send a message. For example,
|
you can follow the usual steps you do in order to send a message. For example,
|
||||||
to send a message as part of a chat just use the message **#send(Message)** of
|
to send a message as part of a chat just use the message **#sendMessage(Message)** of
|
||||||
_**Chat**_ or you can use the message **#send(Stanza)** of
|
_**Chat**_ or you can use the message **#sendStanza(Stanza)** of
|
||||||
_**XMPPConnection**_.
|
_**XMPPConnection**_.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
@ -142,19 +142,20 @@ XHTML bodies of any received message.
|
||||||
|
|
||||||
```
|
```
|
||||||
// Create a listener for the chat and display any XHTML content
|
// Create a listener for the chat and display any XHTML content
|
||||||
PacketListener packetListener = new PacketListener() {
|
IncomingChatMessageListener listener = new IncomingChatMessageListener() {
|
||||||
public void processStanza(Stanza stanza) {
|
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
|
||||||
Message message = (Message) stanza;
|
|
||||||
// Obtain the XHTML bodies of the message
|
// Obtain the XHTML bodies of the message
|
||||||
List<CharSequence> bodies = XHTMLManager.getBodies(message);
|
List<CharSequence> bodies = XHTMLManager.getBodies(message);
|
||||||
if (bodies != null) {
|
if (bodies == null) {
|
||||||
// Display the bodies on the console
|
return;
|
||||||
for (CharSequence body : bodies) {
|
|
||||||
System.out.println(body);
|
// Display the bodies on the console
|
||||||
}
|
for (CharSequence body : bodies) {
|
||||||
|
System.out.println(body);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
chat.addMessageListener(packetListener);
|
chatManager.addListener(listener);
|
||||||
```
|
```
|
||||||
|
|
||||||
Discover support for XHTML Messages
|
Discover support for XHTML Messages
|
||||||
|
|
|
@ -70,7 +70,7 @@ created, such as the ability to disable or require encryption. See
|
||||||
|
|
||||||
Once you've created a connection, you should login with the
|
Once you've created a connection, you should login with the
|
||||||
`XMPPConnection.login()` method. Once you've logged in, you can being
|
`XMPPConnection.login()` method. Once you've logged in, you can being
|
||||||
chatting with other users by creating new `Chat` or `GroupChat`
|
chatting with other users by creating new `Chat` or `MultiUserChat`
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
Working with the Roster
|
Working with the Roster
|
||||||
|
@ -98,18 +98,18 @@ your presence to let people know you're unavailable and "out fishing":
|
||||||
// Create a new presence. Pass in false to indicate we're unavailable._
|
// Create a new presence. Pass in false to indicate we're unavailable._
|
||||||
Presence presence = new Presence(Presence.Type.unavailable);
|
Presence presence = new Presence(Presence.Type.unavailable);
|
||||||
presence.setStatus("Gone fishing");
|
presence.setStatus("Gone fishing");
|
||||||
// Send the packet (assume we have an XMPPConnection instance called "con").
|
// Send the stanza (assume we have an XMPPConnection instance called "con").
|
||||||
con.sendStanza(presence);
|
con.sendStanza(presence);
|
||||||
```
|
```
|
||||||
|
|
||||||
Smack provides two ways to read incoming packets: `PacketListener`, and
|
Smack provides two ways to read incoming packets: `StanzaListener`, and
|
||||||
`PacketCollector`. Both use `StanzaFilter` instances to determine which
|
`StanzaCollector`. Both use `StanzaFilter` instances to determine which
|
||||||
packets should be processed. A packet listener is used for event style
|
stanzas should be processed. A stanza listener is used for event style
|
||||||
programming, while a packet collector has a result queue of packets that you
|
programming, while a stanza collector has a result queue of packets that you
|
||||||
can do polling and blocking operations on. So, a packet listener is useful
|
can do polling and blocking operations on. So, a stanza listener is useful
|
||||||
when you want to take some action whenever a packet happens to come in, while
|
when you want to take some action whenever a stanza happens to come in, while
|
||||||
a packet collector is useful when you want to wait for a specific packet to
|
a stanza collector is useful when you want to wait for a specific packet to
|
||||||
arrive. Packet collectors and listeners can be created using an Connection
|
arrive. Stanza collectors and listeners can be created using an Connection
|
||||||
instance.
|
instance.
|
||||||
|
|
||||||
Copyright (C) Jive Software 2002-2008
|
Copyright (C) Jive Software 2002-2008
|
||||||
|
|
|
@ -6,7 +6,7 @@ Messaging using Chats
|
||||||
Sending messages back and forth is at the core of instant messaging. Although
|
Sending messages back and forth is at the core of instant messaging. Although
|
||||||
individual messages can be sent and received as packets, it's generally easier
|
individual messages can be sent and received as packets, it's generally easier
|
||||||
to treat the string of messages as a chat using the
|
to treat the string of messages as a chat using the
|
||||||
`org.jivesoftware.smack.Chat` class.
|
`org.jivesoftware.smack.chat2.Chat` class.
|
||||||
|
|
||||||
Chat
|
Chat
|
||||||
----
|
----
|
||||||
|
@ -17,80 +17,44 @@ and then send them a text message:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Assume we've created an XMPPConnection name "connection"._
|
// Assume we've created an XMPPConnection name "connection"._
|
||||||
ChatManager chatmanager = ChatManager.getInstanceFor(connection);
|
ChatManager chatManager = ChatManager.getInstanceFor(connection);
|
||||||
Chat newChat = chatmanager.createChat("jsmith@jivesoftware.com", new MessageListener() {
|
chatManager.addListener(new IncomingChatMessageListener() {
|
||||||
public void processMessage(Chat chat, Message message) {
|
@Override
|
||||||
System.out.println("Received message: " + message);
|
void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
|
||||||
}
|
System.out.println("New message from " + from ": " + message.getBody());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
EntityBareJid jid = JidCreate.entityBareFrom("jsmith@jivesoftware.com");
|
||||||
try {
|
Chat chat = chatManager.chatWith(jid);
|
||||||
newChat.sendMessage("Howdy!");
|
chat.sendMessage("Howdy!");
|
||||||
}
|
|
||||||
catch (XMPPException e) {
|
|
||||||
System.out.println("Error Delivering block");
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Chat.sendMessage(String)` method is a convenience method that creates a
|
The `Chat.sendMessage(String)` method is a convenience method that creates a
|
||||||
Message object, sets the body using the String parameter, then sends the
|
Message object, sets the body using the String parameter, then sends the
|
||||||
message. In the case that you wish to set additional values on a Message
|
message. In the case that you wish to set additional values on a Message
|
||||||
before sending it, use the `Chat.createMessage()` and
|
before sending it, use
|
||||||
`Chat.sendMessage(Message)` methods, as in the following code snippet:
|
`Chat.sendMessage(Message)` method, as in the following code snippet:
|
||||||
|
|
||||||
```
|
```
|
||||||
Message newMessage = new Message();
|
Message newMessage = new Message();
|
||||||
newMessage.setBody("Howdy!");
|
newMessage.setBody("Howdy!");
|
||||||
// Additional modifications to the message Stanza.
|
// Additional modifications to the message Stanza.
|
||||||
JivePropertiesManager.addProperty(newMessage, "favoriteColor", "red");
|
JivePropertiesManager.addProperty(newMessage, "favoriteColor", "red");
|
||||||
newChat.sendMessage(newMessage);
|
chat.sendMessage(newMessage);
|
||||||
```
|
```
|
||||||
|
|
||||||
You'll also notice in the example above that we specified a MessageListener
|
You'll also notice in the example above that we specified an IncomingChatMessageListener.
|
||||||
when creating a chat. The listener is notified any time a new message arrives
|
The listener is notified any time a new chat message arrives.
|
||||||
from the other user in the chat. The following code snippet uses the listener
|
The following code snippet uses the listener
|
||||||
as a parrot-bot -- it echoes back everything the other user types.
|
as a parrot-bot -- it echoes back everything the other user types.
|
||||||
|
|
||||||
```
|
```
|
||||||
// Assume a MessageListener we've setup with a chat._
|
// Assume a IncomingChatMessageListener we've setup with a ChatManager
|
||||||
|
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
|
||||||
public void processMessage(Chat chat, Message message) {
|
// Send back the same text the other user sent us.
|
||||||
// Send back the same text the other user sent us._
|
chat.sendMessage(message.getBody());
|
||||||
chat.sendMessage(message.getBody());
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Incoming Chat
|
|
||||||
-------------
|
|
||||||
|
|
||||||
When chats are prompted by another user, the setup is slightly different since
|
|
||||||
you are receiving a chat message first. Instead of explicitly creating a chat
|
|
||||||
to send messages, you need to register to handle newly created Chat instances
|
|
||||||
when the ChatManager creates them. The ChatManager will already find a
|
|
||||||
matching chat (by thread id) and if none exists, then it will create a new one
|
|
||||||
that does match. To get this new chat, you have to register to be notified
|
|
||||||
when it happens. You can register a message listener to receive all future
|
|
||||||
messages as part of this handler.
|
|
||||||
|
|
||||||
```
|
|
||||||
// Assume we've created an XMPPConnection name "connection"._
|
|
||||||
ChatManager chatManager = ChatManager.getInstanceFor(connection);
|
|
||||||
chatManager.addChatListener(
|
|
||||||
new ChatManagerListener() {
|
|
||||||
@Override
|
|
||||||
public void chatCreated(Chat chat, boolean createdLocally)
|
|
||||||
{
|
|
||||||
if (!createdLocally)
|
|
||||||
chat.addMessageListener(new MyNewMessageListener());;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
In addition to thread based chat messages, there are some clients that do not
|
|
||||||
send a thread id as part of the chat. To handle this scenario, Smack will
|
|
||||||
attempt match the incoming messages to the best fit existing chat, based on
|
|
||||||
the JID. It will attempt to find a chat with the same full JID, failing that,
|
|
||||||
it will try the base JID. If no existing chat to the user can found, then a
|
|
||||||
new one is created.
|
|
||||||
|
|
||||||
Copyright (C) Jive Software 2002-2008
|
Copyright (C) Jive Software 2002-2008
|
||||||
|
|
|
@ -182,7 +182,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
// Wait for the response from the server
|
// Wait for the response from the server
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
final long deadline = System.currentTimeMillis() + getPacketReplyTimeout();
|
final long deadline = System.currentTimeMillis() + getReplyTimeout();
|
||||||
while (!notified) {
|
while (!notified) {
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
if (now >= deadline) break;
|
if (now >= deadline) break;
|
||||||
|
@ -198,6 +198,9 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
+ getHost() + ":" + getPort() + ".";
|
+ getHost() + ":" + getPort() + ".";
|
||||||
throw new SmackException(errorMessage);
|
throw new SmackException(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
|
saslFeatureReceived.reportSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecureConnection() {
|
public boolean isSecureConnection() {
|
||||||
|
|
|
@ -169,9 +169,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
protected String streamId;
|
protected String streamId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* The timeout to wait for a reply in milliseconds.
|
||||||
*/
|
*/
|
||||||
private long packetReplyTimeout = SmackConfiguration.getDefaultPacketReplyTimeout();
|
private long replyTimeout = SmackConfiguration.getDefaultReplyTimeout();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SmackDebugger allows to log and debug XML traffic.
|
* The SmackDebugger allows to log and debug XML traffic.
|
||||||
|
@ -188,6 +188,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
*/
|
*/
|
||||||
protected Writer writer;
|
protected Writer writer;
|
||||||
|
|
||||||
|
protected final SynchronizationPoint<SmackException> tlsHandled = new SynchronizationPoint<>(this, "establishing TLS");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to success if the last features stanza from the server has been parsed. A XMPP connection
|
* Set to success if the last features stanza from the server has been parsed. A XMPP connection
|
||||||
* handshake can invoke multiple features stanzas, e.g. when TLS is activated a second feature
|
* handshake can invoke multiple features stanzas, e.g. when TLS is activated a second feature
|
||||||
|
@ -198,9 +200,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
AbstractXMPPConnection.this, "last stream features received from server");
|
AbstractXMPPConnection.this, "last stream features received from server");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to success if the sasl feature has been received.
|
* Set to success if the SASL feature has been received.
|
||||||
*/
|
*/
|
||||||
protected final SynchronizationPoint<SmackException> saslFeatureReceived = new SynchronizationPoint<SmackException>(
|
protected final SynchronizationPoint<XMPPException> saslFeatureReceived = new SynchronizationPoint<>(
|
||||||
AbstractXMPPConnection.this, "SASL mechanisms stream feature from server");
|
AbstractXMPPConnection.this, "SASL mechanisms stream feature from server");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -368,11 +370,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
saslAuthentication.init();
|
saslAuthentication.init();
|
||||||
saslFeatureReceived.init();
|
saslFeatureReceived.init();
|
||||||
lastFeaturesReceived.init();
|
lastFeaturesReceived.init();
|
||||||
|
tlsHandled.init();
|
||||||
streamId = null;
|
streamId = null;
|
||||||
|
|
||||||
// Perform the actual connection to the XMPP service
|
// Perform the actual connection to the XMPP service
|
||||||
connectInternal();
|
connectInternal();
|
||||||
|
|
||||||
|
// TLS handled will be successful either if TLS was established, or if it was not mandatory.
|
||||||
|
tlsHandled.checkIfSuccessOrWaitOrThrow();
|
||||||
|
|
||||||
// Wait with SASL auth until the SASL mechanisms have been received
|
// Wait with SASL auth until the SASL mechanisms have been received
|
||||||
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
|
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
|
||||||
|
|
||||||
|
@ -596,7 +602,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
protected List<HostAddress> hostAddresses;
|
protected List<HostAddress> hostAddresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates {@link #hostAddresses} with at least one host address.
|
* Populates {@link #hostAddresses} with the resolved addresses or with the configured host address. If no host
|
||||||
|
* address was configured and all lookups failed, for example with NX_DOMAIN, then {@link #hostAddresses} will be
|
||||||
|
* populated with the empty list.
|
||||||
*
|
*
|
||||||
* @return a list of host addresses where DNS (SRV) RR resolution failed.
|
* @return a list of host addresses where DNS (SRV) RR resolution failed.
|
||||||
*/
|
*/
|
||||||
|
@ -610,14 +618,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
else if (config.host != null) {
|
else if (config.host != null) {
|
||||||
hostAddresses = new ArrayList<HostAddress>(1);
|
hostAddresses = new ArrayList<HostAddress>(1);
|
||||||
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
|
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
|
||||||
hostAddresses.add(hostAddress);
|
if (hostAddress != null) {
|
||||||
|
hostAddresses.add(hostAddress);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
|
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
|
||||||
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
|
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
|
||||||
}
|
}
|
||||||
// If we reach this, then hostAddresses *must not* be empty, i.e. there is at least one host added, either the
|
// Either the populated host addresses are not empty *or* there must be at least one failed address.
|
||||||
// config.host one or the host representing the service name by DNSUtil
|
assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
|
||||||
assert(!hostAddresses.isEmpty());
|
|
||||||
return failedAddresses;
|
return failedAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,14 +969,26 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public long getPacketReplyTimeout() {
|
public long getPacketReplyTimeout() {
|
||||||
return packetReplyTimeout;
|
return getReplyTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public void setPacketReplyTimeout(long timeout) {
|
||||||
|
setReplyTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPacketReplyTimeout(long timeout) {
|
public long getReplyTimeout() {
|
||||||
packetReplyTimeout = timeout;
|
return replyTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReplyTimeout(long timeout) {
|
||||||
|
replyTimeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean replyToUnknownIqDefault = true;
|
private static boolean replyToUnknownIqDefault = true;
|
||||||
|
@ -1407,6 +1428,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
// Only proceed with SASL auth if TLS is disabled or if the server doesn't announce it
|
// Only proceed with SASL auth if TLS is disabled or if the server doesn't announce it
|
||||||
if (!hasFeature(StartTls.ELEMENT, StartTls.NAMESPACE)
|
if (!hasFeature(StartTls.ELEMENT, StartTls.NAMESPACE)
|
||||||
|| config.getSecurityMode() == SecurityMode.disabled) {
|
|| config.getSecurityMode() == SecurityMode.disabled) {
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
saslFeatureReceived.reportSuccess();
|
saslFeatureReceived.reportSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1456,7 +1478,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
StanzaListener callback, ExceptionCallback exceptionCallback)
|
StanzaListener callback, ExceptionCallback exceptionCallback)
|
||||||
throws NotConnectedException, InterruptedException {
|
throws NotConnectedException, InterruptedException {
|
||||||
sendStanzaWithResponseCallback(stanza, replyFilter, callback, exceptionCallback,
|
sendStanzaWithResponseCallback(stanza, replyFilter, callback, exceptionCallback,
|
||||||
getPacketReplyTimeout());
|
getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1517,7 +1539,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
@Override
|
@Override
|
||||||
public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
|
public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
|
||||||
ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException {
|
ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException {
|
||||||
sendIqWithResponseCallback(iqRequest, callback, exceptionCallback, getPacketReplyTimeout());
|
sendIqWithResponseCallback(iqRequest, callback, exceptionCallback, getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1546,7 +1568,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
public void run() {
|
public void run() {
|
||||||
removeSyncStanzaListener(packetListener);
|
removeSyncStanzaListener(packetListener);
|
||||||
}
|
}
|
||||||
}, getPacketReplyTimeout(), TimeUnit.MILLISECONDS);
|
}, getReplyTimeout(), TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -200,7 +200,7 @@ public final class SASLAuthentication {
|
||||||
else {
|
else {
|
||||||
currentMechanism.authenticate(username, host, xmppServiceDomain, password, authzid, sslSession);
|
currentMechanism.authenticate(username, host, xmppServiceDomain, password, authzid, sslSession);
|
||||||
}
|
}
|
||||||
final long deadline = System.currentTimeMillis() + connection.getPacketReplyTimeout();
|
final long deadline = System.currentTimeMillis() + connection.getReplyTimeout();
|
||||||
while (!authenticationSuccessful && saslException == null) {
|
while (!authenticationSuccessful && saslException == null) {
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
if (now >= deadline) break;
|
if (now >= deadline) break;
|
||||||
|
|
|
@ -101,8 +101,32 @@ public final class SmackConfiguration {
|
||||||
* the server. The default value is 5000 ms.
|
* the server. The default value is 5000 ms.
|
||||||
*
|
*
|
||||||
* @return the milliseconds to wait for a response from the server
|
* @return the milliseconds to wait for a response from the server
|
||||||
|
* @deprecated use {@link #getDefaultReplyTimeout()} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static int getDefaultPacketReplyTimeout() {
|
public static int getDefaultPacketReplyTimeout() {
|
||||||
|
return getDefaultReplyTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the number of milliseconds to wait for a response from
|
||||||
|
* the server.
|
||||||
|
*
|
||||||
|
* @param timeout the milliseconds to wait for a response from the server
|
||||||
|
* @deprecated use {@link #setDefaultReplyTimeout(int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static void setDefaultPacketReplyTimeout(int timeout) {
|
||||||
|
setDefaultReplyTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of milliseconds to wait for a response from
|
||||||
|
* the server. The default value is 5000 ms.
|
||||||
|
*
|
||||||
|
* @return the milliseconds to wait for a response from the server
|
||||||
|
*/
|
||||||
|
public static int getDefaultReplyTimeout() {
|
||||||
// The timeout value must be greater than 0 otherwise we will answer the default value
|
// The timeout value must be greater than 0 otherwise we will answer the default value
|
||||||
if (defaultPacketReplyTimeout <= 0) {
|
if (defaultPacketReplyTimeout <= 0) {
|
||||||
defaultPacketReplyTimeout = 5000;
|
defaultPacketReplyTimeout = 5000;
|
||||||
|
@ -116,7 +140,7 @@ public final class SmackConfiguration {
|
||||||
*
|
*
|
||||||
* @param timeout the milliseconds to wait for a response from the server
|
* @param timeout the milliseconds to wait for a response from the server
|
||||||
*/
|
*/
|
||||||
public static void setDefaultPacketReplyTimeout(int timeout) {
|
public static void setDefaultReplyTimeout(int timeout) {
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class SmackException extends Exception {
|
||||||
/**
|
/**
|
||||||
* Exception thrown always when there was no response to an request within the stanza(/packet) reply timeout of the used
|
* Exception thrown always when there was no response to an request within the stanza(/packet) reply timeout of the used
|
||||||
* connection instance. You can modify (e.g. increase) the stanza(/packet) reply timeout with
|
* connection instance. You can modify (e.g. increase) the stanza(/packet) reply timeout with
|
||||||
* {@link XMPPConnection#setPacketReplyTimeout(long)}.
|
* {@link XMPPConnection#setReplyTimeout(long)}.
|
||||||
*/
|
*/
|
||||||
public static final class NoResponseException extends SmackException {
|
public static final class NoResponseException extends SmackException {
|
||||||
/**
|
/**
|
||||||
|
@ -111,7 +111,7 @@ public class SmackException extends Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StringBuilder getWaitingFor(XMPPConnection connection) {
|
private static StringBuilder getWaitingFor(XMPPConnection connection) {
|
||||||
final long replyTimeout = connection.getPacketReplyTimeout();
|
final long replyTimeout = connection.getReplyTimeout();
|
||||||
final StringBuilder sb = new StringBuilder(256);
|
final StringBuilder sb = new StringBuilder(256);
|
||||||
sb.append("No response received within reply timeout. Timeout was "
|
sb.append("No response received within reply timeout. Timeout was "
|
||||||
+ replyTimeout + "ms (~"
|
+ replyTimeout + "ms (~"
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class StanzaCollector {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public <P extends Stanza> P nextResult() throws InterruptedException {
|
public <P extends Stanza> P nextResult() throws InterruptedException {
|
||||||
return nextResult(connection.getPacketReplyTimeout());
|
return nextResult(connection.getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
private volatile long waitStart;
|
private volatile long waitStart;
|
||||||
|
@ -205,7 +205,7 @@ public class StanzaCollector {
|
||||||
*/
|
*/
|
||||||
public <P extends Stanza> P nextResultOrThrow() throws NoResponseException, XMPPErrorException,
|
public <P extends Stanza> P nextResultOrThrow() throws NoResponseException, XMPPErrorException,
|
||||||
InterruptedException, NotConnectedException {
|
InterruptedException, NotConnectedException {
|
||||||
return nextResultOrThrow(connection.getPacketReplyTimeout());
|
return nextResultOrThrow(connection.getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -234,7 +234,7 @@ public class SynchronizationPoint<E extends Exception> {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
private void waitForConditionOrTimeout() throws InterruptedException {
|
private void waitForConditionOrTimeout() throws InterruptedException {
|
||||||
long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getPacketReplyTimeout());
|
long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getReplyTimeout());
|
||||||
while (state == State.RequestSent || state == State.Initial) {
|
while (state == State.RequestSent || state == State.Initial) {
|
||||||
if (remainingWait <= 0) {
|
if (remainingWait <= 0) {
|
||||||
state = State.NoResponse;
|
state = State.NoResponse;
|
||||||
|
|
|
@ -410,7 +410,9 @@ public interface XMPPConnection {
|
||||||
* XMPPConnection instance.
|
* XMPPConnection instance.
|
||||||
*
|
*
|
||||||
* @return the stanza(/packet) reply timeout in milliseconds
|
* @return the stanza(/packet) reply timeout in milliseconds
|
||||||
|
* @deprecated use {@link #getReplyTimeout()} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public long getPacketReplyTimeout();
|
public long getPacketReplyTimeout();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -418,9 +420,27 @@ public interface XMPPConnection {
|
||||||
* {@link NoResponseException} if no reply to a request was received within the timeout period.
|
* {@link NoResponseException} if no reply to a request was received within the timeout period.
|
||||||
*
|
*
|
||||||
* @param timeout the stanza(/packet) reply timeout in milliseconds
|
* @param timeout the stanza(/packet) reply timeout in milliseconds
|
||||||
|
* @deprecated use {@link #setReplyTimeout(long)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setPacketReplyTimeout(long timeout);
|
public void setPacketReplyTimeout(long timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current value of the reply timeout in milliseconds for request for this
|
||||||
|
* XMPPConnection instance.
|
||||||
|
*
|
||||||
|
* @return the reply timeout in milliseconds
|
||||||
|
*/
|
||||||
|
public long getReplyTimeout();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the stanza(/packet) reply timeout in milliseconds. In most cases, Smack will throw a
|
||||||
|
* {@link NoResponseException} if no reply to a request was received within the timeout period.
|
||||||
|
*
|
||||||
|
* @param timeout for a reply in milliseconds
|
||||||
|
*/
|
||||||
|
public void setReplyTimeout(long timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the connection counter of this XMPPConnection instance. Those can be used as ID to
|
* Get the connection counter of this XMPPConnection instance. Those can be used as ID to
|
||||||
* identify the connection, but beware that the ID may not be unique if you create more then
|
* identify the connection, but beware that the ID may not be unique if you create more then
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.filter;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
public abstract class AbstractJidTypeFilter implements StanzaFilter {
|
||||||
|
|
||||||
|
protected enum JidType {
|
||||||
|
entityFull,
|
||||||
|
entityBare,
|
||||||
|
domainFull,
|
||||||
|
domainBare,
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final JidType jidType;
|
||||||
|
|
||||||
|
protected AbstractJidTypeFilter(JidType jidType) {
|
||||||
|
this.jidType = jidType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Jid getJidToInspect(Stanza stanza);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean accept(Stanza stanza) {
|
||||||
|
final Jid jid = stanza.getFrom();
|
||||||
|
|
||||||
|
if (jid == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (jidType) {
|
||||||
|
case entityFull:
|
||||||
|
return jid.isEntityFullJid();
|
||||||
|
case entityBare:
|
||||||
|
return jid.isEntityBareJid();
|
||||||
|
case domainFull:
|
||||||
|
return jid.isDomainFullJid();
|
||||||
|
case domainBare:
|
||||||
|
return jid.isDomainBareJid();
|
||||||
|
default:
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.filter;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
public final class FromTypeFilter extends AbstractJidTypeFilter {
|
||||||
|
|
||||||
|
public static final FromTypeFilter ENTITY_FULL_JID = new FromTypeFilter(JidType.entityFull);
|
||||||
|
public static final FromTypeFilter ENTITY_BARE_JID = new FromTypeFilter(JidType.entityBare);
|
||||||
|
public static final FromTypeFilter DOMAIN_FULL_JID = new FromTypeFilter(JidType.domainFull);
|
||||||
|
public static final FromTypeFilter DOMAIN_BARE_JID = new FromTypeFilter(JidType.domainBare);
|
||||||
|
|
||||||
|
private FromTypeFilter(JidType jidType) {
|
||||||
|
super(jidType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Jid getJidToInspect(Stanza stanza) {
|
||||||
|
return stanza.getFrom();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.filter;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
public final class ToTypeFilter extends AbstractJidTypeFilter {
|
||||||
|
|
||||||
|
public static final ToTypeFilter ENTITY_FULL_JID = new ToTypeFilter(JidType.entityFull);
|
||||||
|
public static final ToTypeFilter ENTITY_BARE_JID = new ToTypeFilter(JidType.entityBare);
|
||||||
|
public static final ToTypeFilter DOMAIN_FULL_JID = new ToTypeFilter(JidType.domainFull);
|
||||||
|
public static final ToTypeFilter DOMAIN_BARE_JID = new ToTypeFilter(JidType.domainBare);
|
||||||
|
|
||||||
|
public static final StanzaFilter ENTITY_FULL_OR_BARE_JID = new OrFilter(ENTITY_FULL_JID, ENTITY_BARE_JID);
|
||||||
|
|
||||||
|
private ToTypeFilter(JidType jidType) {
|
||||||
|
super(jidType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Jid getJidToInspect(Stanza stanza) {
|
||||||
|
return stanza.getTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -250,14 +250,16 @@ public class DNSUtil {
|
||||||
List<SRVRecord> bucket = buckets.get(priority);
|
List<SRVRecord> bucket = buckets.get(priority);
|
||||||
int bucketSize;
|
int bucketSize;
|
||||||
while ((bucketSize = bucket.size()) > 0) {
|
while ((bucketSize = bucket.size()) > 0) {
|
||||||
int[] totals = new int[bucket.size()];
|
int[] totals = new int[bucketSize];
|
||||||
int running_total = 0;
|
int running_total = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int zeroWeight = 1;
|
int zeroWeight = 1;
|
||||||
|
|
||||||
for (SRVRecord r : bucket) {
|
for (SRVRecord r : bucket) {
|
||||||
if (r.getWeight() > 0)
|
if (r.getWeight() > 0) {
|
||||||
zeroWeight = 0;
|
zeroWeight = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SRVRecord r : bucket) {
|
for (SRVRecord r : bucket) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2013-2016 Florian Schmaus
|
* Copyright 2013-2017 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -50,7 +50,7 @@ public abstract class DNSResolver {
|
||||||
public final HostAddress lookupHostAddress(String name, int port, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
|
public final HostAddress lookupHostAddress(String name, int port, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
|
||||||
checkIfDnssecRequestedAndSupported(dnssecMode);
|
checkIfDnssecRequestedAndSupported(dnssecMode);
|
||||||
List<InetAddress> inetAddresses = lookupHostAddress0(name, failedAddresses, dnssecMode);
|
List<InetAddress> inetAddresses = lookupHostAddress0(name, failedAddresses, dnssecMode);
|
||||||
if (inetAddresses == null) {
|
if (inetAddresses == null || inetAddresses.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new HostAddress(name, port, inetAddresses);
|
return new HostAddress(name, port, inetAddresses);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2013-2016 Florian Schmaus
|
* Copyright © 2013-2017 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,7 +25,7 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.ConnectionException;
|
import org.jivesoftware.smack.SmackException.ConnectionException;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
public class HostAddress {
|
public class HostAddress {
|
||||||
private final String fqdn;
|
private final String fqdn;
|
||||||
|
@ -34,18 +34,17 @@ public class HostAddress {
|
||||||
private final List<InetAddress> inetAddresses;
|
private final List<InetAddress> inetAddresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new HostAddress with the given FQDN. The port will be set to the default XMPP client port: 5222
|
* Creates a new HostAddress with the given FQDN.
|
||||||
*
|
*
|
||||||
* @param fqdn Fully qualified domain name.
|
* @param fqdn the optional fully qualified domain name (FQDN).
|
||||||
* @param port The port to connect on.
|
* @param port The port to connect on.
|
||||||
* @throws IllegalArgumentException If the fqdn is null or port is out of valid range (0 - 65535).
|
* @throws IllegalArgumentException If the port is out of valid range (0 - 65535).
|
||||||
*/
|
*/
|
||||||
public HostAddress(String fqdn, int port, List<InetAddress> inetAddresses) {
|
public HostAddress(String fqdn, int port, List<InetAddress> inetAddresses) {
|
||||||
Objects.requireNonNull(fqdn, "FQDN is null");
|
|
||||||
if (port < 0 || port > 65535)
|
if (port < 0 || port > 65535)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
|
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
|
||||||
if (fqdn.charAt(fqdn.length() - 1) == '.') {
|
if (StringUtils.isNotEmpty(fqdn) && fqdn.charAt(fqdn.length() - 1) == '.') {
|
||||||
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -59,7 +58,7 @@ public class HostAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
public HostAddress(int port, InetAddress hostAddress) {
|
public HostAddress(int port, InetAddress hostAddress) {
|
||||||
this("", port, Collections.singletonList(hostAddress));
|
this(null, port, Collections.singletonList(hostAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2013-2016 Florian Schmaus
|
* Copyright 2013-2017 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -19,6 +19,8 @@ package org.jivesoftware.smack.util.dns;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DNS SRV RR.
|
* A DNS SRV RR.
|
||||||
*
|
*
|
||||||
|
@ -43,6 +45,7 @@ public class SRVRecord extends HostAddress implements Comparable<SRVRecord> {
|
||||||
*/
|
*/
|
||||||
public SRVRecord(String fqdn, int port, int priority, int weight, List<InetAddress> inetAddresses) {
|
public SRVRecord(String fqdn, int port, int priority, int weight, List<InetAddress> inetAddresses) {
|
||||||
super(fqdn, port, inetAddresses);
|
super(fqdn, port, inetAddresses);
|
||||||
|
StringUtils.requireNotNullOrEmpty(fqdn, "The FQDN must not be null");
|
||||||
if (weight < 0 || weight > 65535)
|
if (weight < 0 || weight > 65535)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"DNS SRV records weight must be a 16-bit unsiged integer (i.e. between 0-65535. Weight was: "
|
"DNS SRV records weight must be a 16-bit unsiged integer (i.e. between 0-65535. Weight was: "
|
||||||
|
|
|
@ -91,6 +91,7 @@ public class DummyConnection extends AbstractXMPPConnection {
|
||||||
protected void connectInternal() {
|
protected void connectInternal() {
|
||||||
connected = true;
|
connected = true;
|
||||||
saslFeatureReceived.reportSuccess();
|
saslFeatureReceived.reportSuccess();
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
streamId = "dummy-" + new Random(new Date().getTime()).nextInt();
|
streamId = "dummy-" + new Random(new Date().getTime()).nextInt();
|
||||||
|
|
||||||
if (reconnect) {
|
if (reconnect) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class SmackConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSmackConfiguration() {
|
public void testSmackConfiguration() {
|
||||||
try {
|
try {
|
||||||
SmackConfiguration.getDefaultPacketReplyTimeout();
|
SmackConfiguration.getDefaultReplyTimeout();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
fail("SmackConfiguration threw Throwable");
|
fail("SmackConfiguration threw Throwable");
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public class SmackConfigurationTest {
|
||||||
@Ignore
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void smackConfigurationShouldNotCauseInitializationTest() {
|
public void smackConfigurationShouldNotCauseInitializationTest() {
|
||||||
SmackConfiguration.getDefaultPacketReplyTimeout();
|
SmackConfiguration.getDefaultReplyTimeout();
|
||||||
|
|
||||||
// Only a call to SmackConfiguration.getVersion() should cause Smack to become initialized.
|
// Only a call to SmackConfiguration.getVersion() should cause Smack to become initialized.
|
||||||
assertFalse(SmackConfiguration.isSmackInitialized());
|
assertFalse(SmackConfiguration.isSmackInitialized());
|
||||||
|
|
|
@ -18,6 +18,6 @@ package org.jivesoftware.smackx.iot.data.element;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
public static final String IOT_SENSORDATA_NAMESPACE = "urn:xmpp:iot:data";
|
public static final String IOT_SENSORDATA_NAMESPACE = "urn:xmpp:iot:sensordata";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.StanzaListener;
|
import org.jivesoftware.smack.StanzaListener;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManager;
|
|
||||||
import org.jivesoftware.smack.chat.ChatMessageListener;
|
import org.jivesoftware.smack.chat.ChatMessageListener;
|
||||||
import org.jivesoftware.smack.filter.AndFilter;
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
import org.jivesoftware.smack.filter.FromMatchesFilter;
|
import org.jivesoftware.smack.filter.FromMatchesFilter;
|
||||||
|
@ -146,8 +144,10 @@ public class MultiUserChatLight {
|
||||||
* for the newly created chat.
|
* for the newly created chat.
|
||||||
* @return new Chat for sending private messages to a given room occupant.
|
* @return new Chat for sending private messages to a given room occupant.
|
||||||
*/
|
*/
|
||||||
public Chat createPrivateChat(EntityJid occupant, ChatMessageListener listener) {
|
@Deprecated
|
||||||
return ChatManager.getInstanceFor(connection).createChat(occupant, listener);
|
// Do not re-use Chat API, which was designed for XMPP-IM 1:1 chats and not MUClight private chats.
|
||||||
|
public org.jivesoftware.smack.chat.Chat createPrivateChat(EntityJid occupant, ChatMessageListener listener) {
|
||||||
|
return org.jivesoftware.smack.chat.ChatManager.getInstanceFor(connection).createChat(occupant, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.chat2;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.Manager;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
public final class Chat extends Manager {
|
||||||
|
|
||||||
|
private final EntityBareJid jid;
|
||||||
|
|
||||||
|
volatile EntityFullJid lockedResource;
|
||||||
|
|
||||||
|
Presence lastPresenceOfLockedResource;
|
||||||
|
|
||||||
|
Chat(final XMPPConnection connection, EntityBareJid jid) {
|
||||||
|
super(connection);
|
||||||
|
this.jid = jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(CharSequence message) throws NotConnectedException, InterruptedException {
|
||||||
|
Message stanza = new Message();
|
||||||
|
stanza.setBody(message);
|
||||||
|
send(stanza);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(Message message) throws NotConnectedException, InterruptedException {
|
||||||
|
switch (message.getType()) {
|
||||||
|
case normal:
|
||||||
|
case chat:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Message must be of type 'normal' or 'chat'");
|
||||||
|
}
|
||||||
|
|
||||||
|
Jid to = lockedResource;
|
||||||
|
if (to == null) {
|
||||||
|
to = jid;
|
||||||
|
}
|
||||||
|
message.setTo(to);
|
||||||
|
|
||||||
|
connection().sendStanza(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityBareJid getXmppAddressOfChatPartner() {
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlockResource() {
|
||||||
|
lockedResource = null;
|
||||||
|
lastPresenceOfLockedResource = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.chat2;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.Manager;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.StanzaListener;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
|
import org.jivesoftware.smack.filter.FromTypeFilter;
|
||||||
|
import org.jivesoftware.smack.filter.MessageTypeFilter;
|
||||||
|
import org.jivesoftware.smack.filter.MessageWithBodiesFilter;
|
||||||
|
import org.jivesoftware.smack.filter.OrFilter;
|
||||||
|
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||||
|
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||||
|
import org.jivesoftware.smack.filter.ToTypeFilter;
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
import org.jivesoftware.smack.roster.AbstractRosterListener;
|
||||||
|
import org.jivesoftware.smack.roster.Roster;
|
||||||
|
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chat manager for 1:1 XMPP instant messaging chats.
|
||||||
|
* <p>
|
||||||
|
* This manager and the according {@link Chat} API implement "Resource Locking" (XEP-0296). Support for Carbon Copies
|
||||||
|
* (XEP-0280) will be added once the XEP has progressed from experimental.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0296.html">XEP-0296: Best Practices for Resource Locking</a>
|
||||||
|
*/
|
||||||
|
public final class ChatManager extends Manager {
|
||||||
|
|
||||||
|
private static final Map<XMPPConnection, ChatManager> INSTANCES = new WeakHashMap<>();
|
||||||
|
|
||||||
|
public static synchronized ChatManager getInstanceFor(XMPPConnection connection) {
|
||||||
|
ChatManager chatManager = INSTANCES.get(connection);
|
||||||
|
if (chatManager == null) {
|
||||||
|
chatManager = new ChatManager(connection);
|
||||||
|
INSTANCES.put(connection, chatManager);
|
||||||
|
}
|
||||||
|
return chatManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @FORMATTER:OFF
|
||||||
|
private static final StanzaFilter MESSAGE_FILTER = new AndFilter(
|
||||||
|
MessageTypeFilter.NORMAL_OR_CHAT,
|
||||||
|
new OrFilter(MessageWithBodiesFilter.INSTANCE), new StanzaExtensionFilter(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE)
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final StanzaFilter OUTGOING_MESSAGE_FILTER = new AndFilter(
|
||||||
|
MESSAGE_FILTER,
|
||||||
|
ToTypeFilter.ENTITY_FULL_OR_BARE_JID
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final StanzaFilter INCOMING_MESSAGE_FILTER = new AndFilter(
|
||||||
|
MESSAGE_FILTER,
|
||||||
|
FromTypeFilter.ENTITY_FULL_JID
|
||||||
|
);
|
||||||
|
// @FORMATTER:ON
|
||||||
|
|
||||||
|
private final Map<EntityBareJid, Chat> chats = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final Set<IncomingChatMessageListener> incomingListeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
private final Set<OutgoingChatMessageListener> outgoingListeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
private boolean xhtmlIm;
|
||||||
|
|
||||||
|
private ChatManager(final XMPPConnection connection) {
|
||||||
|
super(connection);
|
||||||
|
connection.addSyncStanzaListener(new StanzaListener() {
|
||||||
|
@Override
|
||||||
|
public void processStanza(Stanza stanza) {
|
||||||
|
Message message = (Message) stanza;
|
||||||
|
if (!shouldAcceptMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Jid from = message.getFrom();
|
||||||
|
final EntityFullJid fullFrom = from.asEntityFullJidOrThrow();
|
||||||
|
final EntityBareJid bareFrom = fullFrom.asEntityBareJid();
|
||||||
|
final Chat chat = chatWith(bareFrom);
|
||||||
|
chat.lockedResource = fullFrom;
|
||||||
|
|
||||||
|
for (IncomingChatMessageListener listener : incomingListeners) {
|
||||||
|
listener.newIncomingMessage(bareFrom, message, chat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, INCOMING_MESSAGE_FILTER);
|
||||||
|
|
||||||
|
connection.addPacketInterceptor(new StanzaListener() {
|
||||||
|
@Override
|
||||||
|
public void processStanza(Stanza stanza) throws NotConnectedException, InterruptedException {
|
||||||
|
Message message = (Message) stanza;
|
||||||
|
if (!shouldAcceptMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EntityBareJid to = message.getTo().asEntityBareJidOrThrow();
|
||||||
|
final Chat chat = chatWith(to);
|
||||||
|
|
||||||
|
for (OutgoingChatMessageListener listener : outgoingListeners) {
|
||||||
|
listener.newOutgoingMessage(to, message, chat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, OUTGOING_MESSAGE_FILTER);
|
||||||
|
|
||||||
|
Roster roster = Roster.getInstanceFor(connection);
|
||||||
|
roster.addRosterListener(new AbstractRosterListener() {
|
||||||
|
@Override
|
||||||
|
public void presenceChanged(Presence presence) {
|
||||||
|
final Jid from = presence.getFrom();
|
||||||
|
final EntityBareJid bareFrom = from.asEntityBareJidIfPossible();
|
||||||
|
if (bareFrom == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Chat chat = chats.get(bareFrom);
|
||||||
|
if (chat == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chat.lockedResource == null) {
|
||||||
|
// According to XEP-0296, no action is required for resource locking upon receiving a presence if no
|
||||||
|
// resource is currently locked.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EntityFullJid fullFrom = from.asEntityFullJidIfPossible();
|
||||||
|
if (!chat.lockedResource.equals(fullFrom)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chat.lastPresenceOfLockedResource == null) {
|
||||||
|
// We have no last known presence from the locked resource.
|
||||||
|
chat.lastPresenceOfLockedResource = presence;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chat.lastPresenceOfLockedResource.getMode() != presence.getMode()
|
||||||
|
|| chat.lastPresenceOfLockedResource.getType() != presence.getType()) {
|
||||||
|
chat.unlockResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldAcceptMessage(Message message) {
|
||||||
|
if (!message.getBodies().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message has no XMPP-IM bodies, abort here if xhtmlIm is not enabled.
|
||||||
|
if (!xhtmlIm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XHTMLExtension xhtmlExtension = XHTMLExtension.from(message);
|
||||||
|
if (xhtmlExtension == null) {
|
||||||
|
// Message has no XHTML-IM extension, abort.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addListener(IncomingChatMessageListener listener) {
|
||||||
|
return incomingListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeListener(IncomingChatMessageListener listener) {
|
||||||
|
return incomingListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addListener(OutgoingChatMessageListener listener) {
|
||||||
|
return outgoingListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeOutoingLIstener(OutgoingChatMessageListener listener) {
|
||||||
|
return outgoingListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a new or retrieve the existing chat with <code>jid</code>.
|
||||||
|
*
|
||||||
|
* @param jid the XMPP address of the other entity to chat with.
|
||||||
|
* @return the Chat API for the given XMPP address.
|
||||||
|
*/
|
||||||
|
public Chat chatWith(EntityBareJid jid) {
|
||||||
|
Chat chat = chats.get(jid);
|
||||||
|
if (chat == null) {
|
||||||
|
synchronized (chats) {
|
||||||
|
// Double-checked locking.
|
||||||
|
chat = chats.get(jid);
|
||||||
|
if (chat != null) {
|
||||||
|
return chat;
|
||||||
|
}
|
||||||
|
chat = new Chat(connection(), jid);
|
||||||
|
chats.put(jid, chat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Also notify about messages containing XHTML-IM.
|
||||||
|
*
|
||||||
|
* @param xhtmlIm
|
||||||
|
*/
|
||||||
|
public void setXhmtlImEnabled(boolean xhtmlIm) {
|
||||||
|
this.xhtmlIm = xhtmlIm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.chat2;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
|
||||||
|
public interface IncomingChatMessageListener {
|
||||||
|
|
||||||
|
void newIncomingMessage(EntityBareJid from, Message message, Chat chat);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.chat2;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
|
||||||
|
public interface OutgoingChatMessageListener {
|
||||||
|
|
||||||
|
void newOutgoingMessage(EntityBareJid to, Message message, Chat chat);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smack's new improved API for 1:1 chats.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.chat2;
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.chatstates;
|
package org.jivesoftware.smackx.chatstates;
|
||||||
|
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatMessageListener;
|
import org.jivesoftware.smack.chat.ChatMessageListener;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
|
||||||
|
@ -35,5 +34,7 @@ public interface ChatStateListener extends ChatMessageListener {
|
||||||
* @param state the new state of the participant.
|
* @param state the new state of the participant.
|
||||||
* @param message the message carrying the chat state.
|
* @param message the message carrying the chat state.
|
||||||
*/
|
*/
|
||||||
void stateChanged(Chat chat, ChatState state, Message message);
|
// TODO Migrate to new chat2 API on Smack 4.3.
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
void stateChanged(org.jivesoftware.smack.chat.Chat chat, ChatState state, Message message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import org.jivesoftware.smack.MessageListener;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.Manager;
|
import org.jivesoftware.smack.Manager;
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManager;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManagerListener;
|
import org.jivesoftware.smack.chat.ChatManagerListener;
|
||||||
import org.jivesoftware.smack.chat.ChatMessageListener;
|
import org.jivesoftware.smack.chat.ChatMessageListener;
|
||||||
import org.jivesoftware.smack.filter.NotFilter;
|
import org.jivesoftware.smack.filter.NotFilter;
|
||||||
|
@ -49,6 +47,8 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
* @see org.jivesoftware.smackx.chatstates.ChatState
|
* @see org.jivesoftware.smackx.chatstates.ChatState
|
||||||
* @see org.jivesoftware.smackx.chatstates.packet.ChatStateExtension
|
* @see org.jivesoftware.smackx.chatstates.packet.ChatStateExtension
|
||||||
*/
|
*/
|
||||||
|
// TODO Migrate to new chat2 API on Smack 4.3.
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public final class ChatStateManager extends Manager {
|
public final class ChatStateManager extends Manager {
|
||||||
public static final String NAMESPACE = "http://jabber.org/protocol/chatstates";
|
public static final String NAMESPACE = "http://jabber.org/protocol/chatstates";
|
||||||
|
|
||||||
|
@ -79,13 +79,13 @@ public final class ChatStateManager extends Manager {
|
||||||
/**
|
/**
|
||||||
* Maps chat to last chat state.
|
* Maps chat to last chat state.
|
||||||
*/
|
*/
|
||||||
private final Map<Chat, ChatState> chatStates = new WeakHashMap<Chat, ChatState>();
|
private final Map<org.jivesoftware.smack.chat.Chat, ChatState> chatStates = new WeakHashMap<>();
|
||||||
|
|
||||||
private final ChatManager chatManager;
|
private final org.jivesoftware.smack.chat.ChatManager chatManager;
|
||||||
|
|
||||||
private ChatStateManager(XMPPConnection connection) {
|
private ChatStateManager(XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
chatManager = ChatManager.getInstanceFor(connection);
|
chatManager = org.jivesoftware.smack.chat.ChatManager.getInstanceFor(connection);
|
||||||
chatManager.addOutgoingMessageInterceptor(outgoingInterceptor, filter);
|
chatManager.addOutgoingMessageInterceptor(outgoingInterceptor, filter);
|
||||||
chatManager.addChatListener(incomingInterceptor);
|
chatManager.addChatListener(incomingInterceptor);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public final class ChatStateManager extends Manager {
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public void setCurrentState(ChatState newState, Chat chat) throws NotConnectedException, InterruptedException {
|
public void setCurrentState(ChatState newState, org.jivesoftware.smack.chat.Chat chat) throws NotConnectedException, InterruptedException {
|
||||||
if(chat == null || newState == null) {
|
if(chat == null || newState == null) {
|
||||||
throw new IllegalArgumentException("Arguments cannot be null.");
|
throw new IllegalArgumentException("Arguments cannot be null.");
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ public final class ChatStateManager extends Manager {
|
||||||
return connection().hashCode();
|
return connection().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean updateChatState(Chat chat, ChatState newState) {
|
private synchronized boolean updateChatState(org.jivesoftware.smack.chat.Chat chat, ChatState newState) {
|
||||||
ChatState lastChatState = chatStates.get(chat);
|
ChatState lastChatState = chatStates.get(chat);
|
||||||
if (lastChatState != newState) {
|
if (lastChatState != newState) {
|
||||||
chatStates.put(chat, newState);
|
chatStates.put(chat, newState);
|
||||||
|
@ -142,7 +142,7 @@ public final class ChatStateManager extends Manager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fireNewChatState(Chat chat, ChatState state, Message message) {
|
private static void fireNewChatState(org.jivesoftware.smack.chat.Chat chat, ChatState state, Message message) {
|
||||||
for (ChatMessageListener listener : chat.getListeners()) {
|
for (ChatMessageListener listener : chat.getListeners()) {
|
||||||
if (listener instanceof ChatStateListener) {
|
if (listener instanceof ChatStateListener) {
|
||||||
((ChatStateListener) listener).stateChanged(chat, state, message);
|
((ChatStateListener) listener).stateChanged(chat, state, message);
|
||||||
|
@ -154,7 +154,7 @@ public final class ChatStateManager extends Manager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processMessage(Message message) {
|
public void processMessage(Message message) {
|
||||||
Chat chat = chatManager.getThreadChat(message.getThread());
|
org.jivesoftware.smack.chat.Chat chat = chatManager.getThreadChat(message.getThread());
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -166,11 +166,11 @@ public final class ChatStateManager extends Manager {
|
||||||
|
|
||||||
private class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
|
private class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
|
||||||
|
|
||||||
public void chatCreated(final Chat chat, boolean createdLocally) {
|
public void chatCreated(final org.jivesoftware.smack.chat.Chat chat, boolean createdLocally) {
|
||||||
chat.addMessageListener(this);
|
chat.addMessageListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processMessage(Chat chat, Message message) {
|
public void processMessage(org.jivesoftware.smack.chat.Chat chat, Message message) {
|
||||||
ExtensionElement extension = message.getExtension(NAMESPACE);
|
ExtensionElement extension = message.getExtension(NAMESPACE);
|
||||||
if (extension == null) {
|
if (extension == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -96,7 +96,7 @@ public abstract class StreamNegotiator {
|
||||||
final String eventKey = initiation.getFrom().toString() + '\t' + initiation.getSessionID();
|
final String eventKey = initiation.getFrom().toString() + '\t' + initiation.getSessionID();
|
||||||
IQ streamMethodInitiation;
|
IQ streamMethodInitiation;
|
||||||
try {
|
try {
|
||||||
streamMethodInitiation = initationSetEvents.performActionAndWaitForEvent(eventKey, connection.getPacketReplyTimeout(), new Callback<NotConnectedException>() {
|
streamMethodInitiation = initationSetEvents.performActionAndWaitForEvent(eventKey, connection.getReplyTimeout(), new Callback<NotConnectedException>() {
|
||||||
@Override
|
@Override
|
||||||
public void action() throws NotConnectedException {
|
public void action() throws NotConnectedException {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -335,12 +335,19 @@ public final class AccountManager extends Manager {
|
||||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
XMPPConnection connection = connection();
|
XMPPConnection connection = connection();
|
||||||
|
|
||||||
ExtensionElement extensionElement = connection.getFeature(Registration.ELEMENT, Registration.NAMESPACE);
|
ExtensionElement extensionElement = connection.getFeature(Registration.Feature.ELEMENT,
|
||||||
|
Registration.Feature.NAMESPACE);
|
||||||
if (extensionElement != null) {
|
if (extensionElement != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ServiceDiscoveryManager.getInstanceFor(connection).serverSupportsFeature(Registration.NAMESPACE);
|
// Fallback to disco#info only if this connection is authenticated, as otherwise we won't have an full JID and
|
||||||
|
// won't be able to do IQs.
|
||||||
|
if (connection.isAuthenticated()) {
|
||||||
|
return ServiceDiscoveryManager.getInstanceFor(connection).serverSupportsFeature(Registration.NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,8 +37,6 @@ import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManager;
|
|
||||||
import org.jivesoftware.smack.chat.ChatMessageListener;
|
import org.jivesoftware.smack.chat.ChatMessageListener;
|
||||||
import org.jivesoftware.smack.filter.AndFilter;
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
import org.jivesoftware.smack.filter.FromMatchesFilter;
|
import org.jivesoftware.smack.filter.FromMatchesFilter;
|
||||||
|
@ -357,7 +355,7 @@ public class MultiUserChat {
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public MucEnterConfiguration.Builder getEnterConfigurationBuilder(Resourcepart nickname) {
|
public MucEnterConfiguration.Builder getEnterConfigurationBuilder(Resourcepart nickname) {
|
||||||
return new MucEnterConfiguration.Builder(nickname, connection.getPacketReplyTimeout());
|
return new MucEnterConfiguration.Builder(nickname, connection.getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1847,8 +1845,11 @@ public class MultiUserChat {
|
||||||
* created chat.
|
* created chat.
|
||||||
* @return new Chat for sending private messages to a given room occupant.
|
* @return new Chat for sending private messages to a given room occupant.
|
||||||
*/
|
*/
|
||||||
public Chat createPrivateChat(EntityFullJid occupant, ChatMessageListener listener) {
|
// TODO This should be made new not using chat.Chat. Private MUC chats are different from XMPP-IM 1:1 chats in to many ways.
|
||||||
return ChatManager.getInstanceFor(connection).createChat(occupant, listener);
|
// API sketch: PrivateMucChat createPrivateChat(Resourcepart nick)
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public org.jivesoftware.smack.chat.Chat createPrivateChat(EntityFullJid occupant, ChatMessageListener listener) {
|
||||||
|
return org.jivesoftware.smack.chat.ChatManager.getInstanceFor(connection).createChat(occupant, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -158,12 +158,14 @@ public class OfflineMessageManager {
|
||||||
return nodes.contains(info.getNode());
|
return nodes.contains(info.getNode());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
int pendingNodes = nodes.size();
|
||||||
StanzaCollector messageCollector = connection.createStanzaCollector(messageFilter);
|
StanzaCollector messageCollector = connection.createStanzaCollector(messageFilter);
|
||||||
try {
|
try {
|
||||||
connection.createStanzaCollectorAndSend(request).nextResultOrThrow();
|
connection.createStanzaCollectorAndSend(request).nextResultOrThrow();
|
||||||
// Collect the received offline messages
|
// Collect the received offline messages
|
||||||
Message message = messageCollector.nextResult();
|
Message message = messageCollector.nextResult();
|
||||||
while (message != null) {
|
while (message != null && pendingNodes > 0) {
|
||||||
|
pendingNodes--;
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
message = messageCollector.nextResult();
|
message = messageCollector.nextResult();
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ public final class PingManager extends Manager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public boolean ping(Jid jid) throws NotConnectedException, NoResponseException, InterruptedException {
|
public boolean ping(Jid jid) throws NotConnectedException, NoResponseException, InterruptedException {
|
||||||
return ping(jid, connection().getPacketReplyTimeout());
|
return ping(jid, connection().getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -231,7 +231,7 @@ public final class PingManager extends Manager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public boolean pingMyServer(boolean notifyListeners) throws NotConnectedException, InterruptedException {
|
public boolean pingMyServer(boolean notifyListeners) throws NotConnectedException, InterruptedException {
|
||||||
return pingMyServer(notifyListeners, connection().getPacketReplyTimeout());
|
return pingMyServer(notifyListeners, connection().getReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -248,7 +248,7 @@ public class PingTest extends InitExtensions {
|
||||||
*/
|
*/
|
||||||
private static DummyConnection getAuthenticatedDummyConnectionWithoutIqReplies() throws SmackException, IOException, XMPPException, InterruptedException {
|
private static DummyConnection getAuthenticatedDummyConnectionWithoutIqReplies() throws SmackException, IOException, XMPPException, InterruptedException {
|
||||||
DummyConnection con = new DummyConnection();
|
DummyConnection con = new DummyConnection();
|
||||||
con.setPacketReplyTimeout(500);
|
con.setReplyTimeout(500);
|
||||||
con.connect();
|
con.connect();
|
||||||
con.login();
|
con.login();
|
||||||
return con;
|
return con;
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class ConfigureFormTest
|
||||||
|
|
||||||
Node node = mgr.getNode("princely_musings");
|
Node node = mgr.getNode("princely_musings");
|
||||||
|
|
||||||
SmackConfiguration.setDefaultPacketReplyTimeout(100);
|
SmackConfiguration.setDefaultReplyTimeout(100);
|
||||||
con.setTimeout();
|
con.setTimeout();
|
||||||
|
|
||||||
node.getNodeConfiguration();
|
node.getNodeConfiguration();
|
||||||
|
|
|
@ -36,7 +36,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
* sender.
|
* sender.
|
||||||
*
|
*
|
||||||
* @author Matt Tucker
|
* @author Matt Tucker
|
||||||
|
* @deprecated use <code>org.jivesoftware.smack.chat2.Chat</code> from <code>smack-extensions</code> instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class Chat {
|
public class Chat {
|
||||||
|
|
||||||
private ChatManager chatManager;
|
private ChatManager chatManager;
|
||||||
|
|
|
@ -52,7 +52,9 @@ import org.jxmpp.jid.EntityJid;
|
||||||
* made aware of new chats, register a listener by calling {@link #addChatListener(ChatManagerListener)}.
|
* made aware of new chats, register a listener by calling {@link #addChatListener(ChatManagerListener)}.
|
||||||
*
|
*
|
||||||
* @author Alexander Wenckus
|
* @author Alexander Wenckus
|
||||||
|
* @deprecated use <code>org.jivesoftware.smack.chat2.ChatManager</code> from <code>smack-extensions</code> instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final class ChatManager extends Manager{
|
public final class ChatManager extends Manager{
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(ChatManager.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(ChatManager.class.getName());
|
||||||
|
|
|
@ -30,5 +30,6 @@ public interface ChatManagerListener {
|
||||||
* @param chat the chat that was created.
|
* @param chat the chat that was created.
|
||||||
* @param createdLocally true if the chat was created by the local user and false if it wasn't.
|
* @param createdLocally true if the chat was created by the local user and false if it wasn't.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
void chatCreated(Chat chat, boolean createdLocally);
|
void chatCreated(Chat chat, boolean createdLocally);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,6 @@ package org.jivesoftware.smack.chat;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
|
||||||
public interface ChatMessageListener {
|
public interface ChatMessageListener {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
void processMessage(Chat chat, Message message);
|
void processMessage(Chat chat, Message message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -473,7 +473,7 @@ public final class Roster extends Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean waitUntilLoaded() throws InterruptedException {
|
protected boolean waitUntilLoaded() throws InterruptedException {
|
||||||
long waitTime = connection().getPacketReplyTimeout();
|
long waitTime = connection().getReplyTimeout();
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
while (!isLoaded()) {
|
while (!isLoaded()) {
|
||||||
if (waitTime <= 0) {
|
if (waitTime <= 0) {
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.jivesoftware.smack.DummyConnection;
|
import org.jivesoftware.smack.DummyConnection;
|
||||||
import org.jivesoftware.smack.chat.ChatManager.MatchMode;
|
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.Message.Type;
|
import org.jivesoftware.smack.packet.Message.Type;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
@ -35,6 +34,7 @@ import org.junit.Test;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
import org.jxmpp.jid.JidTestUtil;
|
import org.jxmpp.jid.JidTestUtil;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class ChatConnectionTest {
|
public class ChatConnectionTest {
|
||||||
|
|
||||||
private DummyConnection dc;
|
private DummyConnection dc;
|
||||||
|
@ -46,7 +46,7 @@ public class ChatConnectionTest {
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// Defaults
|
// Defaults
|
||||||
ChatManager.setDefaultIsNormalIncluded(true);
|
ChatManager.setDefaultIsNormalIncluded(true);
|
||||||
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
|
ChatManager.setDefaultMatchMode(ChatManager.MatchMode.BARE_JID);
|
||||||
|
|
||||||
dc = DummyConnection.newConnectedDummyConnection();
|
dc = DummyConnection.newConnectedDummyConnection();
|
||||||
cm = ChatManager.getInstanceFor(dc);
|
cm = ChatManager.getInstanceFor(dc);
|
||||||
|
@ -77,14 +77,14 @@ public class ChatConnectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateDefaultSetMatchModeNone() {
|
public void validateDefaultSetMatchModeNone() {
|
||||||
ChatManager.setDefaultMatchMode(MatchMode.NONE);
|
ChatManager.setDefaultMatchMode(ChatManager.MatchMode.NONE);
|
||||||
assertEquals(MatchMode.NONE, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
|
assertEquals(ChatManager.MatchMode.NONE, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateDefaultSetMatchModeEntityBareJid() {
|
public void validateDefaultSetMatchModeEntityBareJid() {
|
||||||
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
|
ChatManager.setDefaultMatchMode(ChatManager.MatchMode.BARE_JID);
|
||||||
assertEquals(MatchMode.BARE_JID, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
|
assertEquals(ChatManager.MatchMode.BARE_JID, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -138,7 +138,7 @@ public class ChatConnectionTest {
|
||||||
// No thread behaviour
|
// No thread behaviour
|
||||||
@Test
|
@Test
|
||||||
public void chatMatchedOnJIDWhenNoThreadBareMode() {
|
public void chatMatchedOnJIDWhenNoThreadBareMode() {
|
||||||
// MatchMode.BARE_JID is the default, so setting required.
|
// ChatManager.MatchMode.BARE_JID is the default, so setting required.
|
||||||
TestMessageListener msgListener = new TestMessageListener();
|
TestMessageListener msgListener = new TestMessageListener();
|
||||||
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
||||||
cm.addChatListener(listener);
|
cm.addChatListener(listener);
|
||||||
|
@ -162,7 +162,7 @@ public class ChatConnectionTest {
|
||||||
public void chatMatchedOnJIDWhenNoThreadJidMode() {
|
public void chatMatchedOnJIDWhenNoThreadJidMode() {
|
||||||
TestMessageListener msgListener = new TestMessageListener();
|
TestMessageListener msgListener = new TestMessageListener();
|
||||||
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
||||||
cm.setMatchMode(MatchMode.SUPPLIED_JID);
|
cm.setMatchMode(ChatManager.MatchMode.SUPPLIED_JID);
|
||||||
cm.addChatListener(listener);
|
cm.addChatListener(listener);
|
||||||
Stanza incomingChat = createChatPacket(null, true);
|
Stanza incomingChat = createChatPacket(null, true);
|
||||||
processServerMessage(incomingChat);
|
processServerMessage(incomingChat);
|
||||||
|
@ -188,7 +188,7 @@ public class ChatConnectionTest {
|
||||||
public void chatMatchedOnJIDWhenNoThreadNoneMode() {
|
public void chatMatchedOnJIDWhenNoThreadNoneMode() {
|
||||||
TestMessageListener msgListener = new TestMessageListener();
|
TestMessageListener msgListener = new TestMessageListener();
|
||||||
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
|
||||||
cm.setMatchMode(MatchMode.NONE);
|
cm.setMatchMode(ChatManager.MatchMode.NONE);
|
||||||
cm.addChatListener(listener);
|
cm.addChatListener(listener);
|
||||||
Stanza incomingChat = createChatPacket(null, true);
|
Stanza incomingChat = createChatPacket(null, true);
|
||||||
processServerMessage(incomingChat);
|
processServerMessage(incomingChat);
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class RosterTest extends InitSmackIm {
|
||||||
rosterListener = new TestRosterListener();
|
rosterListener = new TestRosterListener();
|
||||||
roster = Roster.getInstanceFor(connection);
|
roster = Roster.getInstanceFor(connection);
|
||||||
roster.addRosterListener(rosterListener);
|
roster.addRosterListener(rosterListener);
|
||||||
connection.setPacketReplyTimeout(1000 * 60 * 5);
|
connection.setReplyTimeout(1000 * 60 * 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class SubscriptionPreApprovalTest extends InitSmackIm {
|
||||||
rosterListener = new TestRosterListener();
|
rosterListener = new TestRosterListener();
|
||||||
roster = Roster.getInstanceFor(connection);
|
roster = Roster.getInstanceFor(connection);
|
||||||
roster.addRosterListener(rosterListener);
|
roster.addRosterListener(rosterListener);
|
||||||
connection.setPacketReplyTimeout(1000 * 60 * 5);
|
connection.setReplyTimeout(1000 * 60 * 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class SmackIntegrationTestFramework {
|
||||||
SmackConfiguration.DEBUG = true;
|
SmackConfiguration.DEBUG = true;
|
||||||
}
|
}
|
||||||
if (config.replyTimeout > 0) {
|
if (config.replyTimeout > 0) {
|
||||||
SmackConfiguration.setDefaultPacketReplyTimeout(config.replyTimeout);
|
SmackConfiguration.setDefaultReplyTimeout(config.replyTimeout);
|
||||||
}
|
}
|
||||||
if (config.securityMode != SecurityMode.required) {
|
if (config.securityMode != SecurityMode.required) {
|
||||||
AccountManager.sensitiveOperationOverInsecureConnectionDefault(true);
|
AccountManager.sensitiveOperationOverInsecureConnectionDefault(true);
|
||||||
|
|
|
@ -31,8 +31,6 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManager;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManagerListener;
|
import org.jivesoftware.smack.chat.ChatManagerListener;
|
||||||
import org.jivesoftware.smack.filter.ThreadFilter;
|
import org.jivesoftware.smack.filter.ThreadFilter;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
@ -46,12 +44,14 @@ import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
*/
|
*/
|
||||||
public class ChatTest extends AbstractSmackIntegrationTest {
|
public class ChatTest extends AbstractSmackIntegrationTest {
|
||||||
|
|
||||||
private final ChatManager chatManagerOne;
|
@SuppressWarnings("deprecation")
|
||||||
|
private final org.jivesoftware.smack.chat.ChatManager chatManagerOne;
|
||||||
private boolean invoked;
|
private boolean invoked;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public ChatTest(SmackIntegrationTestEnvironment environment) {
|
public ChatTest(SmackIntegrationTestEnvironment environment) {
|
||||||
super(environment);
|
super(environment);
|
||||||
chatManagerOne = ChatManager.getInstanceFor(conOne);
|
chatManagerOne = org.jivesoftware.smack.chat.ChatManager.getInstanceFor(conOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -64,9 +64,10 @@ public class ChatTest extends AbstractSmackIntegrationTest {
|
||||||
JivePropertiesManager.setJavaObjectEnabled(false);
|
JivePropertiesManager.setJavaObjectEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@SmackIntegrationTest
|
@SmackIntegrationTest
|
||||||
public void testProperties() throws XmppStringprepException, NotConnectedException, Exception {
|
public void testProperties() throws XmppStringprepException, NotConnectedException, Exception {
|
||||||
Chat newChat = chatManagerOne.createChat(conTwo.getUser());
|
org.jivesoftware.smack.chat.Chat newChat = chatManagerOne.createChat(conTwo.getUser());
|
||||||
StanzaCollector collector = conTwo.createStanzaCollector(new ThreadFilter(newChat.getThreadID()));
|
StanzaCollector collector = conTwo.createStanzaCollector(new ThreadFilter(newChat.getThreadID()));
|
||||||
|
|
||||||
Message msg = new Message();
|
Message msg = new Message();
|
||||||
|
@ -112,12 +113,13 @@ public class ChatTest extends AbstractSmackIntegrationTest {
|
||||||
getProperty(msg2, "birthdate"));
|
getProperty(msg2, "birthdate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@SmackIntegrationTest
|
@SmackIntegrationTest
|
||||||
public void chatManagerTest() {
|
public void chatManagerTest() {
|
||||||
ChatManagerListener listener = new ChatManagerListener() {
|
ChatManagerListener listener = new ChatManagerListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void chatCreated(Chat chat, boolean createdLocally) {
|
public void chatCreated(org.jivesoftware.smack.chat.Chat chat, boolean createdLocally) {
|
||||||
invoked = true;
|
invoked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
try {
|
try {
|
||||||
rosterOne.createEntry(conTwo.getUser().asBareJid(), conTwosRosterName, null);
|
rosterOne.createEntry(conTwo.getUser().asBareJid(), conTwosRosterName, null);
|
||||||
|
|
||||||
assertTrue(addedAndSubscribed.waitForResult(2 * connection.getPacketReplyTimeout()));
|
assertTrue(addedAndSubscribed.waitForResult(2 * connection.getReplyTimeout()));
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
rosterTwo.removeSubscribeListener(subscribeListener);
|
rosterTwo.removeSubscribeListener(subscribeListener);
|
||||||
|
|
|
@ -26,8 +26,6 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.StanzaCollector;
|
import org.jivesoftware.smack.StanzaCollector;
|
||||||
import org.jivesoftware.smack.chat.Chat;
|
|
||||||
import org.jivesoftware.smack.chat.ChatManager;
|
|
||||||
import org.jivesoftware.smack.filter.ThreadFilter;
|
import org.jivesoftware.smack.filter.ThreadFilter;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
@ -51,7 +49,8 @@ public class FormTest extends AbstractSmackIntegrationTest {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
*/
|
*/
|
||||||
@SmackIntegrationTest
|
@SuppressWarnings("deprecation")
|
||||||
|
@SmackIntegrationTest
|
||||||
public void testFilloutForm() throws NotConnectedException, InterruptedException {
|
public void testFilloutForm() throws NotConnectedException, InterruptedException {
|
||||||
Form formToSend = new Form(DataForm.Type.form);
|
Form formToSend = new Form(DataForm.Type.form);
|
||||||
formToSend.setInstructions(
|
formToSend.setInstructions(
|
||||||
|
@ -88,7 +87,7 @@ public class FormTest extends AbstractSmackIntegrationTest {
|
||||||
formToSend.addField(field);
|
formToSend.addField(field);
|
||||||
|
|
||||||
// Create the chats between the two participants
|
// Create the chats between the two participants
|
||||||
Chat chat = ChatManager.getInstanceFor(conOne).createChat(conTwo.getUser(), null);
|
org.jivesoftware.smack.chat.Chat chat = org.jivesoftware.smack.chat.ChatManager.getInstanceFor(conOne).createChat(conTwo.getUser(), null);
|
||||||
StanzaCollector collector = conOne.createStanzaCollector(
|
StanzaCollector collector = conOne.createStanzaCollector(
|
||||||
new ThreadFilter(chat.getThreadID()));
|
new ThreadFilter(chat.getThreadID()));
|
||||||
StanzaCollector collector2 = conTwo.createStanzaCollector(
|
StanzaCollector collector2 = conTwo.createStanzaCollector(
|
||||||
|
|
|
@ -75,8 +75,8 @@ public class IoT {
|
||||||
final XMPPTCPConnection dataThingConnection = new XMPPTCPConnection(dataThingConnectionConfiguration);
|
final XMPPTCPConnection dataThingConnection = new XMPPTCPConnection(dataThingConnectionConfiguration);
|
||||||
final XMPPTCPConnection readingThingConnection = new XMPPTCPConnection(readingThingConnectionConfiguration);
|
final XMPPTCPConnection readingThingConnection = new XMPPTCPConnection(readingThingConnectionConfiguration);
|
||||||
|
|
||||||
dataThingConnection.setPacketReplyTimeout(TIMEOUT);
|
dataThingConnection.setReplyTimeout(TIMEOUT);
|
||||||
readingThingConnection.setPacketReplyTimeout(TIMEOUT);
|
readingThingConnection.setReplyTimeout(TIMEOUT);
|
||||||
|
|
||||||
dataThingConnection.setUseStreamManagement(false);
|
dataThingConnection.setUseStreamManagement(false);
|
||||||
readingThingConnection.setUseStreamManagement(false);
|
readingThingConnection.setUseStreamManagement(false);
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class TlsTest {
|
||||||
|
|
||||||
XMPPTCPConnection connection = new XMPPTCPConnection(builder.build());
|
XMPPTCPConnection connection = new XMPPTCPConnection(builder.build());
|
||||||
|
|
||||||
connection.setPacketReplyTimeout(20000);
|
connection.setReplyTimeout(20000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection.connect().login();
|
connection.connect().login();
|
||||||
|
|
|
@ -20,8 +20,10 @@ import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
|
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
|
||||||
import org.jivesoftware.smack.initializer.SmackInitializer;
|
import org.jivesoftware.smack.initializer.SmackInitializer;
|
||||||
|
@ -126,10 +128,28 @@ public class MiniDnsResolver extends DNSResolver implements SmackInitializer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<InetAddress> inetAddresses = new ArrayList<>(aResult.getAnswers().size()
|
// TODO: Use ResolverResult.getAnswersOrEmptySet() once we updated MiniDNS.
|
||||||
+ aaaaResult.getAnswers().size());
|
Set<A> aResults;
|
||||||
|
if (aResult.wasSuccessful()) {
|
||||||
|
aResults = aResult.getAnswers();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aResults = Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
for (A a : aResult.getAnswers()) {
|
// TODO: Use ResolverResult.getAnswersOrEmptySet() once we updated MiniDNS.
|
||||||
|
Set<AAAA> aaaaResults;
|
||||||
|
if (aaaaResult.wasSuccessful()) {
|
||||||
|
aaaaResults = aaaaResult.getAnswers();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aaaaResults = Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<InetAddress> inetAddresses = new ArrayList<>(aResults.size()
|
||||||
|
+ aaaaResults.size());
|
||||||
|
|
||||||
|
for (A a : aResults) {
|
||||||
InetAddress inetAddress;
|
InetAddress inetAddress;
|
||||||
try {
|
try {
|
||||||
inetAddress = InetAddress.getByAddress(a.getIp());
|
inetAddress = InetAddress.getByAddress(a.getIp());
|
||||||
|
@ -139,7 +159,7 @@ public class MiniDnsResolver extends DNSResolver implements SmackInitializer {
|
||||||
}
|
}
|
||||||
inetAddresses.add(inetAddress);
|
inetAddresses.add(inetAddress);
|
||||||
}
|
}
|
||||||
for (AAAA aaaa : aaaaResult.getAnswers()) {
|
for (AAAA aaaa : aaaaResults) {
|
||||||
InetAddress inetAddress;
|
InetAddress inetAddress;
|
||||||
try {
|
try {
|
||||||
inetAddress = InetAddress.getByAddress(name, aaaa.getIp());
|
inetAddress = InetAddress.getByAddress(name, aaaa.getIp());
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.jivesoftware.smack.packet.StreamOpen;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
import org.jivesoftware.smack.packet.Presence;
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
import org.jivesoftware.smack.packet.StartTls;
|
import org.jivesoftware.smack.packet.StartTls;
|
||||||
|
import org.jivesoftware.smack.packet.StreamError;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Challenge;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Challenge;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
||||||
|
@ -593,6 +594,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
}
|
}
|
||||||
failedAddresses.add(hostAddress);
|
failedAddresses.add(hostAddress);
|
||||||
} else {
|
} else {
|
||||||
|
socket = socketFactory.createSocket();
|
||||||
|
StringUtils.requireNotNullOrEmpty(host, "Host of HostAddress " + hostAddress + " must not be null when using a Proxy");
|
||||||
final String hostAndPort = host + " at port " + port;
|
final String hostAndPort = host + " at port " + port;
|
||||||
LOGGER.finer("Trying to establish TCP connection via Proxy to " + hostAndPort);
|
LOGGER.finer("Trying to establish TCP connection via Proxy to " + hostAndPort);
|
||||||
try {
|
try {
|
||||||
|
@ -922,13 +925,19 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE);
|
StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE);
|
||||||
if (startTlsFeature != null) {
|
if (startTlsFeature != null) {
|
||||||
if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) {
|
if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) {
|
||||||
notifyConnectionError(new SecurityRequiredByServerException());
|
SmackException smackException = new SecurityRequiredByServerException();
|
||||||
|
tlsHandled.reportFailure(smackException);
|
||||||
|
notifyConnectionError(smackException);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getSecurityMode() != ConnectionConfiguration.SecurityMode.disabled) {
|
if (config.getSecurityMode() != ConnectionConfiguration.SecurityMode.disabled) {
|
||||||
sendNonza(new StartTls());
|
sendNonza(new StartTls());
|
||||||
|
} else {
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSASLAuthentication().authenticationSuccessful()) {
|
if (getSASLAuthentication().authenticationSuccessful()) {
|
||||||
|
@ -1027,7 +1036,13 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "error":
|
case "error":
|
||||||
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
|
StreamError streamError = PacketParserUtils.parseStreamError(parser);
|
||||||
|
saslFeatureReceived.reportFailure(new StreamErrorException(streamError));
|
||||||
|
// Mark the tlsHandled sync point as success, we will use the saslFeatureReceived sync
|
||||||
|
// point to report the error, which is checked immediately after tlsHandled in
|
||||||
|
// connectInternal().
|
||||||
|
tlsHandled.reportSuccess();
|
||||||
|
throw new StreamErrorException(streamError);
|
||||||
case "features":
|
case "features":
|
||||||
parseFeatures(parser);
|
parseFeatures(parser);
|
||||||
break;
|
break;
|
||||||
|
@ -1039,9 +1054,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
openStream();
|
openStream();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
// We report any failure regarding TLS in the second stage of XMPP
|
SmackException smackException = new SmackException(e);
|
||||||
// connection establishment, namely the SASL authentication
|
tlsHandled.reportFailure(smackException);
|
||||||
saslFeatureReceived.reportFailure(new SmackException(e));
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue