mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-02-17 06:16:25 +01:00
Compare commits
21 commits
525f27abf1
...
5782fff2a4
Author | SHA1 | Date | |
---|---|---|---|
|
5782fff2a4 | ||
|
6d39a4e3ac | ||
|
15e3d267f6 | ||
|
048226960b | ||
|
fe7d3bec30 | ||
|
c1b32f8e11 | ||
|
b857f33ac3 | ||
|
02341f6330 | ||
|
6837c305e8 | ||
|
4db7d787f7 | ||
|
08fc0ba0b4 | ||
|
525ee09ea1 | ||
|
488d01796a | ||
|
b7824f008d | ||
|
9e4153435a | ||
|
8c33f56047 | ||
|
0a6c21982b | ||
|
9002be8e7a | ||
|
6533cb7ed1 | ||
|
9e9d30074c | ||
4cc0f1d129 |
85 changed files with 962 additions and 582 deletions
|
@ -62,7 +62,7 @@ allprojects {
|
|||
':smack-bosh',
|
||||
':smack-debug',
|
||||
':smack-debug-slf4j',
|
||||
':smack-java7',
|
||||
':smack-java8',
|
||||
':smack-jingle-old',
|
||||
':smack-resolver-dnsjava',
|
||||
':smack-resolver-javax',
|
||||
|
|
50
documentation/developer/building.md
Normal file
50
documentation/developer/building.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
Building Smack
|
||||
==============
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
Building Smack is as simple as
|
||||
|
||||
```
|
||||
git clone git@github.com:igniterealtime/Smack.git
|
||||
cd Smack
|
||||
gradle assemble
|
||||
```
|
||||
|
||||
Mac
|
||||
---
|
||||
|
||||
Smack requires a case-sensitive file system in order to build. Unfortunately, the macOS operating system is case-insensitive by default.
|
||||
To get around this, you can create a case-sensitive disk image to work from.
|
||||
|
||||
1. Launch Disk Utility (Applications > Utilities)
|
||||
2. Click the +, or go to Edit > Add APFS Volume
|
||||
3. Give it a name, e.g. "Smack"
|
||||
4. Change the format to "APFS (Case-sensitive)"
|
||||
5. Click Add
|
||||
|
||||
It'll auto-mount into /Volumes, e.g. /Volumes/Smack
|
||||
|
||||
```bash
|
||||
cd /Volumes/Smack
|
||||
git clone git@github.com:igniterealtime/Smack.git
|
||||
cd Smack
|
||||
gradle assemble
|
||||
```
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
Smack requires a case-sensitive file system in order to build. Unfortunately, Windows NTFS is case-insensitive by default.
|
||||
To get around this, you can set specific folders as case-sensitive (requires Windows 10 v1803 or higher).
|
||||
|
||||
In an Administrator console:
|
||||
|
||||
```batch
|
||||
fsutil.exe file SetCaseSensitiveInfo C:\git\Smack enable
|
||||
cd \git\Smack
|
||||
git clone git@github.com:igniterealtime/Smack.git
|
||||
cd Smack
|
||||
gradle assemble
|
||||
```
|
|
@ -22,7 +22,7 @@ include 'smack-core',
|
|||
'smack-bosh',
|
||||
'smack-android',
|
||||
'smack-android-extensions',
|
||||
'smack-java7',
|
||||
'smack-java8',
|
||||
'smack-java8-full',
|
||||
'smack-integration-test',
|
||||
'smack-omemo',
|
||||
|
@ -31,6 +31,7 @@ include 'smack-core',
|
|||
'smack-repl',
|
||||
'smack-openpgp',
|
||||
'smack-websocket',
|
||||
'smack-websocket-okhttp',
|
||||
'smack-xmlparser',
|
||||
'smack-xmlparser-stax',
|
||||
'smack-xmlparser-xpp3'
|
||||
|
|
|
@ -590,7 +590,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
|
|||
public XmlStringBuilder toXML(XmlEnvironment enclosingXmlEnvironment) {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingXmlEnvironment);
|
||||
xml.rightAngleBracket();
|
||||
xml.escape(message);
|
||||
xml.text(message);
|
||||
xml.closeElement(getElementName());
|
||||
return xml;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2019 Florian Schmaus.
|
||||
* Copyright 2015-2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -142,7 +142,9 @@ public final class StandardExtensionElement implements ExtensionElement {
|
|||
}
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.optEscape(text);
|
||||
if (text != null) {
|
||||
xml.text(text);
|
||||
}
|
||||
|
||||
if (elements != null) {
|
||||
for (Map.Entry<QName, StandardExtensionElement> entry : elements.entrySet()) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -36,7 +36,16 @@ public class AbstractProvider<E extends Element> {
|
|||
Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments();
|
||||
Type elementType = actualTypeArguments[0];
|
||||
|
||||
elementClass = (Class<E>) elementType;
|
||||
|
||||
if (elementType instanceof Class) {
|
||||
elementClass = (Class<E>) elementType;
|
||||
} else if (elementType instanceof ParameterizedType) {
|
||||
ParameterizedType parameteriezedElementType = (ParameterizedType) elementType;
|
||||
elementClass = (Class<E>) parameteriezedElementType.getRawType();
|
||||
} else {
|
||||
throw new AssertionError(
|
||||
"Element type '" + elementType + "' is neither of type Class or ParameterizedType");
|
||||
}
|
||||
}
|
||||
|
||||
public final Class<E> getElementClass() {
|
||||
|
|
|
@ -293,6 +293,30 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put if the queue has not been shutdown yet.
|
||||
*
|
||||
* @param e the element to put into the queue.
|
||||
* @return <code>true</code> if the element has been put into the queue, <code>false</code> if the queue was shutdown.
|
||||
* @throws InterruptedException if the calling thread was interrupted.
|
||||
* @since 4.4
|
||||
*/
|
||||
public boolean putIfNotShutdown(E e) throws InterruptedException {
|
||||
checkNotNull(e);
|
||||
lock.lockInterruptibly();
|
||||
|
||||
try {
|
||||
if (isShutdown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
putInternal(e, true);
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void putAll(Collection<? extends E> elements) throws InterruptedException {
|
||||
checkNotNull(elements);
|
||||
lock.lockInterruptibly();
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.util;
|
||||
|
||||
public final class Pair<F, S> {
|
||||
|
||||
private final F first;
|
||||
private final S second;
|
||||
|
||||
private Pair(F first, S second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public static <F extends Object, S extends Object> Pair<F, S> create(F first, S second) {
|
||||
return new Pair<>(first, second);
|
||||
}
|
||||
|
||||
public static <F extends Object, S extends Object> Pair<F, S> createAndInitHashCode(F first, S second) {
|
||||
Pair<F, S> pair = new Pair<>(first, second);
|
||||
pair.hashCode();
|
||||
return pair;
|
||||
}
|
||||
|
||||
public F getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public S getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
private final HashCode.Cache hashCodeCache = new HashCode.Cache();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCodeCache.getHashCode(c ->
|
||||
c.append(first)
|
||||
.append(second)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return EqualsUtil.equals(this, object, (e, o) ->
|
||||
e.append(first, o.first)
|
||||
.append(second, o.second)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -456,6 +456,13 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder text(CharSequence text) {
|
||||
assert text != null;
|
||||
CharSequence escapedText = StringUtils.escapeForXmlText(text);
|
||||
sb.append(escapedText);
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder escape(String text) {
|
||||
assert text != null;
|
||||
sb.append(StringUtils.escapeForXml(text));
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<className>org.jivesoftware.smack.android.AndroidSmackInitializer</className>
|
||||
<className>org.jivesoftware.smack.java7.Java7SmackInitializer</className>
|
||||
<className>org.jivesoftware.smack.im.SmackImInitializer</className>
|
||||
<className>org.jivesoftware.smack.websocket.WebsocketInitializer</className>
|
||||
<className>org.jivesoftware.smack.websocket.WebSocketInitializer</className>
|
||||
<className>org.jivesoftware.smackx.omemo.OmemoInitializer</className>
|
||||
<className>org.jivesoftware.smackx.ox.util.OpenPgpInitializer</className>
|
||||
</optionalStartupClasses>
|
||||
|
|
|
@ -206,4 +206,17 @@ public class MessageTest {
|
|||
|
||||
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that only required characters are XML escaped in body.
|
||||
*
|
||||
* @see <a href="https://issues.igniterealtime.org/browse/SMACK-892">SMACK-892</a>
|
||||
*/
|
||||
@Test
|
||||
public void escapeInBodyTest() {
|
||||
String theFive = "\"'<>&";
|
||||
Message.Body body = new Message.Body(null, theFive);
|
||||
|
||||
assertEquals("<body xmlns='jabber:client'>\"'<>&</body>", body.toXML().toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,8 +132,8 @@ public final class CarbonManager extends Manager {
|
|||
final Message wrappingMessage = (Message) stanza;
|
||||
final CarbonExtension carbonExtension = CarbonExtension.from(wrappingMessage);
|
||||
final Direction direction = carbonExtension.getDirection();
|
||||
final Forwarded forwarded = carbonExtension.getForwarded();
|
||||
final Message carbonCopy = (Message) forwarded.getForwardedStanza();
|
||||
final Forwarded<Message> forwarded = carbonExtension.getForwarded();
|
||||
final Message carbonCopy = forwarded.getForwardedStanza();
|
||||
final BareJid from = carbonCopy.getFrom().asBareJid();
|
||||
|
||||
carbonsListenerAsyncButOrdered.performAsyncButOrdered(from, new Runnable() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013-2014 Georg Lukas
|
||||
* Copyright 2013-2014 Georg Lukas, 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -38,7 +38,7 @@ public class CarbonExtension implements ExtensionElement {
|
|||
public static final String NAMESPACE = Carbon.NAMESPACE;
|
||||
|
||||
private final Direction dir;
|
||||
private final Forwarded fwd;
|
||||
private final Forwarded<Message> fwd;
|
||||
|
||||
/**
|
||||
* Construct a Carbon message extension.
|
||||
|
@ -46,7 +46,7 @@ public class CarbonExtension implements ExtensionElement {
|
|||
* @param dir Determines if the carbon is being sent/received
|
||||
* @param fwd The forwarded message.
|
||||
*/
|
||||
public CarbonExtension(Direction dir, Forwarded fwd) {
|
||||
public CarbonExtension(Direction dir, Forwarded<Message> fwd) {
|
||||
this.dir = dir;
|
||||
this.fwd = fwd;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class CarbonExtension implements ExtensionElement {
|
|||
*
|
||||
* @return the {@link Forwarded} message contained in this Carbon.
|
||||
*/
|
||||
public Forwarded getForwarded() {
|
||||
public Forwarded<Message> getForwarded() {
|
||||
return fwd;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013-2014 Georg Lukas
|
||||
* Copyright 2013-2014 Georg Lukas, 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.carbons.provider;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
|
@ -38,25 +39,22 @@ import org.jivesoftware.smackx.forward.provider.ForwardedProvider;
|
|||
*/
|
||||
public class CarbonManagerProvider extends ExtensionElementProvider<CarbonExtension> {
|
||||
|
||||
private static final ForwardedProvider FORWARDED_PROVIDER = new ForwardedProvider();
|
||||
|
||||
@Override
|
||||
public CarbonExtension parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||
Direction dir = Direction.valueOf(parser.getName());
|
||||
Forwarded fwd = null;
|
||||
Forwarded<Message> fwd = null;
|
||||
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
XmlPullParser.Event eventType = parser.next();
|
||||
if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("forwarded")) {
|
||||
fwd = FORWARDED_PROVIDER.parse(parser);
|
||||
fwd = ForwardedProvider.parseForwardedMessage(parser, xmlEnvironment);
|
||||
}
|
||||
else if (eventType == XmlPullParser.Event.END_ELEMENT && dir == Direction.valueOf(parser.getName()))
|
||||
done = true;
|
||||
}
|
||||
if (fwd == null) {
|
||||
// TODO: Should be SmackParseException.
|
||||
throw new IOException("sent/received must contain exactly one <forwarded> tag");
|
||||
throw new SmackParsingException("sent/received must contain exactly one <forwarded/> element");
|
||||
}
|
||||
return new CarbonExtension(dir, fwd);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
* Copyright © 2014-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -35,7 +35,7 @@ public abstract class AbstractJsonPacketExtension implements ExtensionElement {
|
|||
public final XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.rightAngleBracket();
|
||||
xml.append(json);
|
||||
xml.text(json);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
|
|
@ -632,7 +632,7 @@ public final class MamManager extends Manager {
|
|||
private final MamFinIQ mamFin;
|
||||
private final List<Message> mamResultCarrierMessages;
|
||||
private final List<MamResultExtension> mamResultExtensions;
|
||||
private final List<Forwarded> forwardedMessages;
|
||||
private final List<Forwarded<Message>> forwardedMessages;
|
||||
private final List<Message> messages;
|
||||
|
||||
private MamQueryPage(StanzaCollector stanzaCollector, MamFinIQ mamFin) {
|
||||
|
@ -642,7 +642,7 @@ public final class MamManager extends Manager {
|
|||
|
||||
List<Message> mamResultCarrierMessages = new ArrayList<>(mamResultCarrierStanzas.size());
|
||||
List<MamResultExtension> mamResultExtensions = new ArrayList<>(mamResultCarrierStanzas.size());
|
||||
List<Forwarded> forwardedMessages = new ArrayList<>(mamResultCarrierStanzas.size());
|
||||
List<Forwarded<Message>> forwardedMessages = new ArrayList<>(mamResultCarrierStanzas.size());
|
||||
|
||||
for (Stanza mamResultStanza : mamResultCarrierStanzas) {
|
||||
Message resultMessage = (Message) mamResultStanza;
|
||||
|
@ -665,7 +665,7 @@ public final class MamManager extends Manager {
|
|||
return messages;
|
||||
}
|
||||
|
||||
public List<Forwarded> getForwarded() {
|
||||
public List<Forwarded<Message>> getForwarded() {
|
||||
return forwardedMessages;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import javax.xml.namespace.QName;
|
|||
|
||||
import org.jivesoftware.smack.packet.Element;
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.MessageView;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
@ -69,7 +70,7 @@ public class MamElements {
|
|||
/**
|
||||
* the forwarded element.
|
||||
*/
|
||||
private final Forwarded forwarded;
|
||||
private final Forwarded<Message> forwarded;
|
||||
|
||||
/**
|
||||
* the query id.
|
||||
|
@ -83,7 +84,7 @@ public class MamElements {
|
|||
* @param id TODO javadoc me please
|
||||
* @param forwarded TODO javadoc me please
|
||||
*/
|
||||
public MamResultExtension(String queryId, String id, Forwarded forwarded) {
|
||||
public MamResultExtension(String queryId, String id, Forwarded<Message> forwarded) {
|
||||
if (StringUtils.isEmpty(id)) {
|
||||
throw new IllegalArgumentException("id must not be null or empty");
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ public class MamElements {
|
|||
*
|
||||
* @return the forwarded element
|
||||
*/
|
||||
public Forwarded getForwarded() {
|
||||
public Forwarded<Message> getForwarded() {
|
||||
return forwarded;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
* Copyright 2016 Fernando Ramirez, 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.mam.provider;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
|
@ -40,7 +41,7 @@ public class MamResultProvider extends ExtensionElementProvider<MamResultExtensi
|
|||
|
||||
@Override
|
||||
public MamResultExtension parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||
Forwarded forwarded = null;
|
||||
Forwarded<Message> forwarded = null;
|
||||
String queryId = parser.getAttributeValue("", "queryid");
|
||||
String id = parser.getAttributeValue("", "id");
|
||||
|
||||
|
@ -51,7 +52,7 @@ public class MamResultProvider extends ExtensionElementProvider<MamResultExtensi
|
|||
case START_ELEMENT:
|
||||
switch (name) {
|
||||
case Forwarded.ELEMENT:
|
||||
forwarded = ForwardedProvider.INSTANCE.parse(parser);
|
||||
forwarded = ForwardedProvider.parseForwardedMessage(parser, xmlEnvironment);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -19,9 +19,10 @@ package org.jivesoftware.smackx.carbons;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.test.util.SmackTestUtil;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
|
@ -48,7 +49,7 @@ public class CarbonTest extends ExperimentalInitializerTest {
|
|||
XmlPullParser parser;
|
||||
String control;
|
||||
CarbonExtension cc;
|
||||
Forwarded fwd;
|
||||
Forwarded<Message> fwd;
|
||||
|
||||
control = XMLBuilder.create("sent")
|
||||
.e("forwarded")
|
||||
|
@ -107,6 +108,6 @@ public class CarbonTest extends ExperimentalInitializerTest {
|
|||
.a("xmlns", "urn:xmpp:forwarded:0")
|
||||
.asString(outputProperties);
|
||||
|
||||
assertThrows(IOException.class, () -> SmackTestUtil.parse(control, CarbonManagerProvider.class, parserKind));
|
||||
assertThrows(SmackParsingException.class, () -> SmackTestUtil.parse(control, CarbonManagerProvider.class, parserKind));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.jxmpp.jid.impl.JidCreate;
|
|||
public class MarkableExtensionTest {
|
||||
|
||||
String markableMessageStanza = "<message xmlns='jabber:client' to='ingrichard@royalty.england.lit/throne' id='message-1'>"
|
||||
+ "<body>My lord, dispatch; read o'er these articles.</body>"
|
||||
+ "<body>My lord, dispatch; read o'er these articles.</body>"
|
||||
+ "<markable xmlns='urn:xmpp:chat-markers:0'/>" + "</message>";
|
||||
|
||||
String markableExtension = "<markable xmlns='urn:xmpp:chat-markers:0'/>";
|
||||
|
|
|
@ -59,10 +59,10 @@ public class MamResultProviderTest {
|
|||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
Date date = calendar.getTime();
|
||||
|
||||
Forwarded forwarded = mamResultExtension.getForwarded();
|
||||
Forwarded<Message> forwarded = mamResultExtension.getForwarded();
|
||||
assertEquals(forwarded.getDelayInformation().getStamp(), date);
|
||||
|
||||
Message message = (Message) forwarded.getForwardedStanza();
|
||||
Message message = forwarded.getForwardedStanza();
|
||||
assertEquals(message.getFrom().toString(), "romeo@montague.lit/orchard");
|
||||
assertEquals(message.getTo().toString(), "juliet@capulet.lit/balcony");
|
||||
assertEquals(message.getBody(),
|
||||
|
@ -81,10 +81,10 @@ public class MamResultProviderTest {
|
|||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
Date date = calendar.getTime();
|
||||
|
||||
Forwarded forwarded = mamResultExtension.getForwarded();
|
||||
Forwarded<Message> forwarded = mamResultExtension.getForwarded();
|
||||
assertEquals(forwarded.getDelayInformation().getStamp(), date);
|
||||
|
||||
Message forwardedMessage = (Message) forwarded.getForwardedStanza();
|
||||
Message forwardedMessage = forwarded.getForwardedStanza();
|
||||
assertEquals(forwardedMessage.getFrom().toString(), "witch@shakespeare.lit");
|
||||
assertEquals(forwardedMessage.getTo().toString(), "macbeth@shakespeare.lit");
|
||||
assertEquals(forwardedMessage.getBody(), "Hail to thee");
|
||||
|
|
|
@ -79,7 +79,7 @@ public class QueryArchiveTest extends MamTest {
|
|||
.setBody("Thrice the brinded cat hath mew.")
|
||||
.build();
|
||||
|
||||
Forwarded forwarded = new Forwarded(delay, forwardedMessage);
|
||||
Forwarded<Message> forwarded = new Forwarded<>(forwardedMessage, delay);
|
||||
|
||||
message.addExtension(new MamResultExtension("g27", "34482-21985-73620", forwarded));
|
||||
|
||||
|
@ -90,7 +90,7 @@ public class QueryArchiveTest extends MamTest {
|
|||
assertEquals(mamResultExtension.getId(), "34482-21985-73620");
|
||||
assertEquals(mamResultExtension.getForwarded().getDelayInformation().getStamp(), date);
|
||||
|
||||
Message resultMessage = (Message) mamResultExtension.getForwarded().getForwardedStanza();
|
||||
Message resultMessage = mamResultExtension.getForwarded().getForwardedStanza();
|
||||
assertEquals(resultMessage.getFrom(), JidCreate.from("coven@chat.shakespeare.lit/firstwitch"));
|
||||
assertEquals(resultMessage.getStanzaId(), "162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2");
|
||||
assertEquals(resultMessage.getType(), Type.chat);
|
||||
|
|
|
@ -29,14 +29,19 @@ import org.jivesoftware.smack.util.stringencoder.Base64;
|
|||
*/
|
||||
public class BoBData {
|
||||
|
||||
private final int maxAge;
|
||||
private final Integer maxAge;
|
||||
private final String type;
|
||||
|
||||
private byte[] contentBinary;
|
||||
private String contentString;
|
||||
|
||||
private BoBData(String type, Integer maxAge) {
|
||||
this.type = type;
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
public BoBData(String type, byte[] content) {
|
||||
this(type, content, -1);
|
||||
this(type, content, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,20 +51,18 @@ public class BoBData {
|
|||
* @param content TODO javadoc me please
|
||||
* @param maxAge TODO javadoc me please
|
||||
*/
|
||||
public BoBData(String type, byte[] content, int maxAge) {
|
||||
this.type = type;
|
||||
public BoBData(String type, byte[] content, Integer maxAge) {
|
||||
this(type, maxAge);
|
||||
this.contentBinary = content;
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
public BoBData(String type, String content) {
|
||||
this(type, content, -1);
|
||||
this(type, content, null);
|
||||
}
|
||||
|
||||
public BoBData(String type, String content, int maxAge) {
|
||||
this.type = type;
|
||||
public BoBData(String type, String content, Integer maxAge) {
|
||||
this(type, maxAge);
|
||||
this.contentString = content;
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,7 +70,7 @@ public class BoBData {
|
|||
*
|
||||
* @return the max age
|
||||
*/
|
||||
public int getMaxAge() {
|
||||
public Integer getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ import java.util.Set;
|
|||
|
||||
public class BoBInfo {
|
||||
|
||||
private final Set<BoBHash> hashes;
|
||||
private final Set<ContentId> hashes;
|
||||
private final BoBData data;
|
||||
|
||||
BoBInfo(Set<BoBHash> hashes, BoBData data) {
|
||||
BoBInfo(Set<ContentId> hashes, BoBData data) {
|
||||
this.hashes = hashes;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Set<BoBHash> getHashes() {
|
||||
public Set<ContentId> getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016-2017 Fernando Ramirez, Florian Schmaus
|
||||
* Copyright 2016-2020 Fernando Ramirez, Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -81,9 +81,9 @@ public final class BoBManager extends Manager {
|
|||
return bobManager;
|
||||
}
|
||||
|
||||
private static final LruCache<BoBHash, BoBData> BOB_CACHE = new LruCache<>(128);
|
||||
private static final LruCache<ContentId, BoBData> BOB_CACHE = new LruCache<>(128);
|
||||
|
||||
private final Map<BoBHash, BoBInfo> bobs = new ConcurrentHashMap<>();
|
||||
private final Map<ContentId, BoBInfo> bobs = new ConcurrentHashMap<>();
|
||||
|
||||
private BoBManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
@ -95,15 +95,16 @@ public final class BoBManager extends Manager {
|
|||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
BoBIQ bobIQRequest = (BoBIQ) iqRequest;
|
||||
ContentId contentId = bobIQRequest.getContentId();
|
||||
|
||||
BoBInfo bobInfo = bobs.get(bobIQRequest.getBoBHash());
|
||||
BoBInfo bobInfo = bobs.get(contentId);
|
||||
if (bobInfo == null) {
|
||||
// TODO return item-not-found
|
||||
return null;
|
||||
}
|
||||
|
||||
BoBData bobData = bobInfo.getData();
|
||||
BoBIQ responseBoBIQ = new BoBIQ(bobIQRequest.getBoBHash(), bobData);
|
||||
BoBIQ responseBoBIQ = new BoBIQ(contentId, bobData);
|
||||
responseBoBIQ.setType(Type.result);
|
||||
responseBoBIQ.setTo(bobIQRequest.getFrom());
|
||||
return responseBoBIQ;
|
||||
|
@ -137,7 +138,7 @@ public final class BoBManager extends Manager {
|
|||
* @throws NotConnectedException if the XMPP connection is not connected.
|
||||
* @throws InterruptedException if the calling thread was interrupted.
|
||||
*/
|
||||
public BoBData requestBoB(Jid to, BoBHash bobHash) throws NotLoggedInException, NoResponseException,
|
||||
public BoBData requestBoB(Jid to, ContentId bobHash) throws NotLoggedInException, NoResponseException,
|
||||
XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
BoBData bobData = BOB_CACHE.lookup(bobHash);
|
||||
if (bobData != null) {
|
||||
|
@ -159,9 +160,9 @@ public final class BoBManager extends Manager {
|
|||
|
||||
public BoBInfo addBoB(BoBData bobData) {
|
||||
// We only support SHA-1 for now.
|
||||
BoBHash bobHash = new BoBHash(SHA1.hex(bobData.getContent()), "sha1");
|
||||
ContentId bobHash = new ContentId(SHA1.hex(bobData.getContent()), "sha1");
|
||||
|
||||
Set<BoBHash> bobHashes = Collections.singleton(bobHash);
|
||||
Set<ContentId> bobHashes = Collections.singleton(bobHash);
|
||||
bobHashes = Collections.unmodifiableSet(bobHashes);
|
||||
|
||||
BoBInfo bobInfo = new BoBInfo(bobHashes, bobData);
|
||||
|
@ -171,12 +172,12 @@ public final class BoBManager extends Manager {
|
|||
return bobInfo;
|
||||
}
|
||||
|
||||
public BoBInfo removeBoB(BoBHash bobHash) {
|
||||
public BoBInfo removeBoB(ContentId bobHash) {
|
||||
BoBInfo bobInfo = bobs.remove(bobHash);
|
||||
if (bobInfo == null) {
|
||||
return null;
|
||||
}
|
||||
for (BoBHash otherBobHash : bobInfo.getHashes()) {
|
||||
for (ContentId otherBobHash : bobInfo.getHashes()) {
|
||||
bobs.remove(otherBobHash);
|
||||
}
|
||||
return bobInfo;
|
||||
|
|
|
@ -19,29 +19,32 @@ package org.jivesoftware.smackx.bob;
|
|||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Bits of Binary hash class.
|
||||
* Content-ID class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @author Florian Schmaus
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2392">RFC 2392: Content-ID and Message-ID Uniform Resource Locators</a>
|
||||
*/
|
||||
public class BoBHash {
|
||||
public class ContentId {
|
||||
|
||||
private final String hash;
|
||||
private final String hashType;
|
||||
private final String cid;
|
||||
|
||||
private ContentId(String hash, String hashType, String cid) {
|
||||
this.hash = StringUtils.requireNotNullNorEmpty(hash, "hash must not be null nor empty");
|
||||
this.hashType = StringUtils.requireNotNullNorEmpty(hashType, "hashType must not be null nor empty");
|
||||
this.cid = cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* BoB hash constructor.
|
||||
*
|
||||
* @param hash TODO javadoc me please
|
||||
* @param hashType TODO javadoc me please
|
||||
*/
|
||||
public BoBHash(String hash, String hashType) {
|
||||
this.hash = StringUtils.requireNotNullNorEmpty(hash, "hash must not be null nor empty");
|
||||
this.hashType = StringUtils.requireNotNullNorEmpty(hashType, "hashType must not be null nor empty");
|
||||
this.cid = this.hashType + '+' + this.hash + "@bob.xmpp.org";
|
||||
public ContentId(String hash, String hashType) {
|
||||
this(hash, hashType, hashType + '+' + hash + "@bob.xmpp.org");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,8 +85,8 @@ public class BoBHash {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof BoBHash) {
|
||||
BoBHash otherBob = (BoBHash) other;
|
||||
if (other instanceof ContentId) {
|
||||
ContentId otherBob = (ContentId) other;
|
||||
return cid.equals(otherBob.cid);
|
||||
}
|
||||
return false;
|
||||
|
@ -100,10 +103,10 @@ public class BoBHash {
|
|||
* @param src TODO javadoc me please
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public static BoBHash fromSrc(String src) {
|
||||
public static ContentId fromSrc(String src) {
|
||||
String hashType = src.substring(src.lastIndexOf("cid:") + 4, src.indexOf("+"));
|
||||
String hash = src.substring(src.indexOf("+") + 1, src.indexOf("@bob.xmpp.org"));
|
||||
return new BoBHash(hash, hashType);
|
||||
return new ContentId(hash, hashType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,10 +115,10 @@ public class BoBHash {
|
|||
* @param cid TODO javadoc me please
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public static BoBHash fromCid(String cid) {
|
||||
public static ContentId fromCid(String cid) {
|
||||
String hashType = cid.substring(0, cid.indexOf("+"));
|
||||
String hash = cid.substring(cid.indexOf("+") + 1, cid.indexOf("@bob.xmpp.org"));
|
||||
return new BoBHash(hash, hashType);
|
||||
return new ContentId(hash, hashType, cid);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.BoBManager;
|
||||
import org.jivesoftware.smackx.bob.ContentId;
|
||||
|
||||
/**
|
||||
* Bits of Binary data extension element.
|
||||
*
|
||||
* @author Florian Schmaus
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBDataExtension implements ExtensionElement {
|
||||
|
||||
public static final String ELEMENT = "data";
|
||||
public static final String NAMESPACE = BoBManager.NAMESPACE;
|
||||
|
||||
private final ContentId cid;
|
||||
private final BoBData bobData;
|
||||
|
||||
/**
|
||||
* Bits of Binary data extension constructor.
|
||||
*
|
||||
* @param cid TODO javadoc me please
|
||||
* @param bobData TODO javadoc me please
|
||||
*/
|
||||
public BoBDataExtension(ContentId cid, BoBData bobData) {
|
||||
this.cid = Objects.requireNonNull(cid);
|
||||
this.bobData = Objects.requireNonNull(bobData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("cid", cid.getCid());
|
||||
xml.attribute("type", bobData.getType());
|
||||
xml.optAttribute("max-age", bobData.getMaxAge());
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.append(bobData.getContentBase64Encoded());
|
||||
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
public static BoBDataExtension from(Message message) {
|
||||
return message.getExtension(BoBDataExtension.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.xhtmlim.XHTMLText;
|
||||
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
|
||||
|
||||
/**
|
||||
* Bits of Binary extension element.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBExtension extends XHTMLExtension {
|
||||
|
||||
private final BoBHash bobHash;
|
||||
private final String alt;
|
||||
private final String paragraph;
|
||||
|
||||
/**
|
||||
* Bits of Binary extension constructor.
|
||||
*
|
||||
* @param bobHash TODO javadoc me please
|
||||
* @param alt TODO javadoc me please
|
||||
* @param paragraph TODO javadoc me please
|
||||
*/
|
||||
public BoBExtension(BoBHash bobHash, String alt, String paragraph) {
|
||||
this.bobHash = bobHash;
|
||||
this.alt = alt;
|
||||
this.paragraph = paragraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BoB hash.
|
||||
*
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public BoBHash getBoBHash() {
|
||||
return bobHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alt field.
|
||||
*
|
||||
* @return the alt field
|
||||
*/
|
||||
public String getAlt() {
|
||||
return alt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.halfOpenElement(Message.BODY);
|
||||
xml.xmlnsAttribute(XHTMLText.NAMESPACE);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.openElement(XHTMLText.P);
|
||||
xml.optEscape(paragraph);
|
||||
|
||||
xml.halfOpenElement(XHTMLText.IMG);
|
||||
xml.optAttribute("alt", alt);
|
||||
xml.attribute("src", bobHash.toSrc());
|
||||
xml.closeEmptyElement();
|
||||
|
||||
xml.closeElement(XHTMLText.P);
|
||||
xml.closeElement(Message.BODY);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
public static BoBExtension from(Message message) {
|
||||
return (BoBExtension) message.getExtensionElement(ELEMENT, NAMESPACE);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
* Copyright 2016 Fernando Ramirez, 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,8 +19,8 @@ package org.jivesoftware.smackx.bob.element;
|
|||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.bob.BoBManager;
|
||||
import org.jivesoftware.smackx.bob.ContentId;
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ class.
|
||||
|
@ -41,28 +41,40 @@ public class BoBIQ extends IQ {
|
|||
*/
|
||||
public static final String NAMESPACE = BoBManager.NAMESPACE;
|
||||
|
||||
private final BoBHash bobHash;
|
||||
private final ContentId cid;
|
||||
private final BoBData bobData;
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ constructor.
|
||||
*
|
||||
* @param bobHash TODO javadoc me please
|
||||
* @param cid TODO javadoc me please
|
||||
* @param bobData TODO javadoc me please
|
||||
*/
|
||||
public BoBIQ(BoBHash bobHash, BoBData bobData) {
|
||||
public BoBIQ(ContentId cid, BoBData bobData) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.bobHash = bobHash;
|
||||
this.cid = cid;
|
||||
this.bobData = bobData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ constructor.
|
||||
*
|
||||
* @param bobHash TODO javadoc me please
|
||||
* @param cid TODO javadoc me please
|
||||
*/
|
||||
public BoBIQ(BoBHash bobHash) {
|
||||
this(bobHash, null);
|
||||
public BoBIQ(ContentId cid) {
|
||||
this(cid, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BoB hash.
|
||||
*
|
||||
* @return the BoB hash
|
||||
* @deprecated use {@link #getContentId()} instead.
|
||||
*/
|
||||
// TODO: Remove in Smack 4.5.
|
||||
@Deprecated
|
||||
public ContentId getBoBHash() {
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,8 +82,8 @@ public class BoBIQ extends IQ {
|
|||
*
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public BoBHash getBoBHash() {
|
||||
return bobHash;
|
||||
public ContentId getContentId() {
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +97,7 @@ public class BoBIQ extends IQ {
|
|||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("cid", bobHash.getCid());
|
||||
xml.attribute("cid", cid.getCid());
|
||||
|
||||
if (bobData != null) {
|
||||
xml.optIntAttribute("max_age", bobData.getMaxAge());
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smack.util.Pair;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.ContentId;
|
||||
import org.jivesoftware.smackx.bob.element.BoBDataExtension;
|
||||
|
||||
public class BoBDataExtensionProvider extends ExtensionElementProvider<BoBDataExtension> {
|
||||
|
||||
@Override
|
||||
public BoBDataExtension parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
|
||||
throws XmlPullParserException, IOException {
|
||||
Pair<ContentId, BoBData> parserResult = BoBProviderUtil.parseContentIdAndBobData(parser, initialDepth,
|
||||
xmlEnvironment);
|
||||
|
||||
return new BoBDataExtension(parserResult.getFirst(), parserResult.getSecond());
|
||||
}
|
||||
|
||||
}
|
|
@ -20,12 +20,12 @@ import java.io.IOException;
|
|||
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smack.util.Pair;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.bob.ContentId;
|
||||
import org.jivesoftware.smackx.bob.element.BoBIQ;
|
||||
|
||||
/**
|
||||
|
@ -39,22 +39,10 @@ public class BoBIQProvider extends IQProvider<BoBIQ> {
|
|||
|
||||
@Override
|
||||
public BoBIQ parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException {
|
||||
String cid = parser.getAttributeValue("", "cid");
|
||||
BoBHash bobHash = BoBHash.fromCid(cid);
|
||||
Pair<ContentId, BoBData> parserResult = BoBProviderUtil.parseContentIdAndBobData(parser, initialDepth,
|
||||
xmlEnvironment);
|
||||
|
||||
String dataType = parser.getAttributeValue("", "type");
|
||||
int maxAge = ParserUtils.getIntegerAttribute(parser, "max-age", -1);
|
||||
|
||||
String base64EncodedData = parser.nextText();
|
||||
|
||||
BoBData bobData;
|
||||
if (dataType != null) {
|
||||
bobData = new BoBData(dataType, base64EncodedData, maxAge);
|
||||
} else {
|
||||
bobData = null;
|
||||
}
|
||||
|
||||
return new BoBIQ(bobHash, bobData);
|
||||
return new BoBIQ(parserResult.getFirst(), parserResult.getSecond());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.util.Pair;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.ContentId;
|
||||
|
||||
public class BoBProviderUtil {
|
||||
|
||||
public static Pair<ContentId, BoBData> parseContentIdAndBobData(XmlPullParser parser, int initialDepth,
|
||||
XmlEnvironment xmlEnvironment) throws IOException, XmlPullParserException {
|
||||
String cid = parser.getAttributeValue("", "cid");
|
||||
ContentId contentId = ContentId.fromCid(cid);
|
||||
|
||||
String dataType = parser.getAttributeValue("", "type");
|
||||
Integer maxAge = ParserUtils.getIntegerAttribute(parser, "max-age");
|
||||
|
||||
String base64EncodedData = parser.nextText();
|
||||
|
||||
BoBData bobData = null;
|
||||
if (dataType != null) {
|
||||
bobData = new BoBData(dataType, base64EncodedData, maxAge);
|
||||
}
|
||||
|
||||
return Pair.create(contentId, bobData);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013-2014 Georg Lukas
|
||||
* Copyright 2013-2014 Georg Lukas, 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,6 +25,7 @@ import javax.xml.namespace.QName;
|
|||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
import org.jivesoftware.smackx.delay.packet.DelayInformation;
|
||||
|
@ -35,23 +36,24 @@ import org.jivesoftware.smackx.delay.packet.DelayInformation;
|
|||
* @author Georg Lukas
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0297.html">XEP-0297: Stanza Forwarding</a>
|
||||
*/
|
||||
public class Forwarded implements ExtensionElement {
|
||||
public class Forwarded<S extends Stanza> implements ExtensionElement {
|
||||
public static final String NAMESPACE = "urn:xmpp:forward:0";
|
||||
public static final String ELEMENT = "forwarded";
|
||||
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||
|
||||
private final DelayInformation delay;
|
||||
private final Stanza forwardedPacket;
|
||||
private final S forwardedStanza;
|
||||
|
||||
/**
|
||||
* Creates a new Forwarded stanza extension.
|
||||
*
|
||||
* @param delay an optional {@link DelayInformation} timestamp of the packet.
|
||||
* @param fwdPacket the stanza that is forwarded (required).
|
||||
* @param forwardedStanza the stanza that is forwarded (required).
|
||||
* @deprecated use {@link #Forwarded(Stanza, DelayInformation)} instead.
|
||||
*/
|
||||
public Forwarded(DelayInformation delay, Stanza fwdPacket) {
|
||||
this.delay = delay;
|
||||
this.forwardedPacket = fwdPacket;
|
||||
@Deprecated
|
||||
public Forwarded(DelayInformation delay, S forwardedStanza) {
|
||||
this(forwardedStanza, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,8 +61,19 @@ public class Forwarded implements ExtensionElement {
|
|||
*
|
||||
* @param fwdPacket the stanza that is forwarded (required).
|
||||
*/
|
||||
public Forwarded(Stanza fwdPacket) {
|
||||
this(null, fwdPacket);
|
||||
public Forwarded(S fwdPacket) {
|
||||
this(fwdPacket, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Forwarded stanza extension.
|
||||
*
|
||||
* @param forwardedStanza the stanza that is forwarded (required).
|
||||
* @param delay an optional {@link DelayInformation} timestamp of the packet.
|
||||
*/
|
||||
public Forwarded(S forwardedStanza, DelayInformation delay) {
|
||||
this.forwardedStanza = Objects.requireNonNull(forwardedStanza);
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,7 +91,7 @@ public class Forwarded implements ExtensionElement {
|
|||
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
||||
xml.rightAngleBracket();
|
||||
xml.optElement(getDelayInformation());
|
||||
xml.append(forwardedPacket);
|
||||
xml.append(forwardedStanza);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
@ -88,8 +101,8 @@ public class Forwarded implements ExtensionElement {
|
|||
*
|
||||
* @return the {@link Stanza} (typically a message) that was forwarded.
|
||||
*/
|
||||
public Stanza getForwardedStanza() {
|
||||
return forwardedPacket;
|
||||
public S getForwardedStanza() {
|
||||
return forwardedStanza;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,12 +114,23 @@ public class Forwarded implements ExtensionElement {
|
|||
return delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is forwarding a stanza of the provided class.
|
||||
*
|
||||
* @param stanzaClass the class to check for.
|
||||
* @return <code>true</code> if this is forwarding a stanza of the provided class.
|
||||
* @since 4.4
|
||||
*/
|
||||
public boolean isForwarded(Class<? extends Stanza> stanzaClass) {
|
||||
return stanzaClass.isAssignableFrom(forwardedStanza.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the forwarded extension.
|
||||
* @param packet TODO javadoc me please
|
||||
* @return the Forwarded extension or null
|
||||
*/
|
||||
public static Forwarded from(Stanza packet) {
|
||||
public static Forwarded<?> from(Stanza packet) {
|
||||
return packet.getExtension(Forwarded.class);
|
||||
}
|
||||
|
||||
|
@ -118,10 +142,10 @@ public class Forwarded implements ExtensionElement {
|
|||
* @return a list a the extracted messages.
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public static List<Message> extractMessagesFrom(Collection<Forwarded> forwardedCollection) {
|
||||
public static List<Message> extractMessagesFrom(Collection<Forwarded<Message>> forwardedCollection) {
|
||||
List<Message> res = new ArrayList<>(forwardedCollection.size());
|
||||
for (Forwarded forwarded : forwardedCollection) {
|
||||
Message message = (Message) forwarded.forwardedPacket;
|
||||
for (Forwarded<Message> forwarded : forwardedCollection) {
|
||||
Message message = forwarded.getForwardedStanza();
|
||||
res.add(message);
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013-2014 Georg Lukas
|
||||
* Copyright 2013-2014 Georg Lukas, 2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -38,14 +38,14 @@ import org.jivesoftware.smackx.forward.packet.Forwarded;
|
|||
*
|
||||
* @author Georg Lukas
|
||||
*/
|
||||
public class ForwardedProvider extends ExtensionElementProvider<Forwarded> {
|
||||
public class ForwardedProvider extends ExtensionElementProvider<Forwarded<?>> {
|
||||
|
||||
public static final ForwardedProvider INSTANCE = new ForwardedProvider();
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ForwardedProvider.class.getName());
|
||||
|
||||
@Override
|
||||
public Forwarded parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||
public Forwarded<?> parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||
DelayInformation di = null;
|
||||
Stanza packet = null;
|
||||
|
||||
|
@ -86,6 +86,21 @@ public class ForwardedProvider extends ExtensionElementProvider<Forwarded> {
|
|||
// TODO: Should be SmackParseException.
|
||||
throw new IOException("forwarded extension must contain a packet");
|
||||
}
|
||||
return new Forwarded(di, packet);
|
||||
return new Forwarded<>(packet, di);
|
||||
}
|
||||
|
||||
public static Forwarded<Message> parseForwardedMessage(XmlPullParser parser, XmlEnvironment xmlEnvironment)
|
||||
throws XmlPullParserException, IOException, SmackParsingException {
|
||||
return parseForwardedMessage(parser, parser.getDepth(), xmlEnvironment);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Forwarded<Message> parseForwardedMessage(XmlPullParser parser, int initialDepth,
|
||||
XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||
Forwarded<?> forwarded = INSTANCE.parse(parser, initialDepth, xmlEnvironment);
|
||||
if (!forwarded.isForwarded(Message.class)) {
|
||||
throw new SmackParsingException("Expecting a forwarded message, but got " + forwarded);
|
||||
}
|
||||
return (Forwarded<Message>) forwarded;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
|
|||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class XHTMLExtension implements ExtensionElement {
|
||||
public final class XHTMLExtension implements ExtensionElement {
|
||||
|
||||
public static final String ELEMENT = "html";
|
||||
public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im";
|
||||
|
|
|
@ -500,6 +500,12 @@
|
|||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0231: Bits of Binary -->
|
||||
<extensionProvider>
|
||||
<elementName>data</elementName>
|
||||
<namespace>urn:xmpp:bob</namespace>
|
||||
<className>org.jivesoftware.smackx.bob.provider.BoBDataExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<iqProvider>
|
||||
<elementName>data</elementName>
|
||||
<namespace>urn:xmpp:bob</namespace>
|
||||
|
|
|
@ -41,7 +41,7 @@ public class BoBIQTest extends SmackTestSuite {
|
|||
|
||||
@Test
|
||||
public void checkBoBIQRequest() throws Exception {
|
||||
BoBHash bobHash = new BoBHash("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
ContentId bobHash = new ContentId("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
|
||||
BoBIQ createdBoBIQ = new BoBIQ(bobHash);
|
||||
createdBoBIQ.setStanzaId("sarasa");
|
||||
|
@ -55,7 +55,7 @@ public class BoBIQTest extends SmackTestSuite {
|
|||
public void checkBoBIQResponse() throws Exception {
|
||||
BoBIQ bobIQ = PacketParserUtils.parseStanza(sampleBoBIQResponse);
|
||||
|
||||
BoBHash bobHash = new BoBHash("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
ContentId bobHash = new ContentId("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
BoBData bobData = new BoBData("image/png", "sarasade2354j2".getBytes(StandardCharsets.UTF_8), 86400);
|
||||
|
||||
BoBIQ createdBoBIQ = new BoBIQ(bobHash, bobData);
|
||||
|
@ -63,8 +63,8 @@ public class BoBIQTest extends SmackTestSuite {
|
|||
createdBoBIQ.setTo(JidCreate.from("doctor@shakespeare.lit/pda"));
|
||||
createdBoBIQ.setType(Type.result);
|
||||
|
||||
assertEquals(bobIQ.getBoBHash().getHash(), createdBoBIQ.getBoBHash().getHash());
|
||||
assertEquals(bobIQ.getBoBHash().getHashType(), createdBoBIQ.getBoBHash().getHashType());
|
||||
assertEquals(bobIQ.getContentId().getHash(), createdBoBIQ.getContentId().getHash());
|
||||
assertEquals(bobIQ.getContentId().getHashType(), createdBoBIQ.getContentId().getHashType());
|
||||
assertEquals(bobIQ.getBoBData().getMaxAge(), createdBoBIQ.getBoBData().getMaxAge());
|
||||
assertEquals(bobIQ.getBoBData().getType(), createdBoBIQ.getBoBData().getType());
|
||||
assertEquals(bobIQ.getBoBData().getContentBase64Encoded(), createdBoBIQ.getBoBData().getContentBase64Encoded());
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ForwardedTest {
|
|||
public void forwardedTest() throws Exception {
|
||||
XmlPullParser parser;
|
||||
String control;
|
||||
Forwarded fwd;
|
||||
Forwarded<?> fwd;
|
||||
|
||||
control = XMLBuilder.create("forwarded")
|
||||
.a("xmlns", "urn:xmpp:forwarded:0")
|
||||
|
@ -71,7 +71,7 @@ public class ForwardedTest {
|
|||
public void forwardedWithDelayTest() throws Exception {
|
||||
XmlPullParser parser;
|
||||
String control;
|
||||
Forwarded fwd;
|
||||
Forwarded<?> fwd;
|
||||
|
||||
// @formatter:off
|
||||
control = XMLBuilder.create("forwarded").a("xmlns", "urn:xmpp:forwarded:0")
|
||||
|
|
|
@ -44,7 +44,7 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
|||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.util.MultiMap;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModuleDescriptor;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModuleDescriptor;
|
||||
|
||||
import org.jivesoftware.smackx.admin.ServiceAdministrationManager;
|
||||
import org.jivesoftware.smackx.iqregister.AccountManager;
|
||||
|
@ -92,7 +92,7 @@ public class XmppConnectionManager {
|
|||
.withNickname("modular-websocket")
|
||||
.applyExtraConfguration(cb -> {
|
||||
cb.removeAllModules();
|
||||
cb.addModule(XmppWebsocketTransportModuleDescriptor.class);
|
||||
cb.addModule(XmppWebSocketTransportModuleDescriptor.class);
|
||||
})
|
||||
.build()
|
||||
);
|
||||
|
|
|
@ -6,7 +6,7 @@ dependencies {
|
|||
api project(':smack-debug')
|
||||
api project(':smack-experimental')
|
||||
api project(':smack-extensions')
|
||||
api project(':smack-java7')
|
||||
api project(':smack-java8')
|
||||
api project(':smack-legacy')
|
||||
api project(':smack-omemo')
|
||||
api project(':smack-openpgp')
|
||||
|
|
|
@ -32,7 +32,7 @@ digraph {
|
|||
"ConnectedButUnauthenticated" -> "InstantShutdown" [xlabel="5"];
|
||||
"ConnectedButUnauthenticated" [ style=filled ]
|
||||
"EstablishingTcpConnection" -> "ConnectedButUnauthenticated" [xlabel="2"];
|
||||
"LookupRemoteConnectionEndpoints" -> "EstablishingWebsocketConnection" [xlabel="2"];
|
||||
"EstablishingWebsocketConnection" -> "ConnectedButUnauthenticated";
|
||||
"LookupRemoteConnectionEndpoints" -> "EstablishingWebSocketConnection" [xlabel="2"];
|
||||
"EstablishingWebSocketConnection" -> "ConnectedButUnauthenticated";
|
||||
"Disconnected" [ style=filled ]
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class Java7SmackInitializer implements SmackInitializer {
|
|||
if (SystemUtil.onAndroid()) {
|
||||
// @formatter:off
|
||||
throw new RuntimeException(
|
||||
"You need to remove the smack-java7 dependency/jar from your build, " +
|
||||
"You need to remove the smack-java8 dependency/jar from your build, " +
|
||||
"as it does not run on Android. " +
|
||||
"Use smack-android instead.");
|
||||
// @formatter:on
|
|
@ -8,7 +8,7 @@ dependencies {
|
|||
compile project(':smack-extensions')
|
||||
compile project(':smack-experimental')
|
||||
|
||||
api 'org.pgpainless:pgpainless-core:0.0.1-alpha11'
|
||||
api 'org.pgpainless:pgpainless-core:0.1.0'
|
||||
|
||||
testImplementation "org.bouncycastle:bcprov-jdk15on:${bouncyCastleVersion}"
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.jivesoftware.smack.XMPPException;
|
|||
|
||||
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection;
|
||||
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfiguration;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModuleDescriptor;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModuleDescriptor;
|
||||
|
||||
public class WebsocketConnection {
|
||||
public class WebSocketConnection {
|
||||
|
||||
public static void main(String[] args) throws SmackException, IOException, XMPPException, InterruptedException, URISyntaxException {
|
||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration.builder();
|
||||
|
@ -39,8 +39,8 @@ public class WebsocketConnection {
|
|||
builder.setXmppAddressAndPassword(args[0], args[1]);
|
||||
|
||||
// Set a fallback uri into websocket transport descriptor and add this descriptor into connection builder.
|
||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI(args[2]), false);
|
||||
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI(args[2]), false);
|
||||
builder.addModule(websocketBuilder.build());
|
||||
|
||||
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
|
@ -1592,7 +1592,12 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
|||
}
|
||||
|
||||
private void sendSmAcknowledgementInternal() throws NotConnectedException, InterruptedException {
|
||||
packetWriter.sendStreamElement(new AckAnswer(clientHandledStanzasCount));
|
||||
AckAnswer ackAnswer = new AckAnswer(clientHandledStanzasCount);
|
||||
// Do net put an ack to the queue if it has already been shutdown. Some servers, like ejabberd, like to request
|
||||
// an ack even after we have send a stream close (and hance the queue was shutdown). If we would not check here,
|
||||
// then the ack would dangle around in the queue, and be send on the next re-connection attempt even before the
|
||||
// stream open.
|
||||
packetWriter.queue.putIfNotShutdown(ackAnswer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -500,9 +500,9 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
|
|||
pendingInputFilterData = false;
|
||||
}
|
||||
|
||||
// We have successfully read something. It is now possible that a filter is now also able to write
|
||||
// additional data (for example SSLEngine).
|
||||
if (pendingWriteInterestAfterRead) {
|
||||
// We have successfully read something and someone announced a write interest after a read. It is
|
||||
// now possible that a filter is now also able to write additional data (for example SSLEngine).
|
||||
pendingWriteInterestAfterRead = false;
|
||||
newInterestedOps |= SelectionKey.OP_WRITE;
|
||||
}
|
||||
|
@ -1048,12 +1048,15 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ReferenceEquality")
|
||||
@Override
|
||||
public ByteBuffer input(ByteBuffer inputData) throws SSLException {
|
||||
ByteBuffer accumulatedData;
|
||||
if (pendingInputData == null) {
|
||||
accumulatedData = inputData;
|
||||
} else {
|
||||
assert pendingInputData != inputData;
|
||||
|
||||
int accumulatedDataBytes = pendingInputData.remaining() + inputData.remaining();
|
||||
accumulatedData = ByteBuffer.allocate(accumulatedDataBytes);
|
||||
accumulatedData.put(pendingInputData)
|
||||
|
@ -1084,18 +1087,25 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
|
|||
SSLEngineResult.HandshakeStatus handshakeStatus = handleHandshakeStatus(result);
|
||||
switch (handshakeStatus) {
|
||||
case NEED_TASK:
|
||||
// A delegated task is asynchronously running. Signal that there is pending input data and
|
||||
// cycle again through the smack reactor.
|
||||
// A delegated task is asynchronously running. Take care of the remaining accumulatedData.
|
||||
addAsPendingInputData(accumulatedData);
|
||||
break;
|
||||
// Return here, as the async task created by handleHandshakeStatus will continue calling the
|
||||
// cannelSelectedCallback.
|
||||
return null;
|
||||
case NEED_UNWRAP:
|
||||
continue;
|
||||
case NEED_WRAP:
|
||||
// NEED_WRAP means that the SSLEngine needs to send data, probably without consuming data.
|
||||
// We exploit here the fact that the channelSelectedCallback is single threaded and that the
|
||||
// input processing is after the output processing.
|
||||
addAsPendingInputData(accumulatedData);
|
||||
// Note that it is ok that we the provided argument for pending input filter data to channel
|
||||
// selected callback is false, as setPendingInputFilterData() will have set the internal state
|
||||
// boolean accordingly.
|
||||
connectionInternal.asyncGo(() -> callChannelSelectedCallback(false, true));
|
||||
break;
|
||||
// Do not break here, but instead return and let the asynchronously invoked
|
||||
// callChannelSelectedCallback() do its work.
|
||||
return null;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1127,8 +1137,15 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
|
|||
}
|
||||
|
||||
private void addAsPendingInputData(ByteBuffer byteBuffer) {
|
||||
// Note that we can not simply write
|
||||
// pendingInputData = byteBuffer;
|
||||
// we have to copy the provided byte buffer, because it is possible that this byteBuffer is re-used by some
|
||||
// higher layer. That is, here 'byteBuffer' is typically 'incomingBuffer', which is a direct buffer only
|
||||
// allocated once per connection for performance reasons and hence re-used for read() calls.
|
||||
pendingInputData = ByteBuffer.allocate(byteBuffer.remaining());
|
||||
pendingInputData.put(byteBuffer).flip();
|
||||
|
||||
pendingInputFilterData = pendingInputData.hasRemaining();
|
||||
}
|
||||
|
||||
private SSLEngineResult.HandshakeStatus handleHandshakeStatus(SSLEngineResult sslEngineResult) {
|
||||
|
|
10
smack-websocket-okhttp/build.gradle
Normal file
10
smack-websocket-okhttp/build.gradle
Normal file
|
@ -0,0 +1,10 @@
|
|||
description = """\
|
||||
Smack for XMPP connections over WebSocket (RFC 7395) using OkHttp."""
|
||||
|
||||
dependencies {
|
||||
api project(':smack-websocket')
|
||||
|
||||
testFixturesApi(testFixtures(project(':smack-websocket')))
|
||||
|
||||
implementation("com.squareup.okhttp3:okhttp:4.6.0")
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations.okhttp;
|
||||
package org.jivesoftware.smack.websocket.okhttp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations.okhttp;
|
||||
package org.jivesoftware.smack.websocket.okhttp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
|
@ -27,11 +27,10 @@ import org.jivesoftware.smack.XMPPException;
|
|||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smack.websocket.WebsocketException;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
||||
import org.jivesoftware.smack.websocket.elements.WebsocketOpenElement;
|
||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.WebSocketException;
|
||||
import org.jivesoftware.smack.websocket.elements.WebSocketOpenElement;
|
||||
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
@ -40,9 +39,9 @@ import okhttp3.Response;
|
|||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
|
||||
public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||
public final class OkHttpWebSocket extends AbstractWebSocket {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(OkHttpWebsocket.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(OkHttpWebSocket.class.getName());
|
||||
|
||||
private static OkHttpClient okHttpClient = null;
|
||||
|
||||
|
@ -50,12 +49,11 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
private final LoggingInterceptor interceptor;
|
||||
|
||||
private String openStreamHeader;
|
||||
private WebSocket currentWebsocket;
|
||||
private WebsocketConnectionPhase phase;
|
||||
private WebsocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
private WebSocket currentWebSocket;
|
||||
private WebSocketConnectionPhase phase;
|
||||
private WebSocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
|
||||
public OkHttpWebsocket(ModularXmppClientToServerConnectionInternal connectionInternal,
|
||||
DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints) {
|
||||
public OkHttpWebSocket(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
this.connectionInternal = connectionInternal;
|
||||
|
||||
if (okHttpClient == null) {
|
||||
|
@ -72,8 +70,8 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void connect(WebsocketRemoteConnectionEndpoint endpoint) throws InterruptedException, SmackException, XMPPException {
|
||||
final String currentUri = endpoint.getWebsocketEndpoint().toString();
|
||||
public void connect(WebSocketRemoteConnectionEndpoint endpoint) throws InterruptedException, SmackException, XMPPException {
|
||||
final String currentUri = endpoint.getWebSocketEndpoint().toString();
|
||||
Request request = new Request.Builder()
|
||||
.url(currentUri)
|
||||
.header("Sec-WebSocket-Protocol", "xmpp")
|
||||
|
@ -83,12 +81,12 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
LOGGER.log(Level.FINER, "Websocket is open");
|
||||
phase = WebsocketConnectionPhase.openFrameSent;
|
||||
LOGGER.log(Level.FINER, "WebSocket is open");
|
||||
phase = WebSocketConnectionPhase.openFrameSent;
|
||||
if (interceptor != null) {
|
||||
interceptor.interceptOpenResponse(response);
|
||||
}
|
||||
send(new WebsocketOpenElement(connectionInternal.connection.getXMPPServiceDomain()));
|
||||
send(new WebSocketOpenElement(connectionInternal.connection.getXMPPServiceDomain()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,7 +105,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
if (isOpenElement(text)) {
|
||||
// Converts the <open> element received into <stream> element.
|
||||
openStreamHeader = getStreamFromOpenElement(text);
|
||||
phase = WebsocketConnectionPhase.exchangingTopLevelStreamElements;
|
||||
phase = WebSocketConnectionPhase.exchangingTopLevelStreamElements;
|
||||
|
||||
try {
|
||||
connectionInternal.onStreamOpen(PacketParserUtils.getParserFor(openStreamHeader));
|
||||
|
@ -129,7 +127,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||
LOGGER.log(Level.INFO, "Exception caught", t);
|
||||
WebsocketException websocketException = new WebsocketException(t);
|
||||
WebSocketException websocketException = new WebSocketException(t);
|
||||
if (connectionInternal.connection.isConnected()) {
|
||||
connectionInternal.notifyConnectionError(websocketException);
|
||||
} else {
|
||||
|
@ -139,7 +137,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
};
|
||||
|
||||
// Creates an instance of websocket through okHttpClient.
|
||||
currentWebsocket = okHttpClient.newWebSocket(request, listener);
|
||||
currentWebSocket = okHttpClient.newWebSocket(request, listener);
|
||||
|
||||
// Open a new stream and wait until features are received.
|
||||
connectionInternal.waitForFeaturesReceived("Waiting to receive features");
|
||||
|
@ -153,13 +151,13 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
|||
if (interceptor != null) {
|
||||
interceptor.interceptSentText(textToBeSent);
|
||||
}
|
||||
currentWebsocket.send(textToBeSent);
|
||||
currentWebSocket.send(textToBeSent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(int code, String message) {
|
||||
currentWebsocket.close(code, message);
|
||||
LOGGER.log(Level.INFO, "Websocket has been closed with message: " + message);
|
||||
currentWebSocket.close(code, message);
|
||||
LOGGER.log(Level.INFO, "WebSocket has been closed with message: " + message);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.okhttp;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||
import org.jivesoftware.smack.websocket.impl.WebSocketFactory;
|
||||
|
||||
public class OkHttpWebSocketFactory implements WebSocketFactory {
|
||||
|
||||
@Override
|
||||
public AbstractWebSocket create(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
return new OkHttpWebSocket(connectionInternal);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,4 +14,4 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations.okhttp;
|
||||
package org.jivesoftware.smack.websocket.okhttp;
|
|
@ -0,0 +1 @@
|
|||
org.jivesoftware.smack.websocket.okhttp.OkHttpWebSocketFactory
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.okhttp;
|
||||
|
||||
import org.jivesoftware.smack.websocket.test.WebSocketFactoryServiceTestUtil;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class OkHttpWebSocketFactoryServiceTest {
|
||||
|
||||
@Test
|
||||
public void createWebSocketTest() {
|
||||
WebSocketFactoryServiceTestUtil.createWebSocketTest(OkHttpWebSocket.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
description = """\
|
||||
Smack for standard XMPP connections over Websockets."""
|
||||
Smack for XMPP connections over WebSocket (RFC 7395)."""
|
||||
|
||||
dependencies {
|
||||
compile project(':smack-core')
|
||||
api project(':smack-core')
|
||||
|
||||
testFixturesApi(testFixtures(project(":smack-core")))
|
||||
|
||||
implementation("com.squareup.okhttp3:okhttp:4.6.0")
|
||||
testFixturesApi(testFixtures(project(':smack-core')))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Aditya Borikar
|
||||
* Copyright 2020 Aditya Borikar, Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,58 +16,48 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.websocket;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.EstablishingWebsocketConnectionState;
|
||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
||||
import org.jivesoftware.smack.websocket.implementations.WebsocketImplProvider;
|
||||
import org.jivesoftware.smack.websocket.implementations.okhttp.OkHttpWebsocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.EstablishingWebSocketConnectionState;
|
||||
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||
import org.jivesoftware.smack.websocket.impl.WebSocketFactoryService;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||
|
||||
public final class WebsocketConnectionAttemptState {
|
||||
public final class WebSocketConnectionAttemptState {
|
||||
private final ModularXmppClientToServerConnectionInternal connectionInternal;
|
||||
private final XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints discoveredEndpoints;
|
||||
private final XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints discoveredEndpoints;
|
||||
|
||||
private WebsocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
private WebSocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
|
||||
WebsocketConnectionAttemptState(ModularXmppClientToServerConnectionInternal connectionInternal,
|
||||
XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints,
|
||||
EstablishingWebsocketConnectionState establishingWebsocketConnectionState) {
|
||||
assert discoveredWebsocketEndpoints != null;
|
||||
WebSocketConnectionAttemptState(ModularXmppClientToServerConnectionInternal connectionInternal,
|
||||
XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints,
|
||||
EstablishingWebSocketConnectionState establishingWebSocketConnectionState) {
|
||||
assert discoveredWebSocketEndpoints != null;
|
||||
this.connectionInternal = connectionInternal;
|
||||
this.discoveredEndpoints = discoveredWebsocketEndpoints;
|
||||
this.discoveredEndpoints = discoveredWebSocketEndpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a websocket connection with one of the discoveredRemoteConnectionEndpoints.<br>
|
||||
*
|
||||
* @return {@link AbstractWebsocket} with which connection is establised
|
||||
* @return {@link AbstractWebSocket} with which connection is establised
|
||||
* @throws InterruptedException if the calling thread was interrupted
|
||||
* @throws WebsocketException if encounters a websocket exception
|
||||
* @throws WebSocketException if encounters a websocket exception
|
||||
*/
|
||||
AbstractWebsocket establishWebsocketConnection() throws InterruptedException, WebsocketException {
|
||||
List<WebsocketRemoteConnectionEndpoint> endpoints = discoveredEndpoints.result.discoveredRemoteConnectionEndpoints;
|
||||
AbstractWebSocket establishWebSocketConnection() throws InterruptedException, WebSocketException {
|
||||
List<WebSocketRemoteConnectionEndpoint> endpoints = discoveredEndpoints.result.discoveredRemoteConnectionEndpoints;
|
||||
|
||||
if (endpoints.isEmpty()) {
|
||||
throw new WebsocketException(new Throwable("No Endpoints discovered to establish connection"));
|
||||
throw new WebSocketException(new Throwable("No Endpoints discovered to establish connection"));
|
||||
}
|
||||
|
||||
List<Throwable> connectionFailureList = new ArrayList<>();
|
||||
AbstractWebsocket websocket;
|
||||
|
||||
try {
|
||||
// Obtain desired websocket implementation by using WebsocketImplProvider
|
||||
websocket = WebsocketImplProvider.getWebsocketImpl(OkHttpWebsocket.class, connectionInternal, discoveredEndpoints);
|
||||
} catch (NoSuchMethodException | SecurityException | InstantiationException |
|
||||
IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
|
||||
throw new WebsocketException(exception);
|
||||
}
|
||||
AbstractWebSocket websocket = WebSocketFactoryService.createWebSocket(connectionInternal);
|
||||
|
||||
// Keep iterating over available endpoints until a connection is establised or all endpoints are tried to create a connection with.
|
||||
for (WebsocketRemoteConnectionEndpoint endpoint : endpoints) {
|
||||
for (WebSocketRemoteConnectionEndpoint endpoint : endpoints) {
|
||||
try {
|
||||
websocket.connect(endpoint);
|
||||
connectedEndpoint = endpoint;
|
||||
|
@ -78,8 +68,8 @@ public final class WebsocketConnectionAttemptState {
|
|||
// If the number of entries in connectionFailureList is equal to the number of endpoints,
|
||||
// it means that all endpoints have been tried and have been unsuccessful.
|
||||
if (connectionFailureList.size() == endpoints.size()) {
|
||||
WebsocketException websocketException = new WebsocketException(connectionFailureList);
|
||||
throw new WebsocketException(websocketException);
|
||||
WebSocketException websocketException = new WebSocketException(connectionFailureList);
|
||||
throw new WebSocketException(websocketException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +85,7 @@ public final class WebsocketConnectionAttemptState {
|
|||
*
|
||||
* @return connected websocket endpoint
|
||||
*/
|
||||
public WebsocketRemoteConnectionEndpoint getConnectedEndpoint() {
|
||||
public WebSocketRemoteConnectionEndpoint getConnectedEndpoint() {
|
||||
return connectedEndpoint;
|
||||
}
|
||||
}
|
|
@ -19,16 +19,16 @@ package org.jivesoftware.smack.websocket;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class WebsocketException extends Exception {
|
||||
public final class WebSocketException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Throwable> throwableList;
|
||||
|
||||
public WebsocketException(List<Throwable> throwableList) {
|
||||
public WebSocketException(List<Throwable> throwableList) {
|
||||
this.throwableList = throwableList;
|
||||
}
|
||||
|
||||
public WebsocketException(Throwable throwable) {
|
||||
public WebSocketException(Throwable throwable) {
|
||||
this.throwableList = Collections.singletonList(throwable);
|
||||
}
|
||||
|
|
@ -19,10 +19,10 @@ package org.jivesoftware.smack.websocket;
|
|||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.initializer.UrlInitializer;
|
||||
|
||||
public final class WebsocketInitializer extends UrlInitializer {
|
||||
public final class WebSocketInitializer extends UrlInitializer {
|
||||
|
||||
static {
|
||||
SmackConfiguration.addModule(XmppWebsocketTransportModuleDescriptor.class);
|
||||
SmackConfiguration.addModule(XmppWebSocketTransportModuleDescriptor.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -50,13 +50,13 @@ import org.jivesoftware.smack.packet.AbstractStreamOpen;
|
|||
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
||||
import org.jivesoftware.smack.websocket.elements.WebsocketCloseElement;
|
||||
import org.jivesoftware.smack.websocket.elements.WebsocketOpenElement;
|
||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup.Result;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints;
|
||||
import org.jivesoftware.smack.websocket.elements.WebSocketCloseElement;
|
||||
import org.jivesoftware.smack.websocket.elements.WebSocketOpenElement;
|
||||
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup.Result;
|
||||
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
|
@ -65,44 +65,44 @@ import org.jxmpp.stringprep.XmppStringprepException;
|
|||
/**
|
||||
* The websocket transport module that goes with Smack's modular architecture.
|
||||
*/
|
||||
public final class XmppWebsocketTransportModule
|
||||
extends ModularXmppClientToServerConnectionModule<XmppWebsocketTransportModuleDescriptor> {
|
||||
private final XmppWebsocketTransport websocketTransport;
|
||||
public final class XmppWebSocketTransportModule
|
||||
extends ModularXmppClientToServerConnectionModule<XmppWebSocketTransportModuleDescriptor> {
|
||||
private final XmppWebSocketTransport websocketTransport;
|
||||
|
||||
private AbstractWebsocket websocket;
|
||||
private AbstractWebSocket websocket;
|
||||
|
||||
protected XmppWebsocketTransportModule(XmppWebsocketTransportModuleDescriptor moduleDescriptor,
|
||||
protected XmppWebSocketTransportModule(XmppWebSocketTransportModuleDescriptor moduleDescriptor,
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
super(moduleDescriptor, connectionInternal);
|
||||
|
||||
websocketTransport = new XmppWebsocketTransport(connectionInternal);
|
||||
websocketTransport = new XmppWebSocketTransport(connectionInternal);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XmppWebsocketTransport getTransport() {
|
||||
protected XmppWebSocketTransport getTransport() {
|
||||
return websocketTransport;
|
||||
}
|
||||
|
||||
static final class EstablishingWebsocketConnectionStateDescriptor extends StateDescriptor {
|
||||
private EstablishingWebsocketConnectionStateDescriptor() {
|
||||
super(XmppWebsocketTransportModule.EstablishingWebsocketConnectionState.class);
|
||||
static final class EstablishingWebSocketConnectionStateDescriptor extends StateDescriptor {
|
||||
private EstablishingWebSocketConnectionStateDescriptor() {
|
||||
super(XmppWebSocketTransportModule.EstablishingWebSocketConnectionState.class);
|
||||
addPredeccessor(LookupRemoteConnectionEndpointsStateDescriptor.class);
|
||||
addSuccessor(ConnectedButUnauthenticatedStateDescriptor.class);
|
||||
|
||||
// This states preference to TCP transports over this Websocket transport implementation.
|
||||
// This states preference to TCP transports over this WebSocket transport implementation.
|
||||
declareInferiorityTo("org.jivesoftware.smack.tcp.XmppTcpTransportModule$EstablishingTcpConnectionStateDescriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State constructState(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
XmppWebsocketTransportModule websocketTransportModule = connectionInternal.connection.getConnectionModuleFor(
|
||||
XmppWebsocketTransportModuleDescriptor.class);
|
||||
return websocketTransportModule.constructEstablishingWebsocketConnectionState(this, connectionInternal);
|
||||
XmppWebSocketTransportModule websocketTransportModule = connectionInternal.connection.getConnectionModuleFor(
|
||||
XmppWebSocketTransportModuleDescriptor.class);
|
||||
return websocketTransportModule.constructEstablishingWebSocketConnectionState(this, connectionInternal);
|
||||
}
|
||||
}
|
||||
|
||||
final class EstablishingWebsocketConnectionState extends State {
|
||||
protected EstablishingWebsocketConnectionState(StateDescriptor stateDescriptor,
|
||||
final class EstablishingWebSocketConnectionState extends State {
|
||||
protected EstablishingWebSocketConnectionState(StateDescriptor stateDescriptor,
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
super(stateDescriptor, connectionInternal);
|
||||
}
|
||||
|
@ -110,78 +110,78 @@ public final class XmppWebsocketTransportModule
|
|||
@Override
|
||||
public AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext)
|
||||
throws IOException, SmackException, InterruptedException, XMPPException {
|
||||
WebsocketConnectionAttemptState connectionAttemptState = new WebsocketConnectionAttemptState(
|
||||
connectionInternal, discoveredWebsocketEndpoints, this);
|
||||
WebSocketConnectionAttemptState connectionAttemptState = new WebSocketConnectionAttemptState(
|
||||
connectionInternal, discoveredWebSocketEndpoints, this);
|
||||
|
||||
try {
|
||||
websocket = connectionAttemptState.establishWebsocketConnection();
|
||||
} catch (InterruptedException | WebsocketException e) {
|
||||
websocket = connectionAttemptState.establishWebSocketConnection();
|
||||
} catch (InterruptedException | WebSocketException e) {
|
||||
StateTransitionResult.Failure failure = new StateTransitionResult.FailureCausedByException<Exception>(e);
|
||||
return failure;
|
||||
}
|
||||
|
||||
connectionInternal.setTransport(websocketTransport);
|
||||
|
||||
WebsocketRemoteConnectionEndpoint connectedEndpoint = connectionAttemptState.getConnectedEndpoint();
|
||||
WebSocketRemoteConnectionEndpoint connectedEndpoint = connectionAttemptState.getConnectedEndpoint();
|
||||
|
||||
// Construct a WebsocketConnectedResult using the connected endpoint.
|
||||
return new WebsocketConnectedResult(connectedEndpoint);
|
||||
// Construct a WebSocketConnectedResult using the connected endpoint.
|
||||
return new WebSocketConnectedResult(connectedEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
public EstablishingWebsocketConnectionState constructEstablishingWebsocketConnectionState(
|
||||
EstablishingWebsocketConnectionStateDescriptor establishingWebsocketConnectionStateDescriptor,
|
||||
public EstablishingWebSocketConnectionState constructEstablishingWebSocketConnectionState(
|
||||
EstablishingWebSocketConnectionStateDescriptor establishingWebSocketConnectionStateDescriptor,
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
return new EstablishingWebsocketConnectionState(establishingWebsocketConnectionStateDescriptor,
|
||||
return new EstablishingWebSocketConnectionState(establishingWebSocketConnectionStateDescriptor,
|
||||
connectionInternal);
|
||||
}
|
||||
|
||||
public static final class WebsocketConnectedResult extends StateTransitionResult.Success {
|
||||
final WebsocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
public static final class WebSocketConnectedResult extends StateTransitionResult.Success {
|
||||
final WebSocketRemoteConnectionEndpoint connectedEndpoint;
|
||||
|
||||
public WebsocketConnectedResult(WebsocketRemoteConnectionEndpoint connectedEndpoint) {
|
||||
super("Websocket connection establised with endpoint: " + connectedEndpoint.getWebsocketEndpoint());
|
||||
public WebSocketConnectedResult(WebSocketRemoteConnectionEndpoint connectedEndpoint) {
|
||||
super("WebSocket connection establised with endpoint: " + connectedEndpoint.getWebSocketEndpoint());
|
||||
this.connectedEndpoint = connectedEndpoint;
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints;
|
||||
private DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints;
|
||||
|
||||
/**
|
||||
* Transport class for {@link ModularXmppClientToServerConnectionModule}'s websocket implementation.
|
||||
*/
|
||||
public final class XmppWebsocketTransport extends XmppClientToServerTransport {
|
||||
public final class XmppWebSocketTransport extends XmppClientToServerTransport {
|
||||
|
||||
AsyncButOrdered<Queue<TopLevelStreamElement>> asyncButOrderedOutgoingElementsQueue;
|
||||
|
||||
protected XmppWebsocketTransport(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
protected XmppWebSocketTransport(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
super(connectionInternal);
|
||||
asyncButOrderedOutgoingElementsQueue = new AsyncButOrdered<Queue<TopLevelStreamElement>>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetDiscoveredConnectionEndpoints() {
|
||||
discoveredWebsocketEndpoints = null;
|
||||
discoveredWebSocketEndpoints = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SmackFuture<LookupConnectionEndpointsResult, Exception>> lookupConnectionEndpoints() {
|
||||
// Assert that there are no stale discovered endpoints prior performing the lookup.
|
||||
assert discoveredWebsocketEndpoints == null;
|
||||
assert discoveredWebSocketEndpoints == null;
|
||||
|
||||
InternalSmackFuture<LookupConnectionEndpointsResult, Exception> websocketEndpointsLookupFuture = new InternalSmackFuture<>();
|
||||
|
||||
connectionInternal.asyncGo(() -> {
|
||||
|
||||
WebsocketRemoteConnectionEndpoint providedEndpoint = null;
|
||||
WebSocketRemoteConnectionEndpoint providedEndpoint = null;
|
||||
|
||||
// Check if there is a websocket endpoint already configured.
|
||||
URI uri = moduleDescriptor.getExplicitlyProvidedUri();
|
||||
if (uri != null) {
|
||||
providedEndpoint = new WebsocketRemoteConnectionEndpoint(uri);
|
||||
providedEndpoint = new WebSocketRemoteConnectionEndpoint(uri);
|
||||
}
|
||||
|
||||
if (!moduleDescriptor.isWebsocketEndpointDiscoveryEnabled()) {
|
||||
if (!moduleDescriptor.isWebSocketEndpointDiscoveryEnabled()) {
|
||||
// If discovery is disabled, assert that the provided endpoint isn't null.
|
||||
assert providedEndpoint != null;
|
||||
|
||||
|
@ -190,14 +190,14 @@ public final class XmppWebsocketTransportModule
|
|||
mode.equals(SecurityMode.disabled))
|
||||
|| (!providedEndpoint.isSecureEndpoint() &&
|
||||
mode.equals(SecurityMode.required))) {
|
||||
throw new IllegalStateException("Explicitly configured uri: " + providedEndpoint.getWebsocketEndpoint().toString()
|
||||
throw new IllegalStateException("Explicitly configured uri: " + providedEndpoint.getWebSocketEndpoint().toString()
|
||||
+ " does not comply with the configured security mode: " + mode);
|
||||
}
|
||||
|
||||
// Generate Result for explicitly configured endpoint.
|
||||
Result manualResult = new Result(Arrays.asList(providedEndpoint), null);
|
||||
|
||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebsocketEndpoints(manualResult);
|
||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebSocketEndpoints(manualResult);
|
||||
|
||||
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
||||
} else {
|
||||
|
@ -206,14 +206,14 @@ public final class XmppWebsocketTransportModule
|
|||
SecurityMode mode = configuration.getSecurityMode();
|
||||
|
||||
// Fetch remote endpoints.
|
||||
Result xep0156result = WebsocketRemoteConnectionEndpointLookup.lookup(host, mode);
|
||||
Result xep0156result = WebSocketRemoteConnectionEndpointLookup.lookup(host, mode);
|
||||
|
||||
List<WebsocketRemoteConnectionEndpoint> discoveredEndpoints = xep0156result.discoveredRemoteConnectionEndpoints;
|
||||
List<WebSocketRemoteConnectionEndpoint> discoveredEndpoints = xep0156result.discoveredRemoteConnectionEndpoints;
|
||||
|
||||
// Generate result considering both manual and fetched endpoints.
|
||||
Result finalResult = new Result(discoveredEndpoints, xep0156result.getLookupFailures());
|
||||
|
||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebsocketEndpoints(finalResult);
|
||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebSocketEndpoints(finalResult);
|
||||
|
||||
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ public final class XmppWebsocketTransportModule
|
|||
|
||||
@Override
|
||||
protected void loadConnectionEndpoints(LookupConnectionEndpointsSuccess lookupConnectionEndpointsSuccess) {
|
||||
discoveredWebsocketEndpoints = (DiscoveredWebsocketEndpoints) lookupConnectionEndpointsSuccess;
|
||||
discoveredWebSocketEndpoints = (DiscoveredWebSocketEndpoints) lookupConnectionEndpointsSuccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -233,7 +233,7 @@ public final class XmppWebsocketTransportModule
|
|||
|
||||
@Override
|
||||
protected void disconnect() {
|
||||
websocket.disconnect(1000, "Websocket closed normally");
|
||||
websocket.disconnect(1000, "WebSocket closed normally");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -272,7 +272,7 @@ public final class XmppWebsocketTransportModule
|
|||
@Override
|
||||
public AbstractStreamOpen createStreamOpen(CharSequence to, CharSequence from, String id, String lang) {
|
||||
try {
|
||||
return new WebsocketOpenElement(JidCreate.domainBareFrom(to));
|
||||
return new WebSocketOpenElement(JidCreate.domainBareFrom(to));
|
||||
} catch (XmppStringprepException e) {
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, "Couldn't create OpenElement", e);
|
||||
return null;
|
||||
|
@ -280,7 +280,7 @@ public final class XmppWebsocketTransportModule
|
|||
}
|
||||
@Override
|
||||
public AbstractStreamClose createStreamClose() {
|
||||
return new WebsocketCloseElement();
|
||||
return new WebSocketCloseElement();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -288,15 +288,15 @@ public final class XmppWebsocketTransportModule
|
|||
/**
|
||||
* Contains {@link Result} for successfully discovered endpoints.
|
||||
*/
|
||||
public final class DiscoveredWebsocketEndpoints implements LookupConnectionEndpointsSuccess {
|
||||
final WebsocketRemoteConnectionEndpointLookup.Result result;
|
||||
public final class DiscoveredWebSocketEndpoints implements LookupConnectionEndpointsSuccess {
|
||||
final WebSocketRemoteConnectionEndpointLookup.Result result;
|
||||
|
||||
DiscoveredWebsocketEndpoints(Result result) {
|
||||
DiscoveredWebSocketEndpoints(Result result) {
|
||||
assert result != null;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public WebsocketRemoteConnectionEndpointLookup.Result getResult() {
|
||||
public WebSocketRemoteConnectionEndpointLookup.Result getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -305,11 +305,11 @@ public final class XmppWebsocketTransportModule
|
|||
* Contains list of {@link RemoteConnectionEndpointLookupFailure} when no endpoint
|
||||
* could be found during http lookup.
|
||||
*/
|
||||
final class WebsocketEndpointsDiscoveryFailed implements LookupConnectionEndpointsFailed {
|
||||
final class WebSocketEndpointsDiscoveryFailed implements LookupConnectionEndpointsFailed {
|
||||
final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
||||
|
||||
WebsocketEndpointsDiscoveryFailed(
|
||||
WebsocketRemoteConnectionEndpointLookup.Result result) {
|
||||
WebSocketEndpointsDiscoveryFailed(
|
||||
WebSocketRemoteConnectionEndpointLookup.Result result) {
|
||||
assert result != null;
|
||||
lookupFailures = Collections.unmodifiableList(result.lookupFailures);
|
||||
}
|
|
@ -28,20 +28,20 @@ import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionModuleDescr
|
|||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.fsm.StateDescriptor;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.EstablishingWebsocketConnectionStateDescriptor;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.EstablishingWebSocketConnectionStateDescriptor;
|
||||
|
||||
/**
|
||||
* The descriptor class for {@link XmppWebsocketTransportModule}.
|
||||
* The descriptor class for {@link XmppWebSocketTransportModule}.
|
||||
* <br>
|
||||
* To add {@link XmppWebsocketTransportModule} to {@link ModularXmppClientToServerConnection},
|
||||
* To add {@link XmppWebSocketTransportModule} to {@link ModularXmppClientToServerConnection},
|
||||
* use {@link ModularXmppClientToServerConnectionConfiguration.Builder#addModule(ModularXmppClientToServerConnectionModuleDescriptor)}.
|
||||
*/
|
||||
public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppClientToServerConnectionModuleDescriptor {
|
||||
private boolean performWebsocketEndpointDiscovery;
|
||||
public final class XmppWebSocketTransportModuleDescriptor extends ModularXmppClientToServerConnectionModuleDescriptor {
|
||||
private boolean performWebSocketEndpointDiscovery;
|
||||
private URI uri;
|
||||
|
||||
public XmppWebsocketTransportModuleDescriptor(Builder builder) {
|
||||
this.performWebsocketEndpointDiscovery = builder.performWebsocketEndpointDiscovery;
|
||||
public XmppWebSocketTransportModuleDescriptor(Builder builder) {
|
||||
this.performWebSocketEndpointDiscovery = builder.performWebSocketEndpointDiscovery;
|
||||
this.uri = builder.uri;
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
|||
* Returns true if websocket endpoint discovery is true, returns false otherwise.
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isWebsocketEndpointDiscoveryEnabled() {
|
||||
return performWebsocketEndpointDiscovery;
|
||||
public boolean isWebSocketEndpointDiscoveryEnabled() {
|
||||
return performWebSocketEndpointDiscovery;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,14 +64,14 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
|||
@Override
|
||||
protected Set<Class<? extends StateDescriptor>> getStateDescriptors() {
|
||||
Set<Class<? extends StateDescriptor>> res = new HashSet<>();
|
||||
res.add(EstablishingWebsocketConnectionStateDescriptor.class);
|
||||
res.add(EstablishingWebSocketConnectionStateDescriptor.class);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> constructXmppConnectionModule(
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
return new XmppWebsocketTransportModule(this, connectionInternal);
|
||||
return new XmppWebSocketTransportModule(this, connectionInternal);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,19 +86,19 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
|||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link XmppWebsocketTransportModuleDescriptor}.
|
||||
* Builder class for {@link XmppWebSocketTransportModuleDescriptor}.
|
||||
* <br>
|
||||
* To obtain an instance of {@link XmppWebsocketTransportModuleDescriptor.Builder}, use {@link XmppWebsocketTransportModuleDescriptor#getBuilder(ModularXmppClientToServerConnectionConfiguration.Builder)} method.
|
||||
* To obtain an instance of {@link XmppWebSocketTransportModuleDescriptor.Builder}, use {@link XmppWebSocketTransportModuleDescriptor#getBuilder(ModularXmppClientToServerConnectionConfiguration.Builder)} method.
|
||||
* <br>
|
||||
* Use {@link Builder#explicitlySetWebsocketEndpoint(URI)} to configure the URI of an endpoint as a backup in case connection couldn't be established with endpoints through http lookup.
|
||||
* Use {@link Builder#explicitlySetWebSocketEndpoint(URI)} to configure the URI of an endpoint as a backup in case connection couldn't be established with endpoints through http lookup.
|
||||
* <br>
|
||||
* Use {@link Builder#explicitlySetWebsocketEndpointAndDiscovery(URI, boolean)} to configure endpoint and disallow websocket endpoint discovery through http lookup.
|
||||
* By default, {@link Builder#performWebsocketEndpointDiscovery} is set to true.
|
||||
* Use {@link Builder#explicitlySetWebSocketEndpointAndDiscovery(URI, boolean)} to configure endpoint and disallow websocket endpoint discovery through http lookup.
|
||||
* By default, {@link Builder#performWebSocketEndpointDiscovery} is set to true.
|
||||
* <br>
|
||||
* Use {@link Builder#build()} to obtain {@link XmppWebsocketTransportModuleDescriptor}.
|
||||
* Use {@link Builder#build()} to obtain {@link XmppWebSocketTransportModuleDescriptor}.
|
||||
*/
|
||||
public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder {
|
||||
private boolean performWebsocketEndpointDiscovery = true;
|
||||
private boolean performWebSocketEndpointDiscovery = true;
|
||||
private URI uri;
|
||||
|
||||
private Builder(
|
||||
|
@ -106,31 +106,31 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
|||
super(connectionConfigurationBuilder);
|
||||
}
|
||||
|
||||
public Builder explicitlySetWebsocketEndpoint(URI endpoint) {
|
||||
return explicitlySetWebsocketEndpointAndDiscovery(endpoint, true);
|
||||
public Builder explicitlySetWebSocketEndpoint(URI endpoint) {
|
||||
return explicitlySetWebSocketEndpointAndDiscovery(endpoint, true);
|
||||
}
|
||||
|
||||
public Builder explicitlySetWebsocketEndpointAndDiscovery(URI endpoint, boolean performWebsocketEndpointDiscovery) {
|
||||
public Builder explicitlySetWebSocketEndpointAndDiscovery(URI endpoint, boolean performWebSocketEndpointDiscovery) {
|
||||
Objects.requireNonNull(endpoint, "Provided endpoint URI must not be null");
|
||||
this.uri = endpoint;
|
||||
this.performWebsocketEndpointDiscovery = performWebsocketEndpointDiscovery;
|
||||
this.performWebSocketEndpointDiscovery = performWebSocketEndpointDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder explicitlySetWebsocketEndpoint(CharSequence endpoint) throws URISyntaxException {
|
||||
public Builder explicitlySetWebSocketEndpoint(CharSequence endpoint) throws URISyntaxException {
|
||||
URI endpointUri = new URI(endpoint.toString());
|
||||
return explicitlySetWebsocketEndpointAndDiscovery(endpointUri, true);
|
||||
return explicitlySetWebSocketEndpointAndDiscovery(endpointUri, true);
|
||||
}
|
||||
|
||||
public Builder explicitlySetWebsocketEndpoint(CharSequence endpoint, boolean performWebsocketEndpointDiscovery)
|
||||
public Builder explicitlySetWebSocketEndpoint(CharSequence endpoint, boolean performWebSocketEndpointDiscovery)
|
||||
throws URISyntaxException {
|
||||
URI endpointUri = new URI(endpoint.toString());
|
||||
return explicitlySetWebsocketEndpointAndDiscovery(endpointUri, performWebsocketEndpointDiscovery);
|
||||
return explicitlySetWebSocketEndpointAndDiscovery(endpointUri, performWebSocketEndpointDiscovery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModularXmppClientToServerConnectionModuleDescriptor build() {
|
||||
return new XmppWebsocketTransportModuleDescriptor(this);
|
||||
return new XmppWebSocketTransportModuleDescriptor(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,12 +22,12 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
|
|||
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
|
||||
public abstract class AbstractWebsocketNonza implements Nonza {
|
||||
public abstract class AbstractWebSocketNonza implements Nonza {
|
||||
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||
private static final String VERSION = "1.0";
|
||||
private final DomainBareJid to;
|
||||
|
||||
public AbstractWebsocketNonza(DomainBareJid jid) {
|
||||
public AbstractWebSocketNonza(DomainBareJid jid) {
|
||||
this.to = jid;
|
||||
}
|
||||
|
|
@ -22,12 +22,12 @@ import org.jivesoftware.smack.packet.AbstractStreamClose;
|
|||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public final class WebsocketCloseElement extends AbstractStreamClose {
|
||||
public final class WebSocketCloseElement extends AbstractStreamClose {
|
||||
public static final String ELEMENT = "close";
|
||||
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||
|
||||
public WebsocketCloseElement() {
|
||||
public WebSocketCloseElement() {
|
||||
}
|
||||
|
||||
@Override
|
|
@ -25,12 +25,12 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
|
|||
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
|
||||
public final class WebsocketOpenElement extends AbstractStreamOpen {
|
||||
public final class WebSocketOpenElement extends AbstractStreamOpen {
|
||||
public static final String ELEMENT = "open";
|
||||
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||
|
||||
public WebsocketOpenElement(DomainBareJid to) {
|
||||
public WebSocketOpenElement(DomainBareJid to) {
|
||||
super(to, null, null, null, StreamContentNamespace.client);
|
||||
}
|
||||
|
|
@ -14,16 +14,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations;
|
||||
package org.jivesoftware.smack.websocket.impl;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||
|
||||
public abstract class AbstractWebsocket {
|
||||
public abstract class AbstractWebSocket {
|
||||
|
||||
protected enum WebsocketConnectionPhase {
|
||||
protected enum WebSocketConnectionPhase {
|
||||
openFrameSent,
|
||||
exchangingTopLevelStreamElements
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public abstract class AbstractWebsocket {
|
|||
return false;
|
||||
}
|
||||
|
||||
public abstract void connect(WebsocketRemoteConnectionEndpoint endpoint) throws Throwable;
|
||||
public abstract void connect(WebSocketRemoteConnectionEndpoint endpoint) throws Throwable;
|
||||
|
||||
public abstract void send(TopLevelStreamElement element);
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.impl;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
|
||||
public interface WebSocketFactory {
|
||||
|
||||
AbstractWebSocket create(ModularXmppClientToServerConnectionInternal connectionInternal);
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
|
||||
public final class WebSocketFactoryService {
|
||||
|
||||
private static final ServiceLoader<WebSocketFactory> SERVICE_LOADER = ServiceLoader.load(WebSocketFactory.class);
|
||||
|
||||
public static AbstractWebSocket createWebSocket(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||
assert connectionInternal != null;
|
||||
|
||||
Iterator<WebSocketFactory> websocketFactories = SERVICE_LOADER.iterator();
|
||||
if (!websocketFactories.hasNext()) {
|
||||
throw new IllegalStateException("No smack websocket service configured");
|
||||
}
|
||||
|
||||
WebSocketFactory websocketFactory = websocketFactories.next();
|
||||
return websocketFactory.create(connectionInternal);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,4 +17,4 @@
|
|||
/**
|
||||
* This package contains websocket implementations to be plugged inside websocket transport.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations;
|
||||
package org.jivesoftware.smack.websocket.impl;
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Aditya Borikar.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
||||
|
||||
public final class WebsocketImplProvider {
|
||||
|
||||
public static AbstractWebsocket getWebsocketImpl(Class<? extends AbstractWebsocket> websocketImpl, ModularXmppClientToServerConnectionInternal connectionInternal, DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
Objects.requireNonNull(connectionInternal, "ConnectionInternal cannot be null");
|
||||
|
||||
// Creates an instance of the constructor for the desired websocket implementation.
|
||||
Constructor<? extends AbstractWebsocket> constructor = websocketImpl.getConstructor(ModularXmppClientToServerConnectionInternal.class, DiscoveredWebsocketEndpoints.class);
|
||||
return (AbstractWebsocket) constructor.newInstance(connectionInternal, discoveredWebsocketEndpoints);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Websocket related classes for Smack.
|
||||
* WebSocket related classes for Smack.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket;
|
||||
|
|
|
@ -28,17 +28,17 @@ import java.util.logging.Logger;
|
|||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpoint;
|
||||
|
||||
public final class WebsocketRemoteConnectionEndpoint implements RemoteConnectionEndpoint {
|
||||
public final class WebSocketRemoteConnectionEndpoint implements RemoteConnectionEndpoint {
|
||||
|
||||
private static final Logger LOGGER = Logger.getAnonymousLogger();
|
||||
|
||||
private final URI uri;
|
||||
|
||||
public WebsocketRemoteConnectionEndpoint(String uri) throws URISyntaxException {
|
||||
public WebSocketRemoteConnectionEndpoint(String uri) throws URISyntaxException {
|
||||
this(new URI(uri));
|
||||
}
|
||||
|
||||
public WebsocketRemoteConnectionEndpoint(URI uri) {
|
||||
public WebSocketRemoteConnectionEndpoint(URI uri) {
|
||||
this.uri = uri;
|
||||
String scheme = uri.getScheme();
|
||||
if (!(scheme.equals("ws") || scheme.equals("wss"))) {
|
||||
|
@ -46,7 +46,7 @@ public final class WebsocketRemoteConnectionEndpoint implements RemoteConnection
|
|||
}
|
||||
}
|
||||
|
||||
public URI getWebsocketEndpoint() {
|
||||
public URI getWebSocketEndpoint() {
|
||||
return uri;
|
||||
}
|
||||
|
|
@ -31,11 +31,11 @@ import org.jivesoftware.smack.xml.XmlPullParserException;
|
|||
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
|
||||
public final class WebsocketRemoteConnectionEndpointLookup {
|
||||
public final class WebSocketRemoteConnectionEndpointLookup {
|
||||
|
||||
public static Result lookup(DomainBareJid domainBareJid, SecurityMode securityMode) {
|
||||
List<RemoteConnectionEndpointLookupFailure> lookupFailures = new ArrayList<>(1);
|
||||
List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||
List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||
|
||||
List<URI> rcUriList = null;
|
||||
try {
|
||||
|
@ -52,11 +52,11 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
|||
throw new IllegalStateException("No endpoints were found inside host-meta");
|
||||
}
|
||||
|
||||
// Convert rcUriList to List<WebsocketRemoteConnectionEndpoint>
|
||||
// Convert rcUriList to List<WebSocketRemoteConnectionEndpoint>
|
||||
Iterator<URI> iterator = rcUriList.iterator();
|
||||
List<WebsocketRemoteConnectionEndpoint> rceList = new ArrayList<>();
|
||||
List<WebSocketRemoteConnectionEndpoint> rceList = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
rceList.add(new WebsocketRemoteConnectionEndpoint(iterator.next()));
|
||||
rceList.add(new WebSocketRemoteConnectionEndpoint(iterator.next()));
|
||||
}
|
||||
|
||||
switch (securityMode) {
|
||||
|
@ -64,9 +64,9 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
|||
// If security mode equals `if-possible`, give priority to secure endpoints over insecure endpoints.
|
||||
|
||||
// Seprate secure and unsecure endpoints.
|
||||
List<WebsocketRemoteConnectionEndpoint> secureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||
List<WebsocketRemoteConnectionEndpoint> insecureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||
for (WebsocketRemoteConnectionEndpoint uri : rceList) {
|
||||
List<WebSocketRemoteConnectionEndpoint> secureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||
List<WebSocketRemoteConnectionEndpoint> insecureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||
for (WebSocketRemoteConnectionEndpoint uri : rceList) {
|
||||
if (uri.isSecureEndpoint()) {
|
||||
secureEndpointsForSecurityModeIfPossible.add(uri);
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
|||
* If, SecurityMode equals to required, accept wss endpoints (secure endpoints) only or,
|
||||
* if SecurityMode equals to disabled, accept ws endpoints (unsecure endpoints) only.
|
||||
*/
|
||||
for (WebsocketRemoteConnectionEndpoint uri : rceList) {
|
||||
for (WebSocketRemoteConnectionEndpoint uri : rceList) {
|
||||
if ((securityMode.equals(SecurityMode.disabled) && !uri.isSecureEndpoint())
|
||||
|| (securityMode.equals(SecurityMode.required) && uri.isSecureEndpoint())) {
|
||||
discoveredRemoteConnectionEndpoints.add(uri);
|
||||
|
@ -95,16 +95,16 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
|||
}
|
||||
|
||||
public static final class Result {
|
||||
public final List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints;
|
||||
public final List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints;
|
||||
public final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
||||
|
||||
public Result(List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints,
|
||||
public Result(List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints,
|
||||
List<RemoteConnectionEndpointLookupFailure> lookupFailures) {
|
||||
this.discoveredRemoteConnectionEndpoints = discoveredRemoteConnectionEndpoints;
|
||||
this.lookupFailures = lookupFailures;
|
||||
}
|
||||
|
||||
public List<WebsocketRemoteConnectionEndpoint> getDiscoveredRemoteConnectionEndpoints() {
|
||||
public List<WebSocketRemoteConnectionEndpoint> getDiscoveredRemoteConnectionEndpoints() {
|
||||
return discoveredRemoteConnectionEndpoints;
|
||||
}
|
||||
|
|
@ -20,9 +20,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class WebsocketConnectionAttemptStateTest {
|
||||
public class WebSocketConnectionAttemptStateTest {
|
||||
@Test
|
||||
public void constructorTest() {
|
||||
assertThrows(AssertionError.class, () -> new WebsocketConnectionAttemptState(null, null, null));
|
||||
assertThrows(AssertionError.class, () -> new WebSocketConnectionAttemptState(null, null, null));
|
||||
}
|
||||
}
|
|
@ -22,10 +22,10 @@ import java.util.List;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class WebsocketInitializerTest {
|
||||
public class WebSocketInitializerTest {
|
||||
@Test
|
||||
public void testExtensionInitializer() {
|
||||
WebsocketInitializer initializer = new WebsocketInitializer();
|
||||
WebSocketInitializer initializer = new WebSocketInitializer();
|
||||
List<Exception> exceptions = initializer.initialize();
|
||||
assertTrue(exceptions.size() == 0);
|
||||
}
|
|
@ -31,27 +31,27 @@ import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfigurati
|
|||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure.HttpLookupFailure;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.WebsocketEndpointsDiscoveryFailed;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup.Result;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints;
|
||||
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.WebSocketEndpointsDiscoveryFailed;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup.Result;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
public class XmppWebsocketTransportModuleTest {
|
||||
public class XmppWebSocketTransportModuleTest {
|
||||
@Test
|
||||
public void createWebsocketModuleConnectionInstanceTest() throws URISyntaxException, XmppStringprepException {
|
||||
public void createWebSocketModuleConnectionInstanceTest() throws URISyntaxException, XmppStringprepException {
|
||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
||||
.builder();
|
||||
|
||||
builder.removeAllModules();
|
||||
builder.addModule(XmppWebsocketTransportModuleDescriptor.class);
|
||||
builder.addModule(XmppWebSocketTransportModuleDescriptor.class);
|
||||
builder.setXmppAddressAndPassword("user5@localhost.org", "user5");
|
||||
builder.setHost("localhost.org");
|
||||
|
||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||
|
||||
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
||||
ModularXmppClientToServerConnection connection = new ModularXmppClientToServerConnection(config);
|
||||
|
@ -60,26 +60,26 @@ public class XmppWebsocketTransportModuleTest {
|
|||
|
||||
@Test
|
||||
public void createDescriptorTest() throws URISyntaxException, XmppStringprepException {
|
||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
||||
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||
assertNotNull(websocketTransportModuleDescriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void websocketEndpointDiscoveryTest() throws URISyntaxException {
|
||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
||||
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||
|
||||
XmppWebsocketTransportModule transportModule
|
||||
= new XmppWebsocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
||||
XmppWebSocketTransportModule transportModule
|
||||
= new XmppWebSocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
||||
|
||||
XmppWebsocketTransportModule.XmppWebsocketTransport transport = transportModule.getTransport();
|
||||
XmppWebSocketTransportModule.XmppWebSocketTransport transport = transportModule.getTransport();
|
||||
|
||||
assertThrows(AssertionError.class, () -> transport.new DiscoveredWebsocketEndpoints(null));
|
||||
assertThrows(AssertionError.class, () -> transport.new WebsocketEndpointsDiscoveryFailed(null));
|
||||
assertThrows(AssertionError.class, () -> transport.new DiscoveredWebSocketEndpoints(null));
|
||||
assertThrows(AssertionError.class, () -> transport.new WebSocketEndpointsDiscoveryFailed(null));
|
||||
|
||||
WebsocketRemoteConnectionEndpoint endpoint = new WebsocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||
WebSocketRemoteConnectionEndpoint endpoint = new WebSocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||
|
||||
List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||
List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||
discoveredRemoteConnectionEndpoints.add(endpoint);
|
||||
|
||||
HttpLookupFailure httpLookupFailure = new RemoteConnectionEndpointLookupFailure.HttpLookupFailure(null, null);
|
||||
|
@ -87,38 +87,38 @@ public class XmppWebsocketTransportModuleTest {
|
|||
failureList.add(httpLookupFailure);
|
||||
Result result = new Result(discoveredRemoteConnectionEndpoints, failureList);
|
||||
|
||||
DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints = transport.new DiscoveredWebsocketEndpoints(result);
|
||||
assertNotNull(discoveredWebsocketEndpoints.getResult());
|
||||
DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints = transport.new DiscoveredWebSocketEndpoints(result);
|
||||
assertNotNull(discoveredWebSocketEndpoints.getResult());
|
||||
|
||||
WebsocketEndpointsDiscoveryFailed endpointsDiscoveryFailed = transport.new WebsocketEndpointsDiscoveryFailed(result);
|
||||
WebSocketEndpointsDiscoveryFailed endpointsDiscoveryFailed = transport.new WebSocketEndpointsDiscoveryFailed(result);
|
||||
assertNotNull(endpointsDiscoveryFailed.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void websocketConnectedResultTest() throws URISyntaxException {
|
||||
WebsocketRemoteConnectionEndpoint connectedEndpoint = new WebsocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||
assertNotNull(new XmppWebsocketTransportModule.WebsocketConnectedResult(connectedEndpoint));
|
||||
WebSocketRemoteConnectionEndpoint connectedEndpoint = new WebSocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||
assertNotNull(new XmppWebSocketTransportModule.WebSocketConnectedResult(connectedEndpoint));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupConnectionEndpointsTest() throws URISyntaxException {
|
||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
||||
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||
|
||||
XmppWebsocketTransportModule transportModule
|
||||
= new XmppWebsocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
||||
XmppWebSocketTransportModule transportModule
|
||||
= new XmppWebSocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
||||
|
||||
XmppWebsocketTransportModule.XmppWebsocketTransport transport = transportModule.getTransport();
|
||||
XmppWebSocketTransportModule.XmppWebSocketTransport transport = transportModule.getTransport();
|
||||
assertNotNull(transport.lookupConnectionEndpoints());
|
||||
|
||||
}
|
||||
|
||||
private static XmppWebsocketTransportModuleDescriptor getWebsocketDescriptor() throws URISyntaxException {
|
||||
private static XmppWebSocketTransportModuleDescriptor getWebSocketDescriptor() throws URISyntaxException {
|
||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
||||
.builder();
|
||||
|
||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||
return (XmppWebsocketTransportModuleDescriptor) websocketBuilder.build();
|
||||
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||
return (XmppWebSocketTransportModuleDescriptor) websocketBuilder.build();
|
||||
}
|
||||
}
|
|
@ -23,20 +23,20 @@ import org.junit.jupiter.api.Test;
|
|||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
public class WebsocketElementTest {
|
||||
public class WebSocketElementTest {
|
||||
private static final String OPEN_ELEMENT = "<open xmlns='urn:ietf:params:xml:ns:xmpp-framing' to='foodomain.foo' version='1.0'/>";
|
||||
private static final String CLOSE_ELEMENT = "<close xmlns='urn:ietf:params:xml:ns:xmpp-framing'/>";
|
||||
|
||||
@Test
|
||||
public void websocketOpenElementTest() throws XmppStringprepException {
|
||||
String openElementXml = new WebsocketOpenElement(JidCreate.domainBareFrom("foodomain.foo")).toXML().toString();
|
||||
String openElementXml = new WebSocketOpenElement(JidCreate.domainBareFrom("foodomain.foo")).toXML().toString();
|
||||
assertXmlSimilar(OPEN_ELEMENT, openElementXml);
|
||||
assertXmlNotSimilar(CLOSE_ELEMENT, new WebsocketOpenElement(JidCreate.domainBareFrom("foodomain.foo")).toXML());
|
||||
assertXmlNotSimilar(CLOSE_ELEMENT, new WebSocketOpenElement(JidCreate.domainBareFrom("foodomain.foo")).toXML());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void websocketCloseElementTest() throws XmppStringprepException {
|
||||
String closeElementXml = new WebsocketCloseElement().toXML().toString();
|
||||
String closeElementXml = new WebSocketCloseElement().toXML().toString();
|
||||
assertXmlSimilar(CLOSE_ELEMENT, closeElementXml);
|
||||
assertXmlNotSimilar(OPEN_ELEMENT, closeElementXml);
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations;
|
||||
package org.jivesoftware.smack.websocket.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -22,26 +22,26 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public final class AbstractWebsocketTest {
|
||||
public final class AbstractWebSocketTest {
|
||||
private static final String OPEN_ELEMENT = "<open from='localhost.org' id='aov9ihhmmn' xmlns='urn:ietf:params:xml:ns:xmpp-framing' xml:lang='en' version='1.0'/>";
|
||||
private static final String OPEN_STREAM = "<stream from='localhost.org' id='aov9ihhmmn' xmlns='jabber:client' xml:lang='en' version='1.0'>";
|
||||
private static final String CLOSE_ELEMENT = "<close xmlns='urn:ietf:params:xml:ns:xmpp-framing'/>";
|
||||
|
||||
@Test
|
||||
public void getStreamFromOpenElementTest() {
|
||||
String generatedOpenStream = AbstractWebsocket.getStreamFromOpenElement(OPEN_ELEMENT);
|
||||
String generatedOpenStream = AbstractWebSocket.getStreamFromOpenElement(OPEN_ELEMENT);
|
||||
assertEquals(generatedOpenStream, OPEN_STREAM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isOpenElementTest() {
|
||||
assertTrue(AbstractWebsocket.isOpenElement(OPEN_ELEMENT));
|
||||
assertFalse(AbstractWebsocket.isOpenElement(OPEN_STREAM));
|
||||
assertTrue(AbstractWebSocket.isOpenElement(OPEN_ELEMENT));
|
||||
assertFalse(AbstractWebSocket.isOpenElement(OPEN_STREAM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCloseElementTest() {
|
||||
assertTrue(AbstractWebsocket.isCloseElement(CLOSE_ELEMENT));
|
||||
assertFalse(AbstractWebsocket.isCloseElement(OPEN_STREAM));
|
||||
assertTrue(AbstractWebSocket.isCloseElement(CLOSE_ELEMENT));
|
||||
assertFalse(AbstractWebSocket.isCloseElement(OPEN_STREAM));
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Aditya Borikar.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.implementations;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
||||
|
||||
import org.jivesoftware.smack.websocket.implementations.okhttp.OkHttpWebsocket;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup.Result;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ProviderTest {
|
||||
@Test
|
||||
public void providerTest() {
|
||||
assertThrows(IllegalArgumentException.class, () -> WebsocketImplProvider.getWebsocketImpl(OkHttpWebsocket.class, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getImplTest() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, URISyntaxException {
|
||||
WebsocketRemoteConnectionEndpoint endpoint = new WebsocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||
|
||||
List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||
discoveredRemoteConnectionEndpoints.add(endpoint);
|
||||
|
||||
Result result = new Result(discoveredRemoteConnectionEndpoints, null);
|
||||
|
||||
DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints = mock(DiscoveredWebsocketEndpoints.class);
|
||||
when(discoveredWebsocketEndpoints.getResult()).thenReturn(result);
|
||||
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||
|
||||
assertNotNull(WebsocketImplProvider.getWebsocketImpl(OkHttpWebsocket.class, connectionInternal, discoveredWebsocketEndpoints));
|
||||
}
|
||||
}
|
|
@ -25,21 +25,21 @@ import org.jivesoftware.smack.datatypes.UInt16;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class WebsocketRemoteConnectionEndpointTest {
|
||||
public class WebSocketRemoteConnectionEndpointTest {
|
||||
@Test
|
||||
public void endpointTest() throws URISyntaxException {
|
||||
String endpointString = "ws://fooDomain.org:7070/ws/";
|
||||
WebsocketRemoteConnectionEndpoint endpoint = new WebsocketRemoteConnectionEndpoint(endpointString);
|
||||
WebSocketRemoteConnectionEndpoint endpoint = new WebSocketRemoteConnectionEndpoint(endpointString);
|
||||
assertEquals("fooDomain.org", endpoint.getHost());
|
||||
assertEquals(UInt16.from(7070), endpoint.getPort());
|
||||
assertEquals(endpointString, endpoint.getWebsocketEndpoint().toString());
|
||||
assertEquals(endpointString, endpoint.getWebSocketEndpoint().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void faultyEndpointTest() {
|
||||
String faultyProtocolString = "wst://fooDomain.org:7070/ws/";
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new WebsocketRemoteConnectionEndpoint(faultyProtocolString);
|
||||
new WebSocketRemoteConnectionEndpoint(faultyProtocolString);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.websocket.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||
import org.jivesoftware.smack.websocket.impl.WebSocketFactoryService;
|
||||
|
||||
public class WebSocketFactoryServiceTestUtil {
|
||||
|
||||
public static void createWebSocketTest(Class<? extends AbstractWebSocket> expected) {
|
||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||
|
||||
AbstractWebSocket websocket = WebSocketFactoryService.createWebSocket(connectionInternal);
|
||||
assertEquals(expected, websocket.getClass());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue