mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: POST Connection
parent
43f2f26dbd
commit
759acb1f7c
|
@ -0,0 +1,5 @@
|
|||
package io.openvidu.server.core;
|
||||
|
||||
public enum ConnectionType {
|
||||
WEBRTC, IPCAM
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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(),
|
||||
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);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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':[]}");
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue