openvidu-server: POST Connection

pull/553/head
pabloFuente 2020-10-19 12:52:29 +02:00
parent 43f2f26dbd
commit 759acb1f7c
9 changed files with 302 additions and 216 deletions

View File

@ -0,0 +1,5 @@
package io.openvidu.server.core;
public enum ConnectionType {
WEBRTC, IPCAM
}

View File

@ -43,6 +43,7 @@ public class Participant {
active
}
protected ConnectionType type; // WEBRTC, IPCAM
protected String finalUserId; // ID to match this connection with a final user (HttpSession id)
protected String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id)
protected String participantPublicId; // ID to identify the user on clients
@ -76,9 +77,10 @@ public class Participant {
*/
public Lock singleRecordingLock = new ReentrantLock();
public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId,
Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType,
Long activeAt) {
public Participant(ConnectionType type, String finalUserId, String participantPrivatetId,
String participantPublicId, String sessionId, Token token, String clientMetadata, GeoLocation location,
String platform, EndpointType endpointType, Long activeAt) {
this.type = type;
this.finalUserId = finalUserId;
this.participantPrivatetId = participantPrivatetId;
this.participantPublicId = participantPublicId;
@ -101,6 +103,10 @@ public class Participant {
this.endpointType = endpointType;
}
public ConnectionType getType() {
return type;
}
public String getFinalUserId() {
return finalUserId;
}
@ -300,6 +306,7 @@ public class Participant {
JsonObject json = new JsonObject();
json.addProperty("id", this.participantPublicId);
json.addProperty("object", "connection");
json.addProperty("type", this.type.name());
json.addProperty("status", this.status.name());
json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id"
json.addProperty("sessionId", this.sessionId);

View File

@ -363,8 +363,9 @@ public abstract class SessionManager {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnectionId(), sessionId,
token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null);
Participant p = new Participant(ConnectionType.WEBRTC, finalUserId, participantPrivatetId,
token.getConnectionId(), sessionId, token, clientMetadata, location, platform,
EndpointType.WEBRTC_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p);
@ -384,8 +385,9 @@ public abstract class SessionManager {
public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token,
String clientMetadata) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(null, participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
sessionId, token, clientMetadata, null, null, EndpointType.WEBRTC_ENDPOINT, null);
Participant p = new Participant(ConnectionType.WEBRTC, null, participantPrivatetId,
ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, sessionId, token, clientMetadata, null, null,
EndpointType.WEBRTC_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId)
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
return p;
@ -397,8 +399,8 @@ public abstract class SessionManager {
public Participant newIpcamParticipant(String sessionId, String ipcamId, Token token, GeoLocation location,
String platform) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(ipcamId, ipcamId, ipcamId, sessionId, token, null, location, platform,
EndpointType.PLAYER_ENDPOINT, null);
Participant p = new Participant(ConnectionType.IPCAM, ipcamId, ipcamId, ipcamId, sessionId, token, null,
location, platform, EndpointType.PLAYER_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId).put(ipcamId, p);
return p;
} else {

View File

@ -117,6 +117,7 @@ public class Token {
JsonObject json = new JsonObject();
json.addProperty("id", this.getConnectionId());
json.addProperty("object", "connection");
json.addProperty("type", ConnectionType.WEBRTC.name());
json.addProperty("status", ParticipantStatus.pending.name());
json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id
json.addProperty("sessionId", this.sessionId);

View File

@ -77,7 +77,7 @@ public class KurentoParticipant extends Participant {
public KurentoParticipant(Participant participant, KurentoSession kurentoSession,
KurentoParticipantEndpointConfig endpointConfig, OpenviduConfig openviduConfig,
RecordingManager recordingManager) {
super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(),
super(participant.getType(), participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(),
kurentoSession.getSessionId(), participant.getToken(), participant.getClientMetadata(),
participant.getLocation(), participant.getPlatform(), participant.getEndpointType(),
participant.getActiveAt());

View File

@ -20,6 +20,7 @@ package io.openvidu.server.rest;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@ -57,6 +58,7 @@ import io.openvidu.java.client.RecordingMode;
import io.openvidu.java.client.RecordingProperties;
import io.openvidu.java.client.SessionProperties;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.core.ConnectionType;
import io.openvidu.server.core.EndReason;
import io.openvidu.server.core.IdentifierPrefixes;
import io.openvidu.server.core.Participant;
@ -92,7 +94,7 @@ public class SessionRestController {
protected OpenviduConfig openviduConfig;
@RequestMapping(value = "/sessions", method = RequestMethod.POST)
public ResponseEntity<?> getSessionId(@RequestBody(required = false) Map<?, ?> params) {
public ResponseEntity<?> initializeSession(@RequestBody(required = false) Map<?, ?> params) {
log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}");
@ -267,8 +269,99 @@ public class SessionRestController {
}
}
@RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST)
public ResponseEntity<?> initializeConnection(@PathVariable("sessionId") String sessionId,
@RequestBody Map<?, ?> params) {
log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString());
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String typeString;
String data;
Boolean record;
try {
typeString = (String) params.get("type");
data = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in parameter \"type\"",
"/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
}
ConnectionType type;
try {
if (typeString != null) {
type = ConnectionType.valueOf(typeString);
} else {
type = ConnectionType.WEBRTC;
}
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("Parameter type " + params.get("typeString") + " is not defined",
RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
}
switch (type) {
case WEBRTC:
return this.newWebrtcConnection(session, data, record, params);
case IPCAM:
return this.newIpcamConnection(session, data, record, params);
default:
return this.generateErrorResponse("Wrong type " + typeString,
RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
}
}
@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/{connectionId}", method = RequestMethod.DELETE)
public ResponseEntity<?> disconnectParticipant(@PathVariable("sessionId") String sessionId,
public ResponseEntity<?> closeConnection(@PathVariable("sessionId") String sessionId,
@PathVariable("connectionId") String participantPublicId) {
log.info("REST API: DELETE {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, participantPublicId);
@ -292,127 +385,8 @@ public class SessionRestController {
}
}
@RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE)
public ResponseEntity<?> unpublishStream(@PathVariable("sessionId") String sessionId,
@PathVariable("streamId") String streamId) {
log.info("REST API: DELETE {}/sessions/{}/stream/{}", RequestMappings.API, sessionId, streamId);
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
session = this.sessionManager.getSession(sessionId);
if (session != null) {
final String participantPrivateId = this.sessionManager.getParticipantPrivateIdFromStreamId(sessionId,
streamId);
if (participantPrivateId == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Participant participant = this.sessionManager.getParticipant(participantPrivateId);
if (participant.isIpcam()) {
return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED);
}
this.sessionManager.unpublishStream(session, streamId, null, null, EndReason.forceUnpublishByServer);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@RequestMapping(value = "/tokens", method = RequestMethod.POST)
public ResponseEntity<String> newToken(@RequestBody Map<?, ?> params) {
if (params == null) {
return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/tokens",
HttpStatus.BAD_REQUEST);
}
log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString());
String sessionId;
String roleString;
String metadata;
Boolean record;
try {
sessionId = (String) params.get("session");
roleString = (String) params.get("role");
metadata = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST);
}
if (sessionId == null) {
return this.generateErrorResponse("\"session\" parameter is mandatory", "/tokens", HttpStatus.BAD_REQUEST);
}
final Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND);
}
JsonObject kurentoOptions = null;
if (params.get("kurentoOptions") != null) {
try {
kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject();
} catch (Exception e) {
return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object",
"/tokens", HttpStatus.BAD_REQUEST);
}
}
OpenViduRole role;
try {
if (roleString != null) {
role = OpenViduRole.valueOf(roleString);
} else {
role = OpenViduRole.PUBLISHER;
}
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", "/tokens",
HttpStatus.BAD_REQUEST);
}
KurentoTokenOptions kurentoTokenOptions = null;
if (kurentoOptions != null) {
try {
kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions);
} catch (Exception e) {
return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", "/tokens",
HttpStatus.BAD_REQUEST);
}
}
metadata = (metadata != null) ? metadata : "";
record = (record != null) ? record : true;
// While closing a session tokens can't be generated
if (session.closingLock.readLock().tryLock()) {
try {
Token token = sessionManager.newToken(session, role, metadata, record, kurentoTokenOptions);
return new ResponseEntity<>(token.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} catch (Exception e) {
return this.generateErrorResponse(
"Error generating token for session " + sessionId + ": " + e.getMessage(), "/tokens",
HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
session.closingLock.readLock().unlock();
}
} else {
log.error("Session {} is in the process of closing. Token couldn't be generated", sessionId);
return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND);
}
}
@RequestMapping(value = "/recordings/start", method = RequestMethod.POST)
public ResponseEntity<?> startRecordingSession(@RequestBody Map<?, ?> params) {
public ResponseEntity<?> startRecording(@RequestBody Map<?, ?> params) {
if (params == null) {
return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/recordings/start",
@ -568,7 +542,7 @@ public class SessionRestController {
}
@RequestMapping(value = "/recordings/stop/{recordingId}", method = RequestMethod.POST)
public ResponseEntity<?> stopRecordingSession(@PathVariable("recordingId") String recordingId) {
public ResponseEntity<?> stopRecording(@PathVariable("recordingId") String recordingId) {
log.info("REST API: POST {}/recordings/stop/{}", RequestMappings.API, recordingId);
@ -632,7 +606,7 @@ public class SessionRestController {
}
@RequestMapping(value = "/recordings", method = RequestMethod.GET)
public ResponseEntity<?> getAllRecordings() {
public ResponseEntity<?> listRecordings() {
log.info("REST API: GET {}/recordings", RequestMappings.API);
@ -669,6 +643,87 @@ public class SessionRestController {
return new ResponseEntity<>(this.recordingManager.deleteRecordingFromHost(recordingId, false));
}
@RequestMapping(value = "/tokens", method = RequestMethod.POST)
public ResponseEntity<String> newToken(@RequestBody Map<?, ?> params) {
if (params == null) {
return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/tokens",
HttpStatus.BAD_REQUEST);
}
log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString());
String sessionId;
String metadata;
Boolean record;
try {
sessionId = (String) params.get("session");
metadata = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST);
}
if (sessionId == null) {
return this.generateErrorResponse("\"session\" parameter is mandatory", "/tokens", HttpStatus.BAD_REQUEST);
}
log.warn("Token API is deprecated. Use Connection API instead (POST {}/sessions/{}/connection)",
RequestMappings.API, sessionId);
final Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND);
}
Map<String, Object> map = new HashMap<>();
params.entrySet().forEach(entry -> map.put((String) entry.getKey(), entry.getValue()));
map.put("type", "WEBRTC");
ResponseEntity<?> entity = this.newWebrtcConnection(session, metadata, record, params);
JsonObject jsonResponse = JsonParser.parseString(entity.getBody().toString()).getAsJsonObject();
if (jsonResponse.has("error")) {
return this.generateErrorResponse(jsonResponse.get("message").getAsString(), "/tokens",
HttpStatus.valueOf(jsonResponse.get("status").getAsInt()));
} else {
String connectionId = jsonResponse.get("id").getAsString();
Token token = getTokenFromConnectionId(connectionId, session.getTokenIterator());
return new ResponseEntity<>(token.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
}
}
@RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE)
public ResponseEntity<?> unpublishStream(@PathVariable("sessionId") String sessionId,
@PathVariable("streamId") String streamId) {
log.info("REST API: DELETE {}/sessions/{}/stream/{}", RequestMappings.API, sessionId, streamId);
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
session = this.sessionManager.getSession(sessionId);
if (session != null) {
final String participantPrivateId = this.sessionManager.getParticipantPrivateIdFromStreamId(sessionId,
streamId);
if (participantPrivateId == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Participant participant = this.sessionManager.getParticipant(participantPrivateId);
if (participant.isIpcam()) {
return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED);
}
this.sessionManager.unpublishStream(session, streamId, null, null, EndReason.forceUnpublishByServer);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@RequestMapping(value = "/signal", method = RequestMethod.POST)
public ResponseEntity<?> signal(@RequestBody Map<?, ?> params) {
@ -738,99 +793,108 @@ public class SessionRestController {
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) {
protected ResponseEntity<?> newWebrtcConnection(Session session, String serverData, Boolean record,
Map<?, ?> params) {
log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId);
final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection";
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);
String roleString = null;
try {
roleString = (String) params.get("role");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
OpenViduRole role = null;
try {
if (roleString != null) {
role = OpenViduRole.valueOf(roleString);
} 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);
}
role = OpenViduRole.PUBLISHER;
}
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
JsonObject kurentoOptions = null;
if (params.get("kurentoOptions") != null) {
try {
kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject();
} catch (Exception e) {
return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object",
REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
}
KurentoTokenOptions kurentoTokenOptions = null;
if (kurentoOptions != null) {
try {
kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions);
} catch (Exception e) {
return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
}
serverData = (serverData != null) ? serverData : "";
record = (record != null) ? record : true;
// While closing a session tokens can't be generated
if (session.closingLock.readLock().tryLock()) {
try {
Token token = sessionManager.newToken(session, role, serverData, record, kurentoTokenOptions);
return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (Exception e) {
return this.generateErrorResponse(
"Error creating Connection for session " + session.getSessionId() + ": " + e.getMessage(),
REQUEST_PATH, HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
session.closingLock.readLock().unlock();
}
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
log.error("Session {} is in the process of closing. Connection couldn't be created",
session.getSessionId());
return this.generateErrorResponse("Session " + session.getSessionId() + " not found", REQUEST_PATH,
HttpStatus.NOT_FOUND);
}
}
@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) {
protected ResponseEntity<?> newIpcamConnection(Session session, String serverData, Boolean record,
Map<?, ?> params) {
log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId);
final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection";
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)
public ResponseEntity<?> publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map<?, ?> params) {
if (params == null) {
return this.generateErrorResponse("Error in body parameters. Cannot be empty",
"/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
}
log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString());
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String type;
String rtspUri;
Boolean adaptativeBitrate;
Boolean onlyPlayWithSubscribers;
Integer networkCache;
String data;
try {
type = (String) params.get("type");
rtspUri = (String) params.get("rtspUri");
adaptativeBitrate = (Boolean) params.get("adaptativeBitrate");
onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers");
networkCache = (Integer) params.get("networkCache");
data = (String) params.get("data");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", "/sessions/" + sessionId + "/connection",
HttpStatus.BAD_REQUEST);
}
if (rtspUri == null) {
return this.generateErrorResponse("\"rtspUri\" parameter is mandatory",
"/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
if (rtspUri == null) {
return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
type = "IPCAM"; // Other possible values in the future
adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true;
onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true;
networkCache = networkCache != null ? networkCache : 2000;
data = data != null ? data : "";
serverData = serverData != null ? serverData : "";
record = (record != null) ? record : true;
boolean hasAudio = true;
boolean hasVideo = true;
boolean audioActive = true;
boolean videoActive = true;
String typeOfVideo = type;
String typeOfVideo = ConnectionType.IPCAM.name();
Integer frameRate = null;
String videoDimensions = null;
KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive,
@ -843,15 +907,14 @@ public class SessionRestController {
if (session.isClosed()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, data);
Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, serverData);
return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (MalformedURLException e) {
return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri",
"/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
} catch (Exception e) {
return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection",
HttpStatus.INTERNAL_SERVER_ERROR);
return this.generateErrorResponse(e.getMessage(), REQUEST_PATH, HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
session.closingLock.readLock().unlock();
}

View File

@ -98,7 +98,7 @@ public class SessionGarbageCollectorIntegrationTest {
}
private String getSessionId() {
String stringResponse = (String) sessionRestController.getSessionId(new HashMap<>()).getBody();
String stringResponse = (String) sessionRestController.initializeSession(new HashMap<>()).getBody();
return new Gson().fromJson(stringResponse, JsonObject.class).get("id").getAsString();
}

View File

@ -212,14 +212,16 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Updating only role should let record value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'"
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':"
+ createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}");
// Updating only record should let role value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'record':true}", HttpStatus.SC_OK, true, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'"
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':"
+ createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}");
@ -282,23 +284,28 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Updating only role should let record value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'"
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
// Updating only record should let role value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'record':true}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'"
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'"
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'"
"{'role':'PUBLISHER'}", HttpStatus.SC_OK,
false, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");

View File

@ -86,7 +86,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}";
final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','createdAt':0,'role':'STR','data':'STR','record':true}";
final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}";
final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','type':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}";
@BeforeAll()
protected static void setupAll() {
@ -2647,7 +2647,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
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':'"
+ "','object':'connection','type':'WEBRTC','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'"
+ token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':"
+ createdAt1
+ ",'activeAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}");
@ -2744,13 +2744,13 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
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}");
+ "','object':'connection','type':'WEBRTC','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}");
+ "','object':'connection','type':'WEBRTC','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'"
+ token2 + "','role':'PUBLISHER','serverData':'','record':true}");
/** GET /openvidu/api/recordings (before recording started) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND);
@ -3291,6 +3291,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertEquals("Wrong serverData property", "MY_IP_CAMERA", response.get("serverData").getAsString());
Assert.assertEquals("Wrong platform property", "IPCAM", response.get("platform").getAsString());
Assert.assertEquals("Wrong role property", "PUBLISHER", response.get("role").getAsString());
Assert.assertEquals("Wrong type property", "IPCAM", response.get("type").getAsString());
Assert.assertEquals("Wrong number of publishers in IPCAM participant", 1,
response.get("publishers").getAsJsonArray().size());