You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/07/12 16:43:07 UTC
[1/2] openmeetings git commit: [OPENMEETINGS-1664] sip seems to work
Repository: openmeetings
Updated Branches:
refs/heads/3.3.x 280247cb7 -> 8aeb1b306
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
deleted file mode 100644
index 267cf91..0000000
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
+++ /dev/null
@@ -1,1951 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License") + you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openmeetings.core.remote.red5;
-
-import static org.apache.openmeetings.util.OmFileHelper.EXTENSION_MP4;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_EXT_PROCESS_TTL;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_CSP;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_XFRAME;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.EXT_PROCESS_TTL;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_CSP_SELF;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
-
-import java.awt.Point;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.openmeetings.IApplication;
-import org.apache.openmeetings.core.data.conference.RoomManager;
-import org.apache.openmeetings.core.data.whiteboard.WhiteboardCache;
-import org.apache.openmeetings.core.data.whiteboard.WhiteboardManager;
-import org.apache.openmeetings.core.remote.RecordingService;
-import org.apache.openmeetings.core.remote.WhiteboardService;
-import org.apache.openmeetings.core.remote.util.SessionVariablesUtil;
-import org.apache.openmeetings.core.util.WebSocketHelper;
-import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
-import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
-import org.apache.openmeetings.db.dao.label.LabelDao;
-import org.apache.openmeetings.db.dao.log.ConferenceLogDao;
-import org.apache.openmeetings.db.dao.record.RecordingDao;
-import org.apache.openmeetings.db.dao.room.RoomDao;
-import org.apache.openmeetings.db.dao.server.ISessionManager;
-import org.apache.openmeetings.db.dao.server.ServerDao;
-import org.apache.openmeetings.db.dao.server.SessiondataDao;
-import org.apache.openmeetings.db.dao.user.UserDao;
-import org.apache.openmeetings.db.dto.room.BrowserStatus;
-import org.apache.openmeetings.db.dto.room.RoomStatus;
-import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
-import org.apache.openmeetings.db.entity.file.FileItem;
-import org.apache.openmeetings.db.entity.log.ConferenceLog;
-import org.apache.openmeetings.db.entity.room.Client;
-import org.apache.openmeetings.db.entity.room.Room;
-import org.apache.openmeetings.db.entity.room.Room.RoomElement;
-import org.apache.openmeetings.db.entity.server.Server;
-import org.apache.openmeetings.db.entity.server.Sessiondata;
-import org.apache.openmeetings.db.entity.user.User;
-import org.apache.openmeetings.db.util.AuthLevelUtil;
-import org.apache.openmeetings.util.CalendarPatterns;
-import org.apache.openmeetings.util.InitializationContainer;
-import org.apache.openmeetings.util.OmFileHelper;
-import org.apache.openmeetings.util.OpenmeetingsVariables;
-import org.apache.openmeetings.util.Version;
-import org.apache.openmeetings.util.message.RoomMessage;
-import org.apache.openmeetings.util.message.TextRoomMessage;
-import org.apache.wicket.Application;
-import org.apache.wicket.util.string.Strings;
-import org.red5.logging.Red5LoggerFactory;
-import org.red5.server.adapter.MultiThreadedApplicationAdapter;
-import org.red5.server.api.IClient;
-import org.red5.server.api.IConnection;
-import org.red5.server.api.Red5;
-import org.red5.server.api.scope.IBasicScope;
-import org.red5.server.api.scope.IBroadcastScope;
-import org.red5.server.api.scope.IScope;
-import org.red5.server.api.scope.ScopeType;
-import org.red5.server.api.service.IPendingServiceCall;
-import org.red5.server.api.service.IPendingServiceCallback;
-import org.red5.server.api.service.IServiceCapableConnection;
-import org.red5.server.api.stream.IBroadcastStream;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter implements IPendingServiceCallback {
- private static final Logger _log = Red5LoggerFactory.getLogger(ScopeApplicationAdapter.class, webAppRootKey);
- private static final String SECURITY_CODE_PARAM = "securityCode";
- private static final String WIDTH_PARAM = "width";
- private static final String HEIGHT_PARAM = "height";
- private static final String NATIVE_SSL_PARAM = "nativeSsl";
- public static final String HIBERNATE_SCOPE = "hibernate";
- private static final String SIP_PARAM = "sipClient";
-
- @Autowired
- private ISessionManager sessionManager;
- @Autowired
- private WhiteboardService whiteBoardService;
- @Autowired
- private WhiteboardManager whiteboardManager;
- @Autowired
- private WhiteboardCache whiteboardCache;
- @Autowired
- private RecordingService recordingService;
- @Autowired
- private ConfigurationDao cfgDao;
- @Autowired
- private AppointmentDao appointmentDao;
- @Autowired
- private SessiondataDao sessiondataDao;
- @Autowired
- private RoomManager roomManager;
- @Autowired
- private ConferenceLogDao conferenceLogDao;
- @Autowired
- private UserDao userDao;
- @Autowired
- private RoomDao roomDao;
- @Autowired
- private RecordingDao recordingDao;
- @Autowired
- private ServerDao serverDao;
-
- private static AtomicLong broadCastCounter = new AtomicLong(0);
-
- @Override
- public void resultReceived(IPendingServiceCall arg0) {
- if (_log.isTraceEnabled()) {
- _log.trace("resultReceived:: {}", arg0);
- }
- }
-
- @Override
- public boolean appStart(IScope scope) {
- try {
- OmFileHelper.setOmHome(scope.getResource("/").getFile());
- LabelDao.initLanguageMap();
-
- _log.debug("webAppPath : " + OmFileHelper.getOmHome());
-
- // Only load this Class one time Initially this value might by empty, because the DB is empty yet
- getCryptKey();
-
- // init your handler here
-
- for (String scopeName : scope.getScopeNames()) {
- _log.debug("scopeName :: " + scopeName);
- }
-
- InitializationContainer.initComplete = true;
- // Init properties
- IApplication iapp = (IApplication)Application.get(wicketApplicationName);
- iapp.setXFrameOptions(cfgDao.getConfValue(CONFIG_HEADER_XFRAME, String.class, HEADER_XFRAME_SAMEORIGIN));
- iapp.setContentSecurityPolicy(cfgDao.getConfValue(CONFIG_HEADER_CSP, String.class, HEADER_CSP_SELF));
- EXT_PROCESS_TTL = cfgDao.getConfValue(CONFIG_EXT_PROCESS_TTL, Integer.class, "" + EXT_PROCESS_TTL);
- Version.logOMStarted();
- recordingDao.resetProcessingStatus(); //we are starting so all processing recordings are now errors
- sessionManager.clearCache(); // 'sticky' clients should be cleaned up from DB
- } catch (Exception err) {
- _log.error("[appStart]", err);
- }
- return true;
- }
-
- @SuppressWarnings("unchecked")
- private static Map<String, Object> getConnParams(Object[] params) {
- if (params != null && params.length > 0) {
- return (Map<String, Object>)params[0];
- }
- return new HashMap<>();
- }
-
- @Override
- public boolean roomConnect(IConnection conn, Object[] params) {
- _log.debug("roomConnect : ");
-
- IServiceCapableConnection service = (IServiceCapableConnection) conn;
- String streamId = conn.getClient().getId();
-
- _log.debug("### Client connected to OpenMeetings, register Client StreamId: " + streamId + " scope " + conn.getScope().getName());
-
- // Set StreamId in Client
- service.invoke("setId", new Object[] { streamId }, this);
-
- Map<String, Object> map = conn.getConnectParams();
- String swfURL = map.containsKey("swfUrl") ? (String)map.get("swfUrl") : "";
- String tcUrl = map.containsKey("tcUrl") ? (String)map.get("tcUrl") : "";
- Map<String, Object> connParams = getConnParams(params);
- String uid = (String)connParams.get("uid");
- String securityCode = (String)connParams.get(SECURITY_CODE_PARAM);
- String parentSid = (String)map.get("parentSid");
- if (parentSid == null) {
- parentSid = (String)connParams.get("parentSid");
- }
- Client rcm = new Client();
- rcm.setScope(conn.getScope().getName());
- boolean hibernate = HIBERNATE_SCOPE.equals(rcm.getScope());
- IApplication iapp = (IApplication)Application.get(wicketApplicationName);
- if (!Strings.isEmpty(securityCode)) {
- //this is for external applications like ffmpeg [OPENMEETINGS-1574]
- if (rcm.getRoomId() == null) {
- _log.warn("Trying to enter invalid scope using security code, client is rejected:: " + rcm.getRoomId());
- return rejectClient();
- }
- String _uid = null;
- for (org.apache.openmeetings.db.entity.basic.Client wcl : iapp.getOmRoomClients(rcm.getRoomId())) {
- if (wcl.getSid().equals(securityCode)) {
- _uid = wcl.getUid();
- break;
- }
- }
- if (_uid == null) {
- _log.warn("Client is not found by security id, client is rejected");
- return rejectClient();
- }
- Client parent = sessionManager.getClientByPublicSID(_uid, null);
- if (parent == null || !parent.getScope().equals(rcm.getScope())) {
- _log.warn("Security code is invalid, client is rejected");
- return rejectClient();
- }
- rcm.setUsername(parent.getUsername());
- rcm.setFirstname(parent.getFirstname());
- rcm.setLastname(parent.getLastname());
- rcm.setUserId(parent.getUserId());
- rcm.setPublicSID(UUID.randomUUID().toString());
- rcm.setSecurityCode(_uid);
- Number width = (Number)connParams.get(WIDTH_PARAM);
- Number height = (Number)connParams.get(HEIGHT_PARAM);
- if (width != null && height != null) {
- rcm.setVWidth(width.intValue());
- rcm.setVHeight(height.intValue());
- }
- }
- if (Strings.isEmpty(uid) && Strings.isEmpty(securityCode) && Strings.isEmpty(parentSid)) {
- _log.warn("No UIDs are provided, client is rejected");
- return rejectClient();
- }
- if (hibernate && "noclient".equals(uid)) {
- return true;
- }
-
- if (map.containsKey("screenClient")) {
- Client parent = sessionManager.getClientByPublicSID(parentSid, null);
- if (parent == null) {
- _log.warn("Bad parent for screen-sharing client, client is rejected");
- return rejectClient();
- }
- SessionVariablesUtil.setIsScreenClient(conn.getClient());
- rcm.setUserId(parent.getUserId());
- rcm.setScreenClient(true);
- rcm.setPublicSID(UUID.randomUUID().toString());
- rcm.setStreamPublishName(parentSid);
- }
- rcm.setStreamid(conn.getClient().getId());
- if (rcm.getRoomId() == null && !hibernate) {
- _log.warn("Bad room specified, client is rejected");
- return rejectClient();
- }
- if (Boolean.TRUE.equals(connParams.get(SIP_PARAM))) {
- rcm.setSipTransport(true);
- }
- if (connParams.containsKey("mobileClient")) {
- Sessiondata sd = sessiondataDao.check(parentSid);
- if (sd.getUserId() == null && !hibernate) {
- _log.warn("Attempt of unauthorized room enter, client is rejected");
- return rejectClient();
- }
- rcm.setMobile(true);
- rcm.setUserId(sd.getUserId());
- if (rcm.getUserId() != null) {
- User u = userDao.get(rcm.getUserId());
- if (u == null) {
- _log.error("Attempt of unauthorized room enter: USER not found, client is rejected");
- return rejectClient();
- }
- rcm.setUsername(u.getLogin());
- rcm.setFirstname(u.getFirstname());
- rcm.setLastname(u.getLastname());
- rcm.setEmail(u.getAddress() == null ? null : u.getAddress().getEmail());
- }
- rcm.setSecurityCode(sd.getSessionId());
- rcm.setPublicSID(UUID.randomUUID().toString());
- }
- rcm.setUserport(conn.getRemotePort());
- rcm.setUserip(conn.getRemoteAddress());
- rcm.setSwfurl(swfURL);
- rcm.setTcUrl(tcUrl);
- rcm.setNativeSsl(Boolean.TRUE.equals(connParams.get(NATIVE_SSL_PARAM)));
- if (!Strings.isEmpty(uid)) {
- rcm.setPublicSID(uid);
- }
- rcm = sessionManager.add(iapp.updateClient(rcm, false), null);
- if (rcm == null) {
- _log.warn("Failed to create Client on room connect");
- return false;
- }
-
- SessionVariablesUtil.initClient(conn.getClient(), rcm.getPublicSID());
- //TODO add similar code for other connections, merge with above block
- if (map.containsKey("screenClient")) {
- //TODO add check for room rights
- User u = null;
- Long userId = rcm.getUserId();
- SessionVariablesUtil.setUserId(conn.getClient(), userId);
- if (userId != null) {
- long _uid = userId.longValue();
- u = userDao.get(_uid < 0 ? -_uid : _uid);
- }
- if (u != null) {
- rcm.setUsername(u.getLogin());
- rcm.setFirstname(u.getFirstname());
- rcm.setLastname(u.getLastname());
- }
- _log.debug("publishName :: " + rcm.getStreamPublishName());
- sessionManager.updateClientByStreamId(streamId, rcm, false, null);
- }
-
- // Log the User
- conferenceLogDao.add(ConferenceLog.Type.clientConnect,
- rcm.getUserId(), streamId, null, rcm.getUserip(),
- rcm.getScope());
- return true;
- }
-
- public Map<String, String> screenSharerAction(Map<String, Object> map) {
- Map<String, String> returnMap = new HashMap<>();
- try {
- _log.debug("----------- screenSharerAction ENTER");
- IConnection current = Red5.getConnectionLocal();
-
- Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- if (client != null) {
- boolean changed = false;
- if (Boolean.parseBoolean("" + map.get("stopStreaming")) && client.isStartStreaming()) {
- changed = true;
- client.setStartStreaming(false);
- //Send message to all users
- sendMessageToCurrentScope("stopScreenSharingMessage", client, false);
- WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStoped, client.getStreamPublishName()));
-
- returnMap.put("result", "stopSharingOnly");
- }
- if (Boolean.parseBoolean("" + map.get("stopRecording")) && client.getIsRecording()) {
- changed = true;
- client.setStartRecording(false);
- client.setIsRecording(false);
-
- returnMap.put("result", "stopRecordingOnly");
-
- recordingService.stopRecordAndSave(current.getScope(), client, null);
- }
- if (Boolean.parseBoolean("" + map.get("stopPublishing")) && client.isScreenPublishStarted()) {
- changed = true;
- client.setScreenPublishStarted(false);
- returnMap.put("result", "stopPublishingOnly");
-
- //Send message to all users
- sendMessageToCurrentScope("stopPublishingMessage", client, false);
- }
-
- if (changed) {
- sessionManager.updateClientByStreamId(client.getStreamid(), client, false, null);
-
- if (!client.isStartStreaming() && !client.isStartRecording() && !client.isStreamPublishStarted()) {
- returnMap.put("result", "stopAll");
- }
- }
- }
- _log.debug("----------- screenSharerAction, return: " + returnMap);
- } catch (Exception err) {
- _log.error("[screenSharerAction]", err);
- }
- return returnMap;
- }
-
- public List<Client> checkScreenSharing() {
- try {
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
-
- _log.debug("checkScreenSharing -2- " + streamid);
-
- List<Client> screenSharerList = new LinkedList<>();
-
- Client currentClient = sessionManager.getClientByStreamId(streamid, null);
-
- for (Client rcl : sessionManager.getClientListByRoomAll(currentClient.getRoomId())) {
- if (rcl.isStartStreaming()) {
- screenSharerList.add(rcl);
- }
- }
-
- return screenSharerList;
-
- } catch (Exception err) {
- _log.error("[checkScreenSharing]", err);
- }
- return null;
- }
-
- /**
- *
- * @param map
- * @return returns key,value Map with multiple return values or null in case of exception
- *
- */
- public Map<String, Object> setConnectionAsSharingClient(Map<String, Object> map) {
- try {
- _log.debug("----------- setConnectionAsSharingClient");
- IConnection current = Red5.getConnectionLocal();
-
- Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- if (client != null) {
- boolean startRecording = Boolean.parseBoolean("" + map.get("startRecording"));
- boolean startStreaming = Boolean.parseBoolean("" + map.get("startStreaming"));
- boolean startPublishing = Boolean.parseBoolean("" + map.get("startPublishing")) && (0 == sessionManager.getPublishingCount(client.getRoomId()));
-
- boolean alreadyStreaming = client.isStartStreaming();
- if (startStreaming) {
- client.setStartStreaming(true);
- }
- boolean alreadyRecording = client.isStartRecording();
- if (startRecording) {
- client.setStartRecording(true);
- }
- if (startPublishing) {
- client.setStreamPublishStarted(true);
- }
-
- client.setVX(Double.valueOf("" + map.get("screenX")).intValue());
- client.setVY(Double.valueOf("" + map.get("screenY")).intValue());
- client.setVWidth(Double.valueOf("" + map.get("screenWidth")).intValue());
- client.setVHeight(Double.valueOf("" + map.get("screenHeight")).intValue());
- client.setStreamPublishName("" + map.get("publishName"));
- sessionManager.updateClientByStreamId(current.getClient().getId(), client, false, null);
-
- Map<String, Object> returnMap = new HashMap<>();
- returnMap.put("alreadyPublished", false);
-
- // if is already started screen sharing, then there is no need
- // to start it again
- if (client.isScreenPublishStarted()) {
- returnMap.put("alreadyPublished", true);
- }
-
- _log.debug("screen x,y,width,height {},{},{},{}", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight());
-
- if (startStreaming) {
- if (!alreadyStreaming) {
- returnMap.put("modus", "startStreaming");
-
- _log.debug("start streamPublishStart Is Screen Sharing ");
-
- //Send message to all users
- sendMessageToCurrentScope("newScreenSharing", client, false);
- WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStarted, client.getStreamPublishName()));
- } else {
- _log.warn("Streaming is already started for the client id=" + client.getId() + ". Second request is ignored.");
- }
- }
- if (startRecording) {
- if (!alreadyRecording) {
- returnMap.put("modus", "startRecording");
-
- String recordingName = "Recording " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date());
-
- recordingService.recordMeetingStream(current, client, recordingName, "", false);
- } else {
- _log.warn("Recording is already started for the client id=" + client.getId() + ". Second request is ignored.");
- }
- }
- if (startPublishing) {
- sendMessageToCurrentScope("startedPublishing", new Object[]{client, "rtmp://" + map.get("publishingHost") + ":1935/"
- + map.get("publishingApp") + "/" + map.get("publishingId")}, false, true);
- returnMap.put("modus", "startPublishing");
- }
- return returnMap;
- } else {
- _log.error("[setConnectionAsSharingClient] Could not find Screen Sharing Client " + current.getClient().getId());
- }
- } catch (Exception err) {
- _log.error("[setConnectionAsSharingClient]", err);
- }
- return null;
- }
-
- public List<Long> listRoomBroadcast() {
- Set<Long> broadcastList = new HashSet<>();
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
- for (IConnection conn : current.getScope().getClientConnections()) {
- if (conn != null) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
- if (rcl == null) {
- // continue;
- } else if (rcl.isScreenClient()) {
- // continue;
- } else {
- if (!streamid.equals(rcl.getStreamid())) {
- // It is not needed to send back
- // that event to the actuall
- // Moderator
- // as it will be already triggered
- // in the result of this Function
- // in the Client
- Long id = Long.valueOf(rcl.getBroadCastID());
- if (!broadcastList.contains(id)) {
- broadcastList.add(id);
- }
- }
- }
- }
- }
- return new ArrayList<>(broadcastList);
- }
-
- /**
- * this function is invoked after a reconnect
- *
- * @param newPublicSID
- */
- public boolean overwritePublicSID(String newPublicSID) {
- try {
- _log.debug("----------- overwritePublicSID");
- IConnection current = Red5.getConnectionLocal();
- IClient c = current.getClient();
- Client currentClient = sessionManager.getClientByStreamId(c.getId(), null);
- if (currentClient == null) {
- return false;
- }
- SessionVariablesUtil.initClient(c, newPublicSID);
- currentClient.setPublicSID(newPublicSID);
- sessionManager.updateClientByStreamId(c.getId(), currentClient, false, null);
- return true;
- } catch (Exception err) {
- _log.error("[overwritePublicSID]", err);
- }
- return false;
- }
-
- /**
- * Logic must be before roomDisconnect cause otherwise you cannot throw a
- * message to each one
- *
- */
- @Override
- public void roomLeave(IClient client, IScope room) {
- try {
- _log.debug("[roomLeave] {} {} {} {}", client.getId(), room.getClients().size(), room.getContextPath(), room.getName());
-
- Client rcl = sessionManager.getClientByStreamId(client.getId(), null);
-
- // The Room Client can be null if the Client left the room by using
- // logicalRoomLeave
- if (rcl != null) {
- _log.debug("currentClient IS NOT NULL");
- roomLeaveByScope(rcl, room);
- }
- } catch (Exception err) {
- _log.error("[roomLeave]", err);
- }
- }
-
- public void roomLeaveByScope(String uid, Long roomId) {
- Client rcl = sessionManager.getClientByPublicSID(uid, null);
- IScope scope = getRoomScope("" + roomId);
- _log.debug("[roomLeaveByScope] {} {} {} {}", uid, roomId, rcl, scope);
- if (rcl != null && scope != null) {
- roomLeaveByScope(rcl, scope);
- }
- }
-
- /**
- * Removes the Client from the List, stops recording, adds the Room-Leave
- * event to running recordings, clear Polls and removes Client from any list
- *
- * This function is kind of private/protected as the client won't be able
- * to call it with proper values.
- *
- * @param client
- * @param scope
- */
- public void roomLeaveByScope(Client client, IScope scope) {
- try {
- _log.debug("[roomLeaveByScope] currentClient " + client);
- Long roomId = client.getRoomId();
-
- if (client.isScreenClient() && client.isStartStreaming()) {
- //TODO check others/find better way
- WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStoped, client.getStreamPublishName()));
- }
-
- // Remove User from Sync List's
- if (roomId != null) {
- whiteBoardService.removeUserFromAllLists(scope, client);
- }
-
- _log.debug("removing Username " + client.getUsername() + " "
- + client.getConnectedSince() + " streamid: "
- + client.getStreamid());
-
- // stop and save any recordings
- if (client.getIsRecording()) {
- _log.debug("*** roomLeave Current Client is Recording - stop that");
- if (client.getInterviewPodId() != null) {
- //interview, TODO need better check
- _stopInterviewRecording(client, scope);
- } else {
- recordingService.stopRecordAndSave(scope, client, null);
-
- // set to true and overwrite the default one cause otherwise no
- // notification is send
- client.setIsRecording(true);
- }
- }
- recordingService.stopRecordingShowForClient(scope, client);
-
- // Notify all clients of the same currentScope (room) with domain
- // and room except the current disconnected cause it could throw an exception
- _log.debug("currentScope " + scope);
-
- new MessageSender(scope, "roomDisconnect", client, this) {
- @Override
- public boolean filter(IConnection conn) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
- if (rcl == null) {
- return true;
- }
- boolean isScreen = rcl.isScreenClient();
- if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
- //going to terminate screen sharing started by this client
- ((IServiceCapableConnection) conn).invoke("stopStream", new Object[] { }, callback);
- }
- return isScreen;
- }
- }.start();
-
- if (client.isMobile() || client.isSipTransport()) {
- IApplication app = (IApplication)Application.get(wicketApplicationName);
- app.exit(client.getPublicSID());
- }
- sessionManager.removeClient(client.getStreamid(), null);
- } catch (Exception err) {
- _log.error("[roomLeaveByScope]", err);
- }
- }
-
- /**
- * This method handles the Event after a stream has been added all connected
- * Clients in the same room will get a notification
- *
- */
- /* (non-Javadoc)
- * @see org.red5.server.adapter.MultiThreadedApplicationAdapter#streamPublishStart(org.red5.server.api.stream.IBroadcastStream)
- */
- @Override
- public void streamPublishStart(IBroadcastStream stream) {
- try {
- _log.debug("----------- streamPublishStart");
- IConnection current = Red5.getConnectionLocal();
- final String streamid = current.getClient().getId();
- final Client c = sessionManager.getClientByStreamId(streamid, null);
-
- //We make a second object the has the reference to the object
- //that we will use to send to all participents
- Client clientObjectSendToSync = c;
-
- // Notify all the clients that the stream had been started
- _log.debug("start streamPublishStart broadcast start: " + stream.getPublishedName() + " CONN " + current);
-
- // In case its a screen sharing we start a new Video for that
- if (c.isScreenClient()) {
- c.setScreenPublishStarted(true);
- sessionManager.updateClientByStreamId(streamid, c, false, null);
- }
- if (!c.isMobile() && !Strings.isEmpty(c.getSecurityCode())) {
- c.setBroadCastID(Long.parseLong(stream.getPublishedName()));
- c.setAvsettings("av");
- c.setIsBroadcasting(true);
- if (c.getVWidth() == 0 || c.getVHeight() == 0) {
- c.setVWidth(320);
- c.setVHeight(240);
- }
- sessionManager.updateClientByStreamId(streamid, c, false, null);
- }
-
- _log.debug("newStream SEND: " + c);
-
- // Notify all users of the same Scope
- // We need to iterate through the streams to catch if anybody is recording
- new MessageSender(current, "newStream", clientObjectSendToSync, this) {
- @Override
- public boolean filter(IConnection conn) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-
- if (rcl == null) {
- _log.debug("RCL IS NULL newStream SEND");
- return true;
- }
-
- _log.debug("check send to "+rcl);
-
- if (Strings.isEmpty(rcl.getPublicSID())) {
- _log.debug("publicSID IS NULL newStream SEND");
- return true;
- }
- if (rcl.getIsRecording()) {
- _log.debug("RCL getIsRecording newStream SEND");
- recordingService.addRecordingByStreamId(current, c, rcl.getRecordingId());
- }
- if (rcl.isScreenClient()) {
- _log.debug("RCL getIsScreenClient newStream SEND");
- return true;
- }
-
- if (rcl.getPublicSID().equals(c.getPublicSID())) {
- _log.debug("RCL publicSID is equal newStream SEND");
- return true;
- }
- _log.debug("RCL SEND is equal newStream SEND "+rcl.getPublicSID()+" || "+rcl.getUserport());
- return false;
- }
- }.start();
- } catch (Exception err) {
- _log.error("[streamPublishStart]", err);
- }
- }
-
- public IBroadcastScope getBroadcastScope(IScope scope, String name) {
- IBasicScope basicScope = scope.getBasicScope(ScopeType.BROADCAST, name);
- if (!(basicScope instanceof IBroadcastScope)) {
- return null;
- } else {
- return (IBroadcastScope) basicScope;
- }
- }
-
- /**
- * This method handles the Event after a stream has been removed all
- * connected Clients in the same room will get a notification
- *
- */
- /* (non-Javadoc)
- * @see org.red5.server.adapter.MultiThreadedApplicationAdapter#streamBroadcastClose(org.red5.server.api.stream.IBroadcastStream)
- */
- @Override
- public void streamBroadcastClose(IBroadcastStream stream) {
- // Notify all the clients that the stream had been closed
- _log.debug("start streamBroadcastClose broadcast close: " + stream.getPublishedName());
- try {
- IConnection current = Red5.getConnectionLocal();
- String streamId = current.getClient().getId();
- Client rcl = sessionManager.getClientByStreamId(streamId, null);
-
- if (rcl == null) {
-
- // In case the client has already left(kicked) this message
- // might be thrown later then the RoomLeave
- // event and the currentClient is already gone
- // The second Use-Case where the currentClient is maybe null is
- // if we remove the client because its a Zombie/Ghost
-
- return;
-
- }
- // Notify all the clients that the stream had been started
- _log.debug("streamBroadcastClose : " + rcl + " " + rcl.getStreamid());
- // this close stream event, stop the recording of this stream
- if (rcl.getIsRecording()) {
- _log.debug("*** +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that");
- recordingService.stopRecordingShowForClient(current.getScope(), rcl);
- }
- if (stream.getPublishedName().equals("" + rcl.getBroadCastID())) {
- rcl.setBroadCastID(-1);
- rcl.setIsBroadcasting(false);
- rcl.setAvsettings("n");
- }
- sessionManager.updateClientByStreamId(streamId, rcl, false, null);
- // Notify all clients of the same scope (room)
- sendMessageToCurrentScope("closeStream", rcl, rcl.isMobile());
- } catch (Exception e) {
- _log.error("[streamBroadcastClose]", e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public void setNewCursorPosition(Object item) {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client c = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- @SuppressWarnings("rawtypes")
- Map cursor = (Map) item;
- cursor.put("streamPublishName", c.getStreamPublishName());
-
- sendMessageToCurrentScope("newRed5ScreenCursor", cursor, true, false);
- } catch (Exception err) {
- _log.error("[setNewCursorPosition]", err);
- }
- }
-
- public long removeModerator(String publicSID) {
- try {
- _log.debug("----------- removeModerator: " + publicSID);
-
- Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
-
- if (currentClient == null) {
- return -1L;
- }
- Long roomId = currentClient.getRoomId();
-
- currentClient.setIsMod(false);
- // Put the mod-flag to true for this client
- sessionManager.updateClientByStreamId(currentClient.getStreamid(), currentClient, false, null);
-
- List<Client> currentMods = sessionManager.getCurrentModeratorByRoom(roomId);
-
- sendMessageToCurrentScope("setNewModeratorByList", currentMods, true);
- } catch (Exception err) {
- _log.error("[removeModerator]", err);
- }
- return -1L;
- }
-
- public long switchMicMuted(String publicSID, boolean mute) {
- try {
- _log.debug("----------- switchMicMuted: " + publicSID);
-
- Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
- if (currentClient == null) {
- return -1L;
- }
-
- currentClient.setMicMuted(mute);
- sessionManager.updateClientByStreamId(currentClient.getStreamid(), currentClient, false, null);
-
- Map<Integer, Object> newMessage = new HashMap<>();
- newMessage.put(0, "updateMuteStatus");
- newMessage.put(1, currentClient);
- sendMessageWithClient(newMessage);
- } catch (Exception err) {
- _log.error("[switchMicMuted]", err);
- }
- return 0L;
- }
-
- public boolean getMicMutedByPublicSID(String publicSID) {
- try {
- Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
- if (currentClient == null) {
- return true;
- }
-
- //Put the mod-flag to true for this client
- return currentClient.getMicMuted();
- } catch (Exception err) {
- _log.error("[getMicMutedByPublicSID]",err);
- }
- return true;
- }
-
- public static long nextBroadCastId() {
- return broadCastCounter.getAndIncrement();
- }
-
- /**
- * This method is used to set/update broadCastID of current client
- *
- * @param updateBroadcastId boolean flag
- *
- * @return BroadcastId in case of no errors, -1 otherwise
- */
- public long setUserAVSettings(boolean updateBroadcastId) {
- try {
- String streamid = Red5.getConnectionLocal().getClient().getId();
- _log.debug("----------- setUserAVSettings {}", streamid);
- Client rcl = sessionManager.getClientByStreamId(streamid, null);
- if (rcl == null) {
- _log.warn("Failed to find appropriate clients");
- return -1;
- }
- if (updateBroadcastId) {
- rcl.setBroadCastID(nextBroadCastId());
- sessionManager.updateAVClientByStreamId(streamid, rcl, null);
- }
- return rcl.getBroadCastID();
- } catch (Exception err) {
- _log.error("[setUserAVSettings]", err);
- }
- return -1;
- }
-
- /*
- * checks if the user is allowed to apply for Moderation
- */
- public boolean checkRoomValues(Long roomId) {
- try {
-
- // appointed meeting or moderated Room?
- Room room = roomDao.get(roomId);
-
- // not really - default logic
- if (!room.isAppointment() && room.isModerated()) {
- // if this is a Moderated Room then the Room can be only
- // locked off by the Moderator Bit
- List<Client> clientModeratorListRoom = sessionManager.getCurrentModeratorByRoom(roomId);
-
- // If there is no Moderator yet and we are asking for it
- // then deny it
- // cause at this moment, the user should wait untill a
- // Moderator enters the Room
- return clientModeratorListRoom.size() != 0;
- } else {
- // FIXME: TODO: For Rooms that are created as Appointment we
- // have to check that too
- // but I don't know yet the Logic behind it - swagner 19.06.2009
- return true;
-
- }
- } catch (Exception err) {
- _log.error("[checkRoomValues]", err);
- }
- return false;
- }
-
- /**
- * This function is called once a User enters a Room
- *
- * It contains several different mechanism depending on what roomtype and
- * what options are available for the room to find out if the current user
- * will be a moderator of that room or not<br/>
- * <br/>
- * Some rules:<br/>
- * <ul>
- * <li>If it is a room that was created through the calendar, the user that
- * organized the room will be moderator, the param Boolean becomeModerator
- * will be ignored then</li>
- * <li>In regular rooms you can use the param Boolean becomeModerator to set
- * any user to become a moderator of the room</li>
- * </ul>
- * <br/>
- * If a new moderator is detected a Push Call to all current users of the
- * room is invoked "setNewModeratorByList" to notify them of the new
- * moderator<br/>
- * <br/>
- * At the end of the mechanism a push call with the new client-object
- * and all the informations about the new user is send to every user of the
- * current conference room<br/>
- * <br/>
- *
- * @param roomId - id of the room
- * @param becomeModerator - is user will become moderator
- * @param isSuperModerator - is user super moderator
- * @param groupId - group id of the user
- * @param colorObj - some color
- * @return RoomStatus object
- */
- public RoomStatus setRoomValues(Long roomId, boolean becomeModerator, boolean isSuperModerator, String colorObj) {
- try {
- _log.debug("----------- setRoomValues");
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
- Client client = sessionManager.getClientByStreamId(streamid, null);
- client.setRoomId(roomId);
- client.setRoomEnter(new Date());
-
- client.setUsercolor(colorObj);
-
- Long userId = client.getUserId();
- User u = userId == null ? null : userDao.get(userId > 0 ? userId : -userId);
- // Inject externalUserId if nothing is set yet
- if (client.getExternalUserId() == null && u != null) {
- client.setExternalUserId(u.getExternalId());
- client.setExternalUserType(u.getExternalType());
- }
-
- Room r = roomDao.get(roomId);
- if (!r.isHidden(RoomElement.MicrophoneStatus)) {
- client.setCanGiveAudio(true);
- }
- sessionManager.updateClientByStreamId(streamid, client, true, null); // first save to get valid room count
-
- // Check for Moderation LogicalRoom ENTER
- List<Client> roomClients = sessionManager.getClientListByRoom(roomId);
-
- // Return Object
- RoomStatus roomStatus = new RoomStatus();
- // appointed meeting or moderated Room? => Check Max Users first
- if (isSuperModerator) {
- // This can be set without checking for Moderation Flag
- client.setIsSuperModerator(isSuperModerator);
- client.setIsMod(isSuperModerator);
- } else {
- Set<Room.Right> rr = AuthLevelUtil.getRoomRight(u, r, r.isAppointment() ? appointmentDao.getByRoom(r.getId()) : null, roomClients.size());
- client.setIsSuperModerator(rr.contains(Room.Right.superModerator));
- client.setIsMod(becomeModerator || rr.contains(Room.Right.moderator));
- }
- if (client.getIsMod()) {
- // Update the Client List
- sessionManager.updateClientByStreamId(streamid, client, false, null);
-
- List<Client> modRoomList = sessionManager.getCurrentModeratorByRoom(client.getRoomId());
-
- //Sync message to everybody
- sendMessageToCurrentScope("setNewModeratorByList", modRoomList, false);
- }
-
- //Sync message to everybody
- sendMessageToCurrentScope("addNewUser", client, false);
-
- //Status object for Shared Browsing
- BrowserStatus browserStatus = (BrowserStatus)current.getScope().getAttribute("browserStatus");
-
- if (browserStatus == null) {
- browserStatus = new BrowserStatus();
- }
-
- // RoomStatus roomStatus = new RoomStatus();
-
- // FIXME: Rework Client Object to DTOs
- roomStatus.setClientList(roomClients);
- roomStatus.setBrowserStatus(browserStatus);
-
- return roomStatus;
- } catch (Exception err) {
- _log.error("[setRoomValues]", err);
- }
- return null;
- }
-
- /**
- * this is set initial directly after login/loading language
- *
- * @param SID - id of the session
- * @param userId - id of the user being set
- * @param username - username of the user
- * @param firstname - firstname of the user
- * @param lastname - lastname of the user
- * @return RoomClient in case of everything is OK, null otherwise
- */
- public Client setUsernameAndSession(String SID, Long userId, String username, String firstname, String lastname) {
- try {
- _log.debug("----------- setUsernameAndSession");
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
- Client currentClient = sessionManager.getClientByStreamId(streamid, null);
-
- currentClient.setUsername(username);
- currentClient.setUserId(userId);
- SessionVariablesUtil.setUserId(current.getClient(), userId);
- currentClient.setUserObject(userId, username, firstname, lastname);
-
- // Update Session Data
- _log.debug("UDPATE SESSION " + SID + ", " + userId);
- sessiondataDao.updateUserWithoutSession(SID, userId);
-
- User user = userDao.get(userId);
-
- if (user != null) {
- currentClient.setExternalUserId(user.getExternalId());
- currentClient.setExternalUserType(user.getExternalType());
- }
-
- // only fill this value from User-Record
- // cause invited users have non
- // you cannot set the firstname,lastname from the UserRecord
- User us = userDao.get(userId);
- if (us != null && us.getPictureuri() != null) {
- // set Picture-URI
- currentClient.setPicture_uri(us.getPictureuri());
- }
- sessionManager.updateClientByStreamId(streamid, currentClient, false, null);
- return currentClient;
- } catch (Exception err) {
- _log.error("[setUsername]", err);
- }
- return null;
- }
-
- /**
- * used by the Screen-Sharing Servlet to trigger events
- *
- * @param roomId
- * @param message
- * @return the list of room clients
- */
- public Map<String, Client> sendMessageByRoomAndDomain(Long roomId, Object message) {
- Map<String, Client> roomClientList = new HashMap<>();
- try {
-
- _log.debug("sendMessageByRoomAndDomain " + roomId);
-
- IScope scope = getRoomScope(roomId.toString());
-
- new MessageSender(scope, "newMessageByRoomAndDomain", message, this) {
- @Override
- public boolean filter(IConnection conn) {
- IClient client = conn.getClient();
- return SessionVariablesUtil.isScreenClient(client);
- }
- }.start();
- } catch (Exception err) {
- _log.error("[getClientListBYRoomAndDomain]", err);
- }
- return roomClientList;
- }
-
- public List<Client> getCurrentModeratorList() {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
- Long roomId = client.getRoomId();
- Room r = roomDao.get(roomId);
- if (r != null) {
- return sessionManager.getCurrentModeratorByRoom(roomId);
- }
- } catch (Exception err) {
- _log.error("[getCurrentModerator]", err);
- }
- return null;
- }
-
- /**
- * This Function is triggered from the Whiteboard
- *
- * @param whiteboardObjParam - array of parameters being sended to whiteboard
- * @param whiteboardId - id of whiteboard parameters will be send to
- * @return 1 in case of no errors, -1 otherwise
- */
- public int sendVarsByWhiteboardId(List<?> whiteboardObjParam, Long whiteboardId) {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
- return sendToWhiteboard(client, whiteboardObjParam, whiteboardId);
- } catch (Exception err) {
- _log.error("[sendVarsByWhiteboardId]", err);
- return -1;
- }
- }
-
- private static Point getSize(FileItem fi) {
- Point result = new Point(0, 0);
- if (fi.getWidth() != null && fi.getHeight() != null) {
- result.x = fi.getWidth();
- result.y = fi.getHeight();
- }
- return result;
- }
-
- private static List<?> getWbObject(FileItem fi, String url) {
- Point size = getSize(fi);
- String type = "n/a";
- switch (fi.getType()) {
- case Image:
- type = "image";
- break;
- case Presentation:
- type = "swf";
- break;
- default:
- }
- return Arrays.asList(
- type // 0
- , url // urlname
- , "--dummy--" // baseurl
- , fi.getName() // fileName //3
- , "--dummy--" // moduleName //4
- , "--dummy--" // parentPath //5
- , "--dummy--" // room //6
- , "--dummy--" // domain //7
- , 1 // slideNumber //8
- , 0 // innerx //9
- , 0 // innery //10
- , size.x // innerwidth //11
- , size.y // innerheight //12
- , 20 // zoomlevel //13
- , size.x // initwidth //14
- , size.y // initheight //15
- , 100 // currentzoom //16 FIXME TODO
- , fi.getHash() // uniquObjectSyncName //17
- , fi.getName() // standardFileName //18
- , true // fullFit //19 FIXME TODO
- , 0 // zIndex //-8
- , null //-7
- , 0 // this.counter //-6 FIXME TODO
- , 0 // posx //-5
- , 0 // posy //-4
- , size.x // width //-3
- , size.y // height //-2
- , fi.getHash() // this.currentlayer.name //-1
- );
- }
-
- private static List<?> getMp4WbObject(FileItem fi, String url) {
- Point size = getSize(fi);
- return Arrays.asList(
- "flv" // 0: 'flv'
- , fi.getId() // 1: 7
- , fi.getName() // 2: 'BigBuckBunny_512kb.mp4'
- , url // 3: posterUrl
- , size.x // 4: 416
- , size.y // 5: 240
- , 0 // 6: 1 // z-index
- , fi.getHash() // 7: null //TODO
- , 0 // 8: 0 //TODO // counter
- , 0 // 9: 0 //TODO // x
- , 0 // 10: 0 //TODO // y
- , size.x // 11: 749 // width
- , size.y // 12: 739 // height
- , fi.getHash() // 13: 'flv_1469602000351'
- );
- }
-
- private static void copyFileToRoom(Long roomId, FileItem f) {
- try {
- if (roomId != null && f != null) {
- File mp4 = f.getFile(EXTENSION_MP4);
-
- File targetFolder = OmFileHelper.getStreamsSubDir(roomId);
-
- File target = new File(targetFolder, mp4.getName());
- if (mp4.exists() && !target.exists()) {
- FileUtils.copyFile(mp4, target, false);
- }
- }
- } catch (Exception err) {
- _log.error("[copyFileToCurrentRoom] ", err);
- }
- }
-
- public void sendToWhiteboard(String uid, Long wbId, FileItem fi, String url, boolean clean) {
- ClientSessionInfo csi = sessionManager.getClientByPublicSIDAnyServer(uid);
- if (csi == null) {
- _log.warn("No client was found to send Wml:: {}", uid);
- return;
- }
- Client client = csi.getRcl();
-
- List<?> wbObject = new ArrayList<>();
- switch (fi.getType()) {
- case Image:
- wbObject = getWbObject(fi, url);
- break;
- case Presentation:
- wbObject = getWbObject(fi, url);
- break;
- case Video:
- case Recording:
- wbObject = getMp4WbObject(fi, url);
- copyFileToRoom(client.getRoomId(), fi);
- break;
- default:
- }
- if (clean) {
- Map<String, Object> wbClear = new HashMap<>();
- wbClear.put("id", wbId);
- wbClear.put("param", Arrays.asList("whiteboard", new Date(), "clear", null));
-
- whiteboardCache.get(client.getRoomId(), wbId).clear();
- sendToScope(client.getRoomId(), "sendVarsToWhiteboardById", Arrays.asList(null, wbClear));
- }
- sendToWhiteboard(client, Arrays.asList("whiteboard", new Date(), "draw", wbObject), wbId);
- }
-
- private int sendToWhiteboard(Client client, List<?> wbObj, Long wbId) {
- try {
- // Check if this User is the Mod:
- if (client == null) {
- return -1;
- }
-
- Map<Integer, Object> whiteboardObj = new HashMap<>();
- int i = 0;
- for (Object obj : wbObj) {
- whiteboardObj.put(i++, obj);
- }
-
- Long roomId = client.getRoomId();
-
- // log.debug("***** sendVars: " + whiteboardObj);
-
- // Store event in list
- String action = whiteboardObj.get(2).toString();
-
- if (action.equals("deleteMindMapNodes")) {
- // Simulate Single Delete Events for z-Index
- List<?> actionObject = (List<?>) whiteboardObj.get(3);
-
- @SuppressWarnings("unchecked")
- List<List<?>> itemObjects = (List<List<?>>) actionObject.get(3);
-
- Map<Integer, Object> whiteboardTempObj = new HashMap<>();
- whiteboardTempObj.put(2, "delete");
-
- for (List<?> itemObject : itemObjects) {
- List<Object> tempActionObject = new ArrayList<>();
- tempActionObject.add("mindmapnode");
- tempActionObject.add(itemObject.get(0)); // z-Index -8
- tempActionObject.add(null); // simulate -7
- tempActionObject.add(null); // simulate -6
- tempActionObject.add(null); // simulate -5
- tempActionObject.add(null); // simulate -4
- tempActionObject.add(null); // simulate -3
- tempActionObject.add(null); // simulate -2
- tempActionObject.add(itemObject.get(1)); // Object-Name -1
-
- whiteboardTempObj.put(3, tempActionObject);
-
- whiteboardManager.add(roomId, whiteboardTempObj, wbId);
- }
- } else {
- whiteboardManager.add(roomId, whiteboardObj, wbId);
- }
-
- Map<String, Object> sendObject = new HashMap<>();
- sendObject.put("id", wbId);
- sendObject.put("param", wbObj);
-
- boolean showDrawStatus = getWhiteboardDrawStatus();
-
- sendToScope(roomId, "sendVarsToWhiteboardById", new Object[] { showDrawStatus ? client : null, sendObject });
- } catch (Exception err) {
- _log.error("[sendToWhiteboard]", err);
- return -1;
- }
- return 1;
- }
-
- public int sendMessage(Object newMessage) {
- sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
- return 1;
- }
-
- public int sendMessageAll(Object newMessage) {
- sendMessageToCurrentScope("sendVarsToMessage", newMessage, true);
- return 1;
- }
-
- /**
- * send status for shared browsing to all members except self
- * @param newMessage
- * @return 1
- */
- @SuppressWarnings({ "rawtypes" })
- public int sendBrowserMessageToMembers(Object newMessage) {
- try {
- IConnection current = Red5.getConnectionLocal();
-
- List newMessageList = (List) newMessage;
-
- String action = newMessageList.get(0).toString();
-
- BrowserStatus browserStatus = (BrowserStatus) current.getScope().getAttribute("browserStatus");
-
- if (browserStatus == null) {
- browserStatus = new BrowserStatus();
- }
-
- if (action.equals("initBrowser") || action.equals("newBrowserURL")) {
- browserStatus.setBrowserInited(true);
- browserStatus.setCurrentURL(newMessageList.get(1).toString());
- } else if (action.equals("closeBrowserURL")) {
- browserStatus.setBrowserInited(false);
- }
-
- current.getScope().setAttribute("browserStatus", browserStatus);
-
- sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
-
- } catch (Exception err) {
- _log.error("[sendMessage]", err);
- }
- return 1;
- }
-
- /**
- * wrapper method
- * @param newMessage
- */
- public void sendMessageToMembers(List<?> newMessage) {
- //Sync to all users of current scope
- sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
- }
-
- /**
- * General sync mechanism for all messages that are send from within the
- * scope of the current client, but:
- * <ul>
- * <li>optionally do not send to self (see param: sendSelf)</li>
- * <li>do not send to clients that are screen sharing clients</li>
- * <li>do not send to clients that are audio/video clients (or potentially ones)</li>
- * <li>do not send to connections where no RoomClient is registered</li>
- * </ul>
- *
- * @param remoteMethodName The method to be called
- * @param newMessage parameters
- * @param sendSelf send to the current client as well
- */
- public void sendMessageToCurrentScope(String remoteMethodName, Object newMessage, boolean sendSelf) {
- sendMessageToCurrentScope(remoteMethodName, newMessage, sendSelf, false);
- }
-
- public void sendMessageToCurrentScope(String scopeName, String remoteMethodName, Object newMessage, boolean sendSelf) {
- sendMessageToCurrentScope(scopeName, remoteMethodName, newMessage, sendSelf, false);
- }
-
- public void sendToScope(final Long roomId, String method, Object obj) {
- new MessageSender(getRoomScope("" + roomId), method, obj, this) {
- @Override
- public boolean filter(IConnection conn) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
- return rcl == null || rcl.isScreenClient()
- || rcl.getRoomId() == null || !rcl.getRoomId().equals(roomId) || userDao.get(rcl.getUserId()) == null;
- }
- }.start();
- }
-
- /**
- * Only temporary for load test, with return argument for the client to have a result
- *
- * @param remoteMethodName
- * @param newMessage
- * @param sendSelf
- * @return true
- */
- @Deprecated
- public boolean loadTestSyncMessage(String remoteMethodName, Object newMessage, boolean sendSelf) {
- sendMessageToCurrentScope(remoteMethodName, newMessage, sendSelf, false);
- return true;
- }
-
- /**
- * General sync mechanism for all messages that are send from within the
- * scope of the current client, but:
- * <ul>
- * <li>optionally do not send to self (see param: sendSelf)</li>
- * <li>send to clients that are screen sharing clients based on parameter</li>
- * <li>do not send to clients that are audio/video clients (or potentially ones)</li>
- * <li>do not send to connections where no RoomClient is registered</li>
- * </ul>
- *
- * @param method The method to be called
- * @param msg parameters
- * @param sendSelf send to the current client as well
- * @param sendScreen send to the current client as well
- */
- public void sendMessageToCurrentScope(final String method, final Object msg, final boolean sendSelf, final boolean sendScreen) {
- IConnection conn = Red5.getConnectionLocal();
- if (conn == null) {
- _log.warn("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' {}, {}", method, msg);
- return;
- }
- sendMessageToCurrentScope(conn.getScope().getName(), method, msg, sendSelf, sendScreen);
- }
-
- public void sendMessageToCurrentScope(final String scopeName, final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
- new MessageSender(getRoomScope(scopeName), remoteMethodName, newMessage, this) {
- @Override
- public boolean filter(IConnection conn) {
- IClient client = conn.getClient();
- return (!sendScreen && SessionVariablesUtil.isScreenClient(client))
- || (!sendSelf && current != null && client.getId().equals(current.getClient().getId()));
- }
- }.start();
- }
-
- public static abstract class MessageSender extends Thread {
- final IScope scope;
- final IConnection current;
- final String method;
- final Object msg;
- final IPendingServiceCallback callback;
-
- public MessageSender(final String remoteMethodName, final Object newMessage, IPendingServiceCallback callback) {
- this((IScope)null, remoteMethodName, newMessage, callback);
- }
-
- public MessageSender(IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
- this(Red5.getConnectionLocal(), _scope, method, msg, callback);
- }
-
- public MessageSender(IConnection current, String method, Object msg, IPendingServiceCallback callback) {
- this(current, null, method, msg, callback);
- }
-
- public MessageSender(IConnection current, IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
- this.current = current;
- scope = _scope == null && current != null ? current.getScope() : _scope;
- this.method = method;
- this.msg = msg;
- this.callback = callback;
- }
-
- public abstract boolean filter(IConnection conn);
-
- @Override
- public void run() {
- try {
- if (scope == null) {
- _log.debug("[MessageSender] -> 'Unable to send message to NULL scope' {}, {}", method, msg);
- } else {
- if (_log.isTraceEnabled()) {
- _log.trace("[MessageSender] -> 'sending message' {}, {}", method, msg);
- }
- // Send to all Clients of that Scope(Room)
- int count = 0;
- for (IConnection conn : scope.getClientConnections()) {
- if (conn != null && conn instanceof IServiceCapableConnection) {
- if (filter(conn)) {
- continue;
- }
- ((IServiceCapableConnection) conn).invoke(method, new Object[] { msg }, callback);
- count++;
- }
- }
- if (_log.isTraceEnabled()) {
- _log.trace("[MessageSender] -> 'sending message to {} clients, DONE' {}", count, method);
- }
- }
- } catch (Exception err) {
- _log.error(String.format("[MessageSender -> %s, %s]", method, msg), err);
- }
- }
- }
-
- /**
- * wrapper method
- * @param newMessage
- * @return 1 in case of success, -1 otherwise
- */
- public int sendMessageWithClient(Object newMessage) {
- try {
- sendMessageWithClientWithSyncObject(newMessage, true);
-
- } catch (Exception err) {
- _log.error("[sendMessageWithClient] ", err);
- return -1;
- }
- return 1;
- }
-
- /**
- * wrapper method
- * @param newMessage
- * @param sync
- * @return 1 in case of success, -1 otherwise
- */
- public int sendMessageWithClientWithSyncObject(Object newMessage, boolean sync) {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- Map<String, Object> hsm = new HashMap<>();
- hsm.put("client", currentClient);
- hsm.put("message", newMessage);
-
- //Sync to all users of current scope
- sendMessageToCurrentScope("sendVarsToMessageWithClient", hsm, sync);
-
- } catch (Exception err) {
- _log.error("[sendMessageWithClient] ", err);
- return -1;
- }
- return 1;
- }
-
- /**
- * Function is used to send the kick Trigger at the moment,
- * it sends a general message to a specific clientId
- *
- * @param newMessage
- * @param clientId
- * @return 1 in case of success, -1 otherwise
- */
- public int sendMessageById(Object newMessage, String clientId, IScope scope) {
- try {
- _log.debug("### sendMessageById ###" + clientId);
-
- Map<String, Object> hsm = new HashMap<>();
- hsm.put("message", newMessage);
-
- // broadcast Message to specific user with id inside the same Scope
- for (IConnection conn : scope.getClientConnections()) {
- if (conn != null) {
- if (conn instanceof IServiceCapableConnection) {
- if (conn.getClient().getId().equals(clientId)) {
- ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this);
- }
- }
- }
- }
- } catch (Exception err) {
- _log.error("[sendMessageWithClient] ", err);
- return -1;
- }
- return 1;
- }
-
- /**
- * Sends a message to a user in the same room by its clientId
- *
- * @param newMessage
- * @param clientId
- * @return 1 in case of no exceptions, -1 otherwise
- */
- public int sendMessageWithClientById(Object newMessage, String clientId) {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- Map<String, Object> hsm = new HashMap<>();
- hsm.put("client", currentClient);
- hsm.put("message", newMessage);
-
- // broadcast Message to specific user with id inside the same Scope
- for (IConnection conn : current.getScope().getClientConnections()) {
- if (conn.getClient().getId().equals(clientId)) {
- ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this);
- }
- }
- } catch (Exception err) {
- _log.error("[sendMessageWithClient] ", err);
- return -1;
- }
- return 1;
- }
-
- public void sendMessageWithClientByPublicSID(Object message, String publicSID) {
- try {
- if (publicSID == null) {
- _log.warn("'null' publicSID was passed to sendMessageWithClientByPublicSID");
- return;
- }
-
- // Get Room Id to send it to the correct Scope
- Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
-
- if (currentClient == null) {
- throw new Exception("Could not Find RoomClient on List publicSID: " + publicSID);
- }
- IScope scope = getRoomScope("" + currentClient.getRoomId());
-
- // log.debug("scopeHibernate "+scopeHibernate);
-
- if (scope != null) {
- // Notify the clients of the same scope (room) with userId
-
- for (IConnection conn : scope.getClientConnections()) {
- IClient client = conn.getClient();
- if (SessionVariablesUtil.isScreenClient(client)) {
- // screen sharing clients do not receive events
- continue;
- }
-
- if (publicSID.equals(SessionVariablesUtil.getPublicSID(client))) {
- ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this);
- }
- }
- } else {
- // Scope not yet started
- }
- } catch (Exception err) {
- _log.error("[sendMessageWithClientByPublicSID] ", err);
- }
- }
-
- /**
- * @deprecated this method should be reworked to use a single SQL query in
- * the cache to get any client in the current room that is
- * recording instead of iterating through connections!
- * @return true in case there is recording session, false otherwise, null if any exception happend
- */
- @Deprecated
- public boolean getInterviewRecordingStatus() {
- try {
- IConnection current = Red5.getConnectionLocal();
-
- for (IConnection conn : current.getScope().getClientConnections()) {
- if (conn != null) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-
- if (rcl.getIsRecording()) {
- return true;
- }
- }
- }
- } catch (Exception err) {
- _log.error("[getInterviewRecordingStatus]", err);
- }
- return false;
- }
-
- /**
- * @deprecated @see {@link ScopeApplicationAdapter#getInterviewRecordingStatus()}
- * @return - false if there were existing recording, true if recording was started successfully, null if any exception happens
- */
- @Deprecated
- public boolean startInterviewRecording() {
- try {
- _log.debug("----------- startInterviewRecording");
- IConnection current = Red5.getConnectionLocal();
-
- for (IConnection conn : current.getScope().getClientConnections()) {
- if (conn != null) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-
- if (rcl != null && rcl.getIsRecording()) {
- return false;
- }
- }
- }
- Client current_rcl = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- // Also set the Recording Flag to Record all Participants that enter
- // later
- current_rcl.setIsRecording(true);
- sessionManager.updateClientByStreamId(current.getClient().getId(), current_rcl, false, null);
-
- Map<String, String> interviewStatus = new HashMap<>();
- interviewStatus.put("action", "start");
-
- for (IConnection conn : current.getScope().getClientConnections()) {
- if (conn != null) {
- IClient client = conn.getClient();
- if (SessionVariablesUtil.isScreenClient(client)) {
- // screen sharing clients do not receive events
- continue;
- }
-
- ((IServiceCapableConnection) conn).invoke("interviewStatus", new Object[] { interviewStatus }, this);
- _log.debug("-- startInterviewRecording " + interviewStatus);
- }
- }
- String recordingName = "Interview " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date());
-
- recordingService.recordMeetingStream(current, current_rcl, recordingName, "", true);
-
- return true;
- } catch (Exception err) {
- _log.debug("[startInterviewRecording]", err);
- }
- return false;
- }
-
- @SuppressWarnings({ "rawtypes" })
- public boolean sendRemoteCursorEvent(final String streamid, Map messageObj) {
- new MessageSender("sendRemoteCursorEvent", messageObj, this) {
-
- @Override
- public boolean filter(IConnection conn) {
- IClient client = conn.getClient();
- return !SessionVariablesUtil.isScreenClient(client) || !conn.getClient().getId().equals(streamid);
- }
- }.start();
- return true;
- }
-
- private Long checkRecordingClient(IConnection conn) {
- Long recordingId = null;
- if (conn != null) {
- Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
- if (rcl != null && rcl.getIsRecording()) {
- rcl.setIsRecording(false);
- recordingId = rcl.getRecordingId();
- rcl.setRecordingId(null);
-
- // Reset the Recording Flag to Record all
- // Participants that enter later
- sessionManager.updateClientByStreamId(conn.getClient().getId(), rcl, false, null);
- }
- }
- return recordingId;
- }
-
- /**
- * Stop the recording of the streams and send event to connected users of scope
- *
- * @return true if interview was found
- */
- public boolean stopInterviewRecording() {
- IConnection current = Red5.getConnectionLocal();
- Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
- return _stopInterviewRecording(currentClient, current.getScope());
- }
-
- /**
- * Stop the recording of the streams and send event to connected users of scope
- *
- * @return true if interview was found
- */
- private boolean _stopInterviewRecording(Client currentClient, IScope currentScope) {
- try {
- _log.debug("----------- stopInterviewRecording");
- Long clientRecordingId = currentClient.getRecordingId();
-
- for (IConnection conn : currentScope.getClientConnections()) {
- Long recordingId = checkRecordingClient(conn);
- if (recordingId != null) {
- clientRecordingId = recordingId;
- }
- }
- if (clientRecordingId == null) {
- _log.debug("stopInterviewRecording:: unable to find recording client");
- return false;
- }
-
- recordingService.stopRecordAndSave(scope, currentClient, clientRecordingId);
-
- Map<String, String> interviewStatus = new HashMap<>();
- interviewStatus.put("action", "stop");
-
- sendMessageToCurrentScope("interviewStatus", interviewStatus, true);
- return true;
-
- } catch (Exception err) {
- _log.debug("[stopInterviewRecording]", err);
- }
- return false;
- }
-
- /**
- * Get all ClientList Objects of that room and domain Used in
- * lz.applyForModeration.lzx
- *
- * @return all ClientList Objects of that room
- */
- public List<Client> getClientListScope() {
- try {
- IConnection current = Red5.getConnectionLocal();
- Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
- return sessionManager.getClientListByRoom(currentClient.getRoomId());
- } catch (Exception err) {
- _log.debug("[getClientListScope]", err);
- }
- return new ArrayList<>();
- }
-
- private boolean getWhiteboardDrawStatus() {
- return cfgDao.getWhiteboardDrawStatus();
- }
-
- public String getCryptKey() {
- return cfgDao.getCryptKey();
- }
-
- public IScope getRoomScope(String room) {
- if (Strings.isEmpty(room)) {
- return null;
- } else {
- IScope globalScope = getContext().getGlobalScope();
- IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey);
-
- return webAppKeyScope.getScope(room);
- }
- }
-
- /*
- * SIP transport methods
- */
-
- private List<Long> getVerifiedActiveRoomIds(Server s) {
- List<Long> result = new ArrayList<>(sessionManager.getActiveRoomIdsByServer(s));
- //verify
- for (Iterator<Long> i = result.iterator(); i.hasNext();) {
- Long id = i.next();
- List<Client> rcs = sessionManager.getClientListByRoom(id);
- if (rcs.size() == 0 || (rcs.size() == 1 && rcs.get(0).isSipTransport())) {
- i.remove();
- }
- }
- return result.isEmpty() ? result : roomDao.getSipRooms(result);
- }
-
- private String getSipTransportLastname(Long roomId) {
- return getSipTransportLastname(roomManager.getSipConferenceMembersNumber(roomId));
- }
-
- private static String getSipTransportLastname(Integer c) {
- return (c != null && c > 0) ? "(" + (c - 1) + ")" : "";
- }
-
- public String getSipNumber(Double roomId) {
- Room r = roomDao.get(roomId.longValue());
- if (r != null && r.getConfno() != null) {
- _log.debug("getSipNumber: roomId: {}, sipNumber: {}", new Object[]{roomId, r.getConfno()});
- return r.getConfno();
- }
- return null;
- }
-
- public List<Long> getActiveRoomIds() {
- Set<Long> ids = new HashSet<>();
- ids.addAll(getVerifiedActiveRoomIds(null));
- for (Server s : serverDao.getActiveServers()) {
- ids.addAll(getVerifiedActiveRoomIds(s));
- }
- return new ArrayList<>(ids);
- }
-
- public synchronized int updateSipTransport() {
- _log.debug("----------- updateSipTransport");
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
- Client client = sessionManager.getClientByStreamId(streamid, null);
- Long roomId = client.getRoomId();
- Integer count = roomManager.getSipConferenceMembersNumber(roomId);
- String newNumber = getSipTransportLastname(count);
- _log.debug("getSipConferenceMembersNumber: " + newNumber);
- if (!newNumber.equals(client.getLastname())) {
- client.setLastname(newNumber);
- sessionManager.updateClientByStreamId(streamid, client, false, null);
- _log.debug("updateSipTransport: {}, {}, {}, {}, {}", new Object[] { client.getPublicSID(), client.getRoomId(),
- client.getFirstname(), client.getLastname(), client.getAvsettings() });
- sendMessageWithClient(new String[] { "personal", client.getFirstname(), client.getLastname() });
- }
- return count != null && count > 0 ? count - 1 : 0;
- }
-
- public void setSipTransport(String broadCastId) {
- _log.debug("----------- setSipTransport");
- IConnection current = Red5.getConnectionLocal();
- String streamid = current.getClient().getId();
- // Notify all clients of the same scope (room)
- Client c = sessionManager.getClientByStreamId(streamid, null);
- c.setLastname(getSipTransportLastname(c.getRoomId()));
- c.setBroadCastID(Long.parseLong(broadCastId));
- sessionManager.updateClientByStreamId(streamid, c, false, null);
-
- sendMessageToCurrentScope("addNewUser", c, false);
- }
-}
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java b/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
index 809f471..a3d65a4 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
@@ -41,6 +41,7 @@ public interface IApplication {
String getOmString(String key, long languageId);
String getOmString(String key, final Locale loc, String... params);
Client updateClient(Client rcl, boolean forceSize);
+ org.apache.openmeetings.db.entity.basic.Client getOmOnlineClient(String uid);
List<org.apache.openmeetings.db.entity.basic.Client> getOmRoomClients(Long roomId);
List<org.apache.openmeetings.db.entity.basic.Client> getOmClients(Long userId);
String getOmContactsLink();
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java
index 0192b9a..33c5636 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java
@@ -41,7 +41,8 @@ public class SipDao {
public static final String ASTERISK_OM_FAMILY = "openmeetings";
public static final String ASTERISK_OM_KEY = "rooms";
public static final Long SIP_USER_ID = -1L;
- public static final String SIP_USER_NAME = "SIP Transport";
+ public static final String SIP_FIRST_NAME = "SIP Transport";
+ public static final String SIP_USER_NAME = "--SIP--";
private String sipHostname;
private int sipPort;
private String sipUsername;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/room/Client.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/room/Client.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/room/Client.java
index e85c8e3..2e50de1 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/room/Client.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/room/Client.java
@@ -130,6 +130,12 @@ public class Client implements IClient {
private String publicSID = "";
/**
+ * {@link Client#getSid()} of the client who initiated the connection
+ */
+ @Column(name = "owner_sid")
+ private String ownerSid = null;
+
+ /**
* @see Client#getIsMod()
*/
@Column(name = "is_mod", nullable = false)
@@ -651,6 +657,14 @@ public class Client implements IClient {
this.publicSID = publicSID;
}
+ public String getOwnerSid() {
+ return ownerSid;
+ }
+
+ public void setOwnerSid(String ownerSid) {
+ this.ownerSid = ownerSid;
+ }
+
public boolean getZombieCheckFlag() {
return zombieCheckFlag;
}
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
----------------------------------------------------------------------
diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
index 000dc60..d09f748 100644
--- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
+++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
@@ -43,7 +43,7 @@ import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.apache.commons.codec.binary.Base64;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.label.LabelDao;
import org.apache.openmeetings.db.dao.server.ISessionManager;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
index 6d25195..c031bfc 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
@@ -19,7 +19,9 @@
package org.apache.openmeetings.web.app;
import static org.apache.openmeetings.core.util.WebSocketHelper.sendRoom;
+import static org.apache.openmeetings.db.dao.room.SipDao.SIP_FIRST_NAME;
import static org.apache.openmeetings.db.dao.room.SipDao.SIP_USER_ID;
+import static org.apache.openmeetings.db.dao.room.SipDao.SIP_USER_NAME;
import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
@@ -45,12 +47,11 @@ import java.util.function.Predicate;
import org.apache.directory.api.util.Strings;
import org.apache.openmeetings.IApplication;
import org.apache.openmeetings.core.remote.MainService;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter;
import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.label.LabelDao;
import org.apache.openmeetings.db.dao.log.ConferenceLogDao;
-import org.apache.openmeetings.db.dao.room.SipDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.basic.Client;
import org.apache.openmeetings.db.entity.basic.Client.Activity;
@@ -323,14 +324,12 @@ public class Application extends AuthenticatedWebApplication implements IApplica
}
//FIXME TODO rights
} else if (client == null && rcl.isSipTransport()) {
- if (!getBean(SipDao.class).getUid().equals(rcl.getPublicSID())) {
- return null;
- }
rcl.setPicture_uri("phone.png");
//SipTransport enters the room
User u = new User();
u.setId(SIP_USER_ID);
- u.setFirstname(SipDao.SIP_USER_NAME);
+ u.setLogin(SIP_USER_NAME);
+ u.setFirstname(SIP_FIRST_NAME);
client = new Client(rcl, u);
addOnlineUser(client);
client.setCam(0);
@@ -391,6 +390,11 @@ public class Application extends AuthenticatedWebApplication implements IApplica
return uid == null ? null : ONLINE_USERS.get(uid);
}
+ @Override
+ public Client getOmOnlineClient(String uid) {
+ return getOnlineClient(uid);
+ }
+
public static boolean isUserOnline(Long userId) {
boolean isUserOnline = false;
for (Map.Entry<String, Client> e : ONLINE_USERS.entrySet()) {
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomBroadcaster.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomBroadcaster.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomBroadcaster.java
index 819a877..17a0a57 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomBroadcaster.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomBroadcaster.java
@@ -21,7 +21,7 @@ package org.apache.openmeetings.web.room;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
import static org.apache.openmeetings.web.app.Application.getBean;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter;
import org.apache.openmeetings.core.session.SessionManager;
import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
import org.apache.openmeetings.db.entity.room.Client;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
index e0bef68..341edd5 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
@@ -38,7 +38,7 @@ import java.util.UUID;
import org.apache.directory.api.util.Strings;
import org.apache.openmeetings.core.data.whiteboard.WhiteboardCache;
import org.apache.openmeetings.core.remote.ConferenceLibrary;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter;
import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
import org.apache.openmeetings.db.dao.log.ConferenceLogDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
index b4b056e..7080258 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
@@ -20,7 +20,7 @@ package org.apache.openmeetings.web.room.activities;
import static org.apache.openmeetings.core.util.WebSocketHelper.sendRoom;
import static org.apache.openmeetings.db.dao.room.SipDao.SIP_USER_ID;
-import static org.apache.openmeetings.db.dao.room.SipDao.SIP_USER_NAME;
+import static org.apache.openmeetings.db.dao.room.SipDao.SIP_FIRST_NAME;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
import static org.apache.openmeetings.web.app.Application.getBean;
import static org.apache.openmeetings.web.app.Application.getOnlineClient;
@@ -183,7 +183,7 @@ public class ActivitiesPanel extends BasePanel {
}
String name;
if (SIP_USER_ID.equals(a.getSender())) {
- name = SIP_USER_NAME;
+ name = SIP_FIRST_NAME;
} else {
User u = getBean(UserDao.class).get(a.getSender());
name = self ? getString("1362") : String.format("%s %s", u.getFirstname(), u.getLastname());
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml b/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml
index 7f2bfdc..ecc1248 100644
--- a/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml
+++ b/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml
@@ -41,7 +41,7 @@
<context:component-scan base-package="org.apache.openmeetings" />
<!-- New Class for the Streaming Handlers -->
- <bean id="web.handler" class="org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter" />
+ <bean id="web.handler" class="org.apache.openmeetings.core.remote.ScopeApplicationAdapter" />
<!-- Session configuration start -->
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-web/src/main/webapp/WEB-INF/classes/logback-config.xml
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/webapp/WEB-INF/classes/logback-config.xml b/openmeetings-web/src/main/webapp/WEB-INF/classes/logback-config.xml
index f173c2a..2106686 100644
--- a/openmeetings-web/src/main/webapp/WEB-INF/classes/logback-config.xml
+++ b/openmeetings-web/src/main/webapp/WEB-INF/classes/logback-config.xml
@@ -32,7 +32,7 @@
<ImmediateFlush>true</ImmediateFlush>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
- %5p %d{MM-dd HH:mm:ss.SSS } %c{15}:%L [%t] - %m%n
+ %5p %d{MM-dd HH:mm:ss.SSS } %c{15}:%L [%.15thread] - %m%n
</Pattern>
</layout>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
@@ -48,7 +48,7 @@
</appender>
<appender name="CONSOLE2" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>%5p %d{MM-dd HH:mm:ss.SSS } %F %r %L %c [%t] - %m%n</pattern>
+ <pattern>%5p %d{MM-dd HH:mm:ss.SSS } %r %L %c{15} [%.15thread] - %m%n</pattern>
</layout>
</appender>
<logger name="com.mchange.v2" level="ERROR" />
[2/2] openmeetings git commit: [OPENMEETINGS-1664] sip seems to work
Posted by so...@apache.org.
[OPENMEETINGS-1664] sip seems to work
Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo
Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/8aeb1b30
Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/8aeb1b30
Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/8aeb1b30
Branch: refs/heads/3.3.x
Commit: 8aeb1b306514042be3e89df85b08c1e8b5fa25fd
Parents: 280247c
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Wed Jul 12 23:42:57 2017 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Wed Jul 12 23:42:57 2017 +0700
----------------------------------------------------------------------
.../core/remote/ConferenceLibrary.java | 1 -
.../openmeetings/core/remote/MainService.java | 1 -
.../openmeetings/core/remote/MobileService.java | 5 +-
.../core/remote/RecordingService.java | 1 -
.../core/remote/ScopeApplicationAdapter.java | 1963 ++++++++++++++++++
.../openmeetings/core/remote/UserService.java | 1 -
.../core/remote/WhiteboardService.java | 1 -
.../remote/red5/ScopeApplicationAdapter.java | 1951 -----------------
.../org/apache/openmeetings/IApplication.java | 1 +
.../apache/openmeetings/db/dao/room/SipDao.java | 3 +-
.../openmeetings/db/entity/room/Client.java | 14 +
.../openmeetings/service/user/UserManager.java | 2 +-
.../openmeetings/web/app/Application.java | 16 +-
.../openmeetings/web/room/RoomBroadcaster.java | 2 +-
.../apache/openmeetings/web/room/RoomPanel.java | 2 +-
.../web/room/activities/ActivitiesPanel.java | 4 +-
.../WEB-INF/classes/applicationContext.xml | 2 +-
.../webapp/WEB-INF/classes/logback-config.xml | 4 +-
18 files changed, 2000 insertions(+), 1974 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ConferenceLibrary.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ConferenceLibrary.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ConferenceLibrary.java
index 58c6350..c7d93eb 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ConferenceLibrary.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ConferenceLibrary.java
@@ -29,7 +29,6 @@ import org.apache.openmeetings.core.data.whiteboard.WhiteboardManager;
import org.apache.openmeetings.core.documents.LibraryChartLoader;
import org.apache.openmeetings.core.documents.LibraryDocumentConverter;
import org.apache.openmeetings.core.documents.LibraryWmlLoader;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.db.dao.file.FileExplorerItemDao;
import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.dao.server.SessiondataDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
index 93a2dc9..a63b1af 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
@@ -26,7 +26,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.core.remote.util.SessionVariablesUtil;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MobileService.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MobileService.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MobileService.java
index 9e4f9b4..6ff394e 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MobileService.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MobileService.java
@@ -18,7 +18,7 @@
*/
package org.apache.openmeetings.core.remote;
-import static org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter.nextBroadCastId;
+import static org.apache.openmeetings.core.remote.ScopeApplicationAdapter.nextBroadCastId;
import static org.apache.openmeetings.db.util.LocaleHelper.getCountryName;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DEFAULT_GROUP_ID;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_FRONTEND_REGISTER_KEY;
@@ -39,8 +39,7 @@ import java.util.UUID;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.openmeetings.core.remote.LanguageService.Language;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter.MessageSender;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter.MessageSender;
import org.apache.openmeetings.core.remote.util.SessionVariablesUtil;
import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.basic.ChatDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
index 0b17639..9e90235 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
@@ -29,7 +29,6 @@ import org.apache.openmeetings.core.converter.BaseConverter;
import org.apache.openmeetings.core.data.record.converter.InterviewConverterTask;
import org.apache.openmeetings.core.data.record.converter.RecordingConverterTask;
import org.apache.openmeetings.core.data.record.listener.StreamListener;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.record.RecordingDao;
import org.apache.openmeetings.db.dao.record.RecordingMetaDataDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
new file mode 100644
index 0000000..5f0efe0
--- /dev/null
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
@@ -0,0 +1,1963 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") + you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.core.remote;
+
+import static org.apache.openmeetings.util.OmFileHelper.EXTENSION_MP4;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_EXT_PROCESS_TTL;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_CSP;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_XFRAME;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.EXT_PROCESS_TTL;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_CSP_SELF;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
+
+import java.awt.Point;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.openmeetings.IApplication;
+import org.apache.openmeetings.core.data.conference.RoomManager;
+import org.apache.openmeetings.core.data.whiteboard.WhiteboardCache;
+import org.apache.openmeetings.core.data.whiteboard.WhiteboardManager;
+import org.apache.openmeetings.core.remote.util.SessionVariablesUtil;
+import org.apache.openmeetings.core.util.WebSocketHelper;
+import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
+import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
+import org.apache.openmeetings.db.dao.label.LabelDao;
+import org.apache.openmeetings.db.dao.log.ConferenceLogDao;
+import org.apache.openmeetings.db.dao.record.RecordingDao;
+import org.apache.openmeetings.db.dao.room.RoomDao;
+import org.apache.openmeetings.db.dao.room.SipDao;
+import org.apache.openmeetings.db.dao.server.ISessionManager;
+import org.apache.openmeetings.db.dao.server.ServerDao;
+import org.apache.openmeetings.db.dao.server.SessiondataDao;
+import org.apache.openmeetings.db.dao.user.UserDao;
+import org.apache.openmeetings.db.dto.room.BrowserStatus;
+import org.apache.openmeetings.db.dto.room.RoomStatus;
+import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
+import org.apache.openmeetings.db.entity.file.FileItem;
+import org.apache.openmeetings.db.entity.log.ConferenceLog;
+import org.apache.openmeetings.db.entity.room.Client;
+import org.apache.openmeetings.db.entity.room.Room;
+import org.apache.openmeetings.db.entity.room.Room.RoomElement;
+import org.apache.openmeetings.db.entity.server.Server;
+import org.apache.openmeetings.db.entity.server.Sessiondata;
+import org.apache.openmeetings.db.entity.user.User;
+import org.apache.openmeetings.db.util.AuthLevelUtil;
+import org.apache.openmeetings.util.CalendarPatterns;
+import org.apache.openmeetings.util.InitializationContainer;
+import org.apache.openmeetings.util.OmFileHelper;
+import org.apache.openmeetings.util.OpenmeetingsVariables;
+import org.apache.openmeetings.util.Version;
+import org.apache.openmeetings.util.message.RoomMessage;
+import org.apache.openmeetings.util.message.TextRoomMessage;
+import org.apache.wicket.Application;
+import org.apache.wicket.util.string.Strings;
+import org.red5.logging.Red5LoggerFactory;
+import org.red5.server.adapter.MultiThreadedApplicationAdapter;
+import org.red5.server.api.IClient;
+import org.red5.server.api.IConnection;
+import org.red5.server.api.Red5;
+import org.red5.server.api.scope.IBasicScope;
+import org.red5.server.api.scope.IBroadcastScope;
+import org.red5.server.api.scope.IScope;
+import org.red5.server.api.scope.ScopeType;
+import org.red5.server.api.service.IPendingServiceCall;
+import org.red5.server.api.service.IPendingServiceCallback;
+import org.red5.server.api.service.IServiceCapableConnection;
+import org.red5.server.api.stream.IBroadcastStream;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter implements IPendingServiceCallback {
+ private static final Logger _log = Red5LoggerFactory.getLogger(ScopeApplicationAdapter.class, webAppRootKey);
+ private static final String OWNER_SID_PARAM = "ownerSid";
+ private static final String SECURITY_CODE_PARAM = "securityCode";
+ private static final String WIDTH_PARAM = "width";
+ private static final String HEIGHT_PARAM = "height";
+ private static final String NATIVE_SSL_PARAM = "nativeSsl";
+ public static final String HIBERNATE_SCOPE = "hibernate";
+
+ @Autowired
+ private ISessionManager sessionManager;
+ @Autowired
+ private WhiteboardService whiteBoardService;
+ @Autowired
+ private WhiteboardManager whiteboardManager;
+ @Autowired
+ private WhiteboardCache whiteboardCache;
+ @Autowired
+ private RecordingService recordingService;
+ @Autowired
+ private ConfigurationDao cfgDao;
+ @Autowired
+ private AppointmentDao appointmentDao;
+ @Autowired
+ private SessiondataDao sessiondataDao;
+ @Autowired
+ private RoomManager roomManager;
+ @Autowired
+ private ConferenceLogDao conferenceLogDao;
+ @Autowired
+ private UserDao userDao;
+ @Autowired
+ private RoomDao roomDao;
+ @Autowired
+ private RecordingDao recordingDao;
+ @Autowired
+ private ServerDao serverDao;
+ @Autowired
+ private SipDao sipDao;
+
+ private static AtomicLong broadCastCounter = new AtomicLong(0);
+
+ @Override
+ public void resultReceived(IPendingServiceCall arg0) {
+ if (_log.isTraceEnabled()) {
+ _log.trace("resultReceived:: {}", arg0);
+ }
+ }
+
+ @Override
+ public boolean appStart(IScope scope) {
+ try {
+ OmFileHelper.setOmHome(scope.getResource("/").getFile());
+ LabelDao.initLanguageMap();
+
+ _log.debug("webAppPath : " + OmFileHelper.getOmHome());
+
+ // Only load this Class one time Initially this value might by empty, because the DB is empty yet
+ getCryptKey();
+
+ // init your handler here
+
+ for (String scopeName : scope.getScopeNames()) {
+ _log.debug("scopeName :: " + scopeName);
+ }
+
+ InitializationContainer.initComplete = true;
+ // Init properties
+ IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+ iapp.setXFrameOptions(cfgDao.getConfValue(CONFIG_HEADER_XFRAME, String.class, HEADER_XFRAME_SAMEORIGIN));
+ iapp.setContentSecurityPolicy(cfgDao.getConfValue(CONFIG_HEADER_CSP, String.class, HEADER_CSP_SELF));
+ EXT_PROCESS_TTL = cfgDao.getConfValue(CONFIG_EXT_PROCESS_TTL, Integer.class, "" + EXT_PROCESS_TTL);
+ Version.logOMStarted();
+ recordingDao.resetProcessingStatus(); //we are starting so all processing recordings are now errors
+ sessionManager.clearCache(); // 'sticky' clients should be cleaned up from DB
+ } catch (Exception err) {
+ _log.error("[appStart]", err);
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Map<String, Object> getConnParams(Object[] params) {
+ if (params != null && params.length > 0) {
+ return (Map<String, Object>)params[0];
+ }
+ return new HashMap<>();
+ }
+
+ @Override
+ public boolean roomConnect(IConnection conn, Object[] params) {
+ _log.debug("roomConnect : ");
+
+ IServiceCapableConnection service = (IServiceCapableConnection) conn;
+ String streamId = conn.getClient().getId();
+
+ _log.debug("### Client connected to OpenMeetings, register Client StreamId: {} scope {}", streamId, conn.getScope().getName());
+
+ // Set StreamId in Client
+ service.invoke("setId", new Object[] { streamId }, this);
+
+ Map<String, Object> map = conn.getConnectParams();
+ String swfURL = map.containsKey("swfUrl") ? (String)map.get("swfUrl") : "";
+ String tcUrl = map.containsKey("tcUrl") ? (String)map.get("tcUrl") : "";
+ Map<String, Object> connParams = getConnParams(params);
+ String uid = (String)connParams.get("uid");
+ String securityCode = (String)connParams.get(SECURITY_CODE_PARAM);
+ String ownerSid = (String)connParams.get(OWNER_SID_PARAM);
+ String parentSid = (String)map.get("parentSid");
+ if (parentSid == null) {
+ parentSid = (String)connParams.get("parentSid");
+ }
+ Client rcm = new Client();
+ rcm.setScope(conn.getScope().getName());
+ rcm.setOwnerSid(ownerSid);
+ boolean hibernate = HIBERNATE_SCOPE.equals(rcm.getScope());
+ IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+ if (!Strings.isEmpty(securityCode)) {
+ //this is for external applications like ffmpeg [OPENMEETINGS-1574]
+ if (rcm.getRoomId() == null) {
+ _log.warn("Trying to enter invalid scope using security code, client is rejected:: " + rcm.getRoomId());
+ return rejectClient();
+ }
+ String _uid = null;
+ for (org.apache.openmeetings.db.entity.basic.Client wcl : iapp.getOmRoomClients(rcm.getRoomId())) {
+ if (wcl.getSid().equals(securityCode)) {
+ _uid = wcl.getUid();
+ break;
+ }
+ }
+ if (_uid == null) {
+ _log.warn("Client is not found by security id, client is rejected");
+ return rejectClient();
+ }
+ Client parent = sessionManager.getClientByPublicSID(_uid, null);
+ if (parent == null || !parent.getScope().equals(rcm.getScope())) {
+ _log.warn("Security code is invalid, client is rejected");
+ return rejectClient();
+ }
+ rcm.setUsername(parent.getUsername());
+ rcm.setFirstname(parent.getFirstname());
+ rcm.setLastname(parent.getLastname());
+ rcm.setUserId(parent.getUserId());
+ rcm.setPublicSID(UUID.randomUUID().toString());
+ rcm.setSecurityCode(_uid);
+ Number width = (Number)connParams.get(WIDTH_PARAM);
+ Number height = (Number)connParams.get(HEIGHT_PARAM);
+ if (width != null && height != null) {
+ rcm.setVWidth(width.intValue());
+ rcm.setVHeight(height.intValue());
+ }
+ }
+ if (Strings.isEmpty(uid) && Strings.isEmpty(securityCode) && Strings.isEmpty(parentSid) && Strings.isEmpty(ownerSid)) {
+ _log.warn("No UIDs are provided, client is rejected");
+ return rejectClient();
+ }
+ if (hibernate && "noclient".equals(uid)) {
+ return true;
+ }
+
+ if (map.containsKey("screenClient")) {
+ Client parent = sessionManager.getClientByPublicSID(parentSid, null);
+ if (parent == null) {
+ _log.warn("Bad parent for screen-sharing client, client is rejected");
+ return rejectClient();
+ }
+ SessionVariablesUtil.setIsScreenClient(conn.getClient());
+ rcm.setUserId(parent.getUserId());
+ rcm.setScreenClient(true);
+ rcm.setPublicSID(UUID.randomUUID().toString());
+ rcm.setStreamPublishName(parentSid);
+ }
+ rcm.setStreamid(conn.getClient().getId());
+ if (rcm.getRoomId() == null && !hibernate) {
+ _log.warn("Bad room specified, client is rejected");
+ return rejectClient();
+ }
+ if (connParams.containsKey("mobileClient")) {
+ Sessiondata sd = sessiondataDao.check(parentSid);
+ if (sd.getUserId() == null && !hibernate) {
+ _log.warn("Attempt of unauthorized room enter, client is rejected");
+ return rejectClient();
+ }
+ rcm.setMobile(true);
+ rcm.setUserId(sd.getUserId());
+ if (rcm.getUserId() != null) {
+ User u = userDao.get(rcm.getUserId());
+ if (u == null) {
+ _log.error("Attempt of unauthorized room enter: USER not found, client is rejected");
+ return rejectClient();
+ }
+ rcm.setUsername(u.getLogin());
+ rcm.setFirstname(u.getFirstname());
+ rcm.setLastname(u.getLastname());
+ rcm.setEmail(u.getAddress() == null ? null : u.getAddress().getEmail());
+ }
+ rcm.setSecurityCode(sd.getSessionId());
+ rcm.setPublicSID(UUID.randomUUID().toString());
+ }
+ if (sipDao.getUid() != null && sipDao.getUid().equals(rcm.getOwnerSid())) {
+ rcm.setSipTransport(true);
+ }
+ rcm.setUserport(conn.getRemotePort());
+ rcm.setUserip(conn.getRemoteAddress());
+ rcm.setSwfurl(swfURL);
+ rcm.setTcUrl(tcUrl);
+ rcm.setNativeSsl(Boolean.TRUE.equals(connParams.get(NATIVE_SSL_PARAM)));
+ if (!Strings.isEmpty(uid)) {
+ rcm.setPublicSID(uid);
+ }
+ rcm = sessionManager.add(iapp.updateClient(rcm, false), null);
+ if (rcm == null) {
+ _log.warn("Failed to create Client on room connect");
+ return false;
+ }
+
+ SessionVariablesUtil.initClient(conn.getClient(), rcm.getPublicSID());
+ //TODO add similar code for other connections, merge with above block
+ if (map.containsKey("screenClient")) {
+ //TODO add check for room rights
+ User u = null;
+ Long userId = rcm.getUserId();
+ SessionVariablesUtil.setUserId(conn.getClient(), userId);
+ if (userId != null) {
+ long _uid = userId.longValue();
+ u = userDao.get(_uid < 0 ? -_uid : _uid);
+ }
+ if (u != null) {
+ rcm.setUsername(u.getLogin());
+ rcm.setFirstname(u.getFirstname());
+ rcm.setLastname(u.getLastname());
+ }
+ _log.debug("publishName :: " + rcm.getStreamPublishName());
+ sessionManager.updateClientByStreamId(streamId, rcm, false, null);
+ }
+
+ // Log the User
+ conferenceLogDao.add(ConferenceLog.Type.clientConnect,
+ rcm.getUserId(), streamId, null, rcm.getUserip(),
+ rcm.getScope());
+ return true;
+ }
+
+ public Map<String, String> screenSharerAction(Map<String, Object> map) {
+ Map<String, String> returnMap = new HashMap<>();
+ try {
+ _log.debug("----------- screenSharerAction ENTER");
+ IConnection current = Red5.getConnectionLocal();
+
+ Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ if (client != null) {
+ boolean changed = false;
+ if (Boolean.parseBoolean("" + map.get("stopStreaming")) && client.isStartStreaming()) {
+ changed = true;
+ client.setStartStreaming(false);
+ //Send message to all users
+ sendMessageToCurrentScope("stopScreenSharingMessage", client, false);
+ WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStoped, client.getStreamPublishName()));
+
+ returnMap.put("result", "stopSharingOnly");
+ }
+ if (Boolean.parseBoolean("" + map.get("stopRecording")) && client.getIsRecording()) {
+ changed = true;
+ client.setStartRecording(false);
+ client.setIsRecording(false);
+
+ returnMap.put("result", "stopRecordingOnly");
+
+ recordingService.stopRecordAndSave(current.getScope(), client, null);
+ }
+ if (Boolean.parseBoolean("" + map.get("stopPublishing")) && client.isScreenPublishStarted()) {
+ changed = true;
+ client.setScreenPublishStarted(false);
+ returnMap.put("result", "stopPublishingOnly");
+
+ //Send message to all users
+ sendMessageToCurrentScope("stopPublishingMessage", client, false);
+ }
+
+ if (changed) {
+ sessionManager.updateClientByStreamId(client.getStreamid(), client, false, null);
+
+ if (!client.isStartStreaming() && !client.isStartRecording() && !client.isStreamPublishStarted()) {
+ returnMap.put("result", "stopAll");
+ }
+ }
+ }
+ _log.debug("----------- screenSharerAction, return: " + returnMap);
+ } catch (Exception err) {
+ _log.error("[screenSharerAction]", err);
+ }
+ return returnMap;
+ }
+
+ public List<Client> checkScreenSharing() {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+
+ _log.debug("checkScreenSharing -2- " + streamid);
+
+ List<Client> screenSharerList = new LinkedList<>();
+
+ Client currentClient = sessionManager.getClientByStreamId(streamid, null);
+
+ for (Client rcl : sessionManager.getClientListByRoomAll(currentClient.getRoomId())) {
+ if (rcl.isStartStreaming()) {
+ screenSharerList.add(rcl);
+ }
+ }
+
+ return screenSharerList;
+
+ } catch (Exception err) {
+ _log.error("[checkScreenSharing]", err);
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param map
+ * @return returns key,value Map with multiple return values or null in case of exception
+ *
+ */
+ public Map<String, Object> setConnectionAsSharingClient(Map<String, Object> map) {
+ try {
+ _log.debug("----------- setConnectionAsSharingClient");
+ IConnection current = Red5.getConnectionLocal();
+
+ Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ if (client != null) {
+ boolean startRecording = Boolean.parseBoolean("" + map.get("startRecording"));
+ boolean startStreaming = Boolean.parseBoolean("" + map.get("startStreaming"));
+ boolean startPublishing = Boolean.parseBoolean("" + map.get("startPublishing")) && (0 == sessionManager.getPublishingCount(client.getRoomId()));
+
+ boolean alreadyStreaming = client.isStartStreaming();
+ if (startStreaming) {
+ client.setStartStreaming(true);
+ }
+ boolean alreadyRecording = client.isStartRecording();
+ if (startRecording) {
+ client.setStartRecording(true);
+ }
+ if (startPublishing) {
+ client.setStreamPublishStarted(true);
+ }
+
+ client.setVX(Double.valueOf("" + map.get("screenX")).intValue());
+ client.setVY(Double.valueOf("" + map.get("screenY")).intValue());
+ client.setVWidth(Double.valueOf("" + map.get("screenWidth")).intValue());
+ client.setVHeight(Double.valueOf("" + map.get("screenHeight")).intValue());
+ client.setStreamPublishName("" + map.get("publishName"));
+ sessionManager.updateClientByStreamId(current.getClient().getId(), client, false, null);
+
+ Map<String, Object> returnMap = new HashMap<>();
+ returnMap.put("alreadyPublished", false);
+
+ // if is already started screen sharing, then there is no need
+ // to start it again
+ if (client.isScreenPublishStarted()) {
+ returnMap.put("alreadyPublished", true);
+ }
+
+ _log.debug("screen x,y,width,height {},{},{},{}", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight());
+
+ if (startStreaming) {
+ if (!alreadyStreaming) {
+ returnMap.put("modus", "startStreaming");
+
+ _log.debug("start streamPublishStart Is Screen Sharing ");
+
+ //Send message to all users
+ sendMessageToCurrentScope("newScreenSharing", client, false);
+ WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStarted, client.getStreamPublishName()));
+ } else {
+ _log.warn("Streaming is already started for the client id=" + client.getId() + ". Second request is ignored.");
+ }
+ }
+ if (startRecording) {
+ if (!alreadyRecording) {
+ returnMap.put("modus", "startRecording");
+
+ String recordingName = "Recording " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date());
+
+ recordingService.recordMeetingStream(current, client, recordingName, "", false);
+ } else {
+ _log.warn("Recording is already started for the client id=" + client.getId() + ". Second request is ignored.");
+ }
+ }
+ if (startPublishing) {
+ sendMessageToCurrentScope("startedPublishing", new Object[]{client, "rtmp://" + map.get("publishingHost") + ":1935/"
+ + map.get("publishingApp") + "/" + map.get("publishingId")}, false, true);
+ returnMap.put("modus", "startPublishing");
+ }
+ return returnMap;
+ } else {
+ _log.error("[setConnectionAsSharingClient] Could not find Screen Sharing Client " + current.getClient().getId());
+ }
+ } catch (Exception err) {
+ _log.error("[setConnectionAsSharingClient]", err);
+ }
+ return null;
+ }
+
+ public List<Long> listRoomBroadcast() {
+ Set<Long> broadcastList = new HashSet<>();
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+ for (IConnection conn : current.getScope().getClientConnections()) {
+ if (conn != null) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+ if (rcl == null) {
+ // continue;
+ } else if (rcl.isScreenClient()) {
+ // continue;
+ } else {
+ if (!streamid.equals(rcl.getStreamid())) {
+ // It is not needed to send back
+ // that event to the actuall
+ // Moderator
+ // as it will be already triggered
+ // in the result of this Function
+ // in the Client
+ Long id = Long.valueOf(rcl.getBroadCastID());
+ if (!broadcastList.contains(id)) {
+ broadcastList.add(id);
+ }
+ }
+ }
+ }
+ }
+ return new ArrayList<>(broadcastList);
+ }
+
+ /**
+ * this function is invoked after a reconnect
+ *
+ * @param newPublicSID
+ */
+ public boolean overwritePublicSID(String newPublicSID) {
+ try {
+ _log.debug("----------- overwritePublicSID");
+ IConnection current = Red5.getConnectionLocal();
+ IClient c = current.getClient();
+ Client currentClient = sessionManager.getClientByStreamId(c.getId(), null);
+ if (currentClient == null) {
+ return false;
+ }
+ SessionVariablesUtil.initClient(c, newPublicSID);
+ currentClient.setPublicSID(newPublicSID);
+ sessionManager.updateClientByStreamId(c.getId(), currentClient, false, null);
+ return true;
+ } catch (Exception err) {
+ _log.error("[overwritePublicSID]", err);
+ }
+ return false;
+ }
+
+ /**
+ * Logic must be before roomDisconnect cause otherwise you cannot throw a
+ * message to each one
+ *
+ */
+ @Override
+ public void roomLeave(IClient client, IScope room) {
+ try {
+ _log.debug("[roomLeave] {} {} {} {}", client.getId(), room.getClients().size(), room.getContextPath(), room.getName());
+
+ Client rcl = sessionManager.getClientByStreamId(client.getId(), null);
+
+ // The Room Client can be null if the Client left the room by using
+ // logicalRoomLeave
+ if (rcl != null) {
+ _log.debug("currentClient IS NOT NULL");
+ roomLeaveByScope(rcl, room);
+ }
+ } catch (Exception err) {
+ _log.error("[roomLeave]", err);
+ }
+ }
+
+ public void roomLeaveByScope(String uid, Long roomId) {
+ Client rcl = sessionManager.getClientByPublicSID(uid, null);
+ IScope scope = getRoomScope("" + roomId);
+ _log.debug("[roomLeaveByScope] {} {} {} {}", uid, roomId, rcl, scope);
+ if (rcl != null && scope != null) {
+ roomLeaveByScope(rcl, scope);
+ }
+ }
+
+ /**
+ * Removes the Client from the List, stops recording, adds the Room-Leave
+ * event to running recordings, clear Polls and removes Client from any list
+ *
+ * This function is kind of private/protected as the client won't be able
+ * to call it with proper values.
+ *
+ * @param client
+ * @param scope
+ */
+ public void roomLeaveByScope(Client client, IScope scope) {
+ try {
+ _log.debug("[roomLeaveByScope] currentClient " + client);
+ Long roomId = client.getRoomId();
+
+ if (client.isScreenClient() && client.isStartStreaming()) {
+ //TODO check others/find better way
+ WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.sharingStoped, client.getStreamPublishName()));
+ }
+
+ // Remove User from Sync List's
+ if (roomId != null) {
+ whiteBoardService.removeUserFromAllLists(scope, client);
+ }
+
+ _log.debug("removing Username " + client.getUsername() + " "
+ + client.getConnectedSince() + " streamid: "
+ + client.getStreamid());
+
+ // stop and save any recordings
+ if (client.getIsRecording()) {
+ _log.debug("*** roomLeave Current Client is Recording - stop that");
+ if (client.getInterviewPodId() != null) {
+ //interview, TODO need better check
+ _stopInterviewRecording(client, scope);
+ } else {
+ recordingService.stopRecordAndSave(scope, client, null);
+
+ // set to true and overwrite the default one cause otherwise no
+ // notification is send
+ client.setIsRecording(true);
+ }
+ }
+ recordingService.stopRecordingShowForClient(scope, client);
+
+ // Notify all clients of the same currentScope (room) with domain
+ // and room except the current disconnected cause it could throw an exception
+ _log.debug("currentScope " + scope);
+
+ new MessageSender(scope, "roomDisconnect", client, this) {
+ @Override
+ public boolean filter(IConnection conn) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+ if (rcl == null) {
+ return true;
+ }
+ boolean isScreen = rcl.isScreenClient();
+ if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
+ //going to terminate screen sharing started by this client
+ ((IServiceCapableConnection) conn).invoke("stopStream", new Object[] { }, callback);
+ }
+ return isScreen;
+ }
+ }.start();
+
+ if (client.isMobile() || client.isSipTransport()) {
+ IApplication app = (IApplication)Application.get(wicketApplicationName);
+ app.exit(client.getPublicSID());
+ }
+ sessionManager.removeClient(client.getStreamid(), null);
+ } catch (Exception err) {
+ _log.error("[roomLeaveByScope]", err);
+ }
+ }
+
+ /**
+ * This method handles the Event after a stream has been added all connected
+ * Clients in the same room will get a notification
+ *
+ */
+ /* (non-Javadoc)
+ * @see org.red5.server.adapter.MultiThreadedApplicationAdapter#streamPublishStart(org.red5.server.api.stream.IBroadcastStream)
+ */
+ @Override
+ public void streamPublishStart(IBroadcastStream stream) {
+ try {
+ _log.debug("----------- streamPublishStart");
+ IConnection current = Red5.getConnectionLocal();
+ final String streamid = current.getClient().getId();
+ final Client c = sessionManager.getClientByStreamId(streamid, null);
+
+ //We make a second object the has the reference to the object
+ //that we will use to send to all participents
+ Client clientObjectSendToSync = c;
+
+ // Notify all the clients that the stream had been started
+ _log.debug("start streamPublishStart broadcast start: " + stream.getPublishedName() + " CONN " + current);
+
+ // In case its a screen sharing we start a new Video for that
+ if (c.isScreenClient()) {
+ c.setScreenPublishStarted(true);
+ sessionManager.updateClientByStreamId(streamid, c, false, null);
+ }
+ if (!c.isMobile() && !Strings.isEmpty(c.getSecurityCode())) {
+ c.setBroadCastID(Long.parseLong(stream.getPublishedName()));
+ c.setAvsettings("av");
+ c.setIsBroadcasting(true);
+ if (c.getVWidth() == 0 || c.getVHeight() == 0) {
+ c.setVWidth(320);
+ c.setVHeight(240);
+ }
+ sessionManager.updateClientByStreamId(streamid, c, false, null);
+ }
+
+ _log.debug("newStream SEND: " + c);
+
+ // Notify all users of the same Scope
+ // We need to iterate through the streams to catch if anybody is recording
+ new MessageSender(current, "newStream", clientObjectSendToSync, this) {
+ @Override
+ public boolean filter(IConnection conn) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+
+ if (rcl == null) {
+ _log.debug("RCL IS NULL newStream SEND");
+ return true;
+ }
+
+ _log.debug("check send to "+rcl);
+
+ if (Strings.isEmpty(rcl.getPublicSID())) {
+ _log.debug("publicSID IS NULL newStream SEND");
+ return true;
+ }
+ if (rcl.getIsRecording()) {
+ _log.debug("RCL getIsRecording newStream SEND");
+ recordingService.addRecordingByStreamId(current, c, rcl.getRecordingId());
+ }
+ if (rcl.isScreenClient()) {
+ _log.debug("RCL getIsScreenClient newStream SEND");
+ return true;
+ }
+
+ if (rcl.getPublicSID().equals(c.getPublicSID())) {
+ _log.debug("RCL publicSID is equal newStream SEND");
+ return true;
+ }
+ _log.debug("RCL SEND is equal newStream SEND "+rcl.getPublicSID()+" || "+rcl.getUserport());
+ return false;
+ }
+ }.start();
+ } catch (Exception err) {
+ _log.error("[streamPublishStart]", err);
+ }
+ }
+
+ public IBroadcastScope getBroadcastScope(IScope scope, String name) {
+ IBasicScope basicScope = scope.getBasicScope(ScopeType.BROADCAST, name);
+ if (!(basicScope instanceof IBroadcastScope)) {
+ return null;
+ } else {
+ return (IBroadcastScope) basicScope;
+ }
+ }
+
+ /**
+ * This method handles the Event after a stream has been removed all
+ * connected Clients in the same room will get a notification
+ *
+ */
+ /* (non-Javadoc)
+ * @see org.red5.server.adapter.MultiThreadedApplicationAdapter#streamBroadcastClose(org.red5.server.api.stream.IBroadcastStream)
+ */
+ @Override
+ public void streamBroadcastClose(IBroadcastStream stream) {
+ // Notify all the clients that the stream had been closed
+ _log.debug("start streamBroadcastClose broadcast close: " + stream.getPublishedName());
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ String streamId = current.getClient().getId();
+ Client rcl = sessionManager.getClientByStreamId(streamId, null);
+
+ if (rcl == null) {
+
+ // In case the client has already left(kicked) this message
+ // might be thrown later then the RoomLeave
+ // event and the currentClient is already gone
+ // The second Use-Case where the currentClient is maybe null is
+ // if we remove the client because its a Zombie/Ghost
+
+ return;
+
+ }
+ // Notify all the clients that the stream had been started
+ _log.debug("streamBroadcastClose : " + rcl + " " + rcl.getStreamid());
+ // this close stream event, stop the recording of this stream
+ if (rcl.getIsRecording()) {
+ _log.debug("*** +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that");
+ recordingService.stopRecordingShowForClient(current.getScope(), rcl);
+ }
+ if (stream.getPublishedName().equals("" + rcl.getBroadCastID())) {
+ rcl.setBroadCastID(-1);
+ rcl.setIsBroadcasting(false);
+ rcl.setAvsettings("n");
+ }
+ sessionManager.updateClientByStreamId(streamId, rcl, false, null);
+ // Notify all clients of the same scope (room)
+ sendMessageToCurrentScope("closeStream", rcl, rcl.isMobile());
+ } catch (Exception e) {
+ _log.error("[streamBroadcastClose]", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setNewCursorPosition(Object item) {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client c = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ @SuppressWarnings("rawtypes")
+ Map cursor = (Map) item;
+ cursor.put("streamPublishName", c.getStreamPublishName());
+
+ sendMessageToCurrentScope("newRed5ScreenCursor", cursor, true, false);
+ } catch (Exception err) {
+ _log.error("[setNewCursorPosition]", err);
+ }
+ }
+
+ public long removeModerator(String publicSID) {
+ try {
+ _log.debug("----------- removeModerator: " + publicSID);
+
+ Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
+
+ if (currentClient == null) {
+ return -1L;
+ }
+ Long roomId = currentClient.getRoomId();
+
+ currentClient.setIsMod(false);
+ // Put the mod-flag to true for this client
+ sessionManager.updateClientByStreamId(currentClient.getStreamid(), currentClient, false, null);
+
+ List<Client> currentMods = sessionManager.getCurrentModeratorByRoom(roomId);
+
+ sendMessageToCurrentScope("setNewModeratorByList", currentMods, true);
+ } catch (Exception err) {
+ _log.error("[removeModerator]", err);
+ }
+ return -1L;
+ }
+
+ public long switchMicMuted(String publicSID, boolean mute) {
+ try {
+ _log.debug("----------- switchMicMuted: " + publicSID);
+
+ Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
+ if (currentClient == null) {
+ return -1L;
+ }
+
+ currentClient.setMicMuted(mute);
+ sessionManager.updateClientByStreamId(currentClient.getStreamid(), currentClient, false, null);
+
+ Map<Integer, Object> newMessage = new HashMap<>();
+ newMessage.put(0, "updateMuteStatus");
+ newMessage.put(1, currentClient);
+ sendMessageWithClient(newMessage);
+ } catch (Exception err) {
+ _log.error("[switchMicMuted]", err);
+ }
+ return 0L;
+ }
+
+ public boolean getMicMutedByPublicSID(String publicSID) {
+ try {
+ Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
+ if (currentClient == null) {
+ return true;
+ }
+
+ //Put the mod-flag to true for this client
+ return currentClient.getMicMuted();
+ } catch (Exception err) {
+ _log.error("[getMicMutedByPublicSID]",err);
+ }
+ return true;
+ }
+
+ public static long nextBroadCastId() {
+ return broadCastCounter.getAndIncrement();
+ }
+
+ /**
+ * This method is used to set/update broadCastID of current client
+ *
+ * @param updateBroadcastId boolean flag
+ *
+ * @return BroadcastId in case of no errors, -1 otherwise
+ */
+ public long setUserAVSettings(boolean updateBroadcastId) {
+ try {
+ String streamid = Red5.getConnectionLocal().getClient().getId();
+ _log.debug("----------- setUserAVSettings {}", streamid);
+ Client rcl = sessionManager.getClientByStreamId(streamid, null);
+ if (rcl == null) {
+ _log.warn("Failed to find appropriate clients");
+ return -1;
+ }
+ if (updateBroadcastId) {
+ rcl.setBroadCastID(nextBroadCastId());
+ sessionManager.updateAVClientByStreamId(streamid, rcl, null);
+ }
+ return rcl.getBroadCastID();
+ } catch (Exception err) {
+ _log.error("[setUserAVSettings]", err);
+ }
+ return -1;
+ }
+
+ /*
+ * checks if the user is allowed to apply for Moderation
+ */
+ public boolean checkRoomValues(Long roomId) {
+ try {
+
+ // appointed meeting or moderated Room?
+ Room room = roomDao.get(roomId);
+
+ // not really - default logic
+ if (!room.isAppointment() && room.isModerated()) {
+ // if this is a Moderated Room then the Room can be only
+ // locked off by the Moderator Bit
+ List<Client> clientModeratorListRoom = sessionManager.getCurrentModeratorByRoom(roomId);
+
+ // If there is no Moderator yet and we are asking for it
+ // then deny it
+ // cause at this moment, the user should wait untill a
+ // Moderator enters the Room
+ return clientModeratorListRoom.size() != 0;
+ } else {
+ // FIXME: TODO: For Rooms that are created as Appointment we
+ // have to check that too
+ // but I don't know yet the Logic behind it - swagner 19.06.2009
+ return true;
+
+ }
+ } catch (Exception err) {
+ _log.error("[checkRoomValues]", err);
+ }
+ return false;
+ }
+
+ /**
+ * This function is called once a User enters a Room
+ *
+ * It contains several different mechanism depending on what roomtype and
+ * what options are available for the room to find out if the current user
+ * will be a moderator of that room or not<br/>
+ * <br/>
+ * Some rules:<br/>
+ * <ul>
+ * <li>If it is a room that was created through the calendar, the user that
+ * organized the room will be moderator, the param Boolean becomeModerator
+ * will be ignored then</li>
+ * <li>In regular rooms you can use the param Boolean becomeModerator to set
+ * any user to become a moderator of the room</li>
+ * </ul>
+ * <br/>
+ * If a new moderator is detected a Push Call to all current users of the
+ * room is invoked "setNewModeratorByList" to notify them of the new
+ * moderator<br/>
+ * <br/>
+ * At the end of the mechanism a push call with the new client-object
+ * and all the informations about the new user is send to every user of the
+ * current conference room<br/>
+ * <br/>
+ *
+ * @param roomId - id of the room
+ * @param becomeModerator - is user will become moderator
+ * @param isSuperModerator - is user super moderator
+ * @param groupId - group id of the user
+ * @param colorObj - some color
+ * @return RoomStatus object
+ */
+ public RoomStatus setRoomValues(Long roomId, boolean becomeModerator, boolean isSuperModerator, String colorObj) {
+ try {
+ _log.debug("----------- setRoomValues");
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+ Client client = sessionManager.getClientByStreamId(streamid, null);
+ client.setRoomId(roomId);
+ client.setRoomEnter(new Date());
+
+ client.setUsercolor(colorObj);
+
+ Long userId = client.getUserId();
+ User u = userId == null ? null : userDao.get(userId > 0 ? userId : -userId);
+ // Inject externalUserId if nothing is set yet
+ if (client.getExternalUserId() == null && u != null) {
+ client.setExternalUserId(u.getExternalId());
+ client.setExternalUserType(u.getExternalType());
+ }
+
+ Room r = roomDao.get(roomId);
+ if (!r.isHidden(RoomElement.MicrophoneStatus)) {
+ client.setCanGiveAudio(true);
+ }
+ sessionManager.updateClientByStreamId(streamid, client, true, null); // first save to get valid room count
+
+ // Check for Moderation LogicalRoom ENTER
+ List<Client> roomClients = sessionManager.getClientListByRoom(roomId);
+
+ // Return Object
+ RoomStatus roomStatus = new RoomStatus();
+ // appointed meeting or moderated Room? => Check Max Users first
+ if (isSuperModerator) {
+ // This can be set without checking for Moderation Flag
+ client.setIsSuperModerator(isSuperModerator);
+ client.setIsMod(isSuperModerator);
+ } else {
+ Set<Room.Right> rr = AuthLevelUtil.getRoomRight(u, r, r.isAppointment() ? appointmentDao.getByRoom(r.getId()) : null, roomClients.size());
+ client.setIsSuperModerator(rr.contains(Room.Right.superModerator));
+ client.setIsMod(becomeModerator || rr.contains(Room.Right.moderator));
+ }
+ if (client.getIsMod()) {
+ // Update the Client List
+ sessionManager.updateClientByStreamId(streamid, client, false, null);
+
+ List<Client> modRoomList = sessionManager.getCurrentModeratorByRoom(client.getRoomId());
+
+ //Sync message to everybody
+ sendMessageToCurrentScope("setNewModeratorByList", modRoomList, false);
+ }
+
+ //Sync message to everybody
+ sendMessageToCurrentScope("addNewUser", client, false);
+
+ //Status object for Shared Browsing
+ BrowserStatus browserStatus = (BrowserStatus)current.getScope().getAttribute("browserStatus");
+
+ if (browserStatus == null) {
+ browserStatus = new BrowserStatus();
+ }
+
+ // RoomStatus roomStatus = new RoomStatus();
+
+ // FIXME: Rework Client Object to DTOs
+ roomStatus.setClientList(roomClients);
+ roomStatus.setBrowserStatus(browserStatus);
+
+ return roomStatus;
+ } catch (Exception err) {
+ _log.error("[setRoomValues]", err);
+ }
+ return null;
+ }
+
+ /**
+ * this is set initial directly after login/loading language
+ *
+ * @param SID - id of the session
+ * @param userId - id of the user being set
+ * @param username - username of the user
+ * @param firstname - firstname of the user
+ * @param lastname - lastname of the user
+ * @return RoomClient in case of everything is OK, null otherwise
+ */
+ public Client setUsernameAndSession(String SID, Long userId, String username, String firstname, String lastname) {
+ try {
+ _log.debug("----------- setUsernameAndSession");
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+ Client currentClient = sessionManager.getClientByStreamId(streamid, null);
+
+ currentClient.setUsername(username);
+ currentClient.setUserId(userId);
+ SessionVariablesUtil.setUserId(current.getClient(), userId);
+ currentClient.setUserObject(userId, username, firstname, lastname);
+
+ // Update Session Data
+ _log.debug("UDPATE SESSION " + SID + ", " + userId);
+ sessiondataDao.updateUserWithoutSession(SID, userId);
+
+ User user = userDao.get(userId);
+
+ if (user != null) {
+ currentClient.setExternalUserId(user.getExternalId());
+ currentClient.setExternalUserType(user.getExternalType());
+ }
+
+ // only fill this value from User-Record
+ // cause invited users have non
+ // you cannot set the firstname,lastname from the UserRecord
+ User us = userDao.get(userId);
+ if (us != null && us.getPictureuri() != null) {
+ // set Picture-URI
+ currentClient.setPicture_uri(us.getPictureuri());
+ }
+ sessionManager.updateClientByStreamId(streamid, currentClient, false, null);
+ return currentClient;
+ } catch (Exception err) {
+ _log.error("[setUsername]", err);
+ }
+ return null;
+ }
+
+ /**
+ * used by the Screen-Sharing Servlet to trigger events
+ *
+ * @param roomId
+ * @param message
+ * @return the list of room clients
+ */
+ public Map<String, Client> sendMessageByRoomAndDomain(Long roomId, Object message) {
+ Map<String, Client> roomClientList = new HashMap<>();
+ try {
+
+ _log.debug("sendMessageByRoomAndDomain " + roomId);
+
+ IScope scope = getRoomScope(roomId.toString());
+
+ new MessageSender(scope, "newMessageByRoomAndDomain", message, this) {
+ @Override
+ public boolean filter(IConnection conn) {
+ IClient client = conn.getClient();
+ return SessionVariablesUtil.isScreenClient(client);
+ }
+ }.start();
+ } catch (Exception err) {
+ _log.error("[getClientListBYRoomAndDomain]", err);
+ }
+ return roomClientList;
+ }
+
+ public List<Client> getCurrentModeratorList() {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+ Long roomId = client.getRoomId();
+ Room r = roomDao.get(roomId);
+ if (r != null) {
+ return sessionManager.getCurrentModeratorByRoom(roomId);
+ }
+ } catch (Exception err) {
+ _log.error("[getCurrentModerator]", err);
+ }
+ return null;
+ }
+
+ /**
+ * This Function is triggered from the Whiteboard
+ *
+ * @param whiteboardObjParam - array of parameters being sended to whiteboard
+ * @param whiteboardId - id of whiteboard parameters will be send to
+ * @return 1 in case of no errors, -1 otherwise
+ */
+ public int sendVarsByWhiteboardId(List<?> whiteboardObjParam, Long whiteboardId) {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+ return sendToWhiteboard(client, whiteboardObjParam, whiteboardId);
+ } catch (Exception err) {
+ _log.error("[sendVarsByWhiteboardId]", err);
+ return -1;
+ }
+ }
+
+ private static Point getSize(FileItem fi) {
+ Point result = new Point(0, 0);
+ if (fi.getWidth() != null && fi.getHeight() != null) {
+ result.x = fi.getWidth();
+ result.y = fi.getHeight();
+ }
+ return result;
+ }
+
+ private static List<?> getWbObject(FileItem fi, String url) {
+ Point size = getSize(fi);
+ String type = "n/a";
+ switch (fi.getType()) {
+ case Image:
+ type = "image";
+ break;
+ case Presentation:
+ type = "swf";
+ break;
+ default:
+ }
+ return Arrays.asList(
+ type // 0
+ , url // urlname
+ , "--dummy--" // baseurl
+ , fi.getName() // fileName //3
+ , "--dummy--" // moduleName //4
+ , "--dummy--" // parentPath //5
+ , "--dummy--" // room //6
+ , "--dummy--" // domain //7
+ , 1 // slideNumber //8
+ , 0 // innerx //9
+ , 0 // innery //10
+ , size.x // innerwidth //11
+ , size.y // innerheight //12
+ , 20 // zoomlevel //13
+ , size.x // initwidth //14
+ , size.y // initheight //15
+ , 100 // currentzoom //16 FIXME TODO
+ , fi.getHash() // uniquObjectSyncName //17
+ , fi.getName() // standardFileName //18
+ , true // fullFit //19 FIXME TODO
+ , 0 // zIndex //-8
+ , null //-7
+ , 0 // this.counter //-6 FIXME TODO
+ , 0 // posx //-5
+ , 0 // posy //-4
+ , size.x // width //-3
+ , size.y // height //-2
+ , fi.getHash() // this.currentlayer.name //-1
+ );
+ }
+
+ private static List<?> getMp4WbObject(FileItem fi, String url) {
+ Point size = getSize(fi);
+ return Arrays.asList(
+ "flv" // 0: 'flv'
+ , fi.getId() // 1: 7
+ , fi.getName() // 2: 'BigBuckBunny_512kb.mp4'
+ , url // 3: posterUrl
+ , size.x // 4: 416
+ , size.y // 5: 240
+ , 0 // 6: 1 // z-index
+ , fi.getHash() // 7: null //TODO
+ , 0 // 8: 0 //TODO // counter
+ , 0 // 9: 0 //TODO // x
+ , 0 // 10: 0 //TODO // y
+ , size.x // 11: 749 // width
+ , size.y // 12: 739 // height
+ , fi.getHash() // 13: 'flv_1469602000351'
+ );
+ }
+
+ private static void copyFileToRoom(Long roomId, FileItem f) {
+ try {
+ if (roomId != null && f != null) {
+ File mp4 = f.getFile(EXTENSION_MP4);
+
+ File targetFolder = OmFileHelper.getStreamsSubDir(roomId);
+
+ File target = new File(targetFolder, mp4.getName());
+ if (mp4.exists() && !target.exists()) {
+ FileUtils.copyFile(mp4, target, false);
+ }
+ }
+ } catch (Exception err) {
+ _log.error("[copyFileToCurrentRoom] ", err);
+ }
+ }
+
+ public void sendToWhiteboard(String uid, Long wbId, FileItem fi, String url, boolean clean) {
+ ClientSessionInfo csi = sessionManager.getClientByPublicSIDAnyServer(uid);
+ if (csi == null) {
+ _log.warn("No client was found to send Wml:: {}", uid);
+ return;
+ }
+ Client client = csi.getRcl();
+
+ List<?> wbObject = new ArrayList<>();
+ switch (fi.getType()) {
+ case Image:
+ wbObject = getWbObject(fi, url);
+ break;
+ case Presentation:
+ wbObject = getWbObject(fi, url);
+ break;
+ case Video:
+ case Recording:
+ wbObject = getMp4WbObject(fi, url);
+ copyFileToRoom(client.getRoomId(), fi);
+ break;
+ default:
+ }
+ if (clean) {
+ Map<String, Object> wbClear = new HashMap<>();
+ wbClear.put("id", wbId);
+ wbClear.put("param", Arrays.asList("whiteboard", new Date(), "clear", null));
+
+ whiteboardCache.get(client.getRoomId(), wbId).clear();
+ sendToScope(client.getRoomId(), "sendVarsToWhiteboardById", Arrays.asList(null, wbClear));
+ }
+ sendToWhiteboard(client, Arrays.asList("whiteboard", new Date(), "draw", wbObject), wbId);
+ }
+
+ private int sendToWhiteboard(Client client, List<?> wbObj, Long wbId) {
+ try {
+ // Check if this User is the Mod:
+ if (client == null) {
+ return -1;
+ }
+
+ Map<Integer, Object> whiteboardObj = new HashMap<>();
+ int i = 0;
+ for (Object obj : wbObj) {
+ whiteboardObj.put(i++, obj);
+ }
+
+ Long roomId = client.getRoomId();
+
+ // log.debug("***** sendVars: " + whiteboardObj);
+
+ // Store event in list
+ String action = whiteboardObj.get(2).toString();
+
+ if (action.equals("deleteMindMapNodes")) {
+ // Simulate Single Delete Events for z-Index
+ List<?> actionObject = (List<?>) whiteboardObj.get(3);
+
+ @SuppressWarnings("unchecked")
+ List<List<?>> itemObjects = (List<List<?>>) actionObject.get(3);
+
+ Map<Integer, Object> whiteboardTempObj = new HashMap<>();
+ whiteboardTempObj.put(2, "delete");
+
+ for (List<?> itemObject : itemObjects) {
+ List<Object> tempActionObject = new ArrayList<>();
+ tempActionObject.add("mindmapnode");
+ tempActionObject.add(itemObject.get(0)); // z-Index -8
+ tempActionObject.add(null); // simulate -7
+ tempActionObject.add(null); // simulate -6
+ tempActionObject.add(null); // simulate -5
+ tempActionObject.add(null); // simulate -4
+ tempActionObject.add(null); // simulate -3
+ tempActionObject.add(null); // simulate -2
+ tempActionObject.add(itemObject.get(1)); // Object-Name -1
+
+ whiteboardTempObj.put(3, tempActionObject);
+
+ whiteboardManager.add(roomId, whiteboardTempObj, wbId);
+ }
+ } else {
+ whiteboardManager.add(roomId, whiteboardObj, wbId);
+ }
+
+ Map<String, Object> sendObject = new HashMap<>();
+ sendObject.put("id", wbId);
+ sendObject.put("param", wbObj);
+
+ boolean showDrawStatus = getWhiteboardDrawStatus();
+
+ sendToScope(roomId, "sendVarsToWhiteboardById", new Object[] { showDrawStatus ? client : null, sendObject });
+ } catch (Exception err) {
+ _log.error("[sendToWhiteboard]", err);
+ return -1;
+ }
+ return 1;
+ }
+
+ public int sendMessage(Object newMessage) {
+ sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
+ return 1;
+ }
+
+ public int sendMessageAll(Object newMessage) {
+ sendMessageToCurrentScope("sendVarsToMessage", newMessage, true);
+ return 1;
+ }
+
+ /**
+ * send status for shared browsing to all members except self
+ * @param newMessage
+ * @return 1
+ */
+ @SuppressWarnings({ "rawtypes" })
+ public int sendBrowserMessageToMembers(Object newMessage) {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+
+ List newMessageList = (List) newMessage;
+
+ String action = newMessageList.get(0).toString();
+
+ BrowserStatus browserStatus = (BrowserStatus) current.getScope().getAttribute("browserStatus");
+
+ if (browserStatus == null) {
+ browserStatus = new BrowserStatus();
+ }
+
+ if (action.equals("initBrowser") || action.equals("newBrowserURL")) {
+ browserStatus.setBrowserInited(true);
+ browserStatus.setCurrentURL(newMessageList.get(1).toString());
+ } else if (action.equals("closeBrowserURL")) {
+ browserStatus.setBrowserInited(false);
+ }
+
+ current.getScope().setAttribute("browserStatus", browserStatus);
+
+ sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
+
+ } catch (Exception err) {
+ _log.error("[sendMessage]", err);
+ }
+ return 1;
+ }
+
+ /**
+ * wrapper method
+ * @param newMessage
+ */
+ public void sendMessageToMembers(List<?> newMessage) {
+ //Sync to all users of current scope
+ sendMessageToCurrentScope("sendVarsToMessage", newMessage, false);
+ }
+
+ /**
+ * General sync mechanism for all messages that are send from within the
+ * scope of the current client, but:
+ * <ul>
+ * <li>optionally do not send to self (see param: sendSelf)</li>
+ * <li>do not send to clients that are screen sharing clients</li>
+ * <li>do not send to clients that are audio/video clients (or potentially ones)</li>
+ * <li>do not send to connections where no RoomClient is registered</li>
+ * </ul>
+ *
+ * @param remoteMethodName The method to be called
+ * @param newMessage parameters
+ * @param sendSelf send to the current client as well
+ */
+ public void sendMessageToCurrentScope(String remoteMethodName, Object newMessage, boolean sendSelf) {
+ sendMessageToCurrentScope(remoteMethodName, newMessage, sendSelf, false);
+ }
+
+ public void sendMessageToCurrentScope(String scopeName, String remoteMethodName, Object newMessage, boolean sendSelf) {
+ sendMessageToCurrentScope(scopeName, remoteMethodName, newMessage, sendSelf, false);
+ }
+
+ public void sendToScope(final Long roomId, String method, Object obj) {
+ new MessageSender(getRoomScope("" + roomId), method, obj, this) {
+ @Override
+ public boolean filter(IConnection conn) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+ return rcl == null || rcl.isScreenClient()
+ || rcl.getRoomId() == null || !rcl.getRoomId().equals(roomId) || userDao.get(rcl.getUserId()) == null;
+ }
+ }.start();
+ }
+
+ /**
+ * Only temporary for load test, with return argument for the client to have a result
+ *
+ * @param remoteMethodName
+ * @param newMessage
+ * @param sendSelf
+ * @return true
+ */
+ @Deprecated
+ public boolean loadTestSyncMessage(String remoteMethodName, Object newMessage, boolean sendSelf) {
+ sendMessageToCurrentScope(remoteMethodName, newMessage, sendSelf, false);
+ return true;
+ }
+
+ /**
+ * General sync mechanism for all messages that are send from within the
+ * scope of the current client, but:
+ * <ul>
+ * <li>optionally do not send to self (see param: sendSelf)</li>
+ * <li>send to clients that are screen sharing clients based on parameter</li>
+ * <li>do not send to clients that are audio/video clients (or potentially ones)</li>
+ * <li>do not send to connections where no RoomClient is registered</li>
+ * </ul>
+ *
+ * @param method The method to be called
+ * @param msg parameters
+ * @param sendSelf send to the current client as well
+ * @param sendScreen send to the current client as well
+ */
+ public void sendMessageToCurrentScope(final String method, final Object msg, final boolean sendSelf, final boolean sendScreen) {
+ IConnection conn = Red5.getConnectionLocal();
+ if (conn == null) {
+ _log.warn("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' {}, {}", method, msg);
+ return;
+ }
+ sendMessageToCurrentScope(conn.getScope().getName(), method, msg, sendSelf, sendScreen);
+ }
+
+ public void sendMessageToCurrentScope(final String scopeName, final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
+ new MessageSender(getRoomScope(scopeName), remoteMethodName, newMessage, this) {
+ @Override
+ public boolean filter(IConnection conn) {
+ IClient client = conn.getClient();
+ return (!sendScreen && SessionVariablesUtil.isScreenClient(client))
+ || (!sendSelf && current != null && client.getId().equals(current.getClient().getId()));
+ }
+ }.start();
+ }
+
+ public static abstract class MessageSender extends Thread {
+ final IScope scope;
+ final IConnection current;
+ final String method;
+ final Object msg;
+ final IPendingServiceCallback callback;
+
+ public MessageSender(final String remoteMethodName, final Object newMessage, IPendingServiceCallback callback) {
+ this((IScope)null, remoteMethodName, newMessage, callback);
+ }
+
+ public MessageSender(IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
+ this(Red5.getConnectionLocal(), _scope, method, msg, callback);
+ }
+
+ public MessageSender(IConnection current, String method, Object msg, IPendingServiceCallback callback) {
+ this(current, null, method, msg, callback);
+ }
+
+ public MessageSender(IConnection current, IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
+ this.current = current;
+ scope = _scope == null && current != null ? current.getScope() : _scope;
+ this.method = method;
+ this.msg = msg;
+ this.callback = callback;
+ }
+
+ public abstract boolean filter(IConnection conn);
+
+ @Override
+ public void run() {
+ try {
+ if (scope == null) {
+ _log.debug("[MessageSender] -> 'Unable to send message to NULL scope' {}, {}", method, msg);
+ } else {
+ if (_log.isTraceEnabled()) {
+ _log.trace("[MessageSender] -> 'sending message' {}, {}", method, msg);
+ }
+ // Send to all Clients of that Scope(Room)
+ int count = 0;
+ for (IConnection conn : scope.getClientConnections()) {
+ if (conn != null && conn instanceof IServiceCapableConnection) {
+ if (filter(conn)) {
+ continue;
+ }
+ ((IServiceCapableConnection) conn).invoke(method, new Object[] { msg }, callback);
+ count++;
+ }
+ }
+ if (_log.isTraceEnabled()) {
+ _log.trace("[MessageSender] -> 'sending message to {} clients, DONE' {}", count, method);
+ }
+ }
+ } catch (Exception err) {
+ _log.error(String.format("[MessageSender -> %s, %s]", method, msg), err);
+ }
+ }
+ }
+
+ /**
+ * wrapper method
+ * @param newMessage
+ * @return 1 in case of success, -1 otherwise
+ */
+ public int sendMessageWithClient(Object newMessage) {
+ try {
+ sendMessageWithClientWithSyncObject(newMessage, true);
+
+ } catch (Exception err) {
+ _log.error("[sendMessageWithClient] ", err);
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * wrapper method
+ * @param newMessage
+ * @param sync
+ * @return 1 in case of success, -1 otherwise
+ */
+ public int sendMessageWithClientWithSyncObject(Object newMessage, boolean sync) {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ Map<String, Object> hsm = new HashMap<>();
+ hsm.put("client", currentClient);
+ hsm.put("message", newMessage);
+
+ //Sync to all users of current scope
+ sendMessageToCurrentScope("sendVarsToMessageWithClient", hsm, sync);
+
+ } catch (Exception err) {
+ _log.error("[sendMessageWithClient] ", err);
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Function is used to send the kick Trigger at the moment,
+ * it sends a general message to a specific clientId
+ *
+ * @param newMessage
+ * @param clientId
+ * @return 1 in case of success, -1 otherwise
+ */
+ public int sendMessageById(Object newMessage, String clientId, IScope scope) {
+ try {
+ _log.debug("### sendMessageById ###" + clientId);
+
+ Map<String, Object> hsm = new HashMap<>();
+ hsm.put("message", newMessage);
+
+ // broadcast Message to specific user with id inside the same Scope
+ for (IConnection conn : scope.getClientConnections()) {
+ if (conn != null) {
+ if (conn instanceof IServiceCapableConnection) {
+ if (conn.getClient().getId().equals(clientId)) {
+ ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this);
+ }
+ }
+ }
+ }
+ } catch (Exception err) {
+ _log.error("[sendMessageWithClient] ", err);
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Sends a message to a user in the same room by its clientId
+ *
+ * @param newMessage
+ * @param clientId
+ * @return 1 in case of no exceptions, -1 otherwise
+ */
+ public int sendMessageWithClientById(Object newMessage, String clientId) {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ Map<String, Object> hsm = new HashMap<>();
+ hsm.put("client", currentClient);
+ hsm.put("message", newMessage);
+
+ // broadcast Message to specific user with id inside the same Scope
+ for (IConnection conn : current.getScope().getClientConnections()) {
+ if (conn.getClient().getId().equals(clientId)) {
+ ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this);
+ }
+ }
+ } catch (Exception err) {
+ _log.error("[sendMessageWithClient] ", err);
+ return -1;
+ }
+ return 1;
+ }
+
+ public void sendMessageWithClientByPublicSID(Object message, String publicSID) {
+ try {
+ if (publicSID == null) {
+ _log.warn("'null' publicSID was passed to sendMessageWithClientByPublicSID");
+ return;
+ }
+
+ // Get Room Id to send it to the correct Scope
+ Client currentClient = sessionManager.getClientByPublicSID(publicSID, null);
+
+ if (currentClient == null) {
+ throw new Exception("Could not Find RoomClient on List publicSID: " + publicSID);
+ }
+ IScope scope = getRoomScope("" + currentClient.getRoomId());
+
+ // log.debug("scopeHibernate "+scopeHibernate);
+
+ if (scope != null) {
+ // Notify the clients of the same scope (room) with userId
+
+ for (IConnection conn : scope.getClientConnections()) {
+ IClient client = conn.getClient();
+ if (SessionVariablesUtil.isScreenClient(client)) {
+ // screen sharing clients do not receive events
+ continue;
+ }
+
+ if (publicSID.equals(SessionVariablesUtil.getPublicSID(client))) {
+ ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this);
+ }
+ }
+ } else {
+ // Scope not yet started
+ }
+ } catch (Exception err) {
+ _log.error("[sendMessageWithClientByPublicSID] ", err);
+ }
+ }
+
+ /**
+ * @deprecated this method should be reworked to use a single SQL query in
+ * the cache to get any client in the current room that is
+ * recording instead of iterating through connections!
+ * @return true in case there is recording session, false otherwise, null if any exception happend
+ */
+ @Deprecated
+ public boolean getInterviewRecordingStatus() {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+
+ for (IConnection conn : current.getScope().getClientConnections()) {
+ if (conn != null) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+
+ if (rcl.getIsRecording()) {
+ return true;
+ }
+ }
+ }
+ } catch (Exception err) {
+ _log.error("[getInterviewRecordingStatus]", err);
+ }
+ return false;
+ }
+
+ /**
+ * @deprecated @see {@link ScopeApplicationAdapter#getInterviewRecordingStatus()}
+ * @return - false if there were existing recording, true if recording was started successfully, null if any exception happens
+ */
+ @Deprecated
+ public boolean startInterviewRecording() {
+ try {
+ _log.debug("----------- startInterviewRecording");
+ IConnection current = Red5.getConnectionLocal();
+
+ for (IConnection conn : current.getScope().getClientConnections()) {
+ if (conn != null) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+
+ if (rcl != null && rcl.getIsRecording()) {
+ return false;
+ }
+ }
+ }
+ Client current_rcl = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ // Also set the Recording Flag to Record all Participants that enter
+ // later
+ current_rcl.setIsRecording(true);
+ sessionManager.updateClientByStreamId(current.getClient().getId(), current_rcl, false, null);
+
+ Map<String, String> interviewStatus = new HashMap<>();
+ interviewStatus.put("action", "start");
+
+ for (IConnection conn : current.getScope().getClientConnections()) {
+ if (conn != null) {
+ IClient client = conn.getClient();
+ if (SessionVariablesUtil.isScreenClient(client)) {
+ // screen sharing clients do not receive events
+ continue;
+ }
+
+ ((IServiceCapableConnection) conn).invoke("interviewStatus", new Object[] { interviewStatus }, this);
+ _log.debug("-- startInterviewRecording " + interviewStatus);
+ }
+ }
+ String recordingName = "Interview " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date());
+
+ recordingService.recordMeetingStream(current, current_rcl, recordingName, "", true);
+
+ return true;
+ } catch (Exception err) {
+ _log.debug("[startInterviewRecording]", err);
+ }
+ return false;
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ public boolean sendRemoteCursorEvent(final String streamid, Map messageObj) {
+ new MessageSender("sendRemoteCursorEvent", messageObj, this) {
+
+ @Override
+ public boolean filter(IConnection conn) {
+ IClient client = conn.getClient();
+ return !SessionVariablesUtil.isScreenClient(client) || !conn.getClient().getId().equals(streamid);
+ }
+ }.start();
+ return true;
+ }
+
+ private Long checkRecordingClient(IConnection conn) {
+ Long recordingId = null;
+ if (conn != null) {
+ Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+ if (rcl != null && rcl.getIsRecording()) {
+ rcl.setIsRecording(false);
+ recordingId = rcl.getRecordingId();
+ rcl.setRecordingId(null);
+
+ // Reset the Recording Flag to Record all
+ // Participants that enter later
+ sessionManager.updateClientByStreamId(conn.getClient().getId(), rcl, false, null);
+ }
+ }
+ return recordingId;
+ }
+
+ /**
+ * Stop the recording of the streams and send event to connected users of scope
+ *
+ * @return true if interview was found
+ */
+ public boolean stopInterviewRecording() {
+ IConnection current = Red5.getConnectionLocal();
+ Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+ return _stopInterviewRecording(currentClient, current.getScope());
+ }
+
+ /**
+ * Stop the recording of the streams and send event to connected users of scope
+ *
+ * @return true if interview was found
+ */
+ private boolean _stopInterviewRecording(Client currentClient, IScope currentScope) {
+ try {
+ _log.debug("----------- stopInterviewRecording");
+ Long clientRecordingId = currentClient.getRecordingId();
+
+ for (IConnection conn : currentScope.getClientConnections()) {
+ Long recordingId = checkRecordingClient(conn);
+ if (recordingId != null) {
+ clientRecordingId = recordingId;
+ }
+ }
+ if (clientRecordingId == null) {
+ _log.debug("stopInterviewRecording:: unable to find recording client");
+ return false;
+ }
+
+ recordingService.stopRecordAndSave(scope, currentClient, clientRecordingId);
+
+ Map<String, String> interviewStatus = new HashMap<>();
+ interviewStatus.put("action", "stop");
+
+ sendMessageToCurrentScope("interviewStatus", interviewStatus, true);
+ return true;
+
+ } catch (Exception err) {
+ _log.debug("[stopInterviewRecording]", err);
+ }
+ return false;
+ }
+
+ /**
+ * Get all ClientList Objects of that room and domain Used in
+ * lz.applyForModeration.lzx
+ *
+ * @return all ClientList Objects of that room
+ */
+ public List<Client> getClientListScope() {
+ try {
+ IConnection current = Red5.getConnectionLocal();
+ Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
+
+ return sessionManager.getClientListByRoom(currentClient.getRoomId());
+ } catch (Exception err) {
+ _log.debug("[getClientListScope]", err);
+ }
+ return new ArrayList<>();
+ }
+
+ private boolean getWhiteboardDrawStatus() {
+ return cfgDao.getWhiteboardDrawStatus();
+ }
+
+ public String getCryptKey() {
+ return cfgDao.getCryptKey();
+ }
+
+ public IScope getRoomScope(String room) {
+ if (Strings.isEmpty(room)) {
+ return null;
+ } else {
+ IScope globalScope = getContext().getGlobalScope();
+ IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey);
+
+ return webAppKeyScope.getScope(room);
+ }
+ }
+
+ /*
+ * SIP transport methods
+ */
+
+ private List<Long> getVerifiedActiveRoomIds(Server s) {
+ List<Long> result = new ArrayList<>(sessionManager.getActiveRoomIdsByServer(s));
+ //verify
+ for (Iterator<Long> i = result.iterator(); i.hasNext();) {
+ Long id = i.next();
+ List<Client> rcs = sessionManager.getClientListByRoom(id);
+ if (rcs.size() == 0 || (rcs.size() == 1 && rcs.get(0).isSipTransport())) {
+ i.remove();
+ }
+ }
+ return result.isEmpty() ? result : roomDao.getSipRooms(result);
+ }
+
+ private String getSipTransportLastname(Long roomId) {
+ return getSipTransportLastname(roomManager.getSipConferenceMembersNumber(roomId));
+ }
+
+ private static String getSipTransportLastname(Integer c) {
+ return (c != null && c > 0) ? "(" + (c - 1) + ")" : "";
+ }
+
+ public String getSipNumber(Double roomId) {
+ Room r = roomDao.get(roomId.longValue());
+ if (r != null && r.getConfno() != null) {
+ _log.debug("getSipNumber: roomId: {}, sipNumber: {}", new Object[]{roomId, r.getConfno()});
+ return r.getConfno();
+ }
+ return null;
+ }
+
+ public List<Long> getActiveRoomIds() {
+ Set<Long> ids = new HashSet<>();
+ ids.addAll(getVerifiedActiveRoomIds(null));
+ for (Server s : serverDao.getActiveServers()) {
+ ids.addAll(getVerifiedActiveRoomIds(s));
+ }
+ return new ArrayList<>(ids);
+ }
+
+ public synchronized int updateSipTransport() {
+ _log.debug("----------- updateSipTransport");
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+ Client client = sessionManager.getClientByStreamId(streamid, null);
+ Long roomId = client.getRoomId();
+ Integer count = roomManager.getSipConferenceMembersNumber(roomId);
+ String newNumber = getSipTransportLastname(count);
+ _log.debug("getSipConferenceMembersNumber: " + newNumber);
+ if (!newNumber.equals(client.getLastname())) {
+ IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+ org.apache.openmeetings.db.entity.basic.Client cl = iapp.getOmOnlineClient(client.getPublicSID());
+ cl.getUser().setLastname(newNumber);
+ client.setLastname(newNumber);
+ sessionManager.updateClientByStreamId(streamid, client, false, null);
+ _log.debug("updateSipTransport: {}, {}, {}, {}, {}", new Object[] { client.getPublicSID(), client.getRoomId(),
+ client.getFirstname(), client.getLastname(), client.getAvsettings() });
+ WebSocketHelper.sendRoom(new TextRoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.rightUpdated, client.getPublicSID()));
+ sendMessageWithClient(new String[] { "personal", client.getFirstname(), client.getLastname() });
+ }
+ return count != null && count > 0 ? count - 1 : 0;
+ }
+
+ public void setSipTransport(String broadCastId) {
+ _log.debug("----------- setSipTransport");
+ IConnection current = Red5.getConnectionLocal();
+ String streamid = current.getClient().getId();
+ // Notify all clients of the same scope (room)
+ Client c = sessionManager.getClientByStreamId(streamid, null);
+ IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+ org.apache.openmeetings.db.entity.basic.Client cl = iapp.getOmOnlineClient(c.getPublicSID());
+ String newNumber = getSipTransportLastname(c.getRoomId());
+ cl.getUser().setLastname(newNumber);
+ c.setLastname(newNumber);
+ c.setBroadCastID(Long.parseLong(broadCastId));
+ sessionManager.updateClientByStreamId(streamid, c, false, null);
+
+ WebSocketHelper.sendRoom(new TextRoomMessage(c.getRoomId(), c.getUserId(), RoomMessage.Type.rightUpdated, c.getPublicSID()));
+ sendMessageToCurrentScope("addNewUser", c, false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
index 4837982..7cc741a 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
@@ -26,7 +26,6 @@ import java.util.List;
import java.util.Map;
import org.apache.openmeetings.IApplication;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.dao.server.ServerDao;
import org.apache.openmeetings.db.dao.server.SessiondataDao;
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8aeb1b30/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/WhiteboardService.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/WhiteboardService.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/WhiteboardService.java
index 7633422..d597aa3 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/WhiteboardService.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/WhiteboardService.java
@@ -34,7 +34,6 @@ import java.util.Map;
import org.apache.commons.collections4.ComparatorUtils;
import org.apache.openmeetings.core.data.whiteboard.WhiteboardCache;
import org.apache.openmeetings.core.data.whiteboard.WhiteboardObjectSyncManager;
-import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.label.LabelDao;
import org.apache.openmeetings.db.dao.server.ISessionManager;