mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 06:12:05 +01:00
Merge branch '4.2'
This commit is contained in:
commit
81002c4fbd
63 changed files with 391 additions and 266 deletions
|
@ -79,6 +79,14 @@ allprojects {
|
||||||
':smack-android',
|
':smack-android',
|
||||||
':smack-android-extensions',
|
':smack-android-extensions',
|
||||||
].collect{ project(it) }
|
].collect{ project(it) }
|
||||||
|
androidOptionalProjects = [
|
||||||
|
':smack-tcp',
|
||||||
|
':smack-extensions',
|
||||||
|
':smack-experimental',
|
||||||
|
':smack-bosh',
|
||||||
|
':smack-omemo',
|
||||||
|
':smack-omemo-signal',
|
||||||
|
].collect{ project(it) }
|
||||||
gplLicensedProjects = [
|
gplLicensedProjects = [
|
||||||
':smack-omemo-signal',
|
':smack-omemo-signal',
|
||||||
':smack-omemo-signal-integration-test',
|
':smack-omemo-signal-integration-test',
|
||||||
|
|
|
@ -60,6 +60,10 @@
|
||||||
<property name="format" value="^\s*[\S&&[^\*/]]+\s+$"/>
|
<property name="format" value="^\s*[\S&&[^\*/]]+\s+$"/>
|
||||||
<property name="message" value="Line containing trailing whitespace character(s)"/>
|
<property name="message" value="Line containing trailing whitespace character(s)"/>
|
||||||
</module>
|
</module>
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="^\s*//[^\s]"/>
|
||||||
|
<property name="message" value="Comment start ('//') followed by non-space character. You would not continue after a punctuation without a space, would you?"/>
|
||||||
|
</module>
|
||||||
<module name="JavadocPackage"/>
|
<module name="JavadocPackage"/>
|
||||||
<module name="TreeWalker">
|
<module name="TreeWalker">
|
||||||
<module name="FinalClass"/>
|
<module name="FinalClass"/>
|
||||||
|
|
|
@ -6,24 +6,24 @@ Smack: Getting Started
|
||||||
This document will introduce you to the Smack API and provide an overview of
|
This document will introduce you to the Smack API and provide an overview of
|
||||||
important classes and concepts.
|
important classes and concepts.
|
||||||
|
|
||||||
JAR Files and Requirements
|
Smack Modules and Requirements
|
||||||
--------------------------
|
-------------------------------
|
||||||
|
|
||||||
Smack is meant to be easily embedded into any existing Java application. The
|
Smack is meant to be easily embedded into any existing Java application. The
|
||||||
library ships as several JAR files to provide more flexibility over which
|
library ships as several modulesto provide more flexibility over which
|
||||||
features applications require:
|
features applications require:
|
||||||
|
|
||||||
* `smack-core.jar` -- provides core XMPP functionality. All XMPP features that are part of the XMPP RFCs are included.
|
* `smack-core` -- provides core XMPP functionality. All XMPP features that are part of the XMPP RFCs are included.
|
||||||
* `smack-im.jar` -- provides functinoality defined in RFC 6121 (XMPP-IM), like the Roster.
|
* `smack-im` -- provides functinoality defined in RFC 6121 (XMPP-IM), like the Roster.
|
||||||
* `smack-tcp.jar` -- support for XMPP over TCP. Includes XMPPTCPConnection class, which you usually want to use
|
* `smack-tcp` -- support for XMPP over TCP. Includes XMPPTCPConnection class, which you usually want to use
|
||||||
* `smack-extensions.jar` -- support for many of the extensions (XEPs) defined by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc. The extensions are documented in the [extensions manual](extensions/index.md).
|
* `smack-extensions` -- support for many of the extensions (XEPs) defined by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc. The extensions are documented in the [extensions manual](extensions/index.md).
|
||||||
* `smack-experimental.jar` -- support for experimental extensions (XEPs) defined by the XMPP Standards Foundation. The API and functionality of those extensions should be considered as unstable.
|
* `smack-experimental` -- support for experimental extensions (XEPs) defined by the XMPP Standards Foundation. The API and functionality of those extensions should be considered as unstable.
|
||||||
* `smack-legacy.jar` -- support for legacy extensions (XEPs) defined by the XMPP Standards Foundation.
|
* `smack-legacy` -- support for legacy extensions (XEPs) defined by the XMPP Standards Foundation.
|
||||||
* `smack-bosh.jar` -- support for BOSH (XEP-0124). This code should be considered as beta.
|
* `smack-bosh` -- support for BOSH (XEP-0124). This code should be considered as beta.
|
||||||
* `smack-jingle.jar` -- support for Jingle. This code is old and currenlty unmaintained.
|
* `smack-resolver-minidns` -- support for resolving DNS SRV records with the help of MiniDNS. Ideal for platforms that do not support the javax.naming API. Also supports [DNSSEC](dnssec.md).
|
||||||
* `smack-resolver-dnsjava.jar` -- support for resolving DNS SRV records with the help of dnsjava. Ideal for platforms that do not support the javax.naming API.
|
* `smack-resolver-dnsjava` -- support for resolving DNS SRV records with the help of dnsjava.
|
||||||
* `smack-resolver-javax.jar` -- support for resolving DNS SRV records with the javax namespace API.
|
* `smack-resolver-javax` -- support for resolving DNS SRV records with the javax namespace API.
|
||||||
* `smack-debug.jar` -- an enhanced GUI debugger for protocol traffic. It will automatically be used when found in the classpath and when [debugging](debugging.md) is enabled.
|
* `smack-debug` -- an enhanced GUI debugger for protocol traffic. It will automatically be used when found in the classpath and when [debugging](debugging.md) is enabled.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
@ -46,10 +46,14 @@ The `XMPPTCPConnection` class is used to create a connection to an XMPP
|
||||||
server. Below are code examples for making a connection:
|
server. Below are code examples for making a connection:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Create a connection to the jabber.org server.
|
// Create a connection and login to the example.org XMPP service.
|
||||||
AbstractXMPPConnection conn1 = **new** XMPPTCPConnection("username", "password", "jabber.org");
|
AbstractXMPPConnection connection = new XMPPTCPConnection("username", "password" "example.org");
|
||||||
conn1.connect();
|
conn1.connect().login();
|
||||||
|
```
|
||||||
|
|
||||||
|
Further connection parameters can be configured by using a configuration builder:
|
||||||
|
|
||||||
|
```
|
||||||
// Create a connection to the jabber.org server on a specific port.
|
// Create a connection to the jabber.org server on a specific port.
|
||||||
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
|
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
|
||||||
.setUsernameAndPassword("username", "password")
|
.setUsernameAndPassword("username", "password")
|
||||||
|
@ -59,7 +63,7 @@ XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
AbstractXMPPConnection conn2 = **new** XMPPTCPConnection(config);
|
AbstractXMPPConnection conn2 = **new** XMPPTCPConnection(config);
|
||||||
conn2.connect();
|
conn2.connect().login();
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that maximum security will be used when connecting to the server by
|
Note that maximum security will be used when connecting to the server by
|
||||||
|
|
|
@ -9,9 +9,8 @@ smack-extensions and smack-experimental."""
|
||||||
dependencies {
|
dependencies {
|
||||||
// androidProjects lists all projects that are checked to compile against android.jar
|
// androidProjects lists all projects that are checked to compile against android.jar
|
||||||
// Filter out the optional Smack dependencies from androidProjects
|
// Filter out the optional Smack dependencies from androidProjects
|
||||||
androidProjects.findAll {
|
(androidProjects - androidOptionalProjects)
|
||||||
![':smack-tcp', ':smack-extensions', ':smack-experimental', ':smack-bosh'].contains(it.getPath())
|
.each { project ->
|
||||||
}.each { project ->
|
|
||||||
compile project
|
compile project
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -524,7 +524,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "error":
|
case "error":
|
||||||
//Some bosh error isn't stream error.
|
// Some BOSH error isn't stream error.
|
||||||
if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) {
|
if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) {
|
||||||
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
|
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.jivesoftware.smack.SmackException.AlreadyConnectedException;
|
||||||
import org.jivesoftware.smack.SmackException.AlreadyLoggedInException;
|
import org.jivesoftware.smack.SmackException.AlreadyLoggedInException;
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException;
|
import org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException;
|
||||||
import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException;
|
import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException;
|
||||||
import org.jivesoftware.smack.SmackException.SecurityRequiredException;
|
import org.jivesoftware.smack.SmackException.SecurityRequiredException;
|
||||||
|
@ -1541,7 +1542,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
final StanzaListener packetListener = new StanzaListener() {
|
final StanzaListener packetListener = new StanzaListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
|
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException {
|
||||||
boolean removed = removeAsyncStanzaListener(this);
|
boolean removed = removeAsyncStanzaListener(this);
|
||||||
if (!removed) {
|
if (!removed) {
|
||||||
// We lost a race against the "no response" handling runnable. Avoid calling the callback, as the
|
// We lost a race against the "no response" handling runnable. Avoid calling the callback, as the
|
||||||
|
@ -1609,7 +1610,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
public void addOneTimeSyncCallback(final StanzaListener callback, final StanzaFilter packetFilter) {
|
public void addOneTimeSyncCallback(final StanzaListener callback, final StanzaFilter packetFilter) {
|
||||||
final StanzaListener packetListener = new StanzaListener() {
|
final StanzaListener packetListener = new StanzaListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
|
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException {
|
||||||
try {
|
try {
|
||||||
callback.processStanza(packet);
|
callback.processStanza(packet);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.jivesoftware.smack;
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +50,8 @@ public interface StanzaListener {
|
||||||
* @param packet the stanza(/packet) to process.
|
* @param packet the stanza(/packet) to process.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
|
* @throws NotLoggedInException
|
||||||
*/
|
*/
|
||||||
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException;
|
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,15 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
|
|
||||||
private Type type = Type.available;
|
private Type type = Type.available;
|
||||||
private String status = null;
|
private String status = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The priority of the presence. The magic value {@link Integer#MIN_VALUE} is used to indicate that the original
|
||||||
|
* presence stanza did not had an explicit priority set. In which case the priority defaults to 0.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3.</a>
|
||||||
|
*/
|
||||||
private int priority = Integer.MIN_VALUE;
|
private int priority = Integer.MIN_VALUE;
|
||||||
|
|
||||||
private Mode mode = null;
|
private Mode mode = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,6 +209,9 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
|
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
|
||||||
*/
|
*/
|
||||||
public int getPriority() {
|
public int getPriority() {
|
||||||
|
if (priority == Integer.MIN_VALUE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,9 +226,13 @@ public class XMPPError extends AbstractError {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XMPPError.Builder from(Condition condition, String descriptiveText) {
|
public static XMPPError.Builder from(Condition condition, String descriptiveText) {
|
||||||
Map<String, String> descriptiveTexts = new HashMap<String, String>();
|
XMPPError.Builder builder = getBuilder().setCondition(condition);
|
||||||
|
if (descriptiveText != null) {
|
||||||
|
Map<String, String> descriptiveTexts = new HashMap<>();
|
||||||
descriptiveTexts.put("en", descriptiveText);
|
descriptiveTexts.put("en", descriptiveText);
|
||||||
return getBuilder().setCondition(condition).setDescriptiveTexts(descriptiveTexts);
|
builder.setDescriptiveTexts(descriptiveTexts);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder getBuilder() {
|
public static Builder getBuilder() {
|
||||||
|
|
|
@ -97,7 +97,6 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
| 1 | 1 |
|
| 1 | 1 |
|
||||||
+----+--------+
|
+----+--------+
|
||||||
*/
|
*/
|
||||||
//in.read(buf, 0, 2);
|
|
||||||
fill(in, buf, 2);
|
fill(in, buf, 2);
|
||||||
|
|
||||||
boolean check = false;
|
boolean check = false;
|
||||||
|
@ -160,7 +159,6 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
`failure' (STATUS value other than X'00') status, it MUST close the
|
`failure' (STATUS value other than X'00') status, it MUST close the
|
||||||
connection.
|
connection.
|
||||||
*/
|
*/
|
||||||
//in.read(buf, 0, 2);
|
|
||||||
fill(in, buf, 2);
|
fill(in, buf, 2);
|
||||||
if (buf[1] == 0)
|
if (buf[1] == 0)
|
||||||
{
|
{
|
||||||
|
@ -260,7 +258,6 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
o BND.PORT server bound port in network octet order
|
o BND.PORT server bound port in network octet order
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//in.read(buf, 0, 4);
|
|
||||||
fill(in, buf, 4);
|
fill(in, buf, 4);
|
||||||
|
|
||||||
if (buf[1] != 0)
|
if (buf[1] != 0)
|
||||||
|
@ -279,17 +276,13 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
switch (buf[3] & 0xff)
|
switch (buf[3] & 0xff)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
//in.read(buf, 0, 6);
|
|
||||||
fill(in, buf, 6);
|
fill(in, buf, 6);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
//in.read(buf, 0, 1);
|
|
||||||
fill(in, buf, 1);
|
fill(in, buf, 1);
|
||||||
//in.read(buf, 0, buf[0]+2);
|
|
||||||
fill(in, buf, (buf[0] & 0xff) + 2);
|
fill(in, buf, (buf[0] & 0xff) + 2);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
//in.read(buf, 0, 18);
|
|
||||||
fill(in, buf, 18);
|
fill(in, buf, 18);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -272,7 +272,7 @@ public class StringUtils {
|
||||||
* array index.
|
* array index.
|
||||||
*/
|
*/
|
||||||
private static final char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
|
private static final char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random String of numbers and letters (lower and upper case)
|
* Returns a random String of numbers and letters (lower and upper case)
|
||||||
|
@ -288,17 +288,7 @@ public class StringUtils {
|
||||||
* @return a random String of numbers and letters of the specified length.
|
* @return a random String of numbers and letters of the specified length.
|
||||||
*/
|
*/
|
||||||
public static String insecureRandomString(int length) {
|
public static String insecureRandomString(int length) {
|
||||||
if (length < 1) {
|
return randomString(length, randGen.get());
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Random random = randGen.get();
|
|
||||||
// Create a char buffer to put random letters and numbers in.
|
|
||||||
char[] randBuffer = new char[length];
|
|
||||||
for (int i = 0; i < randBuffer.length; i++) {
|
|
||||||
randBuffer[i] = numbersAndLetters[random.nextInt(numbersAndLetters.length)];
|
|
||||||
}
|
|
||||||
return new String(randBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ThreadLocal<SecureRandom> SECURE_RANDOM = new ThreadLocal<SecureRandom>() {
|
private static final ThreadLocal<SecureRandom> SECURE_RANDOM = new ThreadLocal<SecureRandom>() {
|
||||||
|
@ -309,12 +299,16 @@ public class StringUtils {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static String randomString(final int length) {
|
public static String randomString(final int length) {
|
||||||
|
return randomString(length, SECURE_RANDOM.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String randomString(final int length, Random random) {
|
||||||
if (length < 1) {
|
if (length < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] randomBytes = new byte[length];
|
byte[] randomBytes = new byte[length];
|
||||||
SECURE_RANDOM.get().nextBytes(randomBytes);
|
random.nextBytes(randomBytes);
|
||||||
char[] randomChars = new char[length];
|
char[] randomChars = new char[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
randomChars[i] = getPrintableChar(randomBytes[i]);
|
randomChars[i] = getPrintableChar(randomBytes[i]);
|
||||||
|
|
|
@ -172,7 +172,7 @@ public class StanzaCollectorTest
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
//We cannot guarantee that this is going to pass due to the possible issue of timing between consumer 1
|
// We cannot guarantee that this is going to pass due to the possible issue of timing between consumer 1
|
||||||
// and main, but the probability is extremely remote.
|
// and main, but the probability is extremely remote.
|
||||||
assertNull(collector.pollResult());
|
assertNull(collector.pollResult());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jivesoftware.smackx.bytestreams.ibb;
|
package org.jivesoftware.smackx.bytestreams.ibb;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ class DataListener extends AbstractIqRequestHandler {
|
||||||
ibbSession.processIQPacket(data);
|
ibbSession.processIQPacket(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NotConnectedException | InterruptedException e) {
|
catch (NotConnectedException | InterruptedException | NotLoggedInException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.StanzaListener;
|
import org.jivesoftware.smack.StanzaListener;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.filter.AndFilter;
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
|
@ -847,8 +848,9 @@ public class InBandBytestreamSession implements BytestreamSession {
|
||||||
* @param data
|
* @param data
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
|
* @throws NotLoggedInException
|
||||||
*/
|
*/
|
||||||
public void processIQPacket(Data data) throws NotConnectedException, InterruptedException {
|
public void processIQPacket(Data data) throws NotConnectedException, InterruptedException, NotLoggedInException {
|
||||||
inputStream.dataPacketListener.processStanza(data);
|
inputStream.dataPacketListener.processStanza(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||||
|
@ -766,6 +765,25 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
*/
|
*/
|
||||||
public List<DiscoverInfo> findServicesDiscoverInfo(String feature, boolean stopOnFirst, boolean useCache)
|
public List<DiscoverInfo> findServicesDiscoverInfo(String feature, boolean stopOnFirst, boolean useCache)
|
||||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
|
return findServicesDiscoverInfo(feature, stopOnFirst, useCache, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all services under the users service that provide a given feature.
|
||||||
|
*
|
||||||
|
* @param feature the feature to search for
|
||||||
|
* @param stopOnFirst if true, stop searching after the first service was found
|
||||||
|
* @param useCache if true, query a cache first to avoid network I/O
|
||||||
|
* @param encounteredExceptions an optional map which will be filled with the exceptions encountered
|
||||||
|
* @return a possible empty list of services providing the given feature
|
||||||
|
* @throws NoResponseException
|
||||||
|
* @throws XMPPErrorException
|
||||||
|
* @throws NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @since 4.2.2
|
||||||
|
*/
|
||||||
|
public List<DiscoverInfo> findServicesDiscoverInfo(String feature, boolean stopOnFirst, boolean useCache, Map<? super Jid, Exception> encounteredExceptions)
|
||||||
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
List<DiscoverInfo> serviceDiscoInfo = null;
|
List<DiscoverInfo> serviceDiscoInfo = null;
|
||||||
DomainBareJid serviceName = connection().getXMPPServiceDomain();
|
DomainBareJid serviceName = connection().getXMPPServiceDomain();
|
||||||
if (useCache) {
|
if (useCache) {
|
||||||
|
@ -780,8 +798,9 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
try {
|
try {
|
||||||
info = discoverInfo(serviceName);
|
info = discoverInfo(serviceName);
|
||||||
} catch (XMPPErrorException e) {
|
} catch (XMPPErrorException e) {
|
||||||
// Be extra robust here: Return the empty linked list and log this situation
|
if (encounteredExceptions != null) {
|
||||||
LOGGER.log(Level.WARNING, "Could not discover information about service", e);
|
encounteredExceptions.put(serviceName, e);
|
||||||
|
}
|
||||||
return serviceDiscoInfo;
|
return serviceDiscoInfo;
|
||||||
}
|
}
|
||||||
// Check if the server supports the feature
|
// Check if the server supports the feature
|
||||||
|
@ -800,25 +819,27 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
// Get the disco items and send the disco packet to each server item
|
// Get the disco items and send the disco packet to each server item
|
||||||
items = discoverItems(serviceName);
|
items = discoverItems(serviceName);
|
||||||
} catch (XMPPErrorException e) {
|
} catch (XMPPErrorException e) {
|
||||||
LOGGER.log(Level.WARNING, "Could not discover items about service", e);
|
if (encounteredExceptions != null) {
|
||||||
|
encounteredExceptions.put(serviceName, e);
|
||||||
|
}
|
||||||
return serviceDiscoInfo;
|
return serviceDiscoInfo;
|
||||||
}
|
}
|
||||||
for (DiscoverItems.Item item : items.getItems()) {
|
for (DiscoverItems.Item item : items.getItems()) {
|
||||||
|
Jid address = item.getEntityID();
|
||||||
try {
|
try {
|
||||||
// TODO is it OK here in all cases to query without the node attribute?
|
// TODO is it OK here in all cases to query without the node attribute?
|
||||||
// MultipleRecipientManager queried initially also with the node attribute, but this
|
// MultipleRecipientManager queried initially also with the node attribute, but this
|
||||||
// could be simply a fault instead of intentional.
|
// could be simply a fault instead of intentional.
|
||||||
info = discoverInfo(item.getEntityID());
|
info = discoverInfo(address);
|
||||||
}
|
}
|
||||||
catch (XMPPErrorException | NoResponseException e) {
|
catch (XMPPErrorException | NoResponseException e) {
|
||||||
// Don't throw this exceptions if one of the server's items fail
|
if (encounteredExceptions != null) {
|
||||||
LOGGER.log(Level.WARNING, "Exception while discovering info for feature " + feature
|
encounteredExceptions.put(address, e);
|
||||||
+ " of " + item.getEntityID() + " node: " + item.getNode(), e);
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (info.containsFeature(feature)) {
|
if (info.containsFeature(feature)) {
|
||||||
serviceDiscoInfo.add(info);
|
serviceDiscoInfo.add(info);
|
||||||
//serviceAddresses.add(item.getEntityID().asDomainBareJid());
|
|
||||||
if (stopOnFirst) {
|
if (stopOnFirst) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,7 +303,7 @@ public class OutgoingFileTransfer extends FileTransfer {
|
||||||
transferThread = new Thread(new Runnable() {
|
transferThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
//Create packet filter
|
// Create packet filter.
|
||||||
try {
|
try {
|
||||||
outputStream = negotiateStream(fileName, fileSize, description);
|
outputStream = negotiateStream(fileName, fileSize, description);
|
||||||
} catch (XMPPErrorException e) {
|
} catch (XMPPErrorException e) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ public final class JingleManager extends Manager {
|
||||||
|
|
||||||
JingleSessionHandler sessionHandler = jingleSessionHandlers.get(fullJidAndSessionId);
|
JingleSessionHandler sessionHandler = jingleSessionHandlers.get(fullJidAndSessionId);
|
||||||
if (sessionHandler != null) {
|
if (sessionHandler != null) {
|
||||||
//Handle existing session
|
// Handle existing session
|
||||||
return sessionHandler.handleJingleSessionRequest(jingle);
|
return sessionHandler.handleJingleSessionRequest(jingle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,19 +96,19 @@ public final class JingleManager extends Manager {
|
||||||
description.getNamespace());
|
description.getNamespace());
|
||||||
|
|
||||||
if (jingleDescriptionHandler == null) {
|
if (jingleDescriptionHandler == null) {
|
||||||
//Unsupported Application
|
// Unsupported Application
|
||||||
LOGGER.log(Level.WARNING, "Unsupported Jingle application.");
|
LOGGER.log(Level.WARNING, "Unsupported Jingle application.");
|
||||||
return jutil.createSessionTerminateUnsupportedApplications(fullFrom, sid);
|
return jutil.createSessionTerminateUnsupportedApplications(fullFrom, sid);
|
||||||
}
|
}
|
||||||
return jingleDescriptionHandler.handleJingleRequest(jingle);
|
return jingleDescriptionHandler.handleJingleRequest(jingle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Unknown session
|
// Unknown session
|
||||||
LOGGER.log(Level.WARNING, "Unknown session.");
|
LOGGER.log(Level.WARNING, "Unknown session.");
|
||||||
return jutil.createErrorUnknownSession(jingle);
|
return jutil.createErrorUnknownSession(jingle);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//Register transports.
|
// Register transports.
|
||||||
JingleTransportMethodManager transportMethodManager = JingleTransportMethodManager.getInstanceFor(connection);
|
JingleTransportMethodManager transportMethodManager = JingleTransportMethodManager.getInstanceFor(connection);
|
||||||
transportMethodManager.registerTransportManager(JingleIBBTransportManager.getInstanceFor(connection));
|
transportMethodManager.registerTransportManager(JingleIBBTransportManager.getInstanceFor(connection));
|
||||||
transportMethodManager.registerTransportManager(JingleS5BTransportManager.getInstanceFor(connection));
|
transportMethodManager.registerTransportManager(JingleS5BTransportManager.getInstanceFor(connection));
|
||||||
|
|
|
@ -59,6 +59,6 @@ public final class JingleIBBTransportManager extends JingleTransportManager<Jing
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticated(XMPPConnection connection, boolean resumed) {
|
public void authenticated(XMPPConnection connection, boolean resumed) {
|
||||||
//Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class JingleIBBTransportSession extends JingleTransportSession<JingleIBBT
|
||||||
@Override
|
@Override
|
||||||
public IQ handleTransportInfo(Jingle transportInfo) {
|
public IQ handleTransportInfo(Jingle transportInfo) {
|
||||||
return IQ.createResultIQ(transportInfo);
|
return IQ.createResultIQ(transportInfo);
|
||||||
//TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
.setStreamId(sid).setMode(mode).setDestinationAddress(
|
.setStreamId(sid).setMode(mode).setDestinationAddress(
|
||||||
Socks5Utils.createDigest(sid, jingleSession.getLocal(), jingleSession.getRemote()));
|
Socks5Utils.createDigest(sid, jingleSession.getLocal(), jingleSession.getRemote()));
|
||||||
|
|
||||||
//Local host
|
// Local host
|
||||||
if (JingleS5BTransportManager.isUseLocalCandidates()) {
|
if (JingleS5BTransportManager.isUseLocalCandidates()) {
|
||||||
for (Bytestream.StreamHost host : transportManager().getLocalStreamHosts()) {
|
for (Bytestream.StreamHost host : transportManager().getLocalStreamHosts()) {
|
||||||
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 100, JingleS5BTransportCandidate.Type.direct));
|
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 100, JingleS5BTransportCandidate.Type.direct));
|
||||||
|
@ -204,7 +204,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
case JingleS5BTransportInfo.ProxyError.ELEMENT:
|
case JingleS5BTransportInfo.ProxyError.ELEMENT:
|
||||||
return handleProxyError(transportInfo);
|
return handleProxyError(transportInfo);
|
||||||
}
|
}
|
||||||
//We should never go here, but lets be gracious...
|
// We should never go here, but lets be gracious...
|
||||||
return IQ.createResultIQ(transportInfo);
|
return IQ.createResultIQ(transportInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
}
|
}
|
||||||
|
|
||||||
public IQ handleProxyError(Jingle jingle) {
|
public IQ handleProxyError(Jingle jingle) {
|
||||||
//TODO
|
// TODO
|
||||||
return IQ.createResultIQ(jingle);
|
return IQ.createResultIQ(jingle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
|
|
||||||
LOGGER.log(Level.INFO, "Ready.");
|
LOGGER.log(Level.INFO, "Ready.");
|
||||||
|
|
||||||
//Determine nominated candidate.
|
// Determine nominated candidate.
|
||||||
UsedCandidate nominated;
|
UsedCandidate nominated;
|
||||||
if (ourChoice != CANDIDATE_FAILURE && theirChoice != CANDIDATE_FAILURE) {
|
if (ourChoice != CANDIDATE_FAILURE && theirChoice != CANDIDATE_FAILURE) {
|
||||||
if (ourChoice.candidate.getPriority() > theirChoice.candidate.getPriority()) {
|
if (ourChoice.candidate.getPriority() > theirChoice.candidate.getPriority()) {
|
||||||
|
@ -288,7 +288,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
nominated = connectToOurCandidate(nominated.candidate);
|
nominated = connectToOurCandidate(nominated.candidate);
|
||||||
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
|
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
|
||||||
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
|
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
|
||||||
//TODO: Proxy-Error
|
// TODO: Proxy-Error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
callback.onSessionInitiated(bs);
|
callback.onSessionInitiated(bs);
|
||||||
|
|
||||||
}
|
}
|
||||||
//Our choice
|
// Our choice
|
||||||
else {
|
else {
|
||||||
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
|
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
|
||||||
boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
|
boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
|
||||||
|
|
|
@ -333,7 +333,7 @@ public class MultiUserChat {
|
||||||
new NotFilter(MessageWithThreadFilter.INSTANCE))
|
new NotFilter(MessageWithThreadFilter.INSTANCE))
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
connection.addSyncStanzaListener(declinesListener, DECLINE_FILTER);
|
connection.addSyncStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER));
|
||||||
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room),
|
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room),
|
||||||
StanzaTypeFilter.PRESENCE));
|
StanzaTypeFilter.PRESENCE));
|
||||||
messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter);
|
messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter);
|
||||||
|
@ -727,20 +727,19 @@ public class MultiUserChat {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public synchronized void leave() throws NotConnectedException, InterruptedException {
|
public synchronized void leave() throws NotConnectedException, InterruptedException {
|
||||||
// If not joined already, do nothing.
|
// Note that this method is intentionally not guarded by
|
||||||
if (!joined) {
|
// "if (!joined) return" because it should be always be possible to leave the room in case the instance's
|
||||||
return;
|
// state does not reflect the actual state.
|
||||||
}
|
|
||||||
|
// Reset occupant information first so that we are assume that we left the room even if sendStanza() would
|
||||||
|
// throw.
|
||||||
|
userHasLeft();
|
||||||
|
|
||||||
// We leave a room by sending a presence packet where the "to"
|
// We leave a room by sending a presence packet where the "to"
|
||||||
// field is in the form "roomName@service/nickname"
|
// field is in the form "roomName@service/nickname"
|
||||||
Presence leavePresence = new Presence(Presence.Type.unavailable);
|
Presence leavePresence = new Presence(Presence.Type.unavailable);
|
||||||
leavePresence.setTo(JidCreate.fullFrom(room, nickname));
|
leavePresence.setTo(JidCreate.fullFrom(room, nickname));
|
||||||
connection.sendStanza(leavePresence);
|
connection.sendStanza(leavePresence);
|
||||||
// Reset occupant information.
|
|
||||||
occupantsMap.clear();
|
|
||||||
nickname = null;
|
|
||||||
joined = false;
|
|
||||||
userHasLeft();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -878,12 +877,21 @@ public class MultiUserChat {
|
||||||
Destroy destroy = new Destroy(alternateJID, reason);
|
Destroy destroy = new Destroy(alternateJID, reason);
|
||||||
iq.setDestroy(destroy);
|
iq.setDestroy(destroy);
|
||||||
|
|
||||||
|
try {
|
||||||
connection.createStanzaCollectorAndSend(iq).nextResultOrThrow();
|
connection.createStanzaCollectorAndSend(iq).nextResultOrThrow();
|
||||||
|
}
|
||||||
|
catch (XMPPErrorException e) {
|
||||||
|
// Note that we do not call userHasLeft() here because an XMPPErrorException would usually indicate that the
|
||||||
|
// room was not destroyed and we therefore we also did not leave the room.
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch (NoResponseException | NotConnectedException | InterruptedException e) {
|
||||||
|
// Reset occupant information.
|
||||||
|
userHasLeft();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset occupant information.
|
// Reset occupant information.
|
||||||
occupantsMap.clear();
|
|
||||||
nickname = null;
|
|
||||||
joined = false;
|
|
||||||
userHasLeft();
|
userHasLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2011,6 +2019,7 @@ public class MultiUserChat {
|
||||||
private void removeConnectionCallbacks() {
|
private void removeConnectionCallbacks() {
|
||||||
connection.removeSyncStanzaListener(messageListener);
|
connection.removeSyncStanzaListener(messageListener);
|
||||||
connection.removeSyncStanzaListener(presenceListener);
|
connection.removeSyncStanzaListener(presenceListener);
|
||||||
|
connection.removeSyncStanzaListener(subjectListener);
|
||||||
connection.removeSyncStanzaListener(declinesListener);
|
connection.removeSyncStanzaListener(declinesListener);
|
||||||
connection.removePacketInterceptor(presenceInterceptor);
|
connection.removePacketInterceptor(presenceInterceptor);
|
||||||
if (messageCollector != null) {
|
if (messageCollector != null) {
|
||||||
|
@ -2023,6 +2032,11 @@ public class MultiUserChat {
|
||||||
* Remove all callbacks and resources necessary when the user has left the room for some reason.
|
* Remove all callbacks and resources necessary when the user has left the room for some reason.
|
||||||
*/
|
*/
|
||||||
private synchronized void userHasLeft() {
|
private synchronized void userHasLeft() {
|
||||||
|
// We do not reset nickname here, in case this method has been called erroneously, it should still be possible
|
||||||
|
// to call leave() in order to resync the state. And leave() requires the nickname to send the unsubscribe
|
||||||
|
// presence.
|
||||||
|
occupantsMap.clear();
|
||||||
|
joined = false;
|
||||||
// Update the list of joined rooms
|
// Update the list of joined rooms
|
||||||
multiUserChatManager.removeJoinedRoom(room);
|
multiUserChatManager.removeJoinedRoom(room);
|
||||||
removeConnectionCallbacks();
|
removeConnectionCallbacks();
|
||||||
|
@ -2340,15 +2354,12 @@ public class MultiUserChat {
|
||||||
if (statusCodes.contains(Status.KICKED_307)) {
|
if (statusCodes.contains(Status.KICKED_307)) {
|
||||||
// Check if this occupant was kicked
|
// Check if this occupant was kicked
|
||||||
if (isUserModification) {
|
if (isUserModification) {
|
||||||
joined = false;
|
// Reset occupant information.
|
||||||
|
userHasLeft();
|
||||||
|
|
||||||
for (UserStatusListener listener : userStatusListeners) {
|
for (UserStatusListener listener : userStatusListeners) {
|
||||||
listener.kicked(mucUser.getItem().getActor(), mucUser.getItem().getReason());
|
listener.kicked(mucUser.getItem().getActor(), mucUser.getItem().getReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset occupant information.
|
|
||||||
occupantsMap.clear();
|
|
||||||
nickname = null;
|
|
||||||
userHasLeft();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||||
|
@ -2397,7 +2408,7 @@ public class MultiUserChat {
|
||||||
listener.nicknameChanged(from, mucUser.getItem().getNick());
|
listener.nicknameChanged(from, mucUser.getItem().getNick());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//The room has been destroyed
|
// The room has been destroyed.
|
||||||
if (mucUser.getDestroy() != null) {
|
if (mucUser.getDestroy() != null) {
|
||||||
MultiUserChat alternateMUC = multiUserChatManager.getMultiUserChat(mucUser.getDestroy().getJid());
|
MultiUserChat alternateMUC = multiUserChatManager.getMultiUserChat(mucUser.getDestroy().getJid());
|
||||||
for (UserStatusListener listener : userStatusListeners) {
|
for (UserStatusListener listener : userStatusListeners) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.jivesoftware.smackx.offline;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
@ -58,6 +60,8 @@ import org.jivesoftware.smackx.xdata.Form;
|
||||||
*/
|
*/
|
||||||
public class OfflineMessageManager {
|
public class OfflineMessageManager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(OfflineMessageManager.class.getName());
|
||||||
|
|
||||||
private final static String namespace = "http://jabber.org/protocol/offline";
|
private final static String namespace = "http://jabber.org/protocol/offline";
|
||||||
|
|
||||||
private final XMPPConnection connection;
|
private final XMPPConnection connection;
|
||||||
|
@ -144,7 +148,7 @@ public class OfflineMessageManager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public List<Message> getMessages(final List<String> nodes) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public List<Message> getMessages(final List<String> nodes) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
List<Message> messages = new ArrayList<Message>();
|
List<Message> messages = new ArrayList<Message>(nodes.size());
|
||||||
OfflineMessageRequest request = new OfflineMessageRequest();
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
||||||
for (String node : nodes) {
|
for (String node : nodes) {
|
||||||
OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
|
OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
|
||||||
|
@ -165,12 +169,17 @@ public class OfflineMessageManager {
|
||||||
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;
|
||||||
while (message != null && pendingNodes > 0) {
|
do {
|
||||||
pendingNodes--;
|
|
||||||
messages.add(message);
|
|
||||||
message = messageCollector.nextResult();
|
message = messageCollector.nextResult();
|
||||||
|
if (message != null) {
|
||||||
|
messages.add(message);
|
||||||
|
pendingNodes--;
|
||||||
|
} else if (message == null && pendingNodes > 0) {
|
||||||
|
LOGGER.log(Level.WARNING,
|
||||||
|
"Did not receive all expected offline messages. " + pendingNodes + " are missing.");
|
||||||
}
|
}
|
||||||
|
} while (message != null && pendingNodes > 0);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
// Stop queuing offline messages
|
// Stop queuing offline messages
|
||||||
|
|
|
@ -704,7 +704,7 @@ public class VCard extends IQ {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasContent() {
|
private boolean hasContent() {
|
||||||
//noinspection OverlyComplexBooleanExpression
|
// noinspection OverlyComplexBooleanExpression
|
||||||
return hasNameField()
|
return hasNameField()
|
||||||
|| hasOrganizationFields()
|
|| hasOrganizationFields()
|
||||||
|| emailHome != null
|
|| emailHome != null
|
||||||
|
|
|
@ -55,8 +55,8 @@ public class VersionTest extends InitExtensions {
|
||||||
assertTrue(replyPacket instanceof Version);
|
assertTrue(replyPacket instanceof Version);
|
||||||
|
|
||||||
Version reply = (Version) replyPacket;
|
Version reply = (Version) replyPacket;
|
||||||
//getFrom check is pending for SMACK-547
|
// getFrom check is pending for SMACK-547
|
||||||
//assertEquals("juliet@capulet.lit/balcony", reply.getFrom());
|
// assertEquals("juliet@capulet.lit/balcony", reply.getFrom());
|
||||||
assertThat("capulet.lit", equalsCharSequence(reply.getTo()));
|
assertThat("capulet.lit", equalsCharSequence(reply.getTo()));
|
||||||
assertEquals("s2c1", reply.getStanzaId());
|
assertEquals("s2c1", reply.getStanzaId());
|
||||||
assertEquals(IQ.Type.result, reply.getType());
|
assertEquals(IQ.Type.result, reply.getType());
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class PingTest extends InitExtensions {
|
||||||
@Test
|
@Test
|
||||||
public void checkFailedPingToEntityError() throws Exception {
|
public void checkFailedPingToEntityError() throws Exception {
|
||||||
ThreadedDummyConnection threadedCon = getAuthentiactedDummyConnection();
|
ThreadedDummyConnection threadedCon = getAuthentiactedDummyConnection();
|
||||||
//@formatter:off
|
// @formatter:off
|
||||||
String reply =
|
String reply =
|
||||||
"<iq type='error' id='qrzSp-16' to='test@myserver.com'>" +
|
"<iq type='error' id='qrzSp-16' to='test@myserver.com'>" +
|
||||||
"<ping xmlns='urn:xmpp:ping'/>" +
|
"<ping xmlns='urn:xmpp:ping'/>" +
|
||||||
|
@ -132,7 +132,7 @@ public class PingTest extends InitExtensions {
|
||||||
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
|
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
|
||||||
"</error>" +
|
"</error>" +
|
||||||
"</iq>";
|
"</iq>";
|
||||||
//@formatter:on
|
// @formatter:on
|
||||||
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
|
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
|
||||||
threadedCon.addIQReply(serviceUnavailable);
|
threadedCon.addIQReply(serviceUnavailable);
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ public class PingTest extends InitExtensions {
|
||||||
@Test
|
@Test
|
||||||
public void checkPingToServerError() throws Exception {
|
public void checkPingToServerError() throws Exception {
|
||||||
ThreadedDummyConnection con = getAuthentiactedDummyConnection();
|
ThreadedDummyConnection con = getAuthentiactedDummyConnection();
|
||||||
//@formatter:off
|
// @formatter:off
|
||||||
String reply =
|
String reply =
|
||||||
"<iq type='error' id='qrzSp-16' to='test@myserver.com' from='" + con.getXMPPServiceDomain() + "'>" +
|
"<iq type='error' id='qrzSp-16' to='test@myserver.com' from='" + con.getXMPPServiceDomain() + "'>" +
|
||||||
"<ping xmlns='urn:xmpp:ping'/>" +
|
"<ping xmlns='urn:xmpp:ping'/>" +
|
||||||
|
@ -168,7 +168,7 @@ public class PingTest extends InitExtensions {
|
||||||
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
|
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
|
||||||
"</error>" +
|
"</error>" +
|
||||||
"</iq>";
|
"</iq>";
|
||||||
//@formatter:on
|
// @formatter:on
|
||||||
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
|
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
|
||||||
con.addIQReply(serviceUnavailable);
|
con.addIQReply(serviceUnavailable);
|
||||||
|
|
||||||
|
@ -194,13 +194,13 @@ public class PingTest extends InitExtensions {
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
DiscoverInfo info = new DiscoverInfo();
|
||||||
info.addFeature(Ping.NAMESPACE);
|
info.addFeature(Ping.NAMESPACE);
|
||||||
|
|
||||||
//@formatter:off
|
// @formatter:off
|
||||||
String reply =
|
String reply =
|
||||||
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
|
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
|
||||||
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
|
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
|
||||||
"<feature var='urn:xmpp:ping'/>" +
|
"<feature var='urn:xmpp:ping'/>" +
|
||||||
"</query></iq>";
|
"</query></iq>";
|
||||||
//@formatter:on
|
// @formatter:on
|
||||||
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
|
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
|
||||||
con.addIQReply(discoReply);
|
con.addIQReply(discoReply);
|
||||||
|
|
||||||
|
@ -216,13 +216,13 @@ public class PingTest extends InitExtensions {
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
DiscoverInfo info = new DiscoverInfo();
|
||||||
info.addFeature(Ping.NAMESPACE);
|
info.addFeature(Ping.NAMESPACE);
|
||||||
|
|
||||||
//@formatter:off
|
// @formatter:off
|
||||||
String reply =
|
String reply =
|
||||||
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
|
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
|
||||||
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
|
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
|
||||||
"<feature var='urn:xmpp:noping'/>" +
|
"<feature var='urn:xmpp:noping'/>" +
|
||||||
"</query></iq>";
|
"</query></iq>";
|
||||||
//@formatter:on
|
// @formatter:on
|
||||||
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
|
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
|
||||||
con.addIQReply(discoReply);
|
con.addIQReply(discoReply);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class DataFormTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
//Build a Form
|
// Build a Form.
|
||||||
DataForm df = new DataForm(DataForm.Type.submit);
|
DataForm df = new DataForm(DataForm.Type.submit);
|
||||||
String instruction = "InstructionTest1";
|
String instruction = "InstructionTest1";
|
||||||
df.addInstruction(instruction);
|
df.addInstruction(instruction);
|
||||||
|
@ -77,7 +77,7 @@ public class DataFormTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLayout() throws Exception {
|
public void testLayout() throws Exception {
|
||||||
//Build a Form
|
// Build a Form.
|
||||||
DataForm df = new DataForm(DataForm.Type.submit);
|
DataForm df = new DataForm(DataForm.Type.submit);
|
||||||
String instruction = "InstructionTest1";
|
String instruction = "InstructionTest1";
|
||||||
df.addInstruction(instruction);
|
df.addInstruction(instruction);
|
||||||
|
@ -119,7 +119,7 @@ public class DataFormTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidation() throws Exception {
|
public void testValidation() throws Exception {
|
||||||
//Build a Form
|
// Build a Form.
|
||||||
DataForm df = new DataForm(DataForm.Type.submit);
|
DataForm df = new DataForm(DataForm.Type.submit);
|
||||||
String instruction = "InstructionTest1";
|
String instruction = "InstructionTest1";
|
||||||
df.addInstruction(instruction);
|
df.addInstruction(instruction);
|
||||||
|
|
|
@ -251,9 +251,10 @@ public final class Roster extends Manager {
|
||||||
connection.addSyncStanzaListener(presencePacketListener, PRESENCE_PACKET_FILTER);
|
connection.addSyncStanzaListener(presencePacketListener, PRESENCE_PACKET_FILTER);
|
||||||
|
|
||||||
connection.addAsyncStanzaListener(new StanzaListener() {
|
connection.addAsyncStanzaListener(new StanzaListener() {
|
||||||
|
@SuppressWarnings("fallthrough")
|
||||||
@Override
|
@Override
|
||||||
public void processStanza(Stanza stanza) throws NotConnectedException,
|
public void processStanza(Stanza stanza) throws NotConnectedException,
|
||||||
InterruptedException {
|
InterruptedException, NotLoggedInException {
|
||||||
Presence presence = (Presence) stanza;
|
Presence presence = (Presence) stanza;
|
||||||
Jid from = presence.getFrom();
|
Jid from = presence.getFrom();
|
||||||
SubscribeAnswer subscribeAnswer = null;
|
SubscribeAnswer subscribeAnswer = null;
|
||||||
|
@ -279,13 +280,26 @@ public final class Roster extends Manager {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subscribeAnswer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Presence response;
|
Presence response;
|
||||||
if (subscribeAnswer == SubscribeAnswer.Approve) {
|
switch (subscribeAnswer) {
|
||||||
|
case ApproveAndAlsoRequestIfRequired:
|
||||||
|
BareJid bareFrom = from.asBareJid();
|
||||||
|
RosterUtil.askForSubscriptionIfRequired(Roster.this, bareFrom);
|
||||||
|
// The fall through is intended.
|
||||||
|
case Approve:
|
||||||
response = new Presence(Presence.Type.subscribed);
|
response = new Presence(Presence.Type.subscribed);
|
||||||
}
|
break;
|
||||||
else {
|
case Deny:
|
||||||
response = new Presence(Presence.Type.unsubscribed);
|
response = new Presence(Presence.Type.unsubscribed);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
response.setTo(presence.getFrom());
|
response.setTo(presence.getFrom());
|
||||||
connection.sendStanza(response);
|
connection.sendStanza(response);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException.FeatureNotSupportedException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
@ -86,6 +87,33 @@ public class RosterUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-approve the subscription if it is required and possible.
|
||||||
|
*
|
||||||
|
* @param roster The roster which should be used for the pre-approval.
|
||||||
|
* @param jid The XMPP address which should be pre-approved.
|
||||||
|
* @throws NotLoggedInException
|
||||||
|
* @throws NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @since 4.2.2
|
||||||
|
*/
|
||||||
|
public static void preApproveSubscriptionIfRequiredAndPossible(Roster roster, BareJid jid)
|
||||||
|
throws NotLoggedInException, NotConnectedException, InterruptedException {
|
||||||
|
if (!roster.isSubscriptionPreApprovalSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RosterEntry entry = roster.getEntry(jid);
|
||||||
|
if (entry == null || (!entry.canSeeMyPresence() && !entry.isApproved())) {
|
||||||
|
try {
|
||||||
|
roster.preApprove(jid);
|
||||||
|
} catch (FeatureNotSupportedException e) {
|
||||||
|
// Should never happen since we checked for the feature above.
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void askForSubscriptionIfRequired(Roster roster, BareJid jid)
|
public static void askForSubscriptionIfRequired(Roster roster, BareJid jid)
|
||||||
throws NotLoggedInException, NotConnectedException, InterruptedException {
|
throws NotLoggedInException, NotConnectedException, InterruptedException {
|
||||||
RosterEntry entry = roster.getEntry(jid);
|
RosterEntry entry = roster.getEntry(jid);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015 Florian Schmaus
|
* Copyright 2015-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.
|
||||||
|
@ -23,13 +23,29 @@ import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming requests to subscribe to our presence.
|
* Handle incoming requests to subscribe to our presence. The
|
||||||
|
* {@link #processSubscribe(Jid, Presence)} method may return a subscribe
|
||||||
|
* answer. If no subscribe answer is returned, the next listener will be
|
||||||
|
* notified and asked. If no listener returns an answer, then nothing happens.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface SubscribeListener {
|
public interface SubscribeListener {
|
||||||
|
|
||||||
public enum SubscribeAnswer {
|
public enum SubscribeAnswer {
|
||||||
|
/**
|
||||||
|
* Approve the subscription request.
|
||||||
|
*/
|
||||||
Approve,
|
Approve,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Approve the subscription request and also request subscription from the other party if not already subscribed.
|
||||||
|
* @since 4.2.2
|
||||||
|
*/
|
||||||
|
ApproveAndAlsoRequestIfRequired,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deny the subscription request.
|
||||||
|
*/
|
||||||
Deny,
|
Deny,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
EntityBareJid userOne = conOne.getUser().asEntityBareJid();
|
EntityBareJid userOne = conOne.getUser().asEntityBareJid();
|
||||||
EntityBareJid userTwo = conTwo.getUser().asEntityBareJid();
|
EntityBareJid userTwo = conTwo.getUser().asEntityBareJid();
|
||||||
|
|
||||||
//Make sure MAM is archiving messages
|
// Make sure MAM is archiving messages.
|
||||||
mamManagerConTwo.updateArchivingPreferences(null, null, MamPrefsIQ.DefaultBehavior.always);
|
mamManagerConTwo.updateArchivingPreferences(null, null, MamPrefsIQ.DefaultBehavior.always);
|
||||||
|
|
||||||
Message message = new Message(userTwo);
|
Message message = new Message(userTwo);
|
||||||
|
|
|
@ -55,7 +55,7 @@ public abstract class AbstractOmemoIntegrationTest extends AbstractSmackIntegrat
|
||||||
throw new TestNotPossibleException("Server does not support OMEMO (PubSub)");
|
throw new TestNotPossibleException("Server does not support OMEMO (PubSub)");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for OmemoService
|
// Check for OmemoService
|
||||||
if (!OmemoService.isServiceRegistered()) {
|
if (!OmemoService.isServiceRegistered()) {
|
||||||
throw new TestNotPossibleException("No OmemoService registered.");
|
throw new TestNotPossibleException("No OmemoService registered.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,14 +57,14 @@ public class OmemoInitializationTest extends AbstractOmemoIntegrationTest {
|
||||||
*/
|
*/
|
||||||
@SmackIntegrationTest
|
@SmackIntegrationTest
|
||||||
public void initializationTest() throws XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.NotLoggedInException, CorruptedOmemoKeyException, NotAPubSubNodeException {
|
public void initializationTest() throws XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.NotLoggedInException, CorruptedOmemoKeyException, NotAPubSubNodeException {
|
||||||
//test keys.
|
// test keys.
|
||||||
setUpOmemoManager(alice);
|
setUpOmemoManager(alice);
|
||||||
assertNotNull("IdentityKey must not be null after initialization.", store.loadOmemoIdentityKeyPair(alice));
|
assertNotNull("IdentityKey must not be null after initialization.", store.loadOmemoIdentityKeyPair(alice));
|
||||||
assertTrue("We must have " + OmemoConstants.TARGET_PRE_KEY_COUNT + " preKeys.",
|
assertTrue("We must have " + OmemoConstants.TARGET_PRE_KEY_COUNT + " preKeys.",
|
||||||
store.loadOmemoPreKeys(alice).size() == OmemoConstants.TARGET_PRE_KEY_COUNT);
|
store.loadOmemoPreKeys(alice).size() == OmemoConstants.TARGET_PRE_KEY_COUNT);
|
||||||
assertNotNull("Our signedPreKey must not be null.", store.loadCurrentSignedPreKeyId(alice));
|
assertNotNull("Our signedPreKey must not be null.", store.loadCurrentSignedPreKeyId(alice));
|
||||||
|
|
||||||
//Is deviceId published?
|
// Is deviceId published?
|
||||||
assertTrue("Published deviceList must contain our deviceId.",
|
assertTrue("Published deviceList must contain our deviceId.",
|
||||||
OmemoService.fetchDeviceList(alice, alice.getOwnJid())
|
OmemoService.fetchDeviceList(alice, alice.getOwnJid())
|
||||||
.getDeviceIds().contains(alice.getDeviceId()));
|
.getDeviceIds().contains(alice.getDeviceId()));
|
||||||
|
|
|
@ -63,7 +63,7 @@ final class OmemoIntegrationTestHelper {
|
||||||
try {
|
try {
|
||||||
omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid());
|
omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid());
|
||||||
} catch (SmackException.NotConnectedException | InterruptedException | SmackException.NoResponseException e) {
|
} catch (SmackException.NotConnectedException | InterruptedException | SmackException.NoResponseException e) {
|
||||||
//ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedDeviceList deviceList = OmemoService.getInstance().getOmemoStoreBackend().loadCachedDeviceList(omemoManager, omemoManager.getOwnJid());
|
CachedDeviceList deviceList = OmemoService.getInstance().getOmemoStoreBackend().loadCachedDeviceList(omemoManager, omemoManager.getOwnJid());
|
||||||
|
@ -71,26 +71,26 @@ final class OmemoIntegrationTestHelper {
|
||||||
try {
|
try {
|
||||||
pm.getLeafNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id)).deleteAllItems();
|
pm.getLeafNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id)).deleteAllItems();
|
||||||
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
||||||
//Silent
|
// Silent
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pm.deleteNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id));
|
pm.deleteNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id));
|
||||||
} catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
} catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
||||||
//Silent
|
// Silent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pm.getLeafNode(OmemoConstants.PEP_NODE_DEVICE_LIST).deleteAllItems();
|
pm.getLeafNode(OmemoConstants.PEP_NODE_DEVICE_LIST).deleteAllItems();
|
||||||
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
||||||
//Silent
|
// Silent
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pm.deleteNode(OmemoConstants.PEP_NODE_DEVICE_LIST);
|
pm.deleteNode(OmemoConstants.PEP_NODE_DEVICE_LIST);
|
||||||
} catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
} catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
||||||
//Silent
|
// Silent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ final class OmemoIntegrationTestHelper {
|
||||||
try {
|
try {
|
||||||
roster.removeEntry(r);
|
roster.removeEntry(r);
|
||||||
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | SmackException.NotLoggedInException e) {
|
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | SmackException.NotLoggedInException e) {
|
||||||
//Silent
|
// Silent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ final class OmemoIntegrationTestHelper {
|
||||||
|
|
||||||
|
|
||||||
static void unidirectionalTrust(OmemoManager alice, OmemoManager bob) throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, CannotEstablishOmemoSessionException {
|
static void unidirectionalTrust(OmemoManager alice, OmemoManager bob) throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, CannotEstablishOmemoSessionException {
|
||||||
//Fetch deviceList
|
// Fetch deviceList
|
||||||
alice.requestDeviceListUpdateFor(bob.getOwnJid());
|
alice.requestDeviceListUpdateFor(bob.getOwnJid());
|
||||||
LOGGER.log(Level.INFO, "Current deviceList state: " + alice.getOwnDevice() + " knows " + bob.getOwnDevice() + ": "
|
LOGGER.log(Level.INFO, "Current deviceList state: " + alice.getOwnDevice() + " knows " + bob.getOwnDevice() + ": "
|
||||||
+ OmemoService.getInstance().getOmemoStoreBackend().loadCachedDeviceList(alice, bob.getOwnJid()));
|
+ OmemoService.getInstance().getOmemoStoreBackend().loadCachedDeviceList(alice, bob.getOwnJid()));
|
||||||
|
@ -136,12 +136,12 @@ final class OmemoIntegrationTestHelper {
|
||||||
alice.getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(alice, bob.getOwnJid())
|
alice.getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(alice, bob.getOwnJid())
|
||||||
.getActiveDevices().contains(bob.getDeviceId()));
|
.getActiveDevices().contains(bob.getDeviceId()));
|
||||||
|
|
||||||
//Create sessions
|
// Create sessions
|
||||||
alice.buildSessionsWith(bob.getOwnJid());
|
alice.buildSessionsWith(bob.getOwnJid());
|
||||||
assertTrue("Trusting party must have a session with the other end at this point.",
|
assertTrue("Trusting party must have a session with the other end at this point.",
|
||||||
!alice.getOmemoService().getOmemoStoreBackend().loadAllRawSessionsOf(alice, bob.getOwnJid()).isEmpty());
|
!alice.getOmemoService().getOmemoStoreBackend().loadAllRawSessionsOf(alice, bob.getOwnJid()).isEmpty());
|
||||||
|
|
||||||
//Trust the other party
|
// Trust the other party
|
||||||
alice.getOmemoService().getOmemoStoreBackend().trustOmemoIdentity(alice, bob.getOwnDevice(),
|
alice.getOmemoService().getOmemoStoreBackend().trustOmemoIdentity(alice, bob.getOwnDevice(),
|
||||||
alice.getOmemoService().getOmemoStoreBackend().getFingerprint(alice, bob.getOwnDevice()));
|
alice.getOmemoService().getOmemoStoreBackend().getFingerprint(alice, bob.getOwnDevice()));
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class OmemoKeyTransportTest extends AbstractOmemoIntegrationTest {
|
||||||
bob.addOmemoMessageListener(new OmemoMessageListener() {
|
bob.addOmemoMessageListener(new OmemoMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage, Message wrappingMessage, OmemoMessageInformation omemoInformation) {
|
public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage, Message wrappingMessage, OmemoMessageInformation omemoInformation) {
|
||||||
//Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -101,23 +101,23 @@ public class OmemoMessageSendingTest extends AbstractOmemoIntegrationTest {
|
||||||
final SimpleResultSyncPoint messageOneSyncPoint = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint messageOneSyncPoint = new SimpleResultSyncPoint();
|
||||||
final SimpleResultSyncPoint messageTwoSyncPoint = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint messageTwoSyncPoint = new SimpleResultSyncPoint();
|
||||||
|
|
||||||
//Subscribe to one another
|
// Subscribe to one another
|
||||||
subscribe(alice, bob, "Bob");
|
subscribe(alice, bob, "Bob");
|
||||||
subscribe(bob, alice,"Alice");
|
subscribe(bob, alice,"Alice");
|
||||||
|
|
||||||
//initialize OmemoManagers
|
// initialize OmemoManagers
|
||||||
setUpOmemoManager(alice);
|
setUpOmemoManager(alice);
|
||||||
setUpOmemoManager(bob);
|
setUpOmemoManager(bob);
|
||||||
|
|
||||||
//Save initial bundles
|
// Save initial bundles
|
||||||
OmemoBundleElement aliceBundle = store.packOmemoBundle(alice);
|
OmemoBundleElement aliceBundle = store.packOmemoBundle(alice);
|
||||||
OmemoBundleElement bobsBundle = store.packOmemoBundle(bob);
|
OmemoBundleElement bobsBundle = store.packOmemoBundle(bob);
|
||||||
|
|
||||||
//Trust
|
// Trust
|
||||||
unidirectionalTrust(alice, bob);
|
unidirectionalTrust(alice, bob);
|
||||||
unidirectionalTrust(bob, alice);
|
unidirectionalTrust(bob, alice);
|
||||||
|
|
||||||
//Register messageListeners
|
// Register messageListeners
|
||||||
bob.addOmemoMessageListener(new OmemoMessageListener() {
|
bob.addOmemoMessageListener(new OmemoMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage, Message wrappingMessage, OmemoMessageInformation omemoInformation) {
|
public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage, Message wrappingMessage, OmemoMessageInformation omemoInformation) {
|
||||||
|
@ -151,7 +151,7 @@ public class OmemoMessageSendingTest extends AbstractOmemoIntegrationTest {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//Prepare Alice message for Bob
|
// Prepare Alice message for Bob
|
||||||
Message encryptedA = alice.encrypt(bob.getOwnJid(), alicesSecret);
|
Message encryptedA = alice.encrypt(bob.getOwnJid(), alicesSecret);
|
||||||
ChatManager.getInstanceFor(alice.getConnection()).chatWith(bob.getOwnJid().asEntityBareJidIfPossible())
|
ChatManager.getInstanceFor(alice.getConnection()).chatWith(bob.getOwnJid().asEntityBareJidIfPossible())
|
||||||
.send(encryptedA);
|
.send(encryptedA);
|
||||||
|
@ -163,11 +163,11 @@ public class OmemoMessageSendingTest extends AbstractOmemoIntegrationTest {
|
||||||
TestCase.fail("Bob must have received Alice message.");
|
TestCase.fail("Bob must have received Alice message.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if Bob published a new Bundle
|
// Check if Bob published a new Bundle
|
||||||
assertNotSame("Bob must have published another bundle at this point, since we used a PreKeyMessage.",
|
assertNotSame("Bob must have published another bundle at this point, since we used a PreKeyMessage.",
|
||||||
bobsBundle, OmemoService.fetchBundle(alice, bob.getOwnDevice()));
|
bobsBundle, OmemoService.fetchBundle(alice, bob.getOwnDevice()));
|
||||||
|
|
||||||
//Prepare Bobs response
|
// Prepare Bobs response
|
||||||
Message encryptedB = bob.encrypt(alice.getOwnJid(), bobsSecret);
|
Message encryptedB = bob.encrypt(alice.getOwnJid(), bobsSecret);
|
||||||
ChatManager.getInstanceFor(bob.getConnection()).chatWith(alice.getOwnJid().asEntityBareJidIfPossible())
|
ChatManager.getInstanceFor(bob.getConnection()).chatWith(alice.getOwnJid().asEntityBareJidIfPossible())
|
||||||
.send(encryptedB);
|
.send(encryptedB);
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
@SmackIntegrationTest
|
@SmackIntegrationTest
|
||||||
public void storeTest() throws Exception {
|
public void storeTest() throws Exception {
|
||||||
|
|
||||||
//########### PRE-INITIALIZATION ############
|
// ########### PRE-INITIALIZATION ############
|
||||||
|
|
||||||
assertEquals("Creating an OmemoManager without MUST have set the default deviceId.", alice.getDeviceId(), OmemoService.getInstance().getOmemoStoreBackend().getDefaultDeviceId(alice.getOwnJid()));
|
assertEquals("Creating an OmemoManager without MUST have set the default deviceId.", alice.getDeviceId(), OmemoService.getInstance().getOmemoStoreBackend().getDefaultDeviceId(alice.getOwnJid()));
|
||||||
assertEquals("OmemoManager must be equal, since both got created without giving a deviceId.", alice, bob);
|
assertEquals("OmemoManager must be equal, since both got created without giving a deviceId.", alice, bob);
|
||||||
|
@ -69,11 +69,11 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
|
|
||||||
OmemoStore<?,?,?,?,?,?,?,?,?> store = OmemoService.getInstance().getOmemoStoreBackend();
|
OmemoStore<?,?,?,?,?,?,?,?,?> store = OmemoService.getInstance().getOmemoStoreBackend();
|
||||||
OmemoFingerprint finger = new OmemoFingerprint("FINGER");
|
OmemoFingerprint finger = new OmemoFingerprint("FINGER");
|
||||||
//DefaultDeviceId
|
// DefaultDeviceId
|
||||||
store.setDefaultDeviceId(alice.getOwnJid(), 777);
|
store.setDefaultDeviceId(alice.getOwnJid(), 777);
|
||||||
assertEquals("defaultDeviceId setting/getting must equal.", 777, store.getDefaultDeviceId(alice.getOwnJid()));
|
assertEquals("defaultDeviceId setting/getting must equal.", 777, store.getDefaultDeviceId(alice.getOwnJid()));
|
||||||
|
|
||||||
//Trust/Distrust/Decide
|
// Trust/Distrust/Decide
|
||||||
bob.shutdown();
|
bob.shutdown();
|
||||||
bob = OmemoManager.getInstanceFor(conTwo, 998);
|
bob = OmemoManager.getInstanceFor(conTwo, 998);
|
||||||
assertFalse("Bobs device MUST be undecided at this point",
|
assertFalse("Bobs device MUST be undecided at this point",
|
||||||
|
@ -89,7 +89,7 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
assertFalse("Bobs device MUST be untrusted at this point.",
|
assertFalse("Bobs device MUST be untrusted at this point.",
|
||||||
store.isTrustedOmemoIdentity(alice, bob.getOwnDevice(), finger));
|
store.isTrustedOmemoIdentity(alice, bob.getOwnDevice(), finger));
|
||||||
|
|
||||||
//Dates
|
// Dates
|
||||||
assertNull("Date of last received message must be null when no message was received ever.",
|
assertNull("Date of last received message must be null when no message was received ever.",
|
||||||
store.getDateOfLastReceivedMessage(alice, bob.getOwnDevice()));
|
store.getDateOfLastReceivedMessage(alice, bob.getOwnDevice()));
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
|
@ -102,7 +102,7 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
assertEquals("Date of last signed prekey renewal must match our date.",
|
assertEquals("Date of last signed prekey renewal must match our date.",
|
||||||
now, store.getDateOfLastSignedPreKeyRenewal(alice));
|
now, store.getDateOfLastSignedPreKeyRenewal(alice));
|
||||||
|
|
||||||
//Keys
|
// Keys
|
||||||
assertNull("IdentityKeyPair must be null at this point.",
|
assertNull("IdentityKeyPair must be null at this point.",
|
||||||
store.loadOmemoIdentityKeyPair(alice));
|
store.loadOmemoIdentityKeyPair(alice));
|
||||||
assertNull("IdentityKey of contact must be null at this point.",
|
assertNull("IdentityKey of contact must be null at this point.",
|
||||||
|
@ -118,7 +118,7 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
100, store.generateOmemoPreKeys(1, 100).size());
|
100, store.generateOmemoPreKeys(1, 100).size());
|
||||||
|
|
||||||
|
|
||||||
//LastPreKeyId
|
// LastPreKeyId
|
||||||
assertEquals("LastPreKeyId must be 0 at this point.",
|
assertEquals("LastPreKeyId must be 0 at this point.",
|
||||||
0, store.loadLastPreKeyId(alice));
|
0, store.loadLastPreKeyId(alice));
|
||||||
store.storeLastPreKeyId(alice, 1234);
|
store.storeLastPreKeyId(alice, 1234);
|
||||||
|
@ -126,7 +126,7 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
assertEquals("LastPreKeyId set/get must equal.", 1234, store.loadLastPreKeyId(alice));
|
assertEquals("LastPreKeyId set/get must equal.", 1234, store.loadLastPreKeyId(alice));
|
||||||
store.storeLastPreKeyId(alice, 0);
|
store.storeLastPreKeyId(alice, 0);
|
||||||
|
|
||||||
//CurrentSignedPreKeyId
|
// CurrentSignedPreKeyId
|
||||||
assertEquals("CurrentSignedPreKeyId must be 0 at this point.",
|
assertEquals("CurrentSignedPreKeyId must be 0 at this point.",
|
||||||
0, store.loadCurrentSignedPreKeyId(alice));
|
0, store.loadCurrentSignedPreKeyId(alice));
|
||||||
store.storeCurrentSignedPreKeyId(alice, 554);
|
store.storeCurrentSignedPreKeyId(alice, 554);
|
||||||
|
@ -137,10 +137,10 @@ public class OmemoStoreTest extends AbstractOmemoIntegrationTest {
|
||||||
|
|
||||||
deletePath(alice);
|
deletePath(alice);
|
||||||
|
|
||||||
//################# POST-INITIALIZATION #################
|
// ################# POST-INITIALIZATION #################
|
||||||
setUpOmemoManager(alice);
|
setUpOmemoManager(alice);
|
||||||
|
|
||||||
//Keys
|
// Keys
|
||||||
assertNotNull("IdentityKeyPair must not be null after initialization",
|
assertNotNull("IdentityKeyPair must not be null after initialization",
|
||||||
store.loadOmemoIdentityKeyPair(alice));
|
store.loadOmemoIdentityKeyPair(alice));
|
||||||
assertNotSame("LastPreKeyId must not be 0 after initialization.",
|
assertNotSame("LastPreKeyId must not be 0 after initialization.",
|
||||||
|
|
|
@ -45,7 +45,7 @@ public abstract class JingleNegotiator {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleNegotiator.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleNegotiator.class.getName());
|
||||||
|
|
||||||
//private XMPPConnection connection; // The connection associated
|
// private XMPPConnection connection; // The connection associated
|
||||||
|
|
||||||
protected JingleSession session;
|
protected JingleSession session;
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
|
||||||
public JingleSession(XMPPConnection conn, JingleSessionRequest request, Jid initiator, Jid responder,
|
public JingleSession(XMPPConnection conn, JingleSessionRequest request, Jid initiator, Jid responder,
|
||||||
List<JingleMediaManager> jingleMediaManagers) {
|
List<JingleMediaManager> jingleMediaManagers) {
|
||||||
this(conn, initiator, responder, generateSessionId(), jingleMediaManagers);
|
this(conn, initiator, responder, generateSessionId(), jingleMediaManagers);
|
||||||
//sessionRequest = request; // unused
|
// sessionRequest = request; // unused
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -317,7 +317,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
|
||||||
// Acknowledge the IQ reception
|
// Acknowledge the IQ reception
|
||||||
// Not anymore. The state machine generates an appropriate response IQ that
|
// Not anymore. The state machine generates an appropriate response IQ that
|
||||||
// gets sent back at the end of this routine.
|
// gets sent back at the end of this routine.
|
||||||
//sendAck(iq);
|
// sendAck(iq);
|
||||||
|
|
||||||
} catch (JingleException e) {
|
} catch (JingleException e) {
|
||||||
// Send an error message, if present
|
// Send an error message, if present
|
||||||
|
@ -829,7 +829,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
|
||||||
addExpectedId(jout.getStanzaId());
|
addExpectedId(jout.getStanzaId());
|
||||||
sendStanza(jout);
|
sendStanza(jout);
|
||||||
|
|
||||||
//triggerSessionEstablished();
|
// triggerSessionEstablished();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1143,7 +1143,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
|
||||||
*/
|
*/
|
||||||
public void startIncoming() {
|
public void startIncoming() {
|
||||||
|
|
||||||
//updatePacketListener();
|
// updatePacketListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -118,7 +118,7 @@ public class JingleSessionRequest {
|
||||||
session = manager.createIncomingJingleSession(this);
|
session = manager.createIncomingJingleSession(this);
|
||||||
// Acknowledge the IQ reception
|
// Acknowledge the IQ reception
|
||||||
session.setSid(this.getSessionID());
|
session.setSid(this.getSessionID());
|
||||||
//session.sendAck(this.getJingle());
|
// session.sendAck(this.getJingle());
|
||||||
session.updatePacketListener();
|
session.updatePacketListener();
|
||||||
session.receivePacketAndRespond(this.getJingle());
|
session.receivePacketAndRespond(this.getJingle());
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ public class JingleSessionRequest {
|
||||||
session = manager.createIncomingJingleSession(this);
|
session = manager.createIncomingJingleSession(this);
|
||||||
// Acknowledge the IQ reception
|
// Acknowledge the IQ reception
|
||||||
session.setSid(this.getSessionID());
|
session.setSid(this.getSessionID());
|
||||||
//session.sendAck(this.getJingle());
|
// session.sendAck(this.getJingle());
|
||||||
session.updatePacketListener();
|
session.updatePacketListener();
|
||||||
session.terminate("Declined");
|
session.terminate("Declined");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class JingleSessionStatePending extends JingleSessionState {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Anything other action is an error.
|
// Anything other action is an error.
|
||||||
//response = createJingleError(inJingle, JingleError.OUT_OF_ORDER);
|
// response = createJingleError(inJingle, JingleError.OUT_OF_ORDER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +106,8 @@ public class JingleSessionStatePending extends JingleSessionState {
|
||||||
private IQ receiveContentAcceptAction(Jingle inJingle) {
|
private IQ receiveContentAcceptAction(Jingle inJingle) {
|
||||||
|
|
||||||
// According to XEP-167 the only thing we can do is ack.
|
// According to XEP-167 the only thing we can do is ack.
|
||||||
//setSessionState(JingleSessionStateEnum.ACTIVE);
|
// setSessionState(JingleSessionStateEnum.ACTIVE);
|
||||||
//return createAck(inJingle);
|
// return createAck(inJingle);
|
||||||
|
|
||||||
// This is now handled by the media negotiator for the matching <content> segment.
|
// This is now handled by the media negotiator for the matching <content> segment.
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class MediaNegotiator extends JingleNegotiator {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(MediaNegotiator.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(MediaNegotiator.class.getName());
|
||||||
|
|
||||||
//private JingleSession session; // The session this negotiation
|
// private JingleSession session; // The session this negotiation
|
||||||
|
|
||||||
private final JingleMediaManager mediaManager;
|
private final JingleMediaManager mediaManager;
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ public class MediaNegotiator extends JingleNegotiator {
|
||||||
// If there are suitable/matching payload types then accept this content.
|
// If there are suitable/matching payload types then accept this content.
|
||||||
if (bestCommonAudioPt != null) {
|
if (bestCommonAudioPt != null) {
|
||||||
// Let thre transport negotiators sort-out connectivity and content-accept instead.
|
// Let thre transport negotiators sort-out connectivity and content-accept instead.
|
||||||
//response = createAudioPayloadTypesOffer();
|
// response = createAudioPayloadTypesOffer();
|
||||||
setNegotiatorState(JingleNegotiatorState.PENDING);
|
setNegotiatorState(JingleNegotiatorState.PENDING);
|
||||||
} else {
|
} else {
|
||||||
// Don't really know what to send here. XEP-166 is not clear.
|
// Don't really know what to send here. XEP-166 is not clear.
|
||||||
|
@ -291,7 +291,7 @@ public class MediaNegotiator extends JingleNegotiator {
|
||||||
// and send an accept if we have an agreement...
|
// and send an accept if we have an agreement...
|
||||||
ptChange = !bestCommonAudioPt.equals(oldBestCommonAudioPt);
|
ptChange = !bestCommonAudioPt.equals(oldBestCommonAudioPt);
|
||||||
if (oldBestCommonAudioPt == null || ptChange) {
|
if (oldBestCommonAudioPt == null || ptChange) {
|
||||||
//response = createAcceptMessage();
|
// response = createAcceptMessage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new JingleException(JingleError.NO_COMMON_PAYLOAD);
|
throw new JingleException(JingleError.NO_COMMON_PAYLOAD);
|
||||||
|
@ -319,7 +319,7 @@ public class MediaNegotiator extends JingleNegotiator {
|
||||||
if (bestCommonAudioPt == null) {
|
if (bestCommonAudioPt == null) {
|
||||||
// Update the best common audio PT
|
// Update the best common audio PT
|
||||||
bestCommonAudioPt = calculateBestCommonAudioPt(remoteAudioPts);
|
bestCommonAudioPt = calculateBestCommonAudioPt(remoteAudioPts);
|
||||||
//response = createAcceptMessage();
|
// response = createAcceptMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
offeredPayloads = description.getAudioPayloadTypesList();
|
offeredPayloads = description.getAudioPayloadTypesList();
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class JMFInit extends Frame implements Runnable {
|
||||||
throw td;
|
throw td;
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> jsauto;
|
Class<?> jsauto;
|
||||||
|
@ -226,7 +226,7 @@ public class JMFInit extends Frame implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable tt) {
|
catch (Throwable tt) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ public class JMFInit extends Frame implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable tt) {
|
catch (Throwable tt) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,9 @@ public class JmfMediaManager extends JingleMediaManager {
|
||||||
// should be and put it there.
|
// should be and put it there.
|
||||||
runLinuxPreInstall();
|
runLinuxPreInstall();
|
||||||
|
|
||||||
//if (jmfProperties.length() == 0) {
|
// if (jmfProperties.length() == 0) {
|
||||||
new JMFInit(null, false);
|
new JMFInit(null, false);
|
||||||
//}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ public class ImageReceiver extends Canvas {
|
||||||
|
|
||||||
public void drawTile(int x, int y, BufferedImage bufferedImage) {
|
public void drawTile(int x, int y, BufferedImage bufferedImage) {
|
||||||
tiles[x][y] = bufferedImage;
|
tiles[x][y] = bufferedImage;
|
||||||
//repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
|
// repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
|
||||||
this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
|
this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,8 +221,8 @@ public class ICECandidate extends TransportCandidate implements Comparable<ICECa
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void check(final List<TransportCandidate> localCandidates) {
|
public void check(final List<TransportCandidate> localCandidates) {
|
||||||
//TODO candidate is being checked trigger
|
// TODO candidate is being checked trigger
|
||||||
//candidatesChecking.add(cand);
|
// candidatesChecking.add(cand);
|
||||||
|
|
||||||
final ICECandidate checkingCandidate = this;
|
final ICECandidate checkingCandidate = this;
|
||||||
|
|
||||||
|
@ -287,8 +287,8 @@ public class ICECandidate extends TransportCandidate implements Comparable<ICECa
|
||||||
|
|
||||||
triggerCandidateChecked(result.isReachable());
|
triggerCandidateChecked(result.isReachable());
|
||||||
|
|
||||||
//TODO candidate is being checked trigger
|
// TODO candidate is being checked trigger
|
||||||
//candidatesChecking.remove(cand);
|
// candidatesChecking.remove(cand);
|
||||||
}
|
}
|
||||||
}, "Transport candidate check");
|
}, "Transport candidate check");
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class ICEResolver extends TransportResolver {
|
||||||
String server;
|
String server;
|
||||||
int port;
|
int port;
|
||||||
static Map<String, ICENegociator> negociatorsMap = new HashMap<String, ICENegociator>();
|
static Map<String, ICENegociator> negociatorsMap = new HashMap<String, ICENegociator>();
|
||||||
//ICENegociator iceNegociator = null;
|
// ICENegociator iceNegociator = null;
|
||||||
|
|
||||||
public ICEResolver(XMPPConnection connection, String server, int port) {
|
public ICEResolver(XMPPConnection connection, String server, int port) {
|
||||||
super();
|
super();
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class TcpUdpBridgeClient {
|
||||||
byte[] b = new byte[500];
|
byte[] b = new byte[500];
|
||||||
|
|
||||||
int s = in.read(b);
|
int s = in.read(b);
|
||||||
//if (s == -1) continue;
|
// if (s == -1) continue;
|
||||||
|
|
||||||
LOGGER.fine("TCP Client:" + new String(b, 0, s, "UTF-8"));
|
LOGGER.fine("TCP Client:" + new String(b, 0, s, "UTF-8"));
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class TcpUdpBridgeServer {
|
||||||
byte[] b = new byte[500];
|
byte[] b = new byte[500];
|
||||||
|
|
||||||
int s = in.read(b);
|
int s = in.read(b);
|
||||||
//if (s == -1) continue;
|
// if (s == -1) continue;
|
||||||
|
|
||||||
LOGGER.fine("TCP Server:" + new String(b, 0, s, "UTF-8"));
|
LOGGER.fine("TCP Server:" + new String(b, 0, s, "UTF-8"));
|
||||||
|
|
||||||
|
|
|
@ -352,8 +352,8 @@ public abstract class TransportCandidate {
|
||||||
* Subclasses should provide better methods if they can...
|
* Subclasses should provide better methods if they can...
|
||||||
*/
|
*/
|
||||||
public void check(final List<TransportCandidate> localCandidates) {
|
public void check(final List<TransportCandidate> localCandidates) {
|
||||||
//TODO candidate is being checked trigger
|
// TODO candidate is being checked trigger
|
||||||
//candidatesChecking.add(cand);
|
// candidatesChecking.add(cand);
|
||||||
|
|
||||||
Thread checkThread = new Thread(new Runnable() {
|
Thread checkThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -372,8 +372,8 @@ public abstract class TransportCandidate {
|
||||||
}
|
}
|
||||||
triggerCandidateChecked(isUsable);
|
triggerCandidateChecked(isUsable);
|
||||||
|
|
||||||
//TODO candidate is being checked trigger
|
// TODO candidate is being checked trigger
|
||||||
//candidatesChecking.remove(cand);
|
// candidatesChecking.remove(cand);
|
||||||
}
|
}
|
||||||
}, "Transport candidate check");
|
}, "Transport candidate check");
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ public abstract class TransportCandidate {
|
||||||
|
|
||||||
socket.receive(packet);
|
socket.receive(packet);
|
||||||
|
|
||||||
//LOGGER.fine("ECHO Packet Received in: " + socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort() + " From: " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
// LOGGER.fine("ECHO Packet Received in: " + socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort() + " From: " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
||||||
|
|
||||||
boolean accept = false;
|
boolean accept = false;
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
public final static int CANDIDATES_ACCEPT_PERIOD = 4000;
|
public final static int CANDIDATES_ACCEPT_PERIOD = 4000;
|
||||||
|
|
||||||
// The session this nenotiator belongs to
|
// The session this nenotiator belongs to
|
||||||
//private final JingleSession session;
|
// private final JingleSession session;
|
||||||
|
|
||||||
// The transport manager
|
// The transport manager
|
||||||
private final TransportResolver resolver;
|
private final TransportResolver resolver;
|
||||||
|
@ -137,7 +137,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
*/
|
*/
|
||||||
private void setAcceptedLocalCandidate(TransportCandidate bestLocalCandidate) {
|
private void setAcceptedLocalCandidate(TransportCandidate bestLocalCandidate) {
|
||||||
for (int i = 0; i < resolver.getCandidateCount(); i++) {
|
for (int i = 0; i < resolver.getCandidateCount(); i++) {
|
||||||
//TODO FIX The EQUAL Sentence
|
// TODO FIX The EQUAL Sentence
|
||||||
if (resolver.getCandidate(i).getIp().equals(bestLocalCandidate.getIp())
|
if (resolver.getCandidate(i).getIp().equals(bestLocalCandidate.getIp())
|
||||||
&& resolver.getCandidate(i).getPort() == bestLocalCandidate.getPort()) {
|
&& resolver.getCandidate(i).getPort() == bestLocalCandidate.getPort()) {
|
||||||
acceptedLocalCandidate = resolver.getCandidate(i);
|
acceptedLocalCandidate = resolver.getCandidate(i);
|
||||||
|
@ -145,7 +145,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOGGER.fine("BEST: ip=" + bestLocalCandidate.getIp() + " port=" + bestLocalCandidate.getPort() + " has not been offered.");
|
LOGGER.fine("BEST: ip=" + bestLocalCandidate.getIp() + " port=" + bestLocalCandidate.getPort() + " has not been offered.");
|
||||||
//throw new XMPPException("Local transport candidate has not be offered.");
|
// throw new XMPPException("Local transport candidate has not be offered.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -316,7 +316,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
// Once we are in pending state, look for any valid remote
|
// Once we are in pending state, look for any valid remote
|
||||||
// candidate, and send an "accept" if we have one...
|
// candidate, and send an "accept" if we have one...
|
||||||
TransportCandidate bestRemote = getBestRemoteCandidate();
|
TransportCandidate bestRemote = getBestRemoteCandidate();
|
||||||
//State state = getState();
|
// State state = getState();
|
||||||
|
|
||||||
if ((bestRemote != null)
|
if ((bestRemote != null)
|
||||||
&& ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
|
&& ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
|
||||||
|
@ -359,7 +359,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
if (candidate instanceof ICECandidate) {
|
if (candidate instanceof ICECandidate) {
|
||||||
ICECandidate iceCandidate = (ICECandidate) candidate;
|
ICECandidate iceCandidate = (ICECandidate) candidate;
|
||||||
if (iceCandidate.getType().equals(Type.relay)) {
|
if (iceCandidate.getType().equals(Type.relay)) {
|
||||||
//TODO Check if the relay is reacheable
|
// TODO Check if the relay is reacheable.
|
||||||
addValidRemoteCandidate(iceCandidate);
|
addValidRemoteCandidate(iceCandidate);
|
||||||
foundRemoteRelay = true;
|
foundRemoteRelay = true;
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
bestRemote = getBestRemoteCandidate();
|
bestRemote = getBestRemoteCandidate();
|
||||||
//State state = getState();
|
// State state = getState();
|
||||||
if ((bestRemote != null)
|
if ((bestRemote != null)
|
||||||
&& ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
|
&& ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
|
||||||
if (!acceptedRemoteCandidates.contains(bestRemote)) {
|
if (!acceptedRemoteCandidates.contains(bestRemote)) {
|
||||||
|
@ -699,7 +699,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
IQ response = null;
|
IQ response = null;
|
||||||
|
|
||||||
// Parse the Jingle and get any proposed transport candidates
|
// Parse the Jingle and get any proposed transport candidates
|
||||||
//addRemoteCandidates(obtainCandidatesList(jin));
|
// addRemoteCandidates(obtainCandidatesList(jin));
|
||||||
|
|
||||||
// Start offering candidates
|
// Start offering candidates
|
||||||
sendTransportCandidatesOffer();
|
sendTransportCandidatesOffer();
|
||||||
|
@ -723,7 +723,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
IQ response = null;
|
IQ response = null;
|
||||||
|
|
||||||
// Parse the Jingle and get any proposed transport candidates
|
// Parse the Jingle and get any proposed transport candidates
|
||||||
//addRemoteCandidates(obtainCandidatesList(jin));
|
// addRemoteCandidates(obtainCandidatesList(jin));
|
||||||
|
|
||||||
// // Start offering candidates
|
// // Start offering candidates
|
||||||
// sendTransportCandidatesOffer();
|
// sendTransportCandidatesOffer();
|
||||||
|
@ -771,7 +771,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
|
|
||||||
if (isEstablished()) {
|
if (isEstablished()) {
|
||||||
LOGGER.fine(cand.getIp() + " is set active");
|
LOGGER.fine(cand.getIp() + " is set active");
|
||||||
//setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
|
// setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
@ -785,9 +785,9 @@ public abstract class TransportNegotiator extends JingleNegotiator {
|
||||||
IQ response = null;
|
IQ response = null;
|
||||||
|
|
||||||
LOGGER.fine("Transport stabilished");
|
LOGGER.fine("Transport stabilished");
|
||||||
//triggerTransportEstablished(getAcceptedLocalCandidate(), getBestRemoteCandidate());
|
// triggerTransportEstablished(getAcceptedLocalCandidate(), getBestRemoteCandidate());
|
||||||
|
|
||||||
//setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
|
// setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ public abstract class JingleTransportProvider extends ExtensionElementProvider<J
|
||||||
String name = parser.getAttributeValue("", "name");
|
String name = parser.getAttributeValue("", "name");
|
||||||
String port = parser.getAttributeValue("", "port");
|
String port = parser.getAttributeValue("", "port");
|
||||||
|
|
||||||
//LOGGER.debug();
|
// LOGGER.debug();
|
||||||
|
|
||||||
if (generation != null) {
|
if (generation != null) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -210,7 +210,7 @@ public class SignalOmemoKeyUtil extends OmemoKeyUtil<IdentityKeyPair, IdentityKe
|
||||||
@Override
|
@Override
|
||||||
public OmemoFingerprint getFingerprint(IdentityKey identityKey) {
|
public OmemoFingerprint getFingerprint(IdentityKey identityKey) {
|
||||||
String fp = identityKey.getFingerprint();
|
String fp = identityKey.getFingerprint();
|
||||||
//Cut "(byte)0x" prefixes, remove spaces and commas, cut first two digits.
|
// Cut "(byte)0x" prefixes, remove spaces and commas, cut first two digits.
|
||||||
fp = fp.replace("(byte)0x", "").replace(",", "").replace(" ", "").substring(2);
|
fp = fp.replace("(byte)0x", "").replace(",", "").replace(" ", "").substring(2);
|
||||||
return new OmemoFingerprint(fp);
|
return new OmemoFingerprint(fp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ public class SignalOmemoStoreConnector
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrustedIdentity(SignalProtocolAddress signalProtocolAddress, IdentityKey identityKey) {
|
public boolean isTrustedIdentity(SignalProtocolAddress signalProtocolAddress, IdentityKey identityKey) {
|
||||||
//Disable internal trust management. Instead we use OmemoStore.isTrustedOmemoIdentity() before encrypting for a
|
// Disable internal trust management. Instead we use OmemoStore.isTrustedOmemoIdentity() before encrypting for a
|
||||||
//recipient.
|
// recipient.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -317,7 +317,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
preKeys.put(Integer.parseInt(f.getName()), p);
|
preKeys.put(Integer.parseInt(f.getName()), p);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return preKeys;
|
return preKeys;
|
||||||
|
@ -355,7 +355,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
signedPreKeys.put(Integer.parseInt(f.getName()), p);
|
signedPreKeys.put(Integer.parseInt(f.getName()), p);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return signedPreKeys;
|
return signedPreKeys;
|
||||||
|
@ -414,7 +414,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
sessions.put(id, s);
|
sessions.put(id, s);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//Do nothing
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sessions;
|
return sessions;
|
||||||
|
@ -469,7 +469,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//active
|
// active
|
||||||
File activeDevicesPath = hierarchy.getContactsActiveDevicesPath(omemoManager, contact);
|
File activeDevicesPath = hierarchy.getContactsActiveDevicesPath(omemoManager, contact);
|
||||||
try {
|
try {
|
||||||
cachedDeviceList.getActiveDevices().addAll(readIntegers(activeDevicesPath));
|
cachedDeviceList.getActiveDevices().addAll(readIntegers(activeDevicesPath));
|
||||||
|
@ -477,12 +477,12 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
// Don't worry...
|
// Don't worry...
|
||||||
}
|
}
|
||||||
|
|
||||||
//inactive
|
// inactive
|
||||||
File inactiveDevicesPath = hierarchy.getContactsInactiveDevicesPath(omemoManager, contact);
|
File inactiveDevicesPath = hierarchy.getContactsInactiveDevicesPath(omemoManager, contact);
|
||||||
try {
|
try {
|
||||||
cachedDeviceList.getInactiveDevices().addAll(readIntegers(inactiveDevicesPath));
|
cachedDeviceList.getInactiveDevices().addAll(readIntegers(inactiveDevicesPath));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//It's ok :)
|
// It's ok :)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cachedDeviceList;
|
return cachedDeviceList;
|
||||||
|
@ -631,7 +631,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
throw new IOException("Could not write bytes to null-path.");
|
throw new IOException("Could not write bytes to null-path.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create file
|
// Create file
|
||||||
FileHierarchy.createFile(target);
|
FileHierarchy.createFile(target);
|
||||||
|
|
||||||
IOException io = null;
|
IOException io = null;
|
||||||
|
@ -730,7 +730,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
|
||||||
integers.add(in.readInt());
|
integers.add(in.readInt());
|
||||||
}
|
}
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
//Reached end of the list.
|
// Reached end of the list.
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -178,7 +178,7 @@ public final class OmemoManager extends Manager {
|
||||||
if (connection.getUser() != null) {
|
if (connection.getUser() != null) {
|
||||||
user = connection.getUser().asBareJid();
|
user = connection.getUser().asBareJid();
|
||||||
} else {
|
} else {
|
||||||
//This might be dangerous
|
// This might be dangerous
|
||||||
try {
|
try {
|
||||||
user = JidCreate.bareFrom(((AbstractXMPPConnection) connection).getConfiguration().getUsername());
|
user = JidCreate.bareFrom(((AbstractXMPPConnection) connection).getConfiguration().getUsername());
|
||||||
} catch (XmppStringprepException e) {
|
} catch (XmppStringprepException e) {
|
||||||
|
@ -406,7 +406,7 @@ public final class OmemoManager extends Manager {
|
||||||
* @throws CorruptedOmemoKeyException
|
* @throws CorruptedOmemoKeyException
|
||||||
*/
|
*/
|
||||||
public void regenerate() throws SmackException, InterruptedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException {
|
public void regenerate() throws SmackException, InterruptedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException {
|
||||||
//create a new identity and publish new keys to the server
|
// create a new identity and publish new keys to the server
|
||||||
getOmemoService().regenerate(this, null);
|
getOmemoService().regenerate(this, null);
|
||||||
getOmemoService().publishDeviceIdIfNeeded(this,false);
|
getOmemoService().publishDeviceIdIfNeeded(this,false);
|
||||||
getOmemoService().publishBundle(this);
|
getOmemoService().publishBundle(this);
|
||||||
|
@ -622,9 +622,9 @@ public final class OmemoManager extends Manager {
|
||||||
* @throws PubSubException.NotALeafNodeException if the bundle node on the server is a CollectionNode
|
* @throws PubSubException.NotALeafNodeException if the bundle node on the server is a CollectionNode
|
||||||
*/
|
*/
|
||||||
public void rotateSignedPreKey() throws CorruptedOmemoKeyException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, PubSubException.NotALeafNodeException {
|
public void rotateSignedPreKey() throws CorruptedOmemoKeyException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, PubSubException.NotALeafNodeException {
|
||||||
//generate key
|
// generate key
|
||||||
getOmemoService().getOmemoStoreBackend().changeSignedPreKey(this);
|
getOmemoService().getOmemoStoreBackend().changeSignedPreKey(this);
|
||||||
//publish
|
// publish
|
||||||
getOmemoService().publishDeviceIdIfNeeded(this, false);
|
getOmemoService().publishDeviceIdIfNeeded(this, false);
|
||||||
getOmemoService().publishBundle(this);
|
getOmemoService().publishBundle(this);
|
||||||
}
|
}
|
||||||
|
@ -788,31 +788,31 @@ public final class OmemoManager extends Manager {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Device List <list>
|
// Device List <list>
|
||||||
OmemoDeviceListVAxolotlElement omemoDeviceListElement = (OmemoDeviceListVAxolotlElement) payloadItem.getPayload();
|
OmemoDeviceListVAxolotlElement omemoDeviceListElement = (OmemoDeviceListVAxolotlElement) payloadItem.getPayload();
|
||||||
int ourDeviceId = getDeviceId();
|
int ourDeviceId = getDeviceId();
|
||||||
getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(OmemoManager.this, from, omemoDeviceListElement);
|
getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(OmemoManager.this, from, omemoDeviceListElement);
|
||||||
|
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
//Unknown sender, no more work to do.
|
// Unknown sender, no more work to do.
|
||||||
//TODO: This DOES happen for some reason. Figure out when...
|
// TODO: This DOES happen for some reason. Figure out when...
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!from.equals(getOwnJid())) {
|
if (!from.equals(getOwnJid())) {
|
||||||
//Not our deviceList, so nothing more to do
|
// Not our deviceList, so nothing more to do
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (omemoDeviceListElement.getDeviceIds().contains(ourDeviceId)) {
|
if (omemoDeviceListElement.getDeviceIds().contains(ourDeviceId)) {
|
||||||
//We are on the list. Nothing more to do
|
// We are on the list. Nothing more to do
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Our deviceList and we are not on it! We don't want to miss all the action!!!
|
// Our deviceList and we are not on it! We don't want to miss all the action!!!
|
||||||
LOGGER.log(Level.INFO, "Our deviceId was not on the list!");
|
LOGGER.log(Level.INFO, "Our deviceId was not on the list!");
|
||||||
Set<Integer> deviceListIds = omemoDeviceListElement.copyDeviceIds();
|
Set<Integer> deviceListIds = omemoDeviceListElement.copyDeviceIds();
|
||||||
//enroll at the deviceList
|
// enroll at the deviceList
|
||||||
deviceListIds.add(ourDeviceId);
|
deviceListIds.add(ourDeviceId);
|
||||||
final OmemoDeviceListVAxolotlElement newOmemoDeviceListElement = new OmemoDeviceListVAxolotlElement(deviceListIds);
|
final OmemoDeviceListVAxolotlElement newOmemoDeviceListElement = new OmemoDeviceListVAxolotlElement(deviceListIds);
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
throws NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException,
|
throws NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException,
|
||||||
BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
|
BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
|
||||||
|
|
||||||
//Check availability of algorithms and encodings needed for crypto
|
// Check availability of algorithms and encodings needed for crypto
|
||||||
checkAvailableAlgorithms();
|
checkAvailableAlgorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,12 +214,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
boolean mustPublishId = false;
|
boolean mustPublishId = false;
|
||||||
if (getOmemoStoreBackend().isFreshInstallation(omemoManager)) {
|
if (getOmemoStoreBackend().isFreshInstallation(omemoManager)) {
|
||||||
LOGGER.log(Level.INFO, "No key material found. Looks like we have a fresh installation.");
|
LOGGER.log(Level.INFO, "No key material found. Looks like we have a fresh installation.");
|
||||||
//Create new key material and publish it to the server
|
// Create new key material and publish it to the server
|
||||||
regenerate(omemoManager, omemoManager.getDeviceId());
|
regenerate(omemoManager, omemoManager.getDeviceId());
|
||||||
mustPublishId = true;
|
mustPublishId = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get fresh device list from server
|
// Get fresh device list from server
|
||||||
mustPublishId |= refreshOwnDeviceList(omemoManager);
|
mustPublishId |= refreshOwnDeviceList(omemoManager);
|
||||||
|
|
||||||
publishDeviceIdIfNeeded(omemoManager, false, mustPublishId);
|
publishDeviceIdIfNeeded(omemoManager, false, mustPublishId);
|
||||||
|
@ -244,7 +244,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
protected static void checkAvailableAlgorithms() throws NoSuchPaddingException, UnsupportedEncodingException,
|
protected static void checkAvailableAlgorithms() throws NoSuchPaddingException, UnsupportedEncodingException,
|
||||||
InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException,
|
InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException,
|
||||||
NoSuchProviderException, InvalidKeyException {
|
NoSuchProviderException, InvalidKeyException {
|
||||||
//Test crypto functions
|
// Test crypto functions
|
||||||
new OmemoMessageBuilder<>(null, null, "");
|
new OmemoMessageBuilder<>(null, null, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* (should never ever happen *crosses fingers*)
|
* (should never ever happen *crosses fingers*)
|
||||||
*/
|
*/
|
||||||
void regenerate(OmemoManager omemoManager, Integer nDeviceId) throws CorruptedOmemoKeyException {
|
void regenerate(OmemoManager omemoManager, Integer nDeviceId) throws CorruptedOmemoKeyException {
|
||||||
//Generate unique ID that is not already taken
|
// Generate unique ID that is not already taken
|
||||||
while (nDeviceId == null || !getOmemoStoreBackend().isAvailableDeviceId(omemoManager, nDeviceId)) {
|
while (nDeviceId == null || !getOmemoStoreBackend().isAvailableDeviceId(omemoManager, nDeviceId)) {
|
||||||
nDeviceId = OmemoManager.randomDeviceId();
|
nDeviceId = OmemoManager.randomDeviceId();
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
getOmemoStoreBackend().setDateOfLastSignedPreKeyRenewal(omemoManager);
|
getOmemoStoreBackend().setDateOfLastSignedPreKeyRenewal(omemoManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
//publish
|
// publish
|
||||||
PubSubManager.getInstance(omemoManager.getConnection(), omemoManager.getOwnJid())
|
PubSubManager.getInstance(omemoManager.getConnection(), omemoManager.getOwnJid())
|
||||||
.tryToPublishAndPossibleAutoCreate(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(omemoManager.getDeviceId()),
|
.tryToPublishAndPossibleAutoCreate(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(omemoManager.getDeviceId()),
|
||||||
new PayloadItem<>(getOmemoStoreBackend().packOmemoBundle(omemoManager)));
|
new PayloadItem<>(getOmemoStoreBackend().packOmemoBundle(omemoManager)));
|
||||||
|
@ -369,12 +369,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
boolean removeStaleDevicesIfNeeded(OmemoManager omemoManager, Set<Integer> deviceListIds) {
|
boolean removeStaleDevicesIfNeeded(OmemoManager omemoManager, Set<Integer> deviceListIds) {
|
||||||
boolean publish = false;
|
boolean publish = false;
|
||||||
int ownDeviceId = omemoManager.getDeviceId();
|
int ownDeviceId = omemoManager.getDeviceId();
|
||||||
//Clear devices that we didn't receive a message from for a while
|
// Clear devices that we didn't receive a message from for a while
|
||||||
Iterator<Integer> it = deviceListIds.iterator();
|
Iterator<Integer> it = deviceListIds.iterator();
|
||||||
while (OmemoConfiguration.getDeleteStaleDevices() && it.hasNext()) {
|
while (OmemoConfiguration.getDeleteStaleDevices() && it.hasNext()) {
|
||||||
int id = it.next();
|
int id = it.next();
|
||||||
if (id == ownDeviceId) {
|
if (id == ownDeviceId) {
|
||||||
//Skip own id
|
// Skip own id
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,11 +601,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
for (int id : devices.getActiveDevices()) {
|
for (int id : devices.getActiveDevices()) {
|
||||||
OmemoDevice device = new OmemoDevice(jid, id);
|
OmemoDevice device = new OmemoDevice(jid, id);
|
||||||
if (getOmemoStoreBackend().containsRawSession(omemoManager, device)) {
|
if (getOmemoStoreBackend().containsRawSession(omemoManager, device)) {
|
||||||
//We have a session already.
|
// We have a session already.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build missing session
|
// Build missing session
|
||||||
try {
|
try {
|
||||||
buildSessionFromOmemoBundle(omemoManager, device, false);
|
buildSessionFromOmemoBundle(omemoManager, device, false);
|
||||||
} catch (CannotEstablishOmemoSessionException e) {
|
} catch (CannotEstablishOmemoSessionException e) {
|
||||||
|
@ -648,7 +648,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do not build sessions with devices we already know...
|
// Do not build sessions with devices we already know...
|
||||||
if (!fresh && getOmemoStoreBackend().containsRawSession(omemoManager, device)) {
|
if (!fresh && getOmemoStoreBackend().containsRawSession(omemoManager, device)) {
|
||||||
getOmemoStoreBackend().getOmemoSessionOf(omemoManager, device); //Make sure its loaded though
|
getOmemoStoreBackend().getOmemoSessionOf(omemoManager, device); //Make sure its loaded though
|
||||||
return;
|
return;
|
||||||
|
@ -663,10 +663,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
|
|
||||||
HashMap<Integer, T_Bundle> bundles = getOmemoStoreBackend().keyUtil().BUNDLE.bundles(bundle, device);
|
HashMap<Integer, T_Bundle> bundles = getOmemoStoreBackend().keyUtil().BUNDLE.bundles(bundle, device);
|
||||||
|
|
||||||
//Select random Bundle
|
// Select random Bundle
|
||||||
int randomIndex = new Random().nextInt(bundles.size());
|
int randomIndex = new Random().nextInt(bundles.size());
|
||||||
T_Bundle randomPreKeyBundle = new ArrayList<>(bundles.values()).get(randomIndex);
|
T_Bundle randomPreKeyBundle = new ArrayList<>(bundles.values()).get(randomIndex);
|
||||||
//Build raw session
|
// Build raw session
|
||||||
processBundle(omemoManager, randomPreKeyBundle, device);
|
processBundle(omemoManager, randomPreKeyBundle, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,9 +701,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
CryptoFailedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException {
|
CryptoFailedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException {
|
||||||
|
|
||||||
ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> messageRecipientKeys = message.getHeader().getKeys();
|
ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> messageRecipientKeys = message.getHeader().getKeys();
|
||||||
//Do we have a key with our ID in the message?
|
// Do we have a key with our ID in the message?
|
||||||
for (OmemoVAxolotlElement.OmemoHeader.Key k : messageRecipientKeys) {
|
for (OmemoVAxolotlElement.OmemoHeader.Key k : messageRecipientKeys) {
|
||||||
//Only decrypt with our deviceID
|
// Only decrypt with our deviceID
|
||||||
if (k.getId() != omemoManager.getDeviceId()) {
|
if (k.getId() != omemoManager.getDeviceId()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -785,7 +785,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, CannotEstablishOmemoSessionException {
|
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, CannotEstablishOmemoSessionException {
|
||||||
|
|
||||||
CannotEstablishOmemoSessionException sessionException = null;
|
CannotEstablishOmemoSessionException sessionException = null;
|
||||||
//Them - The contact wants to read the message on all their devices.
|
// Them - The contact wants to read the message on all their devices.
|
||||||
HashMap<BareJid, ArrayList<OmemoDevice>> receivers = new HashMap<>();
|
HashMap<BareJid, ArrayList<OmemoDevice>> receivers = new HashMap<>();
|
||||||
for (BareJid recipient : recipients) {
|
for (BareJid recipient : recipients) {
|
||||||
try {
|
try {
|
||||||
|
@ -820,7 +820,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Us - We want to read the message on all of our devices
|
// Us - We want to read the message on all of our devices
|
||||||
CachedDeviceList ourDevices = getOmemoStoreBackend().loadCachedDeviceList(omemoManager, omemoManager.getOwnJid());
|
CachedDeviceList ourDevices = getOmemoStoreBackend().loadCachedDeviceList(omemoManager, omemoManager.getOwnJid());
|
||||||
if (ourDevices == null) {
|
if (ourDevices == null) {
|
||||||
ourDevices = new CachedDeviceList();
|
ourDevices = new CachedDeviceList();
|
||||||
|
@ -830,7 +830,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
for (int id : ourDevices.getActiveDevices()) {
|
for (int id : ourDevices.getActiveDevices()) {
|
||||||
OmemoDevice ourDevice = new OmemoDevice(omemoManager.getOwnJid(), id);
|
OmemoDevice ourDevice = new OmemoDevice(omemoManager.getOwnJid(), id);
|
||||||
if (id == omemoManager.getDeviceId()) {
|
if (id == omemoManager.getDeviceId()) {
|
||||||
//Don't build session with our exact device.
|
// Don't build session with our exact device.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,11 +957,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
try {
|
try {
|
||||||
builder.addRecipient(c);
|
builder.addRecipient(c);
|
||||||
} catch (CorruptedOmemoKeyException e) {
|
} catch (CorruptedOmemoKeyException e) {
|
||||||
//TODO: How to react?
|
// TODO: How to react?
|
||||||
LOGGER.log(Level.SEVERE, "encryptOmemoMessage failed to establish a session with device "
|
LOGGER.log(Level.SEVERE, "encryptOmemoMessage failed to establish a session with device "
|
||||||
+ c + ": " + e.getMessage());
|
+ c + ": " + e.getMessage());
|
||||||
} catch (UndecidedOmemoIdentityException e) {
|
} catch (UndecidedOmemoIdentityException e) {
|
||||||
//Collect all undecided devices
|
// Collect all undecided devices
|
||||||
if (undecided == null) {
|
if (undecided == null) {
|
||||||
undecided = e;
|
undecided = e;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1132,7 +1132,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
List<ClearTextMessage> result = new ArrayList<>();
|
List<ClearTextMessage> result = new ArrayList<>();
|
||||||
for (Forwarded f : mamQueryResult.forwardedMessages) {
|
for (Forwarded f : mamQueryResult.forwardedMessages) {
|
||||||
if (OmemoManager.stanzaContainsOmemoElement(f.getForwardedStanza())) {
|
if (OmemoManager.stanzaContainsOmemoElement(f.getForwardedStanza())) {
|
||||||
//Decrypt OMEMO messages
|
// Decrypt OMEMO messages
|
||||||
try {
|
try {
|
||||||
result.add(processLocalMessage(omemoManager, f.getForwardedStanza().getFrom().asBareJid(), (Message) f.getForwardedStanza()));
|
result.add(processLocalMessage(omemoManager, f.getForwardedStanza().getFrom().asBareJid(), (Message) f.getForwardedStanza()));
|
||||||
} catch (NoRawSessionException | CorruptedOmemoKeyException | CryptoFailedException e) {
|
} catch (NoRawSessionException | CorruptedOmemoKeyException | CryptoFailedException e) {
|
||||||
|
@ -1140,7 +1140,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
+ f.getForwardedStanza().getFrom() + " due to corrupted session/key: " + e.getMessage());
|
+ f.getForwardedStanza().getFrom() + " due to corrupted session/key: " + e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Wrap cleartext messages
|
// Wrap cleartext messages
|
||||||
Message m = (Message) f.getForwardedStanza();
|
Message m = (Message) f.getForwardedStanza();
|
||||||
result.add(new ClearTextMessage(m.getBody(), m,
|
result.add(new ClearTextMessage(m.getBody(), m,
|
||||||
new OmemoMessageInformation(null, null, OmemoMessageInformation.CARBON.NONE, false)));
|
new OmemoMessageInformation(null, null, OmemoMessageInformation.CARBON.NONE, false)));
|
||||||
|
@ -1210,7 +1210,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
||||||
OmemoDevice senderDevice = getSender(omemoManager, stanza);
|
OmemoDevice senderDevice = getSender(omemoManager, stanza);
|
||||||
try {
|
try {
|
||||||
//Is it a MUC message...
|
// Is it a MUC message...
|
||||||
if (isMucMessage(omemoManager, stanza)) {
|
if (isMucMessage(omemoManager, stanza)) {
|
||||||
|
|
||||||
MultiUserChat muc = mucm.getMultiUserChat(stanza.getFrom().asEntityBareJidIfPossible());
|
MultiUserChat muc = mucm.getMultiUserChat(stanza.getFrom().asEntityBareJidIfPossible());
|
||||||
|
@ -1231,7 +1231,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//... or a normal chat message...
|
// ... or a normal chat message...
|
||||||
else {
|
else {
|
||||||
if (omemoMessage.isMessageElement()) {
|
if (omemoMessage.isMessageElement()) {
|
||||||
|
|
||||||
|
@ -1304,7 +1304,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//Is it a MUC message...
|
// Is it a MUC message...
|
||||||
if (isMucMessage(omemoManager, carbonCopy)) {
|
if (isMucMessage(omemoManager, carbonCopy)) {
|
||||||
|
|
||||||
MultiUserChat muc = mucm.getMultiUserChat(carbonCopy.getFrom().asEntityBareJidIfPossible());
|
MultiUserChat muc = mucm.getMultiUserChat(carbonCopy.getFrom().asEntityBareJidIfPossible());
|
||||||
|
@ -1325,7 +1325,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//... or a normal chat message...
|
// ... or a normal chat message...
|
||||||
else {
|
else {
|
||||||
if (omemoMessage.isMessageElement()) {
|
if (omemoMessage.isMessageElement()) {
|
||||||
|
|
||||||
|
|
|
@ -84,14 +84,14 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
boolean isAvailableDeviceId(OmemoManager omemoManager, int id) {
|
boolean isAvailableDeviceId(OmemoManager omemoManager, int id) {
|
||||||
LOGGER.log(Level.INFO, "Check if id " + id + " is available...");
|
LOGGER.log(Level.INFO, "Check if id " + id + " is available...");
|
||||||
|
|
||||||
//Lookup local cached device list
|
// Lookup local cached device list
|
||||||
BareJid ownJid = omemoManager.getOwnJid();
|
BareJid ownJid = omemoManager.getOwnJid();
|
||||||
CachedDeviceList cachedDeviceList = loadCachedDeviceList(omemoManager, ownJid);
|
CachedDeviceList cachedDeviceList = loadCachedDeviceList(omemoManager, ownJid);
|
||||||
|
|
||||||
if (cachedDeviceList == null) {
|
if (cachedDeviceList == null) {
|
||||||
cachedDeviceList = new CachedDeviceList();
|
cachedDeviceList = new CachedDeviceList();
|
||||||
}
|
}
|
||||||
//Does the list already contain that id?
|
// Does the list already contain that id?
|
||||||
return !cachedDeviceList.contains(id);
|
return !cachedDeviceList.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
*/
|
*/
|
||||||
void initializeOmemoSessions(OmemoManager omemoManager) {
|
void initializeOmemoSessions(OmemoManager omemoManager) {
|
||||||
|
|
||||||
//Get HashMap of our omemoSessions
|
// Get HashMap of our omemoSessions
|
||||||
HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
||||||
sessions = omemoSessions.get(omemoManager);
|
sessions = omemoSessions.get(omemoManager);
|
||||||
if (sessions == null) {
|
if (sessions == null) {
|
||||||
|
@ -228,12 +228,12 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
omemoSessions.put(omemoManager, sessions);
|
omemoSessions.put(omemoManager, sessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sessions with our own devices
|
// Sessions with our own devices
|
||||||
HashMap<Integer, T_Sess> ourRawSessions = loadAllRawSessionsOf(omemoManager, omemoManager.getOwnJid());
|
HashMap<Integer, T_Sess> ourRawSessions = loadAllRawSessionsOf(omemoManager, omemoManager.getOwnJid());
|
||||||
ourRawSessions.remove(omemoManager.getDeviceId()); //Just to make sure we have no session with ourselves...
|
ourRawSessions.remove(omemoManager.getDeviceId()); //Just to make sure we have no session with ourselves...
|
||||||
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, omemoManager.getOwnJid(), ourRawSessions));
|
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, omemoManager.getOwnJid(), ourRawSessions));
|
||||||
|
|
||||||
//Sessions with contacts
|
// Sessions with contacts
|
||||||
for (RosterEntry rosterEntry : Roster.getInstanceFor(omemoManager.getConnection()).getEntries()) {
|
for (RosterEntry rosterEntry : Roster.getInstanceFor(omemoManager.getConnection()).getEntries()) {
|
||||||
HashMap<Integer, T_Sess> contactDevices = loadAllRawSessionsOf(omemoManager, rosterEntry.getJid().asBareJid());
|
HashMap<Integer, T_Sess> contactDevices = loadAllRawSessionsOf(omemoManager, rosterEntry.getJid().asBareJid());
|
||||||
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, rosterEntry.getJid().asBareJid(), contactDevices));
|
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, rosterEntry.getJid().asBareJid(), contactDevices));
|
||||||
|
@ -284,7 +284,7 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
|
|
||||||
OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
||||||
session = sessions.get(device);
|
session = sessions.get(device);
|
||||||
//No OmemoSession found
|
// No OmemoSession found
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
T_IdKey identityKey = null;
|
T_IdKey identityKey = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -129,9 +129,9 @@ public abstract class OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
|
|
||||||
if (unpackedKey.length == 32) {
|
if (unpackedKey.length == 32) {
|
||||||
authTag = new byte[16];
|
authTag = new byte[16];
|
||||||
//copy key part into messageKey
|
// copy key part into messageKey
|
||||||
System.arraycopy(unpackedKey, 0, messageKey, 0, 16);
|
System.arraycopy(unpackedKey, 0, messageKey, 0, 16);
|
||||||
//copy tag part into authTag
|
// copy tag part into authTag
|
||||||
System.arraycopy(unpackedKey, 16, authTag, 0,16);
|
System.arraycopy(unpackedKey, 16, authTag, 0,16);
|
||||||
} else if (element.isKeyTransportElement() && unpackedKey.length == 16) {
|
} else if (element.isKeyTransportElement() && unpackedKey.length == 16) {
|
||||||
messageKey = unpackedKey;
|
messageKey = unpackedKey;
|
||||||
|
|
|
@ -22,14 +22,14 @@ package org.jivesoftware.smackx.omemo.util;
|
||||||
*/
|
*/
|
||||||
public final class OmemoConstants {
|
public final class OmemoConstants {
|
||||||
|
|
||||||
//Constants
|
// Constants
|
||||||
/**
|
/**
|
||||||
* Omemo related namespace.
|
* Omemo related namespace.
|
||||||
*/
|
*/
|
||||||
public static final String OMEMO_NAMESPACE_V_AXOLOTL = "eu.siacs.conversations.axolotl";
|
public static final String OMEMO_NAMESPACE_V_AXOLOTL = "eu.siacs.conversations.axolotl";
|
||||||
public static final String OMEMO = "OMEMO";
|
public static final String OMEMO = "OMEMO";
|
||||||
|
|
||||||
//PubSub Node names
|
// PubSub Node names
|
||||||
public static final String PEP_NODE_DEVICE_LIST = OMEMO_NAMESPACE_V_AXOLOTL + ".devicelist";
|
public static final String PEP_NODE_DEVICE_LIST = OMEMO_NAMESPACE_V_AXOLOTL + ".devicelist";
|
||||||
public static final String PEP_NODE_DEVICE_LIST_NOTIFY = PEP_NODE_DEVICE_LIST + "+notify";
|
public static final String PEP_NODE_DEVICE_LIST_NOTIFY = PEP_NODE_DEVICE_LIST + "+notify";
|
||||||
public static final String PEP_NODE_BUNDLES = OMEMO_NAMESPACE_V_AXOLOTL + ".bundles";
|
public static final String PEP_NODE_BUNDLES = OMEMO_NAMESPACE_V_AXOLOTL + ".bundles";
|
||||||
|
|
|
@ -144,7 +144,7 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Encrypt message body
|
// Encrypt message body
|
||||||
SecretKey secretKey = new SecretKeySpec(messageKey, KEYTYPE);
|
SecretKey secretKey = new SecretKeySpec(messageKey, KEYTYPE);
|
||||||
IvParameterSpec ivSpec = new IvParameterSpec(initializationVector);
|
IvParameterSpec ivSpec = new IvParameterSpec(initializationVector);
|
||||||
Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER);
|
Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||||
|
@ -194,12 +194,12 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
if (!ignoreTrust && !omemoStore.isDecidedOmemoIdentity(omemoManager, device, session.getIdentityKey())) {
|
if (!ignoreTrust && !omemoStore.isDecidedOmemoIdentity(omemoManager, device, session.getIdentityKey())) {
|
||||||
//Warn user of undecided device
|
// Warn user of undecided device
|
||||||
throw new UndecidedOmemoIdentityException(device);
|
throw new UndecidedOmemoIdentityException(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignoreTrust && omemoStore.isTrustedOmemoIdentity(omemoManager, device, session.getIdentityKey())) {
|
if (!ignoreTrust && omemoStore.isTrustedOmemoIdentity(omemoManager, device, session.getIdentityKey())) {
|
||||||
//Encrypt key and save to header
|
// Encrypt key and save to header
|
||||||
CiphertextTuple encryptedKey = session.encryptMessageKey(messageKey);
|
CiphertextTuple encryptedKey = session.encryptMessageKey(messageKey);
|
||||||
keys.add(new OmemoVAxolotlElement.OmemoHeader.Key(encryptedKey.getCiphertext(), device.getDeviceId(), encryptedKey.isPreKeyMessage()));
|
keys.add(new OmemoVAxolotlElement.OmemoHeader.Key(encryptedKey.getCiphertext(), device.getDeviceId(), encryptedKey.isPreKeyMessage()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class OmemoConfigurationTest {
|
||||||
OmemoConfiguration.setMaxNumberOfStoredSignedPreKeys(0);
|
OmemoConfiguration.setMaxNumberOfStoredSignedPreKeys(0);
|
||||||
TestCase.fail("OmemoConfiguration.setMaxNumberOfStoredSignedPreKeys should not accept values <= 0");
|
TestCase.fail("OmemoConfiguration.setMaxNumberOfStoredSignedPreKeys should not accept values <= 0");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
//Expected
|
// Expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ import org.jivesoftware.smack.SmackException.AlreadyLoggedInException;
|
||||||
import org.jivesoftware.smack.SmackException.ConnectionException;
|
import org.jivesoftware.smack.SmackException.ConnectionException;
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||||
import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException;
|
import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException;
|
||||||
import org.jivesoftware.smack.StanzaListener;
|
import org.jivesoftware.smack.StanzaListener;
|
||||||
import org.jivesoftware.smack.SynchronizationPoint;
|
import org.jivesoftware.smack.SynchronizationPoint;
|
||||||
|
@ -309,7 +310,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
addConnectionListener(new AbstractConnectionListener() {
|
addConnectionListener(new AbstractConnectionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
if (e instanceof XMPPException.StreamErrorException) {
|
if (e instanceof XMPPException.StreamErrorException || e instanceof StreamManagementException) {
|
||||||
dropSmState();
|
dropSmState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -716,8 +717,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
else if ("Apple".equals(keyStoreType)) {
|
else if ("Apple".equals(keyStoreType)) {
|
||||||
ks = KeyStore.getInstance("KeychainStore","Apple");
|
ks = KeyStore.getInstance("KeychainStore","Apple");
|
||||||
ks.load(null,null);
|
ks.load(null,null);
|
||||||
//pcb = new PasswordCallback("Apple Keychain",false);
|
// pcb = new PasswordCallback("Apple Keychain",false);
|
||||||
//pcb.setPassword(null);
|
// pcb.setPassword(null);
|
||||||
}
|
}
|
||||||
else if (keyStoreType != null) {
|
else if (keyStoreType != null) {
|
||||||
ks = KeyStore.getInstance(keyStoreType);
|
ks = KeyStore.getInstance(keyStoreType);
|
||||||
|
@ -1146,8 +1147,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
if (!smSessionId.equals(resumed.getPrevId())) {
|
if (!smSessionId.equals(resumed.getPrevId())) {
|
||||||
throw new StreamIdDoesNotMatchException(smSessionId, resumed.getPrevId());
|
throw new StreamIdDoesNotMatchException(smSessionId, resumed.getPrevId());
|
||||||
}
|
}
|
||||||
// Mark SM as enabled and resumption as successful.
|
// Mark SM as enabled
|
||||||
smResumedSyncPoint.reportSuccess();
|
|
||||||
smEnabledSyncPoint.reportSuccess();
|
smEnabledSyncPoint.reportSuccess();
|
||||||
// First, drop the stanzas already handled by the server
|
// First, drop the stanzas already handled by the server
|
||||||
processHandledCount(resumed.getHandledCount());
|
processHandledCount(resumed.getHandledCount());
|
||||||
|
@ -1163,6 +1163,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
if (!stanzasToResend.isEmpty()) {
|
if (!stanzasToResend.isEmpty()) {
|
||||||
requestSmAcknowledgementInternal();
|
requestSmAcknowledgementInternal();
|
||||||
}
|
}
|
||||||
|
// Mark SM resumption as successful
|
||||||
|
smResumedSyncPoint.reportSuccess();
|
||||||
LOGGER.fine("Stream Management (XEP-198): Stream resumed");
|
LOGGER.fine("Stream Management (XEP-198): Stream resumed");
|
||||||
break;
|
break;
|
||||||
case AckAnswer.ELEMENT:
|
case AckAnswer.ELEMENT:
|
||||||
|
@ -1183,7 +1185,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case XmlPullParser.END_TAG:
|
||||||
if (parser.getName().equals("stream")) {
|
final String endTagName = parser.getName();
|
||||||
|
if ("stream".equals(endTagName)) {
|
||||||
if (!parser.getNamespace().equals("http://etherx.jabber.org/streams")) {
|
if (!parser.getNamespace().equals("http://etherx.jabber.org/streams")) {
|
||||||
LOGGER.warning(XMPPTCPConnection.this + " </stream> but different namespace " + parser.getNamespace());
|
LOGGER.warning(XMPPTCPConnection.this + " </stream> but different namespace " + parser.getNamespace());
|
||||||
break;
|
break;
|
||||||
|
@ -1879,7 +1882,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
try {
|
try {
|
||||||
listener.processStanza(ackedStanza);
|
listener.processStanza(ackedStanza);
|
||||||
}
|
}
|
||||||
catch (InterruptedException | NotConnectedException e) {
|
catch (InterruptedException | NotConnectedException | NotLoggedInException e) {
|
||||||
LOGGER.log(Level.FINER, "Received exception", e);
|
LOGGER.log(Level.FINER, "Received exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1892,7 +1895,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
try {
|
try {
|
||||||
listener.processStanza(ackedStanza);
|
listener.processStanza(ackedStanza);
|
||||||
}
|
}
|
||||||
catch (InterruptedException | NotConnectedException e) {
|
catch (InterruptedException | NotConnectedException | NotLoggedInException e) {
|
||||||
LOGGER.log(Level.FINER, "Received exception", e);
|
LOGGER.log(Level.FINER, "Received exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ allprojects {
|
||||||
ext {
|
ext {
|
||||||
shortVersion = '4.3.0-alpha1'
|
shortVersion = '4.3.0-alpha1'
|
||||||
isSnapshot = true
|
isSnapshot = true
|
||||||
jxmppVersion = '0.5.0'
|
jxmppVersion = '0.6.0'
|
||||||
smackMinAndroidSdk = 8
|
smackMinAndroidSdk = 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue