From 9e897d1c97a6f9e71202f61f3eb85bbb632e6f32 Mon Sep 17 00:00:00 2001 From: Sina Madani Date: Tue, 9 May 2023 14:38:08 +0100 Subject: [PATCH] Prepare v4.10.0 release (#240) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Minor fixes in build.gradle * Added support for MultiBroadcastTag and MultiArchiveTag (#226) * Added multiArchiveTag * Added multiBroadcastTag * Updated docs * Removed getMulti*Tag from responses * Revert "Removed getMulti*Tag from responses" This reverts commit 6e7f123c6d1ad402754dda09ca1b7a9c81436de6. * Docs edits re multiArchive/BroadcastTag. Co-authored-by: Jeff Swartz * Add Experience Composer API (#227) * Added startRender * Added listRenders * Deserialize listRenders response to native List * Added stopRender & getRender * Use enum for Render status * Improved RenderProperties * Experience composer docs edits ... And other docs corrections Co-authored-by: Jeff Swartz * Bump dependency versions * Improved release process. bump2version is now manual, but release to Nexus is fully automated. * Ensure version is passed in bumpversion.sh * Bumped dependencies (including WireMock) * Bump version: v4.8.0 → v4.8.1 * Update copyright year * Use wiremock-jre8 * Boost coverage * Boost coverage * Disable codecov temporarily * Revert "Disable codecov temporarily" This reverts commit 613bff0794ff299d1165952a57da903a700136ec. * Add Audio Streamer (lite) API endpoint (#215) * Added Audio Streamer (lite) endpoint * Don't include headers or streams if empty in connect request * Renamed Connect for clarity * Addressed PR comments * Fixed failing test * URI in AudioStreamerConnectionProperties constructor * Docs edits * Bumped dependencies (notably WireMock to 2.x) * Bumped dependencies * Bump dependency versions (#233) Improved release process, bumped dependency versions (including WireMock), slightly improved test coverage, updated copyright year, merged main, ready for release v4.8.1. * Renamed to Audio Connector * Bumped dependencies * Added audio connector to README * Minor docs edits --------- Co-authored-by: Jeff Swartz * Bump version: v4.8.1 → v4.9.0 * Minor docs edit * Enable custom User-Agent (#238) * Add end-to-end encryption support (#237) * Added e2ee support * Added validation for SessionProperties * Only include e2ee if true * Update SessionProperties javadoc Co-authored-by: Jeff Swartz * Minor docs edit --------- Co-authored-by: Jeff Swartz * Bump jackson version * Bump version: v4.9.0 → v4.10.0 --------- Co-authored-by: Jeff Swartz --- .bumpversion.cfg | 2 +- README.md | 4 +- build.gradle | 4 +- src/main/java/com/opentok/OpenTok.java | 23 +++- src/main/java/com/opentok/Session.java | 7 +- .../java/com/opentok/SessionProperties.java | 75 +++++++++---- .../opentok/constants/DefaultUserAgent.java | 13 +++ .../java/com/opentok/constants/Version.java | 2 +- .../java/com/opentok/util/HttpClient.java | 32 +++--- .../java/com/opentok/test/OpenTokTest.java | 102 ++++++++++++++++-- 10 files changed, 206 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/opentok/constants/DefaultUserAgent.java diff --git a/.bumpversion.cfg b/.bumpversion.cfg index f663577e..54ae869e 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,7 +1,7 @@ [bumpversion] commit = True tag = False -current_version = v4.9.0 +current_version = v4.10.0 parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+)(?P\d+))? serialize = {major}.{minor}.{patch}-{release}{build} diff --git a/README.md b/README.md index 84cf0e02..0bdbda12 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ When you use Maven as your build tool, you can manage dependencies in the `pom.x com.tokbox opentok-server-sdk - 4.9.0 + 4.10.0 ``` @@ -44,7 +44,7 @@ When you use Gradle as your build tool, you can manage dependencies in the `buil ```groovy dependencies { - compile group: 'com.tokbox', name: 'opentok-server-sdk', version: '4.9.0' + compile group: 'com.tokbox', name: 'opentok-server-sdk', version: '4.10.0' } ``` diff --git a/build.gradle b/build.gradle index ebe8f69d..c83960e5 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ plugins { group = 'com.tokbox' archivesBaseName = 'opentok-server-sdk' -version = '4.9.0' +version = '4.10.0' sourceCompatibility = "1.8" targetCompatibility = "1.8" @@ -27,7 +27,7 @@ dependencies { implementation 'commons-lang:commons-lang:2.6' implementation 'commons-validator:commons-validator:1.7' implementation 'org.asynchttpclient:async-http-client:2.12.3' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.0' implementation 'commons-codec:commons-codec:1.15' implementation 'org.bitbucket.b_c:jose4j:0.9.3' implementation 'io.netty:netty-handler:4.1.89.Final' diff --git a/src/main/java/com/opentok/OpenTok.java b/src/main/java/com/opentok/OpenTok.java index 95a1b286..da35665d 100644 --- a/src/main/java/com/opentok/OpenTok.java +++ b/src/main/java/com/opentok/OpenTok.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import com.opentok.constants.DefaultUserAgent; import com.opentok.exception.InvalidArgumentException; import com.opentok.exception.OpenTokException; import com.opentok.exception.RequestException; @@ -63,9 +64,7 @@ public class OpenTok { * @param apiSecret Your OpenTok API secret. (See your Vonage Video API account page.) */ public OpenTok(int apiKey, String apiSecret) { - this.apiKey = apiKey; - this.apiSecret = apiSecret.trim(); - this.client = new HttpClient.Builder(apiKey, apiSecret).build(); + this(apiKey, apiSecret, new HttpClient.Builder(apiKey, apiSecret).build()); } private OpenTok(int apiKey, String apiSecret, HttpClient httpClient) { @@ -243,7 +242,7 @@ public String generateToken(String sessionId) throws OpenTokException { */ public Session createSession(SessionProperties properties) throws OpenTokException { final SessionProperties _properties = properties != null ? properties : new SessionProperties.Builder().build(); - final Map> params = _properties.toMap(); + final Map> params = _properties.toMap(); final String response = client.createSession(params); try { @@ -991,6 +990,7 @@ public static class Builder { private int apiKey; private String apiSecret; private String apiUrl; + private String appendUserAgent; private Proxy proxy; private ProxyAuthScheme proxyAuthScheme; private String principal; @@ -1045,6 +1045,18 @@ public Builder proxy(Proxy proxy, ProxyAuthScheme proxyAuthScheme, String princi return this; } + /** + * Append a custom string to the client's User-Agent. This is to enable tracking for custom integrations. + * + * @param appendUserAgent The string to append to the user agent. + * + * @return This Builder with the additional user agent string. + */ + public Builder appendToUserAgent(String appendUserAgent) { + this.appendUserAgent = appendUserAgent; + return this; + } + /** * Builds the OpenTok object with the settings provided to this * Builder object. @@ -1063,6 +1075,9 @@ public OpenTok build() { if (requestTimeout != 0) { clientBuilder.requestTimeoutMS(requestTimeout); } + if (appendUserAgent != null && !appendUserAgent.trim().isEmpty()) { + clientBuilder.userAgent(DefaultUserAgent.DEFAULT_USER_AGENT+" "+appendUserAgent); + } return new OpenTok(apiKey, apiSecret, clientBuilder.build()); } diff --git a/src/main/java/com/opentok/Session.java b/src/main/java/com/opentok/Session.java index 28b14ebd..f78b4c5d 100644 --- a/src/main/java/com/opentok/Session.java +++ b/src/main/java/com/opentok/Session.java @@ -27,17 +27,13 @@ * to get the session ID. */ public class Session { - private String sessionId; private int apiKey; private String apiSecret; private SessionProperties properties; protected Session(String sessionId, int apiKey, String apiSecret) { - this.sessionId = sessionId; - this.apiKey = apiKey; - this.apiSecret = apiSecret; - this.properties = new SessionProperties.Builder().build(); + this(sessionId, apiKey, apiSecret, new SessionProperties.Builder().build()); } protected Session(String sessionId, int apiKey, String apiSecret, SessionProperties properties) { @@ -83,7 +79,6 @@ public SessionProperties getProperties() { * @see #generateToken(TokenOptions tokenOptions) */ public String generateToken() throws OpenTokException { - // NOTE: maybe there should be a static object for the defaultTokenOptions? return this.generateToken(new TokenOptions.Builder().build()); } diff --git a/src/main/java/com/opentok/SessionProperties.java b/src/main/java/com/opentok/SessionProperties.java index f7e6ad9b..55eac725 100644 --- a/src/main/java/com/opentok/SessionProperties.java +++ b/src/main/java/com/opentok/SessionProperties.java @@ -10,10 +10,7 @@ import com.opentok.exception.InvalidArgumentException; import org.apache.commons.validator.routines.InetAddressValidator; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** @@ -23,16 +20,16 @@ * @see OpenTok#createSession(com.opentok.SessionProperties properties) */ public class SessionProperties { - - private String location; private MediaMode mediaMode; private ArchiveMode archiveMode; + private boolean e2ee; private SessionProperties(Builder builder) { this.location = builder.location; this.mediaMode = builder.mediaMode; this.archiveMode = builder.archiveMode; + this.e2ee = builder.e2ee; } /** @@ -41,10 +38,10 @@ private SessionProperties(Builder builder) { * @see SessionProperties */ public static class Builder { - private String location = null; + private String location; private MediaMode mediaMode = MediaMode.RELAYED; private ArchiveMode archiveMode = ArchiveMode.MANUAL; - + private boolean e2ee = false; /** * Call this method to set an IP address that the OpenTok servers will use to @@ -108,7 +105,7 @@ public Builder mediaMode(MediaMode mediaMode) { /** * Call this method to determine whether the session will be automatically archived (ArchiveMode.ALWAYS) * or not (ArchiveMode.MANUAL). - * + *

* Using an always archived session also requires the routed media mode (MediaMode.ROUTED). * * @param archiveMode The Archive mode. @@ -120,19 +117,43 @@ public Builder archiveMode(ArchiveMode archiveMode) { return this; } + /** + * Enables end-to-end encryption for a routed session. + * You must also set {@link #mediaMode(MediaMode)} to {@linkplain MediaMode#ROUTED} when + * calling this method. + * + * @return The SessionProperties.Builder object with the e2ee property set to {@code true}. + */ + public Builder endToEndEncryption() { + this.e2ee = true; + return this; + } + /** * Builds the SessionProperties object. * * @return The SessionProperties object. */ public SessionProperties build() { - // Would throw in this case, but would introduce a backwards incompatible change. - //if (this.archiveMode == ArchiveMode.ALWAYS && this.mediaMode != MediaMode.ROUTED) { - // throw new InvalidArgumentException("A session with always archive mode must also have the routed media mode."); - //} + if (this.archiveMode == ArchiveMode.ALWAYS && this.mediaMode != MediaMode.ROUTED) { + throw new IllegalStateException( + "A session with ALWAYS archive mode must also have the ROUTED media mode." + ); + } + if (e2ee && mediaMode != MediaMode.ROUTED) { + throw new IllegalStateException( + "A session with RELAYED media mode cannot have end-to-end encryption enabled." + ); + } + if (e2ee && archiveMode == ArchiveMode.ALWAYS) { + throw new IllegalStateException( + "A session with ALWAYS archive mode cannot have end-to-end encryption enabled." + ); + } return new SessionProperties(this); } } + /** * The location hint IP address. See {@link SessionProperties.Builder#location(String location)}. */ @@ -158,25 +179,43 @@ public ArchiveMode archiveMode() { return archiveMode; } + /** + * Defines whether the session will use + * end-to-end encryption. + * See {@link com.opentok.SessionProperties.Builder#endToEndEncryption()}. + * + * + * @return {@code true} if end-to-end encryption is enabled, {@code false} otherwise. + */ + public boolean isEndToEndEncrypted() { + return e2ee; + } + /** * Returns the session properties as a Map. */ - public Map> toMap() { - Map> params = new HashMap<>(); + public Map> toMap() { + Map> params = new HashMap<>(); if (null != location) { - ArrayList valueList = new ArrayList<>(); + ArrayList valueList = new ArrayList<>(1); valueList.add(location); params.put("location", valueList); } - ArrayList mediaModeValueList = new ArrayList<>(); + ArrayList mediaModeValueList = new ArrayList<>(1); mediaModeValueList.add(mediaMode.toString()); params.put("p2p.preference", mediaModeValueList); - ArrayList archiveModeValueList = new ArrayList<>(); + ArrayList archiveModeValueList = new ArrayList<>(1); archiveModeValueList.add(archiveMode.toString()); params.put("archiveMode", archiveModeValueList); + if (e2ee) { + ArrayList e2eeValueList = new ArrayList<>(1); + e2eeValueList.add("" + e2ee); + params.put("e2ee", e2eeValueList); + } + return params; } diff --git a/src/main/java/com/opentok/constants/DefaultUserAgent.java b/src/main/java/com/opentok/constants/DefaultUserAgent.java new file mode 100644 index 00000000..51b1b7f4 --- /dev/null +++ b/src/main/java/com/opentok/constants/DefaultUserAgent.java @@ -0,0 +1,13 @@ +/** + * OpenTok Java SDK + * Copyright (C) 2023 Vonage. + * http://www.tokbox.com + * + * Licensed under The MIT License (MIT). See LICENSE file for more information. + */ +package com.opentok.constants; + +public class DefaultUserAgent { + public static final String DEFAULT_USER_AGENT = + "Opentok-Java-SDK/"+Version.VERSION+" JRE/"+System.getProperty("java.version"); +} diff --git a/src/main/java/com/opentok/constants/Version.java b/src/main/java/com/opentok/constants/Version.java index f89f5457..d0ff3692 100644 --- a/src/main/java/com/opentok/constants/Version.java +++ b/src/main/java/com/opentok/constants/Version.java @@ -8,5 +8,5 @@ package com.opentok.constants; public class Version { - public static final String VERSION = "4.9.0"; + public static final String VERSION = "4.10.0"; } diff --git a/src/main/java/com/opentok/util/HttpClient.java b/src/main/java/com/opentok/util/HttpClient.java index d726b3fe..bd0bbc0a 100644 --- a/src/main/java/com/opentok/util/HttpClient.java +++ b/src/main/java/com/opentok/util/HttpClient.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.opentok.*; import com.opentok.constants.DefaultApiUrl; +import com.opentok.constants.DefaultUserAgent; import com.opentok.constants.Version; import com.opentok.exception.InvalidArgumentException; import com.opentok.exception.OpenTokException; @@ -38,7 +39,6 @@ import java.util.concurrent.Future; public class HttpClient extends DefaultAsyncHttpClient { - private final String apiUrl; private final int apiKey; @@ -48,17 +48,9 @@ private HttpClient(Builder builder) { this.apiUrl = builder.apiUrl; } - public String createSession(Map> params) throws RequestException { - Map> paramsWithList = null; - if (params != null) { - paramsWithList = new HashMap<>(); - for (Entry> entry : params.entrySet()) { - paramsWithList.put(entry.getKey(), new ArrayList<>(entry.getValue())); - } - } - + public String createSession(Map> params) throws RequestException { Future request = this.preparePost(this.apiUrl + "/session/create") - .setFormParams(paramsWithList) + .setFormParams(params) .setHeader("Accept", "application/json") // XML version is deprecated .execute(); @@ -1303,6 +1295,7 @@ public static class Builder { private String principal; private String password; private String apiUrl; + private String userAgent = DefaultUserAgent.DEFAULT_USER_AGENT; private AsyncHttpClientConfig config; private int requestTimeoutMS; @@ -1340,18 +1333,29 @@ public Builder requestTimeoutMS(int requestTimeoutMS) { return this; } + /** + * Sets the user agent to a custom value. + * + * @param userAgent The user agent. + * + * @return This Builder with user agent string. + */ + public Builder userAgent(String userAgent) { + this.userAgent = userAgent; + return this; + } + public HttpClient build() { DefaultAsyncHttpClientConfig.Builder configBuilder = new DefaultAsyncHttpClientConfig.Builder() - .setUserAgent("Opentok-Java-SDK/" + Version.VERSION + " JRE/" + System.getProperty("java.version")) + .setUserAgent(userAgent) .addRequestFilter(new TokenAuthRequestFilter(apiKey, apiSecret)); + if (apiUrl == null) { apiUrl = DefaultApiUrl.DEFAULT_API_URI; } - if (proxy != null) { configBuilder.setProxyServer(createProxyServer(proxy, proxyAuthScheme, principal, password)); } - if (requestTimeoutMS != 0) { configBuilder.setRequestTimeout(requestTimeoutMS); } diff --git a/src/test/java/com/opentok/test/OpenTokTest.java b/src/test/java/com/opentok/test/OpenTokTest.java index 9ee804e4..7cc7c1db 100644 --- a/src/test/java/com/opentok/test/OpenTokTest.java +++ b/src/test/java/com/opentok/test/OpenTokTest.java @@ -15,10 +15,12 @@ import com.github.tomakehurst.wiremock.junit.WireMockRule; import com.opentok.*; import com.opentok.Archive.OutputMode; +import com.opentok.constants.DefaultUserAgent; import com.opentok.exception.InvalidArgumentException; import com.opentok.exception.OpenTokException; import com.opentok.exception.RequestException; import org.apache.commons.lang.StringUtils; +import org.checkerframework.common.returnsreceiver.qual.This; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -68,12 +70,32 @@ public void setUp() throws OpenTokException { sdk = new OpenTok.Builder(apiKey, apiSecret).apiUrl(apiUrl).build(); } + @Test + public void testUserAgent() throws Exception { + stubFor(post(anyUrl()) + .withHeader("User-Agent", equalTo(DefaultUserAgent.DEFAULT_USER_AGENT)) + .willReturn(aResponse().withStatus(200)) + ); + sdk.disableForceMute("SESSION_ID"); + verify(postRequestedFor(anyUrl())); + + sdk = new OpenTok.Builder(apiKey, apiSecret).apiUrl(apiUrl).appendToUserAgent("Test_UA").build(); + stubFor(post(anyUrl()) + .withHeader("User-Agent", equalTo(DefaultUserAgent.DEFAULT_USER_AGENT+" Test_UA")) + .willReturn(aResponse().withStatus(200)) + ); + sdk.disableForceMute("SESSION_ID"); + verify(postRequestedFor(anyUrl())); + WireMock.reset(); + } + /** * Test that a request throws exception if request exceeds configured timeout */ @Test public void testConfigureRequestTimeout() { assertThrows(RequestException.class, () -> { + sdk.close(); sdk = new OpenTok.Builder(apiKey, apiSecret).apiUrl(apiUrl).requestTimeout(6).build(); String sessionId = "SESSIONID"; @@ -94,7 +116,6 @@ public void testConfigureRequestTimeout() { assertNull(createdSession.getMediaServerURL()); assertNull(createdSession.getProjectId()); assertNull(createdSession.getPartnerId()); - } @Test @@ -220,6 +241,7 @@ public void testCreateDefaultSession() throws OpenTokException { Session session = sdk.createSession(); assertNotNull(session); + assertFalse(session.getProperties().isEndToEndEncrypted()); assertEquals(apiKey, session.getApiKey()); assertEquals(sessionId, session.getSessionId()); assertEquals(MediaMode.RELAYED, session.getProperties().mediaMode()); @@ -252,6 +274,8 @@ public void testCreateRoutedSession() throws OpenTokException { Session session = sdk.createSession(properties); assertNotNull(session); + assertEquals(properties, session.getProperties()); + assertFalse(session.getProperties().isEndToEndEncrypted()); assertEquals(apiKey, session.getApiKey()); assertEquals(sessionId, session.getSessionId()); assertEquals(MediaMode.ROUTED, session.getProperties().mediaMode()); @@ -284,6 +308,8 @@ public void testCreateLocationHintSession() throws OpenTokException { Session session = sdk.createSession(properties); assertNotNull(session); + assertEquals(properties, session.getProperties()); + assertFalse(session.getProperties().isEndToEndEncrypted()); assertEquals(apiKey, session.getApiKey()); assertEquals(sessionId, session.getSessionId()); assertEquals(MediaMode.RELAYED, session.getProperties().mediaMode()); @@ -297,6 +323,41 @@ public void testCreateLocationHintSession() throws OpenTokException { Helpers.verifyUserAgent(); } + @Test + public void testCreateEncryptedSession() throws OpenTokException { + String sessionId = "SESSION1D"; + stubFor(post(urlEqualTo(SESSION_CREATE)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBody("[{\"session_id\":\"" + sessionId + "\",\"project_id\":\"00000000\"," + + "\"partner_id\":\"123456\"," + + "\"create_dt\":\"Mon Mar 17 00:41:31 PDT 2014\"," + + "\"media_server_url\":\"\"}]"))); + + SessionProperties properties = new SessionProperties.Builder() + .endToEndEncryption() + .mediaMode(MediaMode.ROUTED) + .build(); + Session session = sdk.createSession(properties); + + assertNotNull(session); + assertEquals(properties, session.getProperties()); + assertTrue(session.getProperties().isEndToEndEncrypted()); + assertEquals(apiKey, session.getApiKey()); + assertEquals(sessionId, session.getSessionId()); + assertEquals(MediaMode.ROUTED, session.getProperties().mediaMode()); + assertEquals(ArchiveMode.MANUAL, session.getProperties().archiveMode()); + assertNull(session.getProperties().getLocation()); + + verify(postRequestedFor(urlMatching(SESSION_CREATE)) + // NOTE: this is a pretty bad way to verify, ideally we can decode the body and then query the object + .withRequestBody(matching(".*e2ee=true.*"))); + assertTrue(Helpers.verifyTokenAuth(apiKey, apiSecret, + findAll(postRequestedFor(urlMatching(SESSION_CREATE))))); + Helpers.verifyUserAgent(); + } + @Test public void testCreateAlwaysArchivedSession() throws OpenTokException { String sessionId = "SESSIONID"; @@ -311,6 +372,7 @@ public void testCreateAlwaysArchivedSession() throws OpenTokException { SessionProperties properties = new SessionProperties.Builder() .archiveMode(ArchiveMode.ALWAYS) + .mediaMode(MediaMode.ROUTED) .build(); Session session = sdk.createSession(properties); @@ -335,16 +397,36 @@ public void testCreateBadSession() throws OpenTokException { .build(); } -// This is not part of the API because it would introduce a backwards incompatible change. -// @Test(expected = InvalidArgumentException.class) -// public void testCreateInvalidAlwaysArchivedAndRelayedSession() throws OpenTokException { -// SessionProperties properties = new SessionProperties.Builder() -// .mediaMode(MediaMode.RELAYED) -// .archiveMode(ArchiveMode.ALWAYS) -// .build(); -// } + @Test(expected = IllegalStateException.class) + public void testCreateInvalidAlwaysArchivedAndRelayedSession() { + new SessionProperties.Builder() + .mediaMode(MediaMode.RELAYED) + .archiveMode(ArchiveMode.ALWAYS) + .build(); + } + + @Test(expected = IllegalStateException.class) + public void testCreateInvalidAlwaysArchivedAndE2eeSession() { + new SessionProperties.Builder() + .mediaMode(MediaMode.ROUTED) + .endToEndEncryption() + .archiveMode(ArchiveMode.ALWAYS) + .build(); + } - // TODO: test session creation conditions that result in errors + @Test(expected = IllegalStateException.class) + public void testCreateInvalidRelayedMediaAndE2eeSession() { + new SessionProperties.Builder() + .archiveMode(ArchiveMode.MANUAL) + .endToEndEncryption() + .mediaMode(MediaMode.RELAYED) + .build(); + } + + @Test(expected = IllegalStateException.class) + public void testCreateInvalidE2eeSessionDefault() { + new SessionProperties.Builder().endToEndEncryption().build(); + } @Test public void testTokenDefault() throws