openvidu-server: GET /connection

pull/553/head
pabloFuente 2020-10-16 13:41:19 +02:00
parent e20db3f503
commit 77a63a8e54
9 changed files with 364 additions and 49 deletions

View File

@ -316,4 +316,8 @@ public class Participant {
return json; return json;
} }
public JsonObject withStatsToJson() {
return null;
}
} }

View File

@ -29,7 +29,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function; import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -43,7 +43,6 @@ import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.RecordingLayout; import io.openvidu.java.client.RecordingLayout;
import io.openvidu.java.client.SessionProperties; import io.openvidu.java.client.SessionProperties;
import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.kurento.core.KurentoParticipant;
import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.utils.RecordingUtils; import io.openvidu.server.utils.RecordingUtils;
@ -183,10 +182,6 @@ public class Session implements SessionInterface {
return deleted; return deleted;
} }
public boolean isTokenValid(String token) {
return this.tokens.containsKey(token);
}
public Token consumeToken(String token) { public Token consumeToken(String token) {
Token tokenObj = this.tokens.remove(token); Token tokenObj = this.tokens.remove(token);
return tokenObj; return tokenObj;
@ -214,15 +209,30 @@ public class Session implements SessionInterface {
} }
} }
public JsonObject toJson() { public JsonArray getSnapshotOfConnectionsAsJsonArray(boolean withPendingConnections, boolean withWebrtcStats) {
return this.sharedJson(KurentoParticipant::toJson);
Set<Participant> snapshotOfActiveConnections = this.getParticipants().stream().collect(Collectors.toSet());
JsonArray jsonArray = new JsonArray();
snapshotOfActiveConnections.forEach(participant -> {
// Filter recorder participant
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
jsonArray.add(withWebrtcStats ? participant.withStatsToJson() : participant.toJson());
}
});
if (withPendingConnections) {
Set<Token> snapshotOfPendingConnections = this.tokens.values().stream().collect(Collectors.toSet());
// Eliminate duplicates in case some concurrent situation took place
Set<String> activeConnectionIds = snapshotOfActiveConnections.stream()
.map(participant -> participant.getParticipantPublicId()).collect(Collectors.toSet());
snapshotOfPendingConnections.removeIf(token -> activeConnectionIds.contains(token.getConnectionId()));
snapshotOfPendingConnections.forEach(token -> jsonArray.add(token.toJsonAsParticipant()));
}
return jsonArray;
} }
public JsonObject withStatsToJson() { public JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats) {
return this.sharedJson(KurentoParticipant::withStatsToJson);
}
private JsonObject sharedJson(Function<KurentoParticipant, JsonObject> toJsonFunction) {
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("id", this.sessionId); json.addProperty("id", this.sessionId);
json.addProperty("object", "session"); json.addProperty("object", "session");
@ -241,12 +251,7 @@ public class Session implements SessionInterface {
json.addProperty("customSessionId", this.sessionProperties.customSessionId()); json.addProperty("customSessionId", this.sessionProperties.customSessionId());
} }
JsonObject connections = new JsonObject(); JsonObject connections = new JsonObject();
JsonArray participants = new JsonArray(); JsonArray participants = this.getSnapshotOfConnectionsAsJsonArray(withPendingConnections, withWebrtcStats);
this.participants.values().forEach(p -> {
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId())) {
participants.add(toJsonFunction.apply((KurentoParticipant) p));
}
});
connections.addProperty("numberOfElements", participants.size()); connections.addProperty("numberOfElements", participants.size());
connections.add("content", participants); connections.add("content", participants);
json.add("connections", connections); json.add("connections", connections);

View File

@ -47,9 +47,7 @@ public interface SessionInterface {
String getMediaNodeId(); String getMediaNodeId();
JsonObject toJson(); JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats);
JsonObject withStatsToJson();
Long getStartTime(); Long getStartTime();

View File

