mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-05 08:05:58 +01:00
Merge pull request #430 from Flowdalic/websocket
Introduce smack-websocket-okhttp
This commit is contained in:
commit
0a6c21982b
37 changed files with 404 additions and 341 deletions
|
@ -31,6 +31,7 @@ include 'smack-core',
|
||||||
'smack-repl',
|
'smack-repl',
|
||||||
'smack-openpgp',
|
'smack-openpgp',
|
||||||
'smack-websocket',
|
'smack-websocket',
|
||||||
|
'smack-websocket-okhttp',
|
||||||
'smack-xmlparser',
|
'smack-xmlparser',
|
||||||
'smack-xmlparser-stax',
|
'smack-xmlparser-stax',
|
||||||
'smack-xmlparser-xpp3'
|
'smack-xmlparser-xpp3'
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<className>org.jivesoftware.smack.android.AndroidSmackInitializer</className>
|
<className>org.jivesoftware.smack.android.AndroidSmackInitializer</className>
|
||||||
<className>org.jivesoftware.smack.java7.Java7SmackInitializer</className>
|
<className>org.jivesoftware.smack.java7.Java7SmackInitializer</className>
|
||||||
<className>org.jivesoftware.smack.im.SmackImInitializer</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.omemo.OmemoInitializer</className>
|
||||||
<className>org.jivesoftware.smackx.ox.util.OpenPgpInitializer</className>
|
<className>org.jivesoftware.smackx.ox.util.OpenPgpInitializer</className>
|
||||||
</optionalStartupClasses>
|
</optionalStartupClasses>
|
||||||
|
|
|
@ -44,7 +44,7 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||||
import org.jivesoftware.smack.util.MultiMap;
|
import org.jivesoftware.smack.util.MultiMap;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
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.admin.ServiceAdministrationManager;
|
||||||
import org.jivesoftware.smackx.iqregister.AccountManager;
|
import org.jivesoftware.smackx.iqregister.AccountManager;
|
||||||
|
@ -92,7 +92,7 @@ public class XmppConnectionManager {
|
||||||
.withNickname("modular-websocket")
|
.withNickname("modular-websocket")
|
||||||
.applyExtraConfguration(cb -> {
|
.applyExtraConfguration(cb -> {
|
||||||
cb.removeAllModules();
|
cb.removeAllModules();
|
||||||
cb.addModule(XmppWebsocketTransportModuleDescriptor.class);
|
cb.addModule(XmppWebSocketTransportModuleDescriptor.class);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,7 +32,7 @@ digraph {
|
||||||
"ConnectedButUnauthenticated" -> "InstantShutdown" [xlabel="5"];
|
"ConnectedButUnauthenticated" -> "InstantShutdown" [xlabel="5"];
|
||||||
"ConnectedButUnauthenticated" [ style=filled ]
|
"ConnectedButUnauthenticated" [ style=filled ]
|
||||||
"EstablishingTcpConnection" -> "ConnectedButUnauthenticated" [xlabel="2"];
|
"EstablishingTcpConnection" -> "ConnectedButUnauthenticated" [xlabel="2"];
|
||||||
"LookupRemoteConnectionEndpoints" -> "EstablishingWebsocketConnection" [xlabel="2"];
|
"LookupRemoteConnectionEndpoints" -> "EstablishingWebSocketConnection" [xlabel="2"];
|
||||||
"EstablishingWebsocketConnection" -> "ConnectedButUnauthenticated";
|
"EstablishingWebSocketConnection" -> "ConnectedButUnauthenticated";
|
||||||
"Disconnected" [ style=filled ]
|
"Disconnected" [ style=filled ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ import org.jivesoftware.smack.XMPPException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection;
|
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection;
|
||||||
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfiguration;
|
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 {
|
public static void main(String[] args) throws SmackException, IOException, XMPPException, InterruptedException, URISyntaxException {
|
||||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration.builder();
|
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration.builder();
|
||||||
|
@ -39,8 +39,8 @@ public class WebsocketConnection {
|
||||||
builder.setXmppAddressAndPassword(args[0], args[1]);
|
builder.setXmppAddressAndPassword(args[0], args[1]);
|
||||||
|
|
||||||
// Set a fallback uri into websocket transport descriptor and add this descriptor into connection builder.
|
// Set a fallback uri into websocket transport descriptor and add this descriptor into connection builder.
|
||||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI(args[2]), false);
|
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI(args[2]), false);
|
||||||
builder.addModule(websocketBuilder.build());
|
builder.addModule(websocketBuilder.build());
|
||||||
|
|
||||||
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.websocket.implementations.okhttp;
|
package org.jivesoftware.smack.websocket.okhttp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.websocket.implementations.okhttp;
|
package org.jivesoftware.smack.websocket.okhttp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.logging.Level;
|
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.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||||
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.jivesoftware.smack.websocket.WebsocketException;
|
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.elements.WebsocketOpenElement;
|
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
|
||||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
@ -40,9 +39,9 @@ import okhttp3.Response;
|
||||||
import okhttp3.WebSocket;
|
import okhttp3.WebSocket;
|
||||||
import okhttp3.WebSocketListener;
|
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;
|
private static OkHttpClient okHttpClient = null;
|
||||||
|
|
||||||
|
@ -50,12 +49,11 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
private final LoggingInterceptor interceptor;
|
private final LoggingInterceptor interceptor;
|
||||||
|
|
||||||
private String openStreamHeader;
|
private String openStreamHeader;
|
||||||
private WebSocket currentWebsocket;
|
private WebSocket currentWebSocket;
|
||||||
private WebsocketConnectionPhase phase;
|
private WebSocketConnectionPhase phase;
|
||||||
private WebsocketRemoteConnectionEndpoint connectedEndpoint;
|
private WebSocketRemoteConnectionEndpoint connectedEndpoint;
|
||||||
|
|
||||||
public OkHttpWebsocket(ModularXmppClientToServerConnectionInternal connectionInternal,
|
public OkHttpWebSocket(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints) {
|
|
||||||
this.connectionInternal = connectionInternal;
|
this.connectionInternal = connectionInternal;
|
||||||
|
|
||||||
if (okHttpClient == null) {
|
if (okHttpClient == null) {
|
||||||
|
@ -72,8 +70,8 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connect(WebsocketRemoteConnectionEndpoint endpoint) throws InterruptedException, SmackException, XMPPException {
|
public void connect(WebSocketRemoteConnectionEndpoint endpoint) throws InterruptedException, SmackException, XMPPException {
|
||||||
final String currentUri = endpoint.getWebsocketEndpoint().toString();
|
final String currentUri = endpoint.getWebSocketEndpoint().toString();
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(currentUri)
|
.url(currentUri)
|
||||||
.header("Sec-WebSocket-Protocol", "xmpp")
|
.header("Sec-WebSocket-Protocol", "xmpp")
|
||||||
|
@ -83,12 +81,12 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(WebSocket webSocket, Response response) {
|
public void onOpen(WebSocket webSocket, Response response) {
|
||||||
LOGGER.log(Level.FINER, "Websocket is open");
|
LOGGER.log(Level.FINER, "WebSocket is open");
|
||||||
phase = WebsocketConnectionPhase.openFrameSent;
|
phase = WebSocketConnectionPhase.openFrameSent;
|
||||||
if (interceptor != null) {
|
if (interceptor != null) {
|
||||||
interceptor.interceptOpenResponse(response);
|
interceptor.interceptOpenResponse(response);
|
||||||
}
|
}
|
||||||
send(new WebsocketOpenElement(connectionInternal.connection.getXMPPServiceDomain()));
|
send(new WebSocketOpenElement(connectionInternal.connection.getXMPPServiceDomain()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,7 +105,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
if (isOpenElement(text)) {
|
if (isOpenElement(text)) {
|
||||||
// Converts the <open> element received into <stream> element.
|
// Converts the <open> element received into <stream> element.
|
||||||
openStreamHeader = getStreamFromOpenElement(text);
|
openStreamHeader = getStreamFromOpenElement(text);
|
||||||
phase = WebsocketConnectionPhase.exchangingTopLevelStreamElements;
|
phase = WebSocketConnectionPhase.exchangingTopLevelStreamElements;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connectionInternal.onStreamOpen(PacketParserUtils.getParserFor(openStreamHeader));
|
connectionInternal.onStreamOpen(PacketParserUtils.getParserFor(openStreamHeader));
|
||||||
|
@ -129,7 +127,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||||
LOGGER.log(Level.INFO, "Exception caught", t);
|
LOGGER.log(Level.INFO, "Exception caught", t);
|
||||||
WebsocketException websocketException = new WebsocketException(t);
|
WebSocketException websocketException = new WebSocketException(t);
|
||||||
if (connectionInternal.connection.isConnected()) {
|
if (connectionInternal.connection.isConnected()) {
|
||||||
connectionInternal.notifyConnectionError(websocketException);
|
connectionInternal.notifyConnectionError(websocketException);
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,7 +137,7 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates an instance of websocket through okHttpClient.
|
// 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.
|
// Open a new stream and wait until features are received.
|
||||||
connectionInternal.waitForFeaturesReceived("Waiting to receive features");
|
connectionInternal.waitForFeaturesReceived("Waiting to receive features");
|
||||||
|
@ -153,13 +151,13 @@ public final class OkHttpWebsocket extends AbstractWebsocket {
|
||||||
if (interceptor != null) {
|
if (interceptor != null) {
|
||||||
interceptor.interceptSentText(textToBeSent);
|
interceptor.interceptSentText(textToBeSent);
|
||||||
}
|
}
|
||||||
currentWebsocket.send(textToBeSent);
|
currentWebSocket.send(textToBeSent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(int code, String message) {
|
public void disconnect(int code, String message) {
|
||||||
currentWebsocket.close(code, message);
|
currentWebSocket.close(code, message);
|
||||||
LOGGER.log(Level.INFO, "Websocket has been closed with message: " + message);
|
LOGGER.log(Level.INFO, "WebSocket has been closed with message: " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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 = """\
|
description = """\
|
||||||
Smack for standard XMPP connections over Websockets."""
|
Smack for XMPP connections over WebSocket (RFC 7395)."""
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':smack-core')
|
api project(':smack-core')
|
||||||
|
|
||||||
testFixturesApi(testFixtures(project(":smack-core")))
|
testFixturesApi(testFixtures(project(':smack-core')))
|
||||||
|
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.6.0")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2020 Aditya Borikar
|
* Copyright 2020 Aditya Borikar, Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,58 +16,48 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.websocket;
|
package org.jivesoftware.smack.websocket;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.EstablishingWebsocketConnectionState;
|
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.EstablishingWebSocketConnectionState;
|
||||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||||
import org.jivesoftware.smack.websocket.implementations.WebsocketImplProvider;
|
import org.jivesoftware.smack.websocket.impl.WebSocketFactoryService;
|
||||||
import org.jivesoftware.smack.websocket.implementations.okhttp.OkHttpWebsocket;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
|
||||||
|
|
||||||
public final class WebsocketConnectionAttemptState {
|
public final class WebSocketConnectionAttemptState {
|
||||||
private final ModularXmppClientToServerConnectionInternal connectionInternal;
|
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,
|
WebSocketConnectionAttemptState(ModularXmppClientToServerConnectionInternal connectionInternal,
|
||||||
XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints,
|
XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints,
|
||||||
EstablishingWebsocketConnectionState establishingWebsocketConnectionState) {
|
EstablishingWebSocketConnectionState establishingWebSocketConnectionState) {
|
||||||
assert discoveredWebsocketEndpoints != null;
|
assert discoveredWebSocketEndpoints != null;
|
||||||
this.connectionInternal = connectionInternal;
|
this.connectionInternal = connectionInternal;
|
||||||
this.discoveredEndpoints = discoveredWebsocketEndpoints;
|
this.discoveredEndpoints = discoveredWebSocketEndpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establish a websocket connection with one of the discoveredRemoteConnectionEndpoints.<br>
|
* 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 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 {
|
AbstractWebSocket establishWebSocketConnection() throws InterruptedException, WebSocketException {
|
||||||
List<WebsocketRemoteConnectionEndpoint> endpoints = discoveredEndpoints.result.discoveredRemoteConnectionEndpoints;
|
List<WebSocketRemoteConnectionEndpoint> endpoints = discoveredEndpoints.result.discoveredRemoteConnectionEndpoints;
|
||||||
|
|
||||||
if (endpoints.isEmpty()) {
|
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<>();
|
List<Throwable> connectionFailureList = new ArrayList<>();
|
||||||
AbstractWebsocket websocket;
|
AbstractWebSocket websocket = WebSocketFactoryService.createWebSocket(connectionInternal);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep iterating over available endpoints until a connection is establised or all endpoints are tried to create a connection with.
|
// 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 {
|
try {
|
||||||
websocket.connect(endpoint);
|
websocket.connect(endpoint);
|
||||||
connectedEndpoint = 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,
|
// 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.
|
// it means that all endpoints have been tried and have been unsuccessful.
|
||||||
if (connectionFailureList.size() == endpoints.size()) {
|
if (connectionFailureList.size() == endpoints.size()) {
|
||||||
WebsocketException websocketException = new WebsocketException(connectionFailureList);
|
WebSocketException websocketException = new WebSocketException(connectionFailureList);
|
||||||
throw new WebsocketException(websocketException);
|
throw new WebSocketException(websocketException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +85,7 @@ public final class WebsocketConnectionAttemptState {
|
||||||
*
|
*
|
||||||
* @return connected websocket endpoint
|
* @return connected websocket endpoint
|
||||||
*/
|
*/
|
||||||
public WebsocketRemoteConnectionEndpoint getConnectedEndpoint() {
|
public WebSocketRemoteConnectionEndpoint getConnectedEndpoint() {
|
||||||
return connectedEndpoint;
|
return connectedEndpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,16 +19,16 @@ package org.jivesoftware.smack.websocket;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class WebsocketException extends Exception {
|
public final class WebSocketException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final List<Throwable> throwableList;
|
private final List<Throwable> throwableList;
|
||||||
|
|
||||||
public WebsocketException(List<Throwable> throwableList) {
|
public WebSocketException(List<Throwable> throwableList) {
|
||||||
this.throwableList = throwableList;
|
this.throwableList = throwableList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebsocketException(Throwable throwable) {
|
public WebSocketException(Throwable throwable) {
|
||||||
this.throwableList = Collections.singletonList(throwable);
|
this.throwableList = Collections.singletonList(throwable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ package org.jivesoftware.smack.websocket;
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
import org.jivesoftware.smack.initializer.UrlInitializer;
|
import org.jivesoftware.smack.initializer.UrlInitializer;
|
||||||
|
|
||||||
public final class WebsocketInitializer extends UrlInitializer {
|
public final class WebSocketInitializer extends UrlInitializer {
|
||||||
|
|
||||||
static {
|
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.packet.TopLevelStreamElement;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
||||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints;
|
||||||
import org.jivesoftware.smack.websocket.elements.WebsocketCloseElement;
|
import org.jivesoftware.smack.websocket.elements.WebSocketCloseElement;
|
||||||
import org.jivesoftware.smack.websocket.elements.WebsocketOpenElement;
|
import org.jivesoftware.smack.websocket.elements.WebSocketOpenElement;
|
||||||
import org.jivesoftware.smack.websocket.implementations.AbstractWebsocket;
|
import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup.Result;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup.Result;
|
||||||
|
|
||||||
import org.jxmpp.jid.DomainBareJid;
|
import org.jxmpp.jid.DomainBareJid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
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.
|
* The websocket transport module that goes with Smack's modular architecture.
|
||||||
*/
|
*/
|
||||||
public final class XmppWebsocketTransportModule
|
public final class XmppWebSocketTransportModule
|
||||||
extends ModularXmppClientToServerConnectionModule<XmppWebsocketTransportModuleDescriptor> {
|
extends ModularXmppClientToServerConnectionModule<XmppWebSocketTransportModuleDescriptor> {
|
||||||
private final XmppWebsocketTransport websocketTransport;
|
private final XmppWebSocketTransport websocketTransport;
|
||||||
|
|
||||||
private AbstractWebsocket websocket;
|
private AbstractWebSocket websocket;
|
||||||
|
|
||||||
protected XmppWebsocketTransportModule(XmppWebsocketTransportModuleDescriptor moduleDescriptor,
|
protected XmppWebSocketTransportModule(XmppWebSocketTransportModuleDescriptor moduleDescriptor,
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
super(moduleDescriptor, connectionInternal);
|
super(moduleDescriptor, connectionInternal);
|
||||||
|
|
||||||
websocketTransport = new XmppWebsocketTransport(connectionInternal);
|
websocketTransport = new XmppWebSocketTransport(connectionInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected XmppWebsocketTransport getTransport() {
|
protected XmppWebSocketTransport getTransport() {
|
||||||
return websocketTransport;
|
return websocketTransport;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class EstablishingWebsocketConnectionStateDescriptor extends StateDescriptor {
|
static final class EstablishingWebSocketConnectionStateDescriptor extends StateDescriptor {
|
||||||
private EstablishingWebsocketConnectionStateDescriptor() {
|
private EstablishingWebSocketConnectionStateDescriptor() {
|
||||||
super(XmppWebsocketTransportModule.EstablishingWebsocketConnectionState.class);
|
super(XmppWebSocketTransportModule.EstablishingWebSocketConnectionState.class);
|
||||||
addPredeccessor(LookupRemoteConnectionEndpointsStateDescriptor.class);
|
addPredeccessor(LookupRemoteConnectionEndpointsStateDescriptor.class);
|
||||||
addSuccessor(ConnectedButUnauthenticatedStateDescriptor.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");
|
declareInferiorityTo("org.jivesoftware.smack.tcp.XmppTcpTransportModule$EstablishingTcpConnectionStateDescriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected State constructState(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
protected State constructState(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
XmppWebsocketTransportModule websocketTransportModule = connectionInternal.connection.getConnectionModuleFor(
|
XmppWebSocketTransportModule websocketTransportModule = connectionInternal.connection.getConnectionModuleFor(
|
||||||
XmppWebsocketTransportModuleDescriptor.class);
|
XmppWebSocketTransportModuleDescriptor.class);
|
||||||
return websocketTransportModule.constructEstablishingWebsocketConnectionState(this, connectionInternal);
|
return websocketTransportModule.constructEstablishingWebSocketConnectionState(this, connectionInternal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class EstablishingWebsocketConnectionState extends State {
|
final class EstablishingWebSocketConnectionState extends State {
|
||||||
protected EstablishingWebsocketConnectionState(StateDescriptor stateDescriptor,
|
protected EstablishingWebSocketConnectionState(StateDescriptor stateDescriptor,
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
super(stateDescriptor, connectionInternal);
|
super(stateDescriptor, connectionInternal);
|
||||||
}
|
}
|
||||||
|
@ -110,78 +110,78 @@ public final class XmppWebsocketTransportModule
|
||||||
@Override
|
@Override
|
||||||
public AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext)
|
public AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext)
|
||||||
throws IOException, SmackException, InterruptedException, XMPPException {
|
throws IOException, SmackException, InterruptedException, XMPPException {
|
||||||
WebsocketConnectionAttemptState connectionAttemptState = new WebsocketConnectionAttemptState(
|
WebSocketConnectionAttemptState connectionAttemptState = new WebSocketConnectionAttemptState(
|
||||||
connectionInternal, discoveredWebsocketEndpoints, this);
|
connectionInternal, discoveredWebSocketEndpoints, this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
websocket = connectionAttemptState.establishWebsocketConnection();
|
websocket = connectionAttemptState.establishWebSocketConnection();
|
||||||
} catch (InterruptedException | WebsocketException e) {
|
} catch (InterruptedException | WebSocketException e) {
|
||||||
StateTransitionResult.Failure failure = new StateTransitionResult.FailureCausedByException<Exception>(e);
|
StateTransitionResult.Failure failure = new StateTransitionResult.FailureCausedByException<Exception>(e);
|
||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionInternal.setTransport(websocketTransport);
|
connectionInternal.setTransport(websocketTransport);
|
||||||
|
|
||||||
WebsocketRemoteConnectionEndpoint connectedEndpoint = connectionAttemptState.getConnectedEndpoint();
|
WebSocketRemoteConnectionEndpoint connectedEndpoint = connectionAttemptState.getConnectedEndpoint();
|
||||||
|
|
||||||
// Construct a WebsocketConnectedResult using the connected endpoint.
|
// Construct a WebSocketConnectedResult using the connected endpoint.
|
||||||
return new WebsocketConnectedResult(connectedEndpoint);
|
return new WebSocketConnectedResult(connectedEndpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EstablishingWebsocketConnectionState constructEstablishingWebsocketConnectionState(
|
public EstablishingWebSocketConnectionState constructEstablishingWebSocketConnectionState(
|
||||||
EstablishingWebsocketConnectionStateDescriptor establishingWebsocketConnectionStateDescriptor,
|
EstablishingWebSocketConnectionStateDescriptor establishingWebSocketConnectionStateDescriptor,
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
return new EstablishingWebsocketConnectionState(establishingWebsocketConnectionStateDescriptor,
|
return new EstablishingWebSocketConnectionState(establishingWebSocketConnectionStateDescriptor,
|
||||||
connectionInternal);
|
connectionInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class WebsocketConnectedResult extends StateTransitionResult.Success {
|
public static final class WebSocketConnectedResult extends StateTransitionResult.Success {
|
||||||
final WebsocketRemoteConnectionEndpoint connectedEndpoint;
|
final WebSocketRemoteConnectionEndpoint connectedEndpoint;
|
||||||
|
|
||||||
public WebsocketConnectedResult(WebsocketRemoteConnectionEndpoint connectedEndpoint) {
|
public WebSocketConnectedResult(WebSocketRemoteConnectionEndpoint connectedEndpoint) {
|
||||||
super("Websocket connection establised with endpoint: " + connectedEndpoint.getWebsocketEndpoint());
|
super("WebSocket connection establised with endpoint: " + connectedEndpoint.getWebSocketEndpoint());
|
||||||
this.connectedEndpoint = connectedEndpoint;
|
this.connectedEndpoint = connectedEndpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints;
|
private DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transport class for {@link ModularXmppClientToServerConnectionModule}'s websocket implementation.
|
* Transport class for {@link ModularXmppClientToServerConnectionModule}'s websocket implementation.
|
||||||
*/
|
*/
|
||||||
public final class XmppWebsocketTransport extends XmppClientToServerTransport {
|
public final class XmppWebSocketTransport extends XmppClientToServerTransport {
|
||||||
|
|
||||||
AsyncButOrdered<Queue<TopLevelStreamElement>> asyncButOrderedOutgoingElementsQueue;
|
AsyncButOrdered<Queue<TopLevelStreamElement>> asyncButOrderedOutgoingElementsQueue;
|
||||||
|
|
||||||
protected XmppWebsocketTransport(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
protected XmppWebSocketTransport(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
||||||
super(connectionInternal);
|
super(connectionInternal);
|
||||||
asyncButOrderedOutgoingElementsQueue = new AsyncButOrdered<Queue<TopLevelStreamElement>>();
|
asyncButOrderedOutgoingElementsQueue = new AsyncButOrdered<Queue<TopLevelStreamElement>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetDiscoveredConnectionEndpoints() {
|
protected void resetDiscoveredConnectionEndpoints() {
|
||||||
discoveredWebsocketEndpoints = null;
|
discoveredWebSocketEndpoints = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<SmackFuture<LookupConnectionEndpointsResult, Exception>> lookupConnectionEndpoints() {
|
protected List<SmackFuture<LookupConnectionEndpointsResult, Exception>> lookupConnectionEndpoints() {
|
||||||
// Assert that there are no stale discovered endpoints prior performing the lookup.
|
// Assert that there are no stale discovered endpoints prior performing the lookup.
|
||||||
assert discoveredWebsocketEndpoints == null;
|
assert discoveredWebSocketEndpoints == null;
|
||||||
|
|
||||||
InternalSmackFuture<LookupConnectionEndpointsResult, Exception> websocketEndpointsLookupFuture = new InternalSmackFuture<>();
|
InternalSmackFuture<LookupConnectionEndpointsResult, Exception> websocketEndpointsLookupFuture = new InternalSmackFuture<>();
|
||||||
|
|
||||||
connectionInternal.asyncGo(() -> {
|
connectionInternal.asyncGo(() -> {
|
||||||
|
|
||||||
WebsocketRemoteConnectionEndpoint providedEndpoint = null;
|
WebSocketRemoteConnectionEndpoint providedEndpoint = null;
|
||||||
|
|
||||||
// Check if there is a websocket endpoint already configured.
|
// Check if there is a websocket endpoint already configured.
|
||||||
URI uri = moduleDescriptor.getExplicitlyProvidedUri();
|
URI uri = moduleDescriptor.getExplicitlyProvidedUri();
|
||||||
if (uri != null) {
|
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.
|
// If discovery is disabled, assert that the provided endpoint isn't null.
|
||||||
assert providedEndpoint != null;
|
assert providedEndpoint != null;
|
||||||
|
|
||||||
|
@ -190,14 +190,14 @@ public final class XmppWebsocketTransportModule
|
||||||
mode.equals(SecurityMode.disabled))
|
mode.equals(SecurityMode.disabled))
|
||||||
|| (!providedEndpoint.isSecureEndpoint() &&
|
|| (!providedEndpoint.isSecureEndpoint() &&
|
||||||
mode.equals(SecurityMode.required))) {
|
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);
|
+ " does not comply with the configured security mode: " + mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Result for explicitly configured endpoint.
|
// Generate Result for explicitly configured endpoint.
|
||||||
Result manualResult = new Result(Arrays.asList(providedEndpoint), null);
|
Result manualResult = new Result(Arrays.asList(providedEndpoint), null);
|
||||||
|
|
||||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebsocketEndpoints(manualResult);
|
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebSocketEndpoints(manualResult);
|
||||||
|
|
||||||
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,14 +206,14 @@ public final class XmppWebsocketTransportModule
|
||||||
SecurityMode mode = configuration.getSecurityMode();
|
SecurityMode mode = configuration.getSecurityMode();
|
||||||
|
|
||||||
// Fetch remote endpoints.
|
// 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.
|
// Generate result considering both manual and fetched endpoints.
|
||||||
Result finalResult = new Result(discoveredEndpoints, xep0156result.getLookupFailures());
|
Result finalResult = new Result(discoveredEndpoints, xep0156result.getLookupFailures());
|
||||||
|
|
||||||
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebsocketEndpoints(finalResult);
|
LookupConnectionEndpointsResult endpointsResult = new DiscoveredWebSocketEndpoints(finalResult);
|
||||||
|
|
||||||
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
websocketEndpointsLookupFuture.setResult(endpointsResult);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ public final class XmppWebsocketTransportModule
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadConnectionEndpoints(LookupConnectionEndpointsSuccess lookupConnectionEndpointsSuccess) {
|
protected void loadConnectionEndpoints(LookupConnectionEndpointsSuccess lookupConnectionEndpointsSuccess) {
|
||||||
discoveredWebsocketEndpoints = (DiscoveredWebsocketEndpoints) lookupConnectionEndpointsSuccess;
|
discoveredWebSocketEndpoints = (DiscoveredWebSocketEndpoints) lookupConnectionEndpointsSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -233,7 +233,7 @@ public final class XmppWebsocketTransportModule
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void disconnect() {
|
protected void disconnect() {
|
||||||
websocket.disconnect(1000, "Websocket closed normally");
|
websocket.disconnect(1000, "WebSocket closed normally");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -272,7 +272,7 @@ public final class XmppWebsocketTransportModule
|
||||||
@Override
|
@Override
|
||||||
public AbstractStreamOpen createStreamOpen(CharSequence to, CharSequence from, String id, String lang) {
|
public AbstractStreamOpen createStreamOpen(CharSequence to, CharSequence from, String id, String lang) {
|
||||||
try {
|
try {
|
||||||
return new WebsocketOpenElement(JidCreate.domainBareFrom(to));
|
return new WebSocketOpenElement(JidCreate.domainBareFrom(to));
|
||||||
} catch (XmppStringprepException e) {
|
} catch (XmppStringprepException e) {
|
||||||
Logger.getAnonymousLogger().log(Level.WARNING, "Couldn't create OpenElement", e);
|
Logger.getAnonymousLogger().log(Level.WARNING, "Couldn't create OpenElement", e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -280,7 +280,7 @@ public final class XmppWebsocketTransportModule
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public AbstractStreamClose createStreamClose() {
|
public AbstractStreamClose createStreamClose() {
|
||||||
return new WebsocketCloseElement();
|
return new WebSocketCloseElement();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -288,15 +288,15 @@ public final class XmppWebsocketTransportModule
|
||||||
/**
|
/**
|
||||||
* Contains {@link Result} for successfully discovered endpoints.
|
* Contains {@link Result} for successfully discovered endpoints.
|
||||||
*/
|
*/
|
||||||
public final class DiscoveredWebsocketEndpoints implements LookupConnectionEndpointsSuccess {
|
public final class DiscoveredWebSocketEndpoints implements LookupConnectionEndpointsSuccess {
|
||||||
final WebsocketRemoteConnectionEndpointLookup.Result result;
|
final WebSocketRemoteConnectionEndpointLookup.Result result;
|
||||||
|
|
||||||
DiscoveredWebsocketEndpoints(Result result) {
|
DiscoveredWebSocketEndpoints(Result result) {
|
||||||
assert result != null;
|
assert result != null;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebsocketRemoteConnectionEndpointLookup.Result getResult() {
|
public WebSocketRemoteConnectionEndpointLookup.Result getResult() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,11 +305,11 @@ public final class XmppWebsocketTransportModule
|
||||||
* Contains list of {@link RemoteConnectionEndpointLookupFailure} when no endpoint
|
* Contains list of {@link RemoteConnectionEndpointLookupFailure} when no endpoint
|
||||||
* could be found during http lookup.
|
* could be found during http lookup.
|
||||||
*/
|
*/
|
||||||
final class WebsocketEndpointsDiscoveryFailed implements LookupConnectionEndpointsFailed {
|
final class WebSocketEndpointsDiscoveryFailed implements LookupConnectionEndpointsFailed {
|
||||||
final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
||||||
|
|
||||||
WebsocketEndpointsDiscoveryFailed(
|
WebSocketEndpointsDiscoveryFailed(
|
||||||
WebsocketRemoteConnectionEndpointLookup.Result result) {
|
WebSocketRemoteConnectionEndpointLookup.Result result) {
|
||||||
assert result != null;
|
assert result != null;
|
||||||
lookupFailures = Collections.unmodifiableList(result.lookupFailures);
|
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.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||||
import org.jivesoftware.smack.fsm.StateDescriptor;
|
import org.jivesoftware.smack.fsm.StateDescriptor;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
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>
|
* <br>
|
||||||
* To add {@link XmppWebsocketTransportModule} to {@link ModularXmppClientToServerConnection},
|
* To add {@link XmppWebSocketTransportModule} to {@link ModularXmppClientToServerConnection},
|
||||||
* use {@link ModularXmppClientToServerConnectionConfiguration.Builder#addModule(ModularXmppClientToServerConnectionModuleDescriptor)}.
|
* use {@link ModularXmppClientToServerConnectionConfiguration.Builder#addModule(ModularXmppClientToServerConnectionModuleDescriptor)}.
|
||||||
*/
|
*/
|
||||||
public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppClientToServerConnectionModuleDescriptor {
|
public final class XmppWebSocketTransportModuleDescriptor extends ModularXmppClientToServerConnectionModuleDescriptor {
|
||||||
private boolean performWebsocketEndpointDiscovery;
|
private boolean performWebSocketEndpointDiscovery;
|
||||||
private URI uri;
|
private URI uri;
|
||||||
|
|
||||||
public XmppWebsocketTransportModuleDescriptor(Builder builder) {
|
public XmppWebSocketTransportModuleDescriptor(Builder builder) {
|
||||||
this.performWebsocketEndpointDiscovery = builder.performWebsocketEndpointDiscovery;
|
this.performWebSocketEndpointDiscovery = builder.performWebSocketEndpointDiscovery;
|
||||||
this.uri = builder.uri;
|
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.
|
* Returns true if websocket endpoint discovery is true, returns false otherwise.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public boolean isWebsocketEndpointDiscoveryEnabled() {
|
public boolean isWebSocketEndpointDiscoveryEnabled() {
|
||||||
return performWebsocketEndpointDiscovery;
|
return performWebSocketEndpointDiscovery;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,14 +64,14 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
||||||
@Override
|
@Override
|
||||||
protected Set<Class<? extends StateDescriptor>> getStateDescriptors() {
|
protected Set<Class<? extends StateDescriptor>> getStateDescriptors() {
|
||||||
Set<Class<? extends StateDescriptor>> res = new HashSet<>();
|
Set<Class<? extends StateDescriptor>> res = new HashSet<>();
|
||||||
res.add(EstablishingWebsocketConnectionStateDescriptor.class);
|
res.add(EstablishingWebSocketConnectionStateDescriptor.class);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> constructXmppConnectionModule(
|
protected ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> constructXmppConnectionModule(
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
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>
|
* <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>
|
* <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>
|
* <br>
|
||||||
* Use {@link Builder#explicitlySetWebsocketEndpointAndDiscovery(URI, boolean)} to configure endpoint and disallow websocket endpoint discovery through http lookup.
|
* 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.
|
* By default, {@link Builder#performWebSocketEndpointDiscovery} is set to true.
|
||||||
* <br>
|
* <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 {
|
public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder {
|
||||||
private boolean performWebsocketEndpointDiscovery = true;
|
private boolean performWebSocketEndpointDiscovery = true;
|
||||||
private URI uri;
|
private URI uri;
|
||||||
|
|
||||||
private Builder(
|
private Builder(
|
||||||
|
@ -106,31 +106,31 @@ public final class XmppWebsocketTransportModuleDescriptor extends ModularXmppCli
|
||||||
super(connectionConfigurationBuilder);
|
super(connectionConfigurationBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder explicitlySetWebsocketEndpoint(URI endpoint) {
|
public Builder explicitlySetWebSocketEndpoint(URI endpoint) {
|
||||||
return explicitlySetWebsocketEndpointAndDiscovery(endpoint, true);
|
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");
|
Objects.requireNonNull(endpoint, "Provided endpoint URI must not be null");
|
||||||
this.uri = endpoint;
|
this.uri = endpoint;
|
||||||
this.performWebsocketEndpointDiscovery = performWebsocketEndpointDiscovery;
|
this.performWebSocketEndpointDiscovery = performWebSocketEndpointDiscovery;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder explicitlySetWebsocketEndpoint(CharSequence endpoint) throws URISyntaxException {
|
public Builder explicitlySetWebSocketEndpoint(CharSequence endpoint) throws URISyntaxException {
|
||||||
URI endpointUri = new URI(endpoint.toString());
|
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 {
|
throws URISyntaxException {
|
||||||
URI endpointUri = new URI(endpoint.toString());
|
URI endpointUri = new URI(endpoint.toString());
|
||||||
return explicitlySetWebsocketEndpointAndDiscovery(endpointUri, performWebsocketEndpointDiscovery);
|
return explicitlySetWebSocketEndpointAndDiscovery(endpointUri, performWebSocketEndpointDiscovery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModularXmppClientToServerConnectionModuleDescriptor build() {
|
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;
|
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";
|
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||||
private static final String VERSION = "1.0";
|
private static final String VERSION = "1.0";
|
||||||
private final DomainBareJid to;
|
private final DomainBareJid to;
|
||||||
|
|
||||||
public AbstractWebsocketNonza(DomainBareJid jid) {
|
public AbstractWebSocketNonza(DomainBareJid jid) {
|
||||||
this.to = jid;
|
this.to = jid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,12 @@ import org.jivesoftware.smack.packet.AbstractStreamClose;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
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 ELEMENT = "close";
|
||||||
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||||
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||||
|
|
||||||
public WebsocketCloseElement() {
|
public WebSocketCloseElement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -25,12 +25,12 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
import org.jxmpp.jid.DomainBareJid;
|
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 ELEMENT = "open";
|
||||||
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-framing";
|
||||||
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||||
|
|
||||||
public WebsocketOpenElement(DomainBareJid to) {
|
public WebSocketOpenElement(DomainBareJid to) {
|
||||||
super(to, null, null, null, StreamContentNamespace.client);
|
super(to, null, null, null, StreamContentNamespace.client);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.websocket.implementations;
|
package org.jivesoftware.smack.websocket.impl;
|
||||||
|
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.TopLevelStreamElement;
|
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,
|
openFrameSent,
|
||||||
exchangingTopLevelStreamElements
|
exchangingTopLevelStreamElements
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public abstract class AbstractWebsocket {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void connect(WebsocketRemoteConnectionEndpoint endpoint) throws Throwable;
|
public abstract void connect(WebSocketRemoteConnectionEndpoint endpoint) throws Throwable;
|
||||||
|
|
||||||
public abstract void send(TopLevelStreamElement element);
|
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.
|
* 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.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Websocket related classes for Smack.
|
* WebSocket related classes for Smack.
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.websocket;
|
package org.jivesoftware.smack.websocket;
|
||||||
|
|
|
@ -28,17 +28,17 @@ import java.util.logging.Logger;
|
||||||
import org.jivesoftware.smack.datatypes.UInt16;
|
import org.jivesoftware.smack.datatypes.UInt16;
|
||||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpoint;
|
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 static final Logger LOGGER = Logger.getAnonymousLogger();
|
||||||
|
|
||||||
private final URI uri;
|
private final URI uri;
|
||||||
|
|
||||||
public WebsocketRemoteConnectionEndpoint(String uri) throws URISyntaxException {
|
public WebSocketRemoteConnectionEndpoint(String uri) throws URISyntaxException {
|
||||||
this(new URI(uri));
|
this(new URI(uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebsocketRemoteConnectionEndpoint(URI uri) {
|
public WebSocketRemoteConnectionEndpoint(URI uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
String scheme = uri.getScheme();
|
String scheme = uri.getScheme();
|
||||||
if (!(scheme.equals("ws") || scheme.equals("wss"))) {
|
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;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,11 @@ import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import org.jxmpp.jid.DomainBareJid;
|
import org.jxmpp.jid.DomainBareJid;
|
||||||
|
|
||||||
public final class WebsocketRemoteConnectionEndpointLookup {
|
public final class WebSocketRemoteConnectionEndpointLookup {
|
||||||
|
|
||||||
public static Result lookup(DomainBareJid domainBareJid, SecurityMode securityMode) {
|
public static Result lookup(DomainBareJid domainBareJid, SecurityMode securityMode) {
|
||||||
List<RemoteConnectionEndpointLookupFailure> lookupFailures = new ArrayList<>(1);
|
List<RemoteConnectionEndpointLookupFailure> lookupFailures = new ArrayList<>(1);
|
||||||
List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints = new ArrayList<>();
|
||||||
|
|
||||||
List<URI> rcUriList = null;
|
List<URI> rcUriList = null;
|
||||||
try {
|
try {
|
||||||
|
@ -52,11 +52,11 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
||||||
throw new IllegalStateException("No endpoints were found inside host-meta");
|
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();
|
Iterator<URI> iterator = rcUriList.iterator();
|
||||||
List<WebsocketRemoteConnectionEndpoint> rceList = new ArrayList<>();
|
List<WebSocketRemoteConnectionEndpoint> rceList = new ArrayList<>();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
rceList.add(new WebsocketRemoteConnectionEndpoint(iterator.next()));
|
rceList.add(new WebSocketRemoteConnectionEndpoint(iterator.next()));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (securityMode) {
|
switch (securityMode) {
|
||||||
|
@ -64,9 +64,9 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
||||||
// If security mode equals `if-possible`, give priority to secure endpoints over insecure endpoints.
|
// If security mode equals `if-possible`, give priority to secure endpoints over insecure endpoints.
|
||||||
|
|
||||||
// Seprate secure and unsecure endpoints.
|
// Seprate secure and unsecure endpoints.
|
||||||
List<WebsocketRemoteConnectionEndpoint> secureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
List<WebSocketRemoteConnectionEndpoint> secureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||||
List<WebsocketRemoteConnectionEndpoint> insecureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
List<WebSocketRemoteConnectionEndpoint> insecureEndpointsForSecurityModeIfPossible = new ArrayList<>();
|
||||||
for (WebsocketRemoteConnectionEndpoint uri : rceList) {
|
for (WebSocketRemoteConnectionEndpoint uri : rceList) {
|
||||||
if (uri.isSecureEndpoint()) {
|
if (uri.isSecureEndpoint()) {
|
||||||
secureEndpointsForSecurityModeIfPossible.add(uri);
|
secureEndpointsForSecurityModeIfPossible.add(uri);
|
||||||
} else {
|
} 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 required, accept wss endpoints (secure endpoints) only or,
|
||||||
* if SecurityMode equals to disabled, accept ws endpoints (unsecure endpoints) only.
|
* 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())
|
if ((securityMode.equals(SecurityMode.disabled) && !uri.isSecureEndpoint())
|
||||||
|| (securityMode.equals(SecurityMode.required) && uri.isSecureEndpoint())) {
|
|| (securityMode.equals(SecurityMode.required) && uri.isSecureEndpoint())) {
|
||||||
discoveredRemoteConnectionEndpoints.add(uri);
|
discoveredRemoteConnectionEndpoints.add(uri);
|
||||||
|
@ -95,16 +95,16 @@ public final class WebsocketRemoteConnectionEndpointLookup {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Result {
|
public static final class Result {
|
||||||
public final List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints;
|
public final List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints;
|
||||||
public final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
public final List<RemoteConnectionEndpointLookupFailure> lookupFailures;
|
||||||
|
|
||||||
public Result(List<WebsocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints,
|
public Result(List<WebSocketRemoteConnectionEndpoint> discoveredRemoteConnectionEndpoints,
|
||||||
List<RemoteConnectionEndpointLookupFailure> lookupFailures) {
|
List<RemoteConnectionEndpointLookupFailure> lookupFailures) {
|
||||||
this.discoveredRemoteConnectionEndpoints = discoveredRemoteConnectionEndpoints;
|
this.discoveredRemoteConnectionEndpoints = discoveredRemoteConnectionEndpoints;
|
||||||
this.lookupFailures = lookupFailures;
|
this.lookupFailures = lookupFailures;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WebsocketRemoteConnectionEndpoint> getDiscoveredRemoteConnectionEndpoints() {
|
public List<WebSocketRemoteConnectionEndpoint> getDiscoveredRemoteConnectionEndpoints() {
|
||||||
return discoveredRemoteConnectionEndpoints;
|
return discoveredRemoteConnectionEndpoints;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class WebsocketConnectionAttemptStateTest {
|
public class WebSocketConnectionAttemptStateTest {
|
||||||
@Test
|
@Test
|
||||||
public void constructorTest() {
|
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;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class WebsocketInitializerTest {
|
public class WebSocketInitializerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testExtensionInitializer() {
|
public void testExtensionInitializer() {
|
||||||
WebsocketInitializer initializer = new WebsocketInitializer();
|
WebSocketInitializer initializer = new WebSocketInitializer();
|
||||||
List<Exception> exceptions = initializer.initialize();
|
List<Exception> exceptions = initializer.initialize();
|
||||||
assertTrue(exceptions.size() == 0);
|
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.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
||||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure;
|
||||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure.HttpLookupFailure;
|
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpointLookupFailure.HttpLookupFailure;
|
||||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.DiscoveredWebsocketEndpoints;
|
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.DiscoveredWebSocketEndpoints;
|
||||||
import org.jivesoftware.smack.websocket.XmppWebsocketTransportModule.XmppWebsocketTransport.WebsocketEndpointsDiscoveryFailed;
|
import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.XmppWebSocketTransport.WebSocketEndpointsDiscoveryFailed;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpoint;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
|
||||||
import org.jivesoftware.smack.websocket.rce.WebsocketRemoteConnectionEndpointLookup.Result;
|
import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpointLookup.Result;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
|
|
||||||
public class XmppWebsocketTransportModuleTest {
|
public class XmppWebSocketTransportModuleTest {
|
||||||
@Test
|
@Test
|
||||||
public void createWebsocketModuleConnectionInstanceTest() throws URISyntaxException, XmppStringprepException {
|
public void createWebSocketModuleConnectionInstanceTest() throws URISyntaxException, XmppStringprepException {
|
||||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
||||||
.builder();
|
.builder();
|
||||||
|
|
||||||
builder.removeAllModules();
|
builder.removeAllModules();
|
||||||
builder.addModule(XmppWebsocketTransportModuleDescriptor.class);
|
builder.addModule(XmppWebSocketTransportModuleDescriptor.class);
|
||||||
builder.setXmppAddressAndPassword("user5@localhost.org", "user5");
|
builder.setXmppAddressAndPassword("user5@localhost.org", "user5");
|
||||||
builder.setHost("localhost.org");
|
builder.setHost("localhost.org");
|
||||||
|
|
||||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||||
|
|
||||||
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
ModularXmppClientToServerConnectionConfiguration config = builder.build();
|
||||||
ModularXmppClientToServerConnection connection = new ModularXmppClientToServerConnection(config);
|
ModularXmppClientToServerConnection connection = new ModularXmppClientToServerConnection(config);
|
||||||
|
@ -60,26 +60,26 @@ public class XmppWebsocketTransportModuleTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createDescriptorTest() throws URISyntaxException, XmppStringprepException {
|
public void createDescriptorTest() throws URISyntaxException, XmppStringprepException {
|
||||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||||
assertNotNull(websocketTransportModuleDescriptor);
|
assertNotNull(websocketTransportModuleDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void websocketEndpointDiscoveryTest() throws URISyntaxException {
|
public void websocketEndpointDiscoveryTest() throws URISyntaxException {
|
||||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||||
|
|
||||||
XmppWebsocketTransportModule transportModule
|
XmppWebSocketTransportModule transportModule
|
||||||
= new XmppWebsocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
= 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 DiscoveredWebSocketEndpoints(null));
|
||||||
assertThrows(AssertionError.class, () -> transport.new WebsocketEndpointsDiscoveryFailed(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);
|
discoveredRemoteConnectionEndpoints.add(endpoint);
|
||||||
|
|
||||||
HttpLookupFailure httpLookupFailure = new RemoteConnectionEndpointLookupFailure.HttpLookupFailure(null, null);
|
HttpLookupFailure httpLookupFailure = new RemoteConnectionEndpointLookupFailure.HttpLookupFailure(null, null);
|
||||||
|
@ -87,38 +87,38 @@ public class XmppWebsocketTransportModuleTest {
|
||||||
failureList.add(httpLookupFailure);
|
failureList.add(httpLookupFailure);
|
||||||
Result result = new Result(discoveredRemoteConnectionEndpoints, failureList);
|
Result result = new Result(discoveredRemoteConnectionEndpoints, failureList);
|
||||||
|
|
||||||
DiscoveredWebsocketEndpoints discoveredWebsocketEndpoints = transport.new DiscoveredWebsocketEndpoints(result);
|
DiscoveredWebSocketEndpoints discoveredWebSocketEndpoints = transport.new DiscoveredWebSocketEndpoints(result);
|
||||||
assertNotNull(discoveredWebsocketEndpoints.getResult());
|
assertNotNull(discoveredWebSocketEndpoints.getResult());
|
||||||
|
|
||||||
WebsocketEndpointsDiscoveryFailed endpointsDiscoveryFailed = transport.new WebsocketEndpointsDiscoveryFailed(result);
|
WebSocketEndpointsDiscoveryFailed endpointsDiscoveryFailed = transport.new WebSocketEndpointsDiscoveryFailed(result);
|
||||||
assertNotNull(endpointsDiscoveryFailed.toString());
|
assertNotNull(endpointsDiscoveryFailed.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void websocketConnectedResultTest() throws URISyntaxException {
|
public void websocketConnectedResultTest() throws URISyntaxException {
|
||||||
WebsocketRemoteConnectionEndpoint connectedEndpoint = new WebsocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
WebSocketRemoteConnectionEndpoint connectedEndpoint = new WebSocketRemoteConnectionEndpoint("wss://localhost.org:7443/ws/");
|
||||||
assertNotNull(new XmppWebsocketTransportModule.WebsocketConnectedResult(connectedEndpoint));
|
assertNotNull(new XmppWebSocketTransportModule.WebSocketConnectedResult(connectedEndpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupConnectionEndpointsTest() throws URISyntaxException {
|
public void lookupConnectionEndpointsTest() throws URISyntaxException {
|
||||||
XmppWebsocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebsocketDescriptor();
|
XmppWebSocketTransportModuleDescriptor websocketTransportModuleDescriptor = getWebSocketDescriptor();
|
||||||
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
ModularXmppClientToServerConnectionInternal connectionInternal = mock(ModularXmppClientToServerConnectionInternal.class);
|
||||||
|
|
||||||
XmppWebsocketTransportModule transportModule
|
XmppWebSocketTransportModule transportModule
|
||||||
= new XmppWebsocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
= new XmppWebSocketTransportModule(websocketTransportModuleDescriptor, connectionInternal);
|
||||||
|
|
||||||
XmppWebsocketTransportModule.XmppWebsocketTransport transport = transportModule.getTransport();
|
XmppWebSocketTransportModule.XmppWebSocketTransport transport = transportModule.getTransport();
|
||||||
assertNotNull(transport.lookupConnectionEndpoints());
|
assertNotNull(transport.lookupConnectionEndpoints());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static XmppWebsocketTransportModuleDescriptor getWebsocketDescriptor() throws URISyntaxException {
|
private static XmppWebSocketTransportModuleDescriptor getWebSocketDescriptor() throws URISyntaxException {
|
||||||
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration
|
||||||
.builder();
|
.builder();
|
||||||
|
|
||||||
XmppWebsocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebsocketTransportModuleDescriptor.getBuilder(builder);
|
XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder);
|
||||||
websocketBuilder.explicitlySetWebsocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(new URI("wss://localhost.org:7443/ws/"), false);
|
||||||
return (XmppWebsocketTransportModuleDescriptor) websocketBuilder.build();
|
return (XmppWebSocketTransportModuleDescriptor) websocketBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,20 +23,20 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
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 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'/>";
|
private static final String CLOSE_ELEMENT = "<close xmlns='urn:ietf:params:xml:ns:xmpp-framing'/>";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void websocketOpenElementTest() throws XmppStringprepException {
|
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);
|
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
|
@Test
|
||||||
public void websocketCloseElementTest() throws XmppStringprepException {
|
public void websocketCloseElementTest() throws XmppStringprepException {
|
||||||
String closeElementXml = new WebsocketCloseElement().toXML().toString();
|
String closeElementXml = new WebSocketCloseElement().toXML().toString();
|
||||||
assertXmlSimilar(CLOSE_ELEMENT, closeElementXml);
|
assertXmlSimilar(CLOSE_ELEMENT, closeElementXml);
|
||||||
assertXmlNotSimilar(OPEN_ELEMENT, closeElementXml);
|
assertXmlNotSimilar(OPEN_ELEMENT, closeElementXml);
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
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;
|
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_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 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'/>";
|
private static final String CLOSE_ELEMENT = "<close xmlns='urn:ietf:params:xml:ns:xmpp-framing'/>";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getStreamFromOpenElementTest() {
|
public void getStreamFromOpenElementTest() {
|
||||||
String generatedOpenStream = AbstractWebsocket.getStreamFromOpenElement(OPEN_ELEMENT);
|
String generatedOpenStream = AbstractWebSocket.getStreamFromOpenElement(OPEN_ELEMENT);
|
||||||
assertEquals(generatedOpenStream, OPEN_STREAM);
|
assertEquals(generatedOpenStream, OPEN_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isOpenElementTest() {
|
public void isOpenElementTest() {
|
||||||
assertTrue(AbstractWebsocket.isOpenElement(OPEN_ELEMENT));
|
assertTrue(AbstractWebSocket.isOpenElement(OPEN_ELEMENT));
|
||||||
assertFalse(AbstractWebsocket.isOpenElement(OPEN_STREAM));
|
assertFalse(AbstractWebSocket.isOpenElement(OPEN_STREAM));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isCloseElementTest() {
|
public void isCloseElementTest() {
|
||||||
assertTrue(AbstractWebsocket.isCloseElement(CLOSE_ELEMENT));
|
assertTrue(AbstractWebSocket.isCloseElement(CLOSE_ELEMENT));
|
||||||
assertFalse(AbstractWebsocket.isCloseElement(OPEN_STREAM));
|
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;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class WebsocketRemoteConnectionEndpointTest {
|
public class WebSocketRemoteConnectionEndpointTest {
|
||||||
@Test
|
@Test
|
||||||
public void endpointTest() throws URISyntaxException {
|
public void endpointTest() throws URISyntaxException {
|
||||||
String endpointString = "ws://fooDomain.org:7070/ws/";
|
String endpointString = "ws://fooDomain.org:7070/ws/";
|
||||||
WebsocketRemoteConnectionEndpoint endpoint = new WebsocketRemoteConnectionEndpoint(endpointString);
|
WebSocketRemoteConnectionEndpoint endpoint = new WebSocketRemoteConnectionEndpoint(endpointString);
|
||||||
assertEquals("fooDomain.org", endpoint.getHost());
|
assertEquals("fooDomain.org", endpoint.getHost());
|
||||||
assertEquals(UInt16.from(7070), endpoint.getPort());
|
assertEquals(UInt16.from(7070), endpoint.getPort());
|
||||||
assertEquals(endpointString, endpoint.getWebsocketEndpoint().toString());
|
assertEquals(endpointString, endpoint.getWebSocketEndpoint().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void faultyEndpointTest() {
|
public void faultyEndpointTest() {
|
||||||
String faultyProtocolString = "wst://fooDomain.org:7070/ws/";
|
String faultyProtocolString = "wst://fooDomain.org:7070/ws/";
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
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