XmppWebSocketTransportModuleDescriptor.java

  1. /**
  2.  *
  3.  * Copyright 2020 Aditya Borikar, 2020-2021 Florian Schmaus
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.websocket;

  18. import java.net.URI;
  19. import java.net.URISyntaxException;
  20. import java.util.HashSet;
  21. import java.util.Set;

  22. import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
  23. import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection;
  24. import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfiguration;
  25. import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionModule;
  26. import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionModuleDescriptor;
  27. import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
  28. import org.jivesoftware.smack.fsm.StateDescriptor;
  29. import org.jivesoftware.smack.util.Objects;
  30. import org.jivesoftware.smack.websocket.XmppWebSocketTransportModule.EstablishingWebSocketConnectionStateDescriptor;
  31. import org.jivesoftware.smack.websocket.impl.WebSocketFactory;
  32. import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;

  33. /**
  34.  * The descriptor class for {@link XmppWebSocketTransportModule}.
  35.  * <br>
  36.  * To add {@link XmppWebSocketTransportModule} to {@link ModularXmppClientToServerConnection},
  37.  * use {@link ModularXmppClientToServerConnectionConfiguration.Builder#addModule(ModularXmppClientToServerConnectionModuleDescriptor)}.
  38.  */
  39. public final class XmppWebSocketTransportModuleDescriptor extends ModularXmppClientToServerConnectionModuleDescriptor {
  40.     private final boolean performWebSocketEndpointDiscovery;
  41.     private final boolean implicitWebSocketEndpoint;
  42.     private final WebSocketRemoteConnectionEndpoint wsRce;

  43.     final WebSocketFactory webSocketFactory;

  44.     public XmppWebSocketTransportModuleDescriptor(Builder builder) {
  45.         this.performWebSocketEndpointDiscovery = builder.performWebSocketEndpointDiscovery;
  46.         this.implicitWebSocketEndpoint = builder.implicitWebSocketEndpoint;
  47.         this.webSocketFactory = builder.webSocketFactory;

  48.         URI uri = builder.uri;
  49.         if (uri != null) {
  50.             wsRce = WebSocketRemoteConnectionEndpoint.from(uri);
  51.         } else {
  52.             wsRce = null;
  53.         }
  54.     }

  55.     @Override
  56.     @SuppressWarnings({"incomplete-switch", "MissingCasesInEnumSwitch"})
  57.     protected void validateConfiguration(ModularXmppClientToServerConnectionConfiguration configuration) {
  58.         if (wsRce == null) {
  59.             return;
  60.         }

  61.         SecurityMode securityMode = configuration.getSecurityMode();
  62.         switch (securityMode) {
  63.         case required:
  64.             if (!wsRce.isSecureEndpoint()) {
  65.                 throw new IllegalArgumentException("The provided WebSocket endpoint " + wsRce + " is not a secure endpoint, but the connection configuration requires secure endpoints");
  66.             }
  67.             break;
  68.         case disabled:
  69.             if (wsRce.isSecureEndpoint()) {
  70.                 throw new IllegalArgumentException("The provided WebSocket endpoint " + wsRce + " is a secure endpoint, but the connection configuration has security disabled");
  71.             }
  72.             break;
  73.         }
  74.     }

  75.     /**
  76.      * Returns true if websocket endpoint discovery is true, returns false otherwise.
  77.      * @return boolean
  78.      */
  79.     public boolean isWebSocketEndpointDiscoveryEnabled() {
  80.         return performWebSocketEndpointDiscovery;
  81.     }

  82.     public boolean isImplicitWebSocketEndpointEnabled() {
  83.         return implicitWebSocketEndpoint;
  84.     }

  85.     /**
  86.      * Returns explicitly configured websocket endpoint uri.
  87.      * @return uri
  88.      */
  89.     public URI getExplicitlyProvidedUri() {
  90.         return wsRce.getUri();
  91.     }

  92.     WebSocketRemoteConnectionEndpoint getExplicitlyProvidedEndpoint() {
  93.         return wsRce;
  94.     }

  95.     @Override
  96.     protected Set<Class<? extends StateDescriptor>> getStateDescriptors() {
  97.         Set<Class<? extends StateDescriptor>> res = new HashSet<>();
  98.         res.add(EstablishingWebSocketConnectionStateDescriptor.class);
  99.         return res;
  100.     }

  101.     @Override
  102.     protected ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> constructXmppConnectionModule(
  103.             ModularXmppClientToServerConnectionInternal connectionInternal) {
  104.         return new XmppWebSocketTransportModule(this, connectionInternal);
  105.     }

  106.     /**
  107.      * Returns a new instance of {@link Builder}.
  108.      * <br>
  109.      * @return Builder
  110.      * @param connectionConfigurationBuilder {@link ModularXmppClientToServerConnectionConfiguration.Builder}.
  111.      */
  112.     public static Builder getBuilder(
  113.             ModularXmppClientToServerConnectionConfiguration.Builder connectionConfigurationBuilder) {
  114.         return new Builder(connectionConfigurationBuilder);
  115.     }

  116.     /**
  117.      * Builder class for {@link XmppWebSocketTransportModuleDescriptor}.
  118.      * <br>
  119.      * To obtain an instance of {@link XmppWebSocketTransportModuleDescriptor.Builder}, use {@link XmppWebSocketTransportModuleDescriptor#getBuilder(ModularXmppClientToServerConnectionConfiguration.Builder)} method.
  120.      * <br>
  121.      * 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.
  122.      * <br>
  123.      * Use {@link Builder#explicitlySetWebSocketEndpointAndDiscovery(URI, boolean)} to configure endpoint and disallow websocket endpoint discovery through http lookup.
  124.      * By default, {@link Builder#performWebSocketEndpointDiscovery} is set to true.
  125.      * <br>
  126.      * Use {@link Builder#build()} to obtain {@link XmppWebSocketTransportModuleDescriptor}.
  127.      */
  128.     public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder {
  129.         private boolean performWebSocketEndpointDiscovery = true;
  130.         private boolean implicitWebSocketEndpoint = true;
  131.         private URI uri;
  132.         private WebSocketFactory webSocketFactory;

  133.         private Builder(
  134.                 ModularXmppClientToServerConnectionConfiguration.Builder connectionConfigurationBuilder) {
  135.             super(connectionConfigurationBuilder);
  136.         }

  137.         public Builder explicitlySetWebSocketEndpoint(URI endpoint) {
  138.             return explicitlySetWebSocketEndpointAndDiscovery(endpoint, true);
  139.         }

  140.         public Builder explicitlySetWebSocketEndpointAndDiscovery(URI endpoint, boolean performWebSocketEndpointDiscovery) {
  141.             Objects.requireNonNull(endpoint, "Provided endpoint URI must not be null");
  142.             this.uri = endpoint;
  143.             this.performWebSocketEndpointDiscovery = performWebSocketEndpointDiscovery;
  144.             return this;
  145.         }

  146.         public Builder explicitlySetWebSocketEndpoint(CharSequence endpoint) throws URISyntaxException {
  147.             URI endpointUri = new URI(endpoint.toString());
  148.             return explicitlySetWebSocketEndpoint(endpointUri);
  149.         }

  150.         public Builder explicitlySetWebSocketEndpointAndDiscovery(CharSequence endpoint, boolean performWebSocketEndpointDiscovery)
  151.                 throws URISyntaxException {
  152.             URI endpointUri = new URI(endpoint.toString());
  153.             return explicitlySetWebSocketEndpointAndDiscovery(endpointUri, performWebSocketEndpointDiscovery);
  154.         }

  155.         public Builder disableImplicitWebsocketEndpoint() {
  156.             implicitWebSocketEndpoint = false;
  157.             return this;
  158.         }

  159.         public Builder setWebSocketFactory(WebSocketFactory webSocketFactory) {
  160.             Objects.requireNonNull(webSocketFactory);
  161.             this.webSocketFactory = webSocketFactory;
  162.             return this;
  163.         }

  164.         @Override
  165.         public ModularXmppClientToServerConnectionModuleDescriptor build() {
  166.             return new XmppWebSocketTransportModuleDescriptor(this);
  167.         }
  168.     }
  169. }