@ -568,6 +568,7 @@ public class KurentoParticipant extends Participant {
return this.sharedJson(MediaEndpoint::toJson); return this.sharedJson(MediaEndpoint::toJson);
} }
@Override
public JsonObject withStatsToJson() { public JsonObject withStatsToJson() {
return this.sharedJson(MediaEndpoint::withStatsToJson); return this.sharedJson(MediaEndpoint::withStatsToJson);
} }

View File

@ -171,7 +171,7 @@ public class Kms {
if (withSessions) { if (withSessions) {
JsonArray sessions = new JsonArray(); JsonArray sessions = new JsonArray();
for (KurentoSession session : this.kurentoSessions.values()) { for (KurentoSession session : this.kurentoSessions.values()) {
sessions.add(session.toJson()); sessions.add(session.toJson(false, false));
} }
json.add("sessions", sessions); json.add("sessions", sessions);
} }

View File

@ -20,7 +20,9 @@ package io.openvidu.server.rest;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -177,25 +179,25 @@ public class SessionRestController {
log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream() log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream()
.map(Session::getSessionId).collect(Collectors.toList()).toString()); .map(Session::getSessionId).collect(Collectors.toList()).toString());
return new ResponseEntity<>(sessionNotActive.toJson().toString(), RestUtils.getResponseHeaders(), return new ResponseEntity<>(sessionNotActive.toJson(false, false).toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK); HttpStatus.OK);
} }
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET) @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET)
public ResponseEntity<?> getSession(@PathVariable("sessionId") String sessionId, public ResponseEntity<?> getSession(@PathVariable("sessionId") String sessionId,
@RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections,
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
log.info("REST API: GET {}/sessions/{}", RequestMappings.API, sessionId); log.info("REST API: GET {}/sessions/{}", RequestMappings.API, sessionId);
Session session = this.sessionManager.getSession(sessionId); Session session = this.sessionManager.getSession(sessionId);
if (session != null) { if (session != null) {
JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson(); JsonObject response = session.toJson(pendingConnections, webRtcStats);
return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else { } else {
Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId); Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId);
if (sessionNotActive != null) { if (sessionNotActive != null) {
JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson() JsonObject response = sessionNotActive.toJson(pendingConnections, webRtcStats);
: sessionNotActive.toJson();
return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else { } else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND); return new ResponseEntity<>(HttpStatus.NOT_FOUND);
@ -205,15 +207,16 @@ public class SessionRestController {
@RequestMapping(value = "/sessions", method = RequestMethod.GET) @RequestMapping(value = "/sessions", method = RequestMethod.GET)
public ResponseEntity<?> listSessions( public ResponseEntity<?> listSessions(
@RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections,
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
log.info("REST API: GET {}/sessions?webRtcStats={}", RequestMappings.API, webRtcStats); log.info("REST API: GET {}/sessions", RequestMappings.API);
Collection<Session> sessions = this.sessionManager.getSessionsWithNotActive(); Collection<Session> sessions = this.sessionManager.getSessionsWithNotActive();
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
JsonArray jsonArray = new JsonArray(); JsonArray jsonArray = new JsonArray();
sessions.forEach(s -> { sessions.forEach(session -> {
JsonObject sessionJson = (webRtcStats == true) ? s.withStatsToJson() : s.toJson(); JsonObject sessionJson = session.toJson(pendingConnections, webRtcStats);
jsonArray.add(sessionJson); jsonArray.add(sessionJson);
}); });
json.addProperty("numberOfElements", sessions.size()); json.addProperty("numberOfElements", sessions.size());
@ -735,6 +738,51 @@ public class SessionRestController {
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.GET)
public ResponseEntity<?> getConnection(@PathVariable("sessionId") String sessionId,
@PathVariable("connectionId") String connectionId) {
log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId);
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session != null) {
Participant p = session.getParticipantByPublicId(connectionId);
if (p != null) {
return new ResponseEntity<>(p.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else {
Token t = getTokenFromConnectionId(connectionId, session.getTokenIterator());
if (t != null) {
return new ResponseEntity<>(t.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
@RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.GET)
public ResponseEntity<?> listConnections(@PathVariable("sessionId") String sessionId,
@RequestParam(value = "pendingConnections", defaultValue = "true", required = false) boolean pendingConnections,
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId);
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session != null) {
JsonObject json = new JsonObject();
JsonArray jsonArray = session.getSnapshotOfConnectionsAsJsonArray(pendingConnections, webRtcStats);
json.addProperty("numberOfElements", jsonArray.size());
json.add("content", jsonArray);
return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST) @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST)
public ResponseEntity<?> publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map<?, ?> params) { public ResponseEntity<?> publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map<?, ?> params) {
@ -812,6 +860,19 @@ public class SessionRestController {
} }
} }
protected Token getTokenFromConnectionId(String connectionId, Iterator<Entry<String, Token>> iterator) {
boolean found = false;
Token token = null;
while (iterator.hasNext() && !found) {
Token tAux = iterator.next().getValue();
found = tAux.getConnectionId().equals(connectionId);
if (found) {
token = tAux;
}
}
return token;
}
protected ResponseEntity<String> generateErrorResponse(String errorMessage, String path, HttpStatus status) { protected ResponseEntity<String> generateErrorResponse(String errorMessage, String path, HttpStatus status) {
JsonObject responseJson = new JsonObject(); JsonObject responseJson = new JsonObject();
responseJson.addProperty("timestamp", System.currentTimeMillis()); responseJson.addProperty("timestamp", System.currentTimeMillis());

View File

@ -110,7 +110,7 @@ public class SessionGarbageCollectorIntegrationTest {
} }
private JsonObject listSessions() { private JsonObject listSessions() {
String stringResponse = (String) sessionRestController.listSessions(false).getBody(); String stringResponse = (String) sessionRestController.listSessions(false, false).getBody();
return new Gson().fromJson(stringResponse, JsonObject.class); return new Gson().fromJson(stringResponse, JsonObject.class);
} }

View File

@ -31,6 +31,7 @@ import io.openvidu.java.client.OpenViduHttpException;
import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording; import io.openvidu.java.client.Recording;
import io.openvidu.java.client.Session; import io.openvidu.java.client.Session;
import io.openvidu.java.client.Token;
import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.CustomHttpClient;
import io.openvidu.test.browsers.utils.Unzipper; import io.openvidu.test.browsers.utils.Unzipper;
@ -382,4 +383,21 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
"{'status':'UP'}"); "{'status':'UP'}");
} }
@Test
@DisplayName("openvidu-java-client PRO test")
void openViduJavaClientProTest() throws Exception {
Session session = OV.createSession();
Assert.assertFalse(session.fetch());
Token token = session.createToken();
Assert.assertTrue(session.fetch());
Connection connection = session.getConnection(token.getConnectionId());
Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole());
Assert.assertTrue("Wrong record property", connection.record());
session.updateConnection(connection.getConnectionId(),
new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build());
Assert.assertEquals("Wrong role property", OpenViduRole.SUBSCRIBER, connection.getRole());
Assert.assertFalse("Wrong record property", connection.record());
Assert.assertFalse(session.fetch());
}
} }

