openvidu-server: participant location and platform properties

pull/121/head
pabloFuente 2018-09-05 17:18:13 +02:00
parent 0828bc6f12
commit 4e81e6b600
13 changed files with 154 additions and 13 deletions

View File

@ -37,6 +37,7 @@ public class ProtocolElements {
public static final String JOINROOM_ROOM_PARAM = "session"; public static final String JOINROOM_ROOM_PARAM = "session";
public static final String JOINROOM_METADATA_PARAM = "metadata"; public static final String JOINROOM_METADATA_PARAM = "metadata";
public static final String JOINROOM_SECRET_PARAM = "secret"; public static final String JOINROOM_SECRET_PARAM = "secret";
public static final String JOINROOM_PLATFORM_PARAM = "platform";
public static final String JOINROOM_RECORDER_PARAM = "recorder"; public static final String JOINROOM_RECORDER_PARAM = "recorder";
public static final String JOINROOM_PEERID_PARAM = "id"; public static final String JOINROOM_PEERID_PARAM = "id";

View File

@ -1,5 +1,6 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
@ -280,6 +281,11 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.7</version> <version>3.7</version>
</dependency> </dependency>
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.12.0</version>
</dependency>
<!-- Test dependencies --> <!-- Test dependencies -->

View File

@ -32,6 +32,8 @@ public class CDREvent implements Comparable<CDREvent> {
private Long startTime; private Long startTime;
private Integer duration; private Integer duration;
private Participant participant; private Participant participant;
private String location;
private String platform;
private MediaOptions mediaOptions; private MediaOptions mediaOptions;
private String receivingFrom; private String receivingFrom;
private String reason; private String reason;
@ -88,6 +90,8 @@ public class CDREvent implements Comparable<CDREvent> {
public CDREvent(CDREventName eventName, Participant participant, String sessionId) { public CDREvent(CDREventName eventName, Participant participant, String sessionId) {
this(eventName, sessionId); this(eventName, sessionId);
this.participant = participant; this.participant = participant;
this.location = participant.getLocation();
this.platform = participant.getPlatform();
this.startTime = this.timeStamp; this.startTime = this.timeStamp;
} }
@ -122,6 +126,12 @@ public class CDREvent implements Comparable<CDREvent> {
if (this.participant != null) { if (this.participant != null) {
json.addProperty("participantId", this.participant.getParticipantPublicId()); json.addProperty("participantId", this.participant.getParticipantPublicId());
} }
if (this.location != null) {
json.addProperty("location", this.location);
}
if (this.platform != null) {
json.addProperty("platform", this.platform);
}
if (this.mediaOptions != null) { if (this.mediaOptions != null) {
json.addProperty("connection", this.receivingFrom != null ? "INBOUND" : "OUTBOUND"); json.addProperty("connection", this.receivingFrom != null ? "INBOUND" : "OUTBOUND");
json.addProperty("audioEnabled", this.mediaOptions.hasAudio()); json.addProperty("audioEnabled", this.mediaOptions.hasAudio());

View File

@ -38,7 +38,7 @@ import io.openvidu.server.recording.Recording;
* *
* - 'sessionCreated': {sessionId, timestamp} * - 'sessionCreated': {sessionId, timestamp}
* - 'sessionDestroyed': {sessionId, timestamp, startTime, endTime, duration, reason} * - 'sessionDestroyed': {sessionId, timestamp, startTime, endTime, duration, reason}
* - 'participantJoined': {sessionId, timestamp, participantId} * - 'participantJoined': {sessionId, timestamp, participantId, location, platform}
* - 'participantLeft': {sessionId, timestamp, participantId, startTime, endTime, duration, reason} * - 'participantLeft': {sessionId, timestamp, participantId, startTime, endTime, duration, reason}
* - 'webrtcConnectionCreated' {sessionId, timestamp, participantId, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate]} * - 'webrtcConnectionCreated' {sessionId, timestamp, participantId, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate]}
* - 'webrtcConnectionDestroyed' {sessionId, timestamp, participantId, startTime, endTime, duration, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate], reason} * - 'webrtcConnectionDestroyed' {sessionId, timestamp, participantId, startTime, endTime, duration, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate], reason}

View File

@ -26,19 +26,24 @@ public class Participant {
private String clientMetadata = ""; // Metadata provided on client side private String clientMetadata = ""; // Metadata provided on client side
private String serverMetadata = ""; // Metadata provided on server side private String serverMetadata = ""; // Metadata provided on server side
private Token token; // Token associated to this participant private Token token; // Token associated to this participant
private String location; // Remote IP of the participant
private String platform; // Platform used by the participant to connect to the session
protected boolean streaming = false; protected boolean streaming = false;
protected volatile boolean closed; protected volatile boolean closed;
private final String METADATA_SEPARATOR = "%/%"; private final String METADATA_SEPARATOR = "%/%";
public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata) { public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata,
String location, String platform) {
this.participantPrivatetId = participantPrivatetId; this.participantPrivatetId = participantPrivatetId;
this.participantPublicId = participantPublicId; this.participantPublicId = participantPublicId;
this.token = token; this.token = token;
this.clientMetadata = clientMetadata; this.clientMetadata = clientMetadata;
if (!token.getServerMetadata().isEmpty()) if (!token.getServerMetadata().isEmpty())
this.serverMetadata = token.getServerMetadata(); this.serverMetadata = token.getServerMetadata();
this.location = location;
this.platform = platform;
} }
public String getParticipantPrivateId() { public String getParticipantPrivateId() {
@ -81,6 +86,22 @@ public class Participant {
this.token = token; this.token = token;
} }
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
public String getPlatform() {
return this.platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public boolean isStreaming() { public boolean isStreaming() {
return streaming; return streaming;
} }
@ -166,6 +187,8 @@ public class Participant {
public JsonObject toJson() { public JsonObject toJson() {
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("connectionId", this.participantPublicId); json.addProperty("connectionId", this.participantPublicId);
json.addProperty("location", this.location);
json.addProperty("platform", this.platform);
json.addProperty("token", this.token.getToken()); json.addProperty("token", this.token.getToken());
json.addProperty("role", this.token.getRole().name()); json.addProperty("role", this.token.getRole().name());
json.addProperty("serverData", this.serverMetadata); json.addProperty("serverData", this.serverMetadata);

View File

@ -116,7 +116,8 @@ public abstract class SessionManager {
public abstract void removeFilterEventListener(Session session, Participant subscriber, String streamId, public abstract void removeFilterEventListener(Session session, Participant subscriber, String streamId,
String eventType); String eventType);
public abstract String getParticipantPrivateIdFromStreamId(String sessionId, String streamId) throws OpenViduException; public abstract String getParticipantPrivateIdFromStreamId(String sessionId, String streamId)
throws OpenViduException;
/** /**
* Returns a Session given its id * Returns a Session given its id
@ -331,10 +332,11 @@ public abstract class SessionManager {
} }
public Participant newParticipant(String sessionId, String participantPrivatetId, Token token, public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
String clientMetadata) { String clientMetadata, String location, String platform) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
String participantPublicId = this.generateRandomChain(); String participantPublicId = this.generateRandomChain();
Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata); Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata, location,
platform);
while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId, while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId,
p) != null) { p) != null) {
participantPublicId = this.generateRandomChain(); participantPublicId = this.generateRandomChain();
@ -350,7 +352,7 @@ public abstract class SessionManager {
String clientMetadata) { String clientMetadata) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
token, clientMetadata); token, clientMetadata, null, null);
this.sessionidParticipantpublicidParticipant.get(sessionId) this.sessionidParticipantpublicidParticipant.get(sessionId)
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
return p; return p;

View File

@ -80,7 +80,7 @@ public class KurentoParticipant extends Participant {
public KurentoParticipant(Participant participant, KurentoSession kurentoSession, MediaPipeline pipeline, public KurentoParticipant(Participant participant, KurentoSession kurentoSession, MediaPipeline pipeline,
InfoHandler infoHandler, CallDetailRecord CDR, OpenviduConfig openviduConfig) { InfoHandler infoHandler, CallDetailRecord CDR, OpenviduConfig openviduConfig) {
super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(), super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(),
participant.getClientMetadata()); participant.getClientMetadata(), participant.getLocation(), participant.getPlatform());
this.openviduConfig = openviduConfig; this.openviduConfig = openviduConfig;
this.session = kurentoSession; this.session = kurentoSession;
this.pipeline = pipeline; this.pipeline = pipeline;

View File

@ -17,6 +17,8 @@
package io.openvidu.server.rpc; package io.openvidu.server.rpc;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -25,6 +27,7 @@ import java.util.concurrent.ConcurrentMap;
import org.kurento.jsonrpc.DefaultJsonRpcHandler; import org.kurento.jsonrpc.DefaultJsonRpcHandler;
import org.kurento.jsonrpc.Session; import org.kurento.jsonrpc.Session;
import org.kurento.jsonrpc.Transaction; import org.kurento.jsonrpc.Transaction;
import org.kurento.jsonrpc.internal.ws.WebSocketServerSession;
import org.kurento.jsonrpc.message.Request; import org.kurento.jsonrpc.message.Request;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -34,6 +37,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.OpenViduException.Code;
@ -43,6 +47,7 @@ import io.openvidu.server.core.MediaOptions;
import io.openvidu.server.core.Participant; import io.openvidu.server.core.Participant;
import io.openvidu.server.core.SessionManager; import io.openvidu.server.core.SessionManager;
import io.openvidu.server.core.Token; import io.openvidu.server.core.Token;
import io.openvidu.server.utils.GeoLocationByIpUtils;
public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> { public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
@ -51,6 +56,9 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
@Autowired @Autowired
OpenviduConfig openviduConfig; OpenviduConfig openviduConfig;
@Autowired
GeoLocationByIpUtils geoLocationByIp;
@Autowired @Autowired
SessionManager sessionManager; SessionManager sessionManager;
@ -159,8 +167,26 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
String sessionId = getStringParam(request, ProtocolElements.JOINROOM_ROOM_PARAM); String sessionId = getStringParam(request, ProtocolElements.JOINROOM_ROOM_PARAM);
String token = getStringParam(request, ProtocolElements.JOINROOM_TOKEN_PARAM); String token = getStringParam(request, ProtocolElements.JOINROOM_TOKEN_PARAM);
String secret = getStringParam(request, ProtocolElements.JOINROOM_SECRET_PARAM); String secret = getStringParam(request, ProtocolElements.JOINROOM_SECRET_PARAM);
String platform = getStringParam(request, ProtocolElements.JOINROOM_PLATFORM_PARAM);
String participantPrivatetId = rpcConnection.getParticipantPrivateId(); String participantPrivatetId = rpcConnection.getParticipantPrivateId();
InetAddress remoteAddress = null;
String location = "";
Object obj = rpcConnection.getSession().getAttributes().get("remoteAddress");
if (obj != null && obj instanceof InetAddress) {
remoteAddress = (InetAddress) obj;
try {
location = this.geoLocationByIp.getLocationByIp(remoteAddress);
} catch (IOException e) {
e.printStackTrace();
location = "error";
} catch (GeoIp2Exception e) {
log.warn("Error getting address location: {}", e.getMessage());
location = "unknown";
}
}
boolean recorder = false; boolean recorder = false;
try { try {
@ -193,7 +219,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
clientMetadata); clientMetadata);
} else { } else {
participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj, participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj,
clientMetadata); clientMetadata, location, platform);
} }
rpcConnection.setSessionId(sessionId); rpcConnection.setSessionId(sessionId);
@ -521,6 +547,10 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
@Override @Override
public void afterConnectionEstablished(Session rpcSession) throws Exception { public void afterConnectionEstablished(Session rpcSession) throws Exception {
log.info("After connection established for WebSocket session: {}", rpcSession.getSessionId()); log.info("After connection established for WebSocket session: {}", rpcSession.getSessionId());
if (rpcSession instanceof WebSocketServerSession) {
rpcSession.getAttributes().put("remoteAddress",
((WebSocketServerSession) rpcSession).getWebSocketSession().getRemoteAddress().getAddress());
}
} }
@Override @Override

View File

@ -0,0 +1,69 @@
package io.openvidu.server.utils;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import com.maxmind.db.Reader;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
/**
* This product includes GeoLite2 data created by MaxMind, available from
* <a href="http://www.maxmind.com">http://www.maxmind.com</a>.
*/
@Service("geolocationservice")
public class GeoLocationByIpUtils {
private static final Logger log = LoggerFactory.getLogger(GeoLocationByIpUtils.class);
private static DatabaseReader reader = null;
private ResourceLoader resourceLoader;
@Inject
public GeoLocationByIpUtils(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@PostConstruct
public void init() {
try {
log.info("GeoLocationByIpUtils: Trying to load GeoLite2-City database...");
Resource resource = resourceLoader.getResource("classpath:GeoLite2-City.mmdb");
InputStream dbAsStream = resource.getInputStream();
// Initialize the reader
reader = new DatabaseReader.Builder(dbAsStream).fileMode(Reader.FileMode.MEMORY).build();
log.info("GeoLocationServiceImpl: Database was loaded successfully");
} catch (IOException | NullPointerException e) {
log.error("Database reader cound not be initialized", e);
}
}
@PreDestroy
public void preDestroy() {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error("Failed to close the GeoLocation reader");
}
}
}
public String getLocationByIp(InetAddress ipAddress) throws IOException, GeoIp2Exception {
CityResponse response = reader.city(ipAddress);
return response.getCity().getNames().get("en") + ", " + response.getCountry().getNames().get("en");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 MiB

View File

@ -18,6 +18,6 @@
<app-root> <app-root>
<mat-spinner></mat-spinner> <mat-spinner></mat-spinner>
</app-root> </app-root>
<script type="text/javascript" src="runtime.a66f828dca56eeb90e02.js"></script><script type="text/javascript" src="polyfills.3582350dd6075fd34141.js"></script><script type="text/javascript" src="main.a5878fcbbb284a79712e.js"></script></body> <script type="text/javascript" src="runtime.a66f828dca56eeb90e02.js"></script><script type="text/javascript" src="polyfills.3582350dd6075fd34141.js"></script><script type="text/javascript" src="main.a7de0bb357964fcc90fc.js"></script></body>
</html> </html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long