View File

@ -42,7 +42,9 @@ import org.openqa.selenium.Alert;
import org.openqa.selenium.By; import org.openqa.selenium.By;
import org.openqa.selenium.Dimension; import org.openqa.selenium.Dimension;
import org.openqa.selenium.Keys; import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.ExpectedConditions;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
@ -64,6 +66,7 @@ import io.openvidu.java.client.RecordingMode;
import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.RecordingProperties;
import io.openvidu.java.client.Session; import io.openvidu.java.client.Session;
import io.openvidu.java.client.SessionProperties; import io.openvidu.java.client.SessionProperties;
import io.openvidu.java.client.Token;
import io.openvidu.java.client.TokenOptions; import io.openvidu.java.client.TokenOptions;
import io.openvidu.test.browsers.FirefoxUser; import io.openvidu.test.browsers.FirefoxUser;
import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.CustomHttpClient;
@ -2114,8 +2117,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
log.info("openvidu-java-client test"); log.info("openvidu-java-client test");
System.out.println(getBase64Screenshot(user));
user.getDriver().findElement(By.id("one2one-btn")).click(); user.getDriver().findElement(By.id("one2one-btn")).click();
final String customSessionId = "openviduJavaClientSession"; final String customSessionId = "openviduJavaClientSession";
@ -2142,13 +2143,34 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
.allowedFilters(new String[] { "GStreamerFilter" }).build(); .allowedFilters(new String[] { "GStreamerFilter" }).build();
TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR)
.data(serverDataModerator).kurentoOptions(kurentoOptions).build(); .data(serverDataModerator).kurentoOptions(kurentoOptions).build();
String tokenModerator = session.generateToken(tokenOptionsModerator); Token tokenModerator = session.createToken(tokenOptionsModerator);
String tokenModeratorString = tokenModerator.getToken();
String connectionIdModerator = tokenModerator.getConnectionId();
TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER)
.data(serverDataSubscriber).build(); .data(serverDataSubscriber).build();
String tokenSubscriber = session.generateToken(tokenOptionsSubscriber); Token tokenSubscriber = session.createToken(tokenOptionsSubscriber);
String tokenSubscriberString = tokenSubscriber.getToken();
String connectionIdSubscriber = tokenSubscriber.getConnectionId();
Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch()); Assert.assertTrue("Session.fetch() should return true if new pending connections", session.fetch());
Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch());
Assert.assertEquals("Wrong number of active connections", 0, session.getActiveConnections().size());
Assert.assertEquals("Wrong number of connections", 2, session.getConnections().size());
Connection connectionModerator = session.getConnection(connectionIdModerator);
Connection connectionSubscriber = session.getConnection(connectionIdSubscriber);
Assert.assertEquals("Wrong connectionId property", connectionIdModerator,
connectionModerator.getConnectionId());
Assert.assertEquals("Wrong status property", "pending", connectionModerator.getStatus());
Assert.assertEquals("Wrong role property", OpenViduRole.MODERATOR, connectionModerator.getRole());
Assert.assertTrue("Wrong record property", connectionModerator.record());
Assert.assertNull("Wrong location property", connectionModerator.getLocation());
Assert.assertNull("Wrong platform property", connectionModerator.getPlatform());
Assert.assertEquals("Wrong createdAt property", 0, connectionModerator.createdAt());
Assert.assertNull("Wrong clientData property", connectionModerator.getClientData());
Assert.assertEquals("Wrong publishers property", 0, connectionModerator.getPublishers().size());
Assert.assertEquals("Wrong subscribers property", 0, connectionModerator.getSubscribers().size());
// Set client data 1 // Set client data 1
WebElement clientDataInput = user.getDriver().findElement(By.cssSelector("#client-data-input-0")); WebElement clientDataInput = user.getDriver().findElement(By.cssSelector("#client-data-input-0"));
@ -2160,7 +2182,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000); Thread.sleep(1000);
WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear(); tokeInput.clear();
tokeInput.sendKeys(tokenModerator); tokeInput.sendKeys(tokenModeratorString);
user.getDriver().findElement(By.id("save-btn")).click(); user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000); Thread.sleep(1000);
@ -2175,7 +2197,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000); Thread.sleep(1000);
tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear(); tokeInput.clear();
tokeInput.sendKeys(tokenSubscriber); tokeInput.sendKeys(tokenSubscriberString);
user.getDriver().findElement(By.id("save-btn")).click(); user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000); Thread.sleep(1000);
@ -2215,17 +2237,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections().size(), 2, Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections().size(), 2,
session.getActiveConnections().size()); session.getActiveConnections().size());
Connection connectionModerator; // Verify status
Connection connectionSubscriber; Assert.assertEquals("Wrong status for moderator connection", "active", connectionModerator.getStatus());
if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) { Assert.assertEquals("Wrong status for subscriber connection", "active", connectionSubscriber.getStatus());
connectionModerator = session.getActiveConnections().get(0);
connectionSubscriber = session.getActiveConnections().get(1);
} else {
connectionModerator = session.getActiveConnections().get(1);
connectionSubscriber = session.getActiveConnections().get(0);
}
Assert.assertEquals(OpenViduRole.SUBSCRIBER, connectionSubscriber.getRole());
// Verify platform // Verify platform
Assert.assertTrue("Wrong platform for moderator connection", Assert.assertTrue("Wrong platform for moderator connection",
@ -2579,6 +2593,15 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, false, restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, false,
"{'numberOfElements': 1, 'content': []}"); "{'numberOfElements': 1, 'content': []}");
/** GET /openvidu/api/sessions/ID/connection (with no connections) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection", HttpStatus.SC_NOT_FOUND);
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK,
true, true, true, "{'numberOfElements':0,'content':[]}");
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection/NOT_EXISTS",
HttpStatus.SC_BAD_REQUEST);
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/NOT_EXISTS",
HttpStatus.SC_NOT_FOUND);
/** POST /openvidu/api/tokens **/ /** POST /openvidu/api/tokens **/
// 400 // 400
body = "{}"; body = "{}";
@ -2599,6 +2622,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
"{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}");
final String token1 = res.get("token").getAsString(); final String token1 = res.get("token").getAsString();
final String connectionId1 = res.get("connectionId").getAsString();
Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'",
res.get("id").getAsString(), token1); res.get("id").getAsString(), token1);
Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString());
@ -2608,6 +2632,17 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
DEFAULT_JSON_TOKEN); DEFAULT_JSON_TOKEN);
final String token2 = res.get("id").getAsString(); final String token2 = res.get("id").getAsString();
final String connectionId2 = res.get("connectionId").getAsString();
/** GET /openvidu/api/sessions/ID/connection (with pending connections) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK,
true, true, false, "{'numberOfElements':2,'content':[]}");
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null,
HttpStatus.SC_OK, true, true, true,
"{'id':'" + connectionId1 + "','connectionId':'" + connectionId1
+ "','object':'connection','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'"
+ token1
+ "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}");
/** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/
body = "{}"; body = "{}";
@ -2695,6 +2730,20 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager()
.assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true));
/** GET /openvidu/api/sessions/ID/connection (with active connections) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK,
true, true, false, "{'numberOfElements':2,'content':[]}");
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null,
HttpStatus.SC_OK, false, true, false,
"{'id':'" + connectionId1 + "','connectionId':'" + connectionId1
+ "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token1
+ "','role':'MODERATOR','serverData':'SERVER_DATA','record':true}");
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId2, null,
HttpStatus.SC_OK, false, true, false,
"{'id':'" + connectionId2 + "','connectionId':'" + connectionId2
+ "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token2
+ "','role':'PUBLISHER','serverData':'','record':true}");
/** GET /openvidu/api/recordings (before recording started) **/ /** GET /openvidu/api/recordings (before recording started) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND);
restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true, restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true,
@ -3434,4 +3483,183 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
} }
} }
@Test
@DisplayName("OpenVidu SDK fetch test")
void openviduSdkFetchTest() throws Exception {
isRecordingTest = true;
setupBrowser("chrome");
log.info("OpenVidu SDK fetch test");
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Session session = OV.createSession();
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET);
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'REST_SESSION'}",
HttpStatus.SC_OK);
Assert.assertTrue("Java fetch should be true", OV.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
Assert.assertFalse("Java fetch should be false", session.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
Token token = session.createToken();
// TODO: when using createConnection this below should be false!
Assert.assertTrue("Java fetch should be true", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", "{'session':'REST_SESSION'}", HttpStatus.SC_OK);
Assert.assertFalse("Fetch should be true", session.fetch());
Assert.assertTrue("Fetch should be false", OV.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/REST_SESSION", HttpStatus.SC_NO_CONTENT);
Assert.assertFalse("Java fetch should be true", session.fetch());
Assert.assertTrue("Java fetch should be true", OV.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
// Set token and join session
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.id("session-settings-btn-0")).click();
Thread.sleep(1000);
WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(token.getToken());
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.className("join-btn")).click();
user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
user.getEventManager().waitUntilEventReaches("streamCreated", 1);
user.getEventManager().waitUntilEventReaches("streamPlaying", 1);
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Assert.assertTrue("Java fetch should be true", OV.fetch());
Assert.assertFalse("Java fetch should be false", session.fetch());
checkNodeFetchChanged(false, true);
checkNodeFetchChanged(true, false);
checkNodeFetchChanged(true, false);
// RECORD
user.getDriver().findElement(By.id("rec-properties-btn")).click();
user.getDriver().findElement(By.id("rec-hasvideo-checkbox")).click();
user.getDriver().findElement(By.id("rec-outputmode-select")).click();
Thread.sleep(500);
user.getDriver().findElement(By.id("option-INDIVIDUAL")).click();
Thread.sleep(500);
user.getDriver().findElement(By.id("start-recording-btn")).click();
user.getEventManager().waitUntilEventReaches("recordingStarted", 1);
// Node SDK should return false as the recording has been started with it
checkNodeFetchChanged(false, false);
checkNodeFetchChanged(true, false);
checkNodeFetchChanged(true, false);
// Java SDK should return true as it doesn't know about the recording yet
Assert.assertTrue("Java fetch should be true", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
OV.stopRecording(session.getSessionId());
user.getEventManager().waitUntilEventReaches("recordingStopped", 1);
// Java SDK should return false as the recording has been stopped with it
Assert.assertFalse("Java fetch should be false", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
// Node SDK should return true as it doesn't know about the recording stooped
checkNodeFetchChanged(false, true);
checkNodeFetchChanged(false, false);
checkNodeFetchChanged(true, false);
// NEW SUBSCRIBER
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.id("session-name-input-1")).clear();
user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(session.getSessionId());
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Assert.assertTrue("Java fetch should be true", OV.fetch());
Assert.assertFalse("Java fetch should be false", session.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
checkNodeFetchChanged(false, false);
// MODIFY STREAM
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .pub-video-btn")).click();
user.getEventManager().waitUntilEventReaches("streamPropertyChanged", 2);
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Assert.assertTrue("Java fetch should be true", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(false, true);
checkNodeFetchChanged(true, false);
checkNodeFetchChanged(false, false);
// REMOVE STREAM
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .sub-btn")).click();
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Assert.assertTrue("Java fetch should be true", OV.fetch());
Assert.assertFalse("Java fetch should be false", session.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
checkNodeFetchChanged(false, false);
// REMOVE USER
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .leave-btn")).click();
user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1);
user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(1000);
Assert.assertTrue("Java fetch should be true", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(false, true);
checkNodeFetchChanged(false, false);
checkNodeFetchChanged(true, false);
}
private void checkNodeFetchChanged(boolean global, boolean hasChanged) {
user.getDriver().findElement(By.id(global ? "list-sessions-btn" : "get-session-btn")).click();
user.getWaiter().until(new NodeFetchHasChanged(hasChanged));
}
private class NodeFetchHasChanged implements ExpectedCondition<Boolean> {
private boolean hasChanged;
public NodeFetchHasChanged(boolean hasChanged) {
this.hasChanged = hasChanged;
}
@Override
public Boolean apply(WebDriver driver) {
return driver.findElement(By.id("api-response-text-area")).getAttribute("value")
.endsWith("Changes: " + hasChanged);
}
}
} }