This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push: new 401e498 [OPENMEETINGS-2239, OPENMEETINGS-677] sip transport with user count is added to the room 401e498 is described below commit 401e4981c184764d21036204a75ef5dd3098c36e Author: Maxim Solodovnik <solomax...@gmail.com> AuthorDate: Thu Oct 22 12:35:47 2020 +0700 [OPENMEETINGS-2239, OPENMEETINGS-677] sip transport with user count is added to the room --- openmeetings-core/pom.xml | 8 + .../openmeetings/core/remote/KurentoHandler.java | 85 ++--- .../openmeetings/core/remote/StreamProcessor.java | 15 +- .../apache/openmeetings/core/sip/SipManager.java | 108 +++++-- .../core/util/ChatWebSocketHelper.java | 5 +- .../openmeetings/core/util/WebSocketHelper.java | 33 +- openmeetings-db/pom.xml | 9 - .../db/dao/calendar/AppointmentDao.java | 2 +- .../apache/openmeetings/db/dao/room/RoomDao.java | 7 +- .../apache/openmeetings/db/dao/room/SipConfig.java | 123 ------- .../openmeetings/db/entity/basic/Client.java | 5 + .../openmeetings/db/manager/IClientManager.java | 6 +- .../{dao/room => manager}/IInvitationManager.java | 2 +- .../{IClientManager.java => ISipManager.java} | 20 +- .../openmeetings/db/util/ApplicationHelper.java | 8 +- .../openmeetings/db/util/ws/RoomMessage.java | 2 +- .../installation/ImportInitvalues.java | 4 +- .../src/site/markdown/AsteriskIntegration.md | 9 +- .../src/site/markdown/InstallMediaServer.md | 2 +- openmeetings-server/src/site/site.xml | 2 +- .../src/site/xdoc/PrivacyStatement.xml | 12 +- .../src/site/xdoc/voip-sip-integration.xml | 360 --------------------- .../service/notifier/MailNotifier.java | 2 +- .../service/room/InvitationManager.java | 2 +- .../{quartz => }/scheduler/AbstractJob.java | 2 +- .../service/{quartz => }/scheduler/AtomReader.java | 2 +- .../service/{quartz => }/scheduler/CleanupJob.java | 25 +- .../{quartz => }/scheduler/ReminderJob.java | 2 +- .../web/admin/connection/ConnectionsPanel.java | 12 +- .../openmeetings/web/admin/rooms/RoomForm.java | 3 +- .../apache/openmeetings/web/app/Application.java | 10 + .../apache/openmeetings/web/app/ClientManager.java | 86 ++--- .../apache/openmeetings/web/app/TimerService.java | 61 +++- .../apache/openmeetings/web/app/UserManager.java | 6 +- .../apache/openmeetings/web/room/RoomPanel.java | 51 ++- .../web/room/menu/SipDialerDialog.java | 4 +- .../web/room/wb/WbWebSocketHelper.java | 3 +- .../openmeetings/web/user/MessageDialog.java | 2 +- .../openmeetings/web/user/rooms/RoomListPanel.java | 4 +- .../openmeetings/web/user/rooms/RoomsPanel.java | 3 +- .../webapp/WEB-INF/classes/applicationContext.xml | 51 +-- .../webapp/WEB-INF/classes/openmeetings.properties | 65 ++++ .../openmeetings/service/quartz/TestJob.java | 4 +- .../openmeetings/webservice/RoomWebService.java | 12 +- pom.xml | 37 ++- 45 files changed, 433 insertions(+), 843 deletions(-) diff --git a/openmeetings-core/pom.xml b/openmeetings-core/pom.xml index dd82ded..936ee4c 100644 --- a/openmeetings-core/pom.xml +++ b/openmeetings-core/pom.xml @@ -105,6 +105,14 @@ <groupId>org.kurento</groupId> <artifactId>kurento-client</artifactId> </dependency> + <dependency> + <groupId>org.asteriskjava</groupId> + <artifactId>asterisk-java</artifactId> + </dependency> + <dependency> + <groupId>javax.sip</groupId> + <artifactId>jain-sip-ri</artifactId> + </dependency> <!-- Test dependencies --> <dependency> <groupId>org.junit.jupiter</groupId> diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java index 0aa2934..5f1214e 100644 --- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java @@ -71,10 +71,13 @@ import org.kurento.jsonrpc.client.JsonRpcClientNettyWebSocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import com.github.openjson.JSONArray; import com.github.openjson.JSONObject; +@Component public class KurentoHandler { private static final Logger log = LoggerFactory.getLogger(KurentoHandler.class); public static final String PARAM_ICE = "iceServers"; @@ -88,20 +91,30 @@ public class KurentoHandler { private final ScheduledExecutorService kmsRecheckScheduler = Executors.newScheduledThreadPool(1); public static final String KURENTO_TYPE = "kurento"; private static int FLOWOUT_TIMEOUT_SEC = 5; - private long checkTimeout = 120000; //ms - private long objCheckTimeout = 200; //ms - private int watchThreadCount = 10; + @Value("${kurento.ws.url}") private String kurentoWsUrl; + @Value("${kurento.turn.url}") private String turnUrl; + @Value("${kurento.turn.user}") private String turnUser; + @Value("${kurento.turn.secret}") private String turnSecret; + @Value("${kurento.turn.mode}") private String turnMode; + @Value("${kurento.turn.ttl}") private int turnTtl = 60; //minutes + @Value("${kurento.check.timeout}") + private long checkTimeout = 120000; //ms + @Value("${kurento.object.check.timeout}") + private long objCheckTimeout = 200; //ms + @Value("${kurento.watch.thread.count}") + private int watchThreadCount = 10; + @Value("${kurento.kuid}") + private String kuid; private KurentoClient client; private final AtomicBoolean connected = new AtomicBoolean(false); - private String kuid; - private final Set<String> ignoredKuids = new HashSet<>(); private final Map<Long, KRoom> rooms = new ConcurrentHashMap<>(); + private final Set<String> ignoredKuids = new HashSet<>(); private Runnable check; @Autowired @@ -379,56 +392,6 @@ public class KurentoHandler { return kuid; } - public void setKuid(String kuid) { - this.kuid = kuid; - } - - public void setIgnoredKuids(String ignoredKuids) { - if (!Strings.isEmpty(ignoredKuids)) { - this.ignoredKuids.addAll(List.of(ignoredKuids.split("[, ]"))); - } - } - - public void setCheckTimeout(long checkTimeout) { - this.checkTimeout = checkTimeout; - } - - public void setObjCheckTimeout(long objCheckTimeout) { - this.objCheckTimeout = objCheckTimeout; - } - - public void setWatchThreadCount(int watchThreadCount) { - this.watchThreadCount = watchThreadCount; - } - - public void setKurentoWsUrl(String kurentoWsUrl) { - this.kurentoWsUrl = kurentoWsUrl; - } - - public void setTurnUrl(String turnUrl) { - this.turnUrl = turnUrl; - } - - public void setTurnUser(String turnUser) { - this.turnUser = turnUser; - } - - public void setTurnSecret(String turnSecret) { - this.turnSecret = turnSecret; - } - - public void setTurnMode(String turnMode) { - this.turnMode = turnMode; - } - - public void setTurnTtl(int turnTtl) { - this.turnTtl = turnTtl; - } - - public void setFlowoutTimeout(int timeout) { - FLOWOUT_TIMEOUT_SEC = timeout; - } - IApplication getApp() { return app; } @@ -445,6 +408,18 @@ public class KurentoHandler { return FLOWOUT_TIMEOUT_SEC; } + @Value("${kurento.flowout.timeout}") + private void setFlowoutTimeout(int timeout) { + FLOWOUT_TIMEOUT_SEC = timeout; + } + + @Value("${kurento.ignored.kuids}") + private void setIgnoredKuids(String ignoredKuids) { + if (!Strings.isEmpty(ignoredKuids)) { + this.ignoredKuids.addAll(List.of(ignoredKuids.split("[, ]"))); + } + } + private class KWatchDogCreate implements EventListener<ObjectCreatedEvent> { private ScheduledExecutorService scheduler; diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/StreamProcessor.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/StreamProcessor.java index 7abacce..27fbe41 100644 --- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/StreamProcessor.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/StreamProcessor.java @@ -306,10 +306,12 @@ public class StreamProcessor implements IStreamProcessor { } KRoom room = kHandler.getRoom(roomId); if (room.isSharing()) { - List<StreamDesc> streams = cm.listByRoom(roomId).parallelStream() + if (cm.streamByRoom(roomId) .flatMap(c -> c.getStreams().stream()) - .filter(sd -> StreamType.SCREEN == sd.getType()).collect(Collectors.toList()); - if (streams.isEmpty()) { + .filter(sd -> StreamType.SCREEN == sd.getType()) + .findAny() + .isEmpty()) + { log.info("No more screen streams in the room, stopping sharing"); room.stopSharing(); if (Room.Type.INTERVIEW != room.getType() && room.isRecording()) { @@ -319,10 +321,11 @@ public class StreamProcessor implements IStreamProcessor { } } if (room.isRecording()) { - List<StreamDesc> streams = cm.listByRoom(roomId).parallelStream() + if (cm.streamByRoom(roomId) .flatMap(c -> c.getStreams().stream()) - .collect(Collectors.toList()); - if (streams.isEmpty()) { + .findAny() + .isEmpty()) + { log.info("No more streams in the room, stopping recording"); room.stopRecording(null); } diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java similarity index 84% rename from openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java rename to openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java index 5f8b2f5..5ffa17a 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipDao.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.db.dao.room; +package org.apache.openmeetings.core.sip; import static javax.sip.message.Request.INVITE; import static javax.sip.message.Request.REGISTER; @@ -24,6 +24,8 @@ import static javax.sip.message.Response.OK; import static javax.sip.message.Response.RINGING; import static javax.sip.message.Response.TRYING; import static javax.sip.message.Response.UNAUTHORIZED; +import static org.apache.openmeetings.util.OmFileHelper.SIP_USER_ID; +import static org.apache.openmeetings.util.OpenmeetingsVariables.isSipEnabled; import java.text.ParseException; import java.util.List; @@ -31,6 +33,7 @@ import java.util.Properties; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import java.util.function.Function; import javax.annotation.PostConstruct; import javax.sip.ClientTransaction; @@ -54,6 +57,9 @@ import javax.sip.message.Request; import javax.sip.message.Response; import org.apache.openmeetings.db.entity.room.Room; +import org.apache.openmeetings.db.entity.user.User; +import org.apache.openmeetings.db.manager.ISipManager; +import org.apache.openmeetings.util.OmFileHelper; import org.asteriskjava.manager.DefaultManagerConnection; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionFactory; @@ -70,7 +76,7 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import gov.nist.javax.sip.DialogTimeoutEvent; @@ -82,8 +88,8 @@ import gov.nist.javax.sip.clientauthutils.UserCredentials; import gov.nist.javax.sip.stack.NioMessageProcessorFactory; @Service -public class SipDao implements SipListenerExt { - private static final Logger log = LoggerFactory.getLogger(SipDao.class); +public class SipManager implements ISipManager, SipListenerExt { + private static final Logger log = LoggerFactory.getLogger(SipManager.class); public static final String ASTERISK_OM_FAMILY = "openmeetings"; public static final String ASTERISK_OM_KEY = "rooms"; public static final String SIP_FIRST_NAME = "SIP Transport"; @@ -93,6 +99,28 @@ public class SipDao implements SipListenerExt { return t -> {}; } + @Value("${sip.hostname}") + private String sipHostname; + @Value("${sip.manager.port}") + private int managerPort; + @Value("${sip.manager.user}") + private String managerUser; + @Value("${sip.manager.password}") + private String managerPass; + @Value("${sip.manager.timeout}") + private long managerTimeout; + + @Value("${sip.ws.local.port}") + private int localWsPort = 6666; + @Value("${sip.ws.local.host}") + private String localWsHost; + @Value("${sip.ws.remote.port}") + private int wsPort; + @Value("${sip.ws.remote.user}") + private String omSipUser; + @Value("${sip.ws.remote.password}") + private String omSipPasswd; + private final AtomicLong cseq = new AtomicLong(); private final Random rnd = new Random(); @@ -106,18 +134,16 @@ public class SipDao implements SipListenerExt { private AddressFactory addressFactory; private ContactHeader contactHeader; private ManagerConnectionFactory factory; - - @Autowired - private SipConfig config; + private String sipUserPicture; @PostConstruct public void init() throws Exception { - if (config.getSipHostname() != null) { + if (sipHostname != null) { factory = new ManagerConnectionFactory( - config.getSipHostname() - , config.getManagerPort() - , config.getManagerUser() - , config.getManagerPass()); + sipHostname + , managerPort + , managerUser + , managerPass); final SipFactory sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); @@ -134,14 +160,14 @@ public class SipDao implements SipListenerExt { headerFactory = sipFactory.createHeaderFactory(); addressFactory = sipFactory.createAddressFactory(); final ListeningPoint listeningPoint = sipStack.createListeningPoint( - config.getLocalWsHost() - , config.getLocalWsPort() + localWsHost + , localWsPort , SIP_TRANSPORT); sipProvider = sipStack.createSipProvider(listeningPoint); sipProvider.addSipListener(this); - Address contact = createAddr(config.getOmSipUser(), config.getLocalWsHost(), uri -> { + Address contact = createAddr(omSipUser, localWsHost, uri -> { try { - uri.setPort(config.getLocalWsPort()); + uri.setPort(localWsPort); uri.setTransportParam(SIP_TRANSPORT); } catch (ParseException e) { log.error("fail to create contact address", e); @@ -153,10 +179,10 @@ public class SipDao implements SipListenerExt { private ManagerConnection getConnection() { DefaultManagerConnection con = (DefaultManagerConnection)factory.createManagerConnection(); - con.setDefaultEventTimeout(config.getManagerTimeout()); - con.setDefaultResponseTimeout(config.getManagerTimeout()); - con.setSocketReadTimeout((int)config.getManagerTimeout()); - con.setSocketTimeout((int)config.getManagerTimeout()); + con.setDefaultEventTimeout(managerTimeout); + con.setDefaultResponseTimeout(managerTimeout); + con.setSocketReadTimeout((int)managerTimeout); + con.setSocketTimeout((int)managerTimeout); return con; } @@ -228,6 +254,7 @@ public class SipDao implements SipListenerExt { return pin; } + @Override public void update(String confno, String pin) { delete(confno); DbPutAction da = new DbPutAction(ASTERISK_OM_FAMILY, getKey(confno), pin); @@ -239,6 +266,7 @@ public class SipDao implements SipListenerExt { exec(da); } + @Override public void delete(String confno) { DbDelAction da = new DbDelAction(ASTERISK_OM_FAMILY, getKey(confno)); exec(da); @@ -251,7 +279,7 @@ public class SipDao implements SipListenerExt { ConfbridgeListAction da = new ConfbridgeListAction(confno); ResponseEvents r = execEvent(da); if (r != null) { - log.debug("SipDao::countUsers size == {}", r.getEvents().size()); + log.debug("SipManager::countUsers size == {}", r.getEvents().size()); // "- 1" here means: ListComplete event return r.getEvents().size() - 1; } @@ -278,11 +306,29 @@ public class SipDao implements SipListenerExt { oa.setContext("rooms-out"); oa.setExten(number); oa.setPriority(1); - oa.setTimeout(config.getManagerTimeout()); + oa.setTimeout(managerTimeout); exec(oa); } + public void setUserPicture(Function<User, String> pictureCreator) { + User u = new User(); + u.setId(SIP_USER_ID); + sipUserPicture = pictureCreator.apply(u); + } + + public User getSipUser(Room r) { + if (factory == null || !isSipEnabled() || !r.isSipEnabled()) { + return null; + } + User u = new User(); + u.setId(OmFileHelper.SIP_USER_ID); + u.setFirstname(SIP_FIRST_NAME); + u.setLogin(SIP_USER_NAME); + u.setPictureUri(sipUserPicture); + return u; + } + @Override public void processDialogTerminated(DialogTerminatedEvent evt) { log.error("processDialogTerminated: \n{}", evt); @@ -355,7 +401,7 @@ public class SipDao implements SipListenerExt { } private Address createAddr(String user) { - return createAddr(user, config.getSipHostname(), noop()); + return createAddr(user, sipHostname, noop()); } private Address createAddr(String user, String host, Consumer<SipUri> cons) { @@ -373,11 +419,11 @@ public class SipDao implements SipListenerExt { private void sendRequest(String method, String to, Consumer<SipUri> uriCons, Consumer<Request> reqCons) throws Exception { SipUri uri = new SipUri(); - uri.setHost(config.getSipHostname()); - uri.setPort(config.getWsPort()); + uri.setHost(sipHostname); + uri.setPort(wsPort); uri.setTransportParam(SIP_TRANSPORT); uri.setMethodParam("GET"); - uri.setHeader("Host", config.getSipHostname()); + uri.setHeader("Host", sipHostname); uri.setHeader("Location", "/ws"); uriCons.accept(uri); @@ -386,9 +432,9 @@ public class SipDao implements SipListenerExt { , method , sipProvider.getNewCallId() , headerFactory.createCSeqHeader(cseq.incrementAndGet(), method) - , headerFactory.createFromHeader(createAddr(config.getOmSipUser()), tag) + , headerFactory.createFromHeader(createAddr(omSipUser), tag) , headerFactory.createToHeader(createAddr(to), null) - , List.of(headerFactory.createViaHeader(config.getLocalWsHost(), config.getLocalWsPort(), SIP_TRANSPORT, branch)) + , List.of(headerFactory.createViaHeader(localWsHost, localWsPort, SIP_TRANSPORT, branch)) , headerFactory.createMaxForwardsHeader(70)); request.addHeader(contactHeader); request.addHeader(headerFactory.createExpiresHeader(600)); @@ -407,12 +453,12 @@ public class SipDao implements SipListenerExt { AuthenticationHelper helper = sipStack.getAuthenticationHelper((trans, s) -> new UserCredentials() { @Override public String getUserName() { - return config.getOmSipUser(); + return omSipUser; } @Override public String getPassword() { - return config.getOmSipPasswd(); + return omSipPasswd; } @Override @@ -435,7 +481,7 @@ public class SipDao implements SipListenerExt { private void register() throws Exception { sendRequest( REGISTER - , config.getOmSipUser() + , omSipUser , noop() , req -> { try { diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/ChatWebSocketHelper.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/ChatWebSocketHelper.java index 61d480f..9f733f2 100644 --- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/ChatWebSocketHelper.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/ChatWebSocketHelper.java @@ -18,6 +18,7 @@ */ package org.apache.openmeetings.core.util; +import static org.apache.openmeetings.core.util.WebSocketHelper.alwaysTrue; import static org.apache.openmeetings.core.util.WebSocketHelper.doSend; import static org.apache.openmeetings.core.util.WebSocketHelper.publish; @@ -148,7 +149,7 @@ public class ChatWebSocketHelper { if (publish) { publish(new WsMessageChat2All(m, msg)); } - WebSocketHelper.send(a -> ((IApplication)a).getBean(IClientManager.class).list() - , (t, c) -> doSend(t, c, msg, (o, cm) -> setDates(o, m, c.getUser(), false), "all"), null); + WebSocketHelper.send(a -> ((IApplication)a).getBean(IClientManager.class).stream() + , (t, c) -> doSend(t, c, msg, (o, cm) -> setDates(o, m, c.getUser(), false), "all"), alwaysTrue()); } } diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/WebSocketHelper.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/WebSocketHelper.java index 10a2de7..16c3698 100644 --- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/WebSocketHelper.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/util/WebSocketHelper.java @@ -21,12 +21,12 @@ package org.apache.openmeetings.core.util; import static org.apache.openmeetings.util.OpenmeetingsVariables.getWicketApplicationName; import java.io.IOException; -import java.util.Collection; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Stream; import org.apache.openmeetings.IApplication; import org.apache.openmeetings.core.util.ws.WsMessageAll; @@ -54,6 +54,9 @@ import com.github.openjson.JSONObject; public class WebSocketHelper { private static final Logger log = LoggerFactory.getLogger(WebSocketHelper.class); + public static final <T> Predicate<T> alwaysTrue() { + return x -> true; + } private WebSocketHelper() { // denied @@ -139,7 +142,7 @@ public class WebSocketHelper { publish(new WsMessageRoomMsg(m)); } log.trace("Sending WebSocket message to room: {} {}", m.getType(), m instanceof TextRoomMessage ? ((TextRoomMessage)m).getText() : ""); - sendRoom(m.getRoomId(), (t, c) -> t.sendMessage(m), null); + sendRoom(m.getRoomId(), (t, c) -> t.sendMessage(m), alwaysTrue()); } public static void sendServer(final RoomMessage m) { @@ -161,7 +164,7 @@ public class WebSocketHelper { if (publish) { publish(new WsMessageRoom(roomId, m)); } - sendRoom(roomId, m, null, null); + sendRoom(roomId, m, alwaysTrue(), null); } public static void sendRoomOthers(final Long roomId, final String uid, final JSONObject m) { @@ -183,8 +186,8 @@ public class WebSocketHelper { if (publish) { publish(new WsMessageUser(userId, m)); } - send(a -> ((IApplication)a).getBean(IClientManager.class).listByUser(userId) - , (t, c) -> doSend(t, c, m, func, "user"), null); + send(a -> ((IApplication)a).getBean(IClientManager.class).listByUser(userId).stream() + , (t, c) -> doSend(t, c, m, func, "user"), alwaysTrue()); } public static void sendAll(final String m) { @@ -239,11 +242,11 @@ public class WebSocketHelper { } private static void sendRoom(final Long roomId, BiConsumer<IWebSocketConnection, Client> consumer, Predicate<Client> check) { - send(a -> ((IApplication)a).getBean(IClientManager.class).listByRoom(roomId), consumer, check); + send(a -> ((IApplication)a).getBean(IClientManager.class).streamByRoom(roomId), consumer, check); } static void send( - final Function<Application, Collection<Client>> func + final Function<Application, Stream<Client>> func , BiConsumer<IWebSocketConnection, Client> consumer , Predicate<Client> check) { @@ -255,14 +258,14 @@ public class WebSocketHelper { WebSocketSettings settings = WebSocketSettings.Holder.get(app); IWebSocketConnectionRegistry reg = settings.getConnectionRegistry(); Executor executor = settings.getWebSocketPushMessageExecutor(); - for (Client c : func.apply(app)) { - if (check == null || check.test(c)) { - final IWebSocketConnection wc = reg.getConnection(app, c.getSessionId(), new PageIdKey(c.getPageId())); - if (wc != null && wc.isOpen()) { - executor.run(() -> consumer.accept(wc, c)); - } - } - } + func.apply(app) + .filter(check) + .forEach(c -> { + final IWebSocketConnection wc = reg.getConnection(app, c.getSessionId(), new PageIdKey(c.getPageId())); + if (wc != null && wc.isOpen()) { + executor.run(() -> consumer.accept(wc, c)); + } + }); }).start(); } } diff --git a/openmeetings-db/pom.xml b/openmeetings-db/pom.xml index cd6d82a..16562ac 100644 --- a/openmeetings-db/pom.xml +++ b/openmeetings-db/pom.xml @@ -73,11 +73,6 @@ <version>${spring.version}</version> </dependency> <dependency> - <groupId>org.asteriskjava</groupId> - <artifactId>asterisk-java</artifactId> - <version>${asterisk-java.version}</version> - </dependency> - <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>${commons-dbcp.version}</version> @@ -109,10 +104,6 @@ <version>${mssql.version}</version> </dependency> <dependency> - <groupId>javax.sip</groupId> - <artifactId>jain-sip-ri</artifactId> - </dependency> - <dependency> <groupId>org.apache.openmeetings</groupId> <artifactId>openmeetings-util</artifactId> <version>${project.version}</version> diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/calendar/AppointmentDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/calendar/AppointmentDao.java index 988bc2e..d5b52f8 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/calendar/AppointmentDao.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/calendar/AppointmentDao.java @@ -37,13 +37,13 @@ import javax.persistence.TypedQuery; import org.apache.commons.lang3.StringUtils; import org.apache.openmeetings.db.dao.IDataProviderDao; import org.apache.openmeetings.db.dao.basic.ConfigurationDao; -import org.apache.openmeetings.db.dao.room.IInvitationManager; import org.apache.openmeetings.db.dao.room.RoomDao; import org.apache.openmeetings.db.dto.calendar.AppointmentDTO; import org.apache.openmeetings.db.entity.calendar.Appointment; import org.apache.openmeetings.db.entity.calendar.Appointment.Reminder; import org.apache.openmeetings.db.entity.calendar.MeetingMember; import org.apache.openmeetings.db.entity.room.Invitation.MessageType; +import org.apache.openmeetings.db.manager.IInvitationManager; import org.apache.openmeetings.db.entity.room.Room; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/RoomDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/RoomDao.java index 02b84f5..696959b 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/RoomDao.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/RoomDao.java @@ -46,6 +46,7 @@ import org.apache.openmeetings.db.entity.log.ConferenceLog; import org.apache.openmeetings.db.entity.room.Room; import org.apache.openmeetings.db.entity.room.Room.RoomElement; import org.apache.openmeetings.db.entity.room.Room.Type; +import org.apache.openmeetings.db.manager.ISipManager; import org.apache.openmeetings.db.entity.room.RoomFile; import org.apache.openmeetings.db.entity.room.RoomGroup; import org.apache.openmeetings.db.util.DaoHelper; @@ -70,7 +71,7 @@ public class RoomDao implements IGroupAdminDataProviderDao<Room> { @Autowired private ConfigurationDao cfgDao; @Autowired - private SipDao sipDao; + private ISipManager sipManager; @Autowired private UserDao userDao; @@ -213,9 +214,9 @@ public class RoomDao implements IGroupAdminDataProviderDao<Room> { if (sipNumber != null && !sipNumber.equals(entity.getConfno())) { entity.setConfno(sipNumber); } - sipDao.update(sipNumber, entity.getPin()); + sipManager.update(sipNumber, entity.getPin()); } else { - sipDao.delete(entity.getConfno()); + sipManager.delete(entity.getConfno()); entity.setConfno(null); entity.setPin(null); } diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipConfig.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipConfig.java deleted file mode 100644 index e1a5646..0000000 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/SipConfig.java +++ /dev/null @@ -1,123 +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.db.dao.room; - -public class SipConfig { - private String sipHostname; - private int managerPort; - private String managerUser; - private String managerPass; - private long managerTimeout; - - private int localWsPort = 6666; - private String localWsHost; - private int wsPort; - private String omSipUser; - private String omSipPasswd; - - private String uid; //FIXME TODO is this still required ?! - - public String getSipHostname() { - return sipHostname; - } - - public void setSipHostname(String sipHostname) { - this.sipHostname = sipHostname; - } - - public int getManagerPort() { - return managerPort; - } - - public void setManagerPort(int managerPort) { - this.managerPort = managerPort; - } - - public String getManagerUser() { - return managerUser; - } - - public void setManagerUser(String managerUser) { - this.managerUser = managerUser; - } - - public String getManagerPass() { - return managerPass; - } - - public void setManagerPass(String managerPass) { - this.managerPass = managerPass; - } - - public long getManagerTimeout() { - return managerTimeout; - } - - public void setManagerTimeout(long managerTimeout) { - this.managerTimeout = managerTimeout; - } - - public int getLocalWsPort() { - return localWsPort; - } - - public void setLocalWsPort(int localWsPort) { - this.localWsPort = localWsPort; - } - - public String getLocalWsHost() { - return localWsHost; - } - - public void setLocalWsHost(String localWsHost) { - this.localWsHost = localWsHost; - } - - public int getWsPort() { - return wsPort; - } - - public void setWsPort(int wsPort) { - this.wsPort = wsPort; - } - - public String getOmSipUser() { - return omSipUser; - } - - public void setOmSipUser(String omSipUser) { - this.omSipUser = omSipUser; - } - - public String getOmSipPasswd() { - return omSipPasswd; - } - - public void setOmSipPasswd(String omSipPasswd) { - this.omSipPasswd = omSipPasswd; - } - - public String getUid() { - return uid; - } - - public void setUid(String uid) { - this.uid = uid; - } -} diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java index cdf463b..0304452 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java @@ -19,6 +19,7 @@ package org.apache.openmeetings.db.entity.basic; import static java.util.UUID.randomUUID; +import static org.apache.openmeetings.util.OmFileHelper.SIP_USER_ID; import java.io.Serializable; import java.util.ArrayList; @@ -129,6 +130,10 @@ public class Client implements IDataProviderEntity, IWsClient { return sid; } + public boolean isSip() { + return SIP_USER_ID.equals(getUserId()); + } + public void clear() { activities.clear(); rights.clear(); diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java index 24a1498..0e894da 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java @@ -19,7 +19,7 @@ package org.apache.openmeetings.db.manager; import java.util.Collection; -import java.util.List; +import java.util.stream.Stream; import org.apache.openmeetings.db.entity.basic.Client; @@ -27,8 +27,8 @@ public interface IClientManager { Client get(String uid); Client getBySid(String sid); String uidBySid(String sid); - List<Client> list(); - List<Client> listByRoom(Long roomId); + Stream<Client> stream(); + Stream<Client> streamByRoom(Long roomId); Collection<Client> listByUser(Long userId); Client update(Client c); void exit(Client c); diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/IInvitationManager.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IInvitationManager.java similarity index 97% rename from openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/IInvitationManager.java rename to openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IInvitationManager.java index 2fd0c34..44f3f65 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/room/IInvitationManager.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IInvitationManager.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.db.dao.room; +package org.apache.openmeetings.db.manager; import java.util.Date; diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/ISipManager.java similarity index 69% copy from openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java copy to openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/ISipManager.java index 24a1498..b94263a 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/IClientManager.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/ISipManager.java @@ -18,18 +18,12 @@ */ package org.apache.openmeetings.db.manager; -import java.util.Collection; -import java.util.List; - -import org.apache.openmeetings.db.entity.basic.Client; +/** + * this interface is required to use SipMagager from openmeetings-core + */ +public interface ISipManager { + public static final String SIP_FIRST_NAME = "SIP Transport"; -public interface IClientManager { - Client get(String uid); - Client getBySid(String sid); - String uidBySid(String sid); - List<Client> list(); - List<Client> listByRoom(Long roomId); - Collection<Client> listByUser(Long userId); - Client update(Client c); - void exit(Client c); + void update(String confno, String pin); + void delete(String confno); } diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ApplicationHelper.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ApplicationHelper.java index 38ef520..b8d7919 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ApplicationHelper.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ApplicationHelper.java @@ -116,13 +116,17 @@ public class ApplicationHelper { } } - public static IApplication ensureApplication(Long langId) { - IApplication a = ensureApplication(); + public static void ensureRequestCycle(IApplication a) { if (ThreadContext.getRequestCycle() == null) { ServletWebRequest req = new ServletWebRequest(new MockHttpServletRequest((Application)a, new MockHttpSession(a.getServletContext()), a.getServletContext()), ""); RequestCycleContext rctx = new RequestCycleContext(req, new MockWebResponse(), a.getRootRequestMapper(), a.getExceptionMapperProvider().get()); ThreadContext.setRequestCycle(new RequestCycle(rctx)); } + } + + public static IApplication ensureApplication(Long langId) { + IApplication a = ensureApplication(); + ensureRequestCycle(a); if (ThreadContext.getSession() == null) { WebSession s = WebSession.get(); if (langId > 0) { diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ws/RoomMessage.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ws/RoomMessage.java index 85937b7..9864bc2 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ws/RoomMessage.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/ws/RoomMessage.java @@ -19,7 +19,7 @@ package org.apache.openmeetings.db.util.ws; import static java.util.UUID.randomUUID; -import static org.apache.openmeetings.db.dao.room.SipDao.SIP_FIRST_NAME; +import static org.apache.openmeetings.db.manager.ISipManager.SIP_FIRST_NAME; import static org.apache.openmeetings.util.OmFileHelper.SIP_USER_ID; import java.util.Date; diff --git a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java index 718078e..f987e1d 100644 --- a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java +++ b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java @@ -125,10 +125,10 @@ import java.util.Date; import java.util.List; import java.util.function.Consumer; +import org.apache.openmeetings.core.sip.SipManager; import org.apache.openmeetings.db.dao.basic.ConfigurationDao; import org.apache.openmeetings.db.dao.label.LabelDao; import org.apache.openmeetings.db.dao.room.RoomDao; -import org.apache.openmeetings.db.dao.room.SipDao; import org.apache.openmeetings.db.dao.server.OAuth2Dao; import org.apache.openmeetings.db.dao.user.GroupDao; import org.apache.openmeetings.db.dao.user.UserDao; @@ -170,7 +170,7 @@ public class ImportInitvalues { @Autowired private UserDao userDao; @Autowired - private SipDao sipDao; + private SipManager sipDao; @Autowired private OAuth2Dao oauthDao; @Autowired diff --git a/openmeetings-server/src/site/markdown/AsteriskIntegration.md b/openmeetings-server/src/site/markdown/AsteriskIntegration.md index 2fd9105..554584f 100644 --- a/openmeetings-server/src/site/markdown/AsteriskIntegration.md +++ b/openmeetings-server/src/site/markdown/AsteriskIntegration.md @@ -165,7 +165,7 @@ Modify `/etc/asterisk/extensions.conf` ; If you do not receive an output with that resembles openmeetings/rooms/400## where “##” will equal ; the extension assigned when you created your room ; If you do not receive the above output check your parameters in -; /opt/om/webapps/openmeetings/WEB-INF/classes/applicationContext.xml +; /opt/om/webapps/openmeetings/WEB-INF/classes/openmeetings.properties ; Go back into the Administrator Panel and remove the PIN number in each room save the record with ; no PIN number and then re-enter the pin again resave the record. ; ***************************************************** @@ -246,12 +246,9 @@ write = all ``` Update OpenMeetings with credentials for Asterisk manager. -Modify `/opt/om/webapps/openmeetings/WEB-INF/classes/applicationContext.xml` +Modify `/opt/om/webapps/openmeetings/WEB-INF/classes/openmeetings.properties` -find **<bean class="org.apache.openmeetings.db.dao.room.SipConfig">** -uncomment its properties and set it to your custom values. - -set value for `uid` property to unique secret value (can be generated here <a href="https://www.uuidtools.com">https://www.uuidtools.com</a>) +find all properties start with `sip.` and set it to your custom values. <p style="font-size: larger; color: blue;"> IMPORTANT: this step should be done <strong>BEFORE</strong> system install/restore diff --git a/openmeetings-server/src/site/markdown/InstallMediaServer.md b/openmeetings-server/src/site/markdown/InstallMediaServer.md index 3034ca7..8ffc72e 100644 --- a/openmeetings-server/src/site/markdown/InstallMediaServer.md +++ b/openmeetings-server/src/site/markdown/InstallMediaServer.md @@ -13,4 +13,4 @@ Licensed under the Apache License, Version 2.0 (the "License") http://www.apache ## Specify/Install Turn server -<div class="bd-callout bd-callout-info">Optional step</div> +<div class="bd-callout bd-callout-warning">Only local installation will work without TURN server</div> diff --git a/openmeetings-server/src/site/site.xml b/openmeetings-server/src/site/site.xml index ef599b9..5a27a60 100644 --- a/openmeetings-server/src/site/site.xml +++ b/openmeetings-server/src/site/site.xml @@ -47,7 +47,7 @@ <item name="REST API Sample" href="/RestAPISample.html" /> <item name="Ldap and ADS" href="/LdapAndADS.html" /> <item name="OAuth2" href="/oauth2.html" /> - <item name="VoIP and SIP" href="/voip-sip-integration.html" /> + <item name="VoIP and SIP" href="/AsteriskIntegration.html" /> <item name="Errors table" href="/errorvalues.html" /> <item name="CalDAV and Google Calendar integration" href="/CalDAVandGCal.html" /> <item name="External Video/Camera" href="/ExternalVideo.html" /> diff --git a/openmeetings-server/src/site/xdoc/PrivacyStatement.xml b/openmeetings-server/src/site/xdoc/PrivacyStatement.xml index ad91620..319f18b 100644 --- a/openmeetings-server/src/site/xdoc/PrivacyStatement.xml +++ b/openmeetings-server/src/site/xdoc/PrivacyStatement.xml @@ -24,7 +24,7 @@ <div> To modify privacy statement do the following: <ul> - <li>Open <pp>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage.html</pp></li> + <li>Open <tt>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage.html</tt></li> <li>Perform necessary changes</li> <li>restart OM</li> </ul> @@ -35,11 +35,11 @@ To create privacy statement in your language do the following: <ul> <li> - Create new file <pp>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_<b>LANG_CODE</b>.html</pp> <br/> - <pp>LANG_CODE</pp> should be in format [language code]_[country ISO code], <pp>_[country ISO code]</pp> block is optional<br/> - for ex. <pp>de</pp> can be suffix for German, file name will be <pp>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_de.html</pp><br/> - <pp>pt</pp> can be suffix for Portuguese, file name will be <pp>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_pt.html</pp><br/> - <pp>pt_BR</pp> can be suffix for Brazilian version of Portuguese, file name will be <pp>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_pt_BR.html</pp><br/> + Create new file <tt>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_<b>LANG_CODE</b>.html</tt> <br/> + <tt>LANG_CODE</tt> should be in format [language code]_[country ISO code], <tt>_[country ISO code]</tt> block is optional<br/> + for ex. <tt>de</tt> can be suffix for German, file name will be <tt>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_de.html</tt><br/> + <tt>pt</tt> can be suffix for Portuguese, file name will be <tt>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_pt.html</tt><br/> + <tt>pt_BR</tt> can be suffix for Brazilian version of Portuguese, file name will be <tt>webapps/openmeetings/WEB-INF/classes/org/apache/openmeetings/web/pages/PrivacyPage_pt_BR.html</tt><br/> </li> <li>Perform translation</li> <li>restart OM</li> diff --git a/openmeetings-server/src/site/xdoc/voip-sip-integration.xml b/openmeetings-server/src/site/xdoc/voip-sip-integration.xml deleted file mode 100644 index 85bef4b..0000000 --- a/openmeetings-server/src/site/xdoc/voip-sip-integration.xml +++ /dev/null @@ -1,360 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Licensed 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. - --> -<document xmlns="http://maven.apache.org/XDOC/2.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> - <properties> - <title>VoIP and SIP Integration</title> - <author email="d...@openmeetings.apache.org">Apache OpenMeetings Team</author> - </properties> - <body> - <section name="Not implemented"> - <div class="bd-callout bd-callout-danger"> - Please NOTE: this functionality is not yet implemented in 5.0.x - </div> - </section> - - <section name="VoIP and SIP Integration"> - <p> - There are multiple ways to integrate with VoIP and or SIP. - OpenMeetings does not provide out of the box a ready to run VoIP - integration / integration to cell phone or usual land lane. - The - nature of such integrations is that it depends heavily on the - infrastructure that you are using and where you would like to - integrate OpenMeetings into. - <br /> - <br /> - It also depends on a number of factors of which OpenMeetings is - impossible to set up for you, for example setting up your VoIP - server or provide you with a range of telephone numbers reserved for - conference calls in your national phone network. - Such an integration - project is likely to become a consulting job for a - telecommunications consultant. - <br /> - <br /> - To get help on the integration you can contact the - <a href="mailing-lists.html">mailing lists</a> - or for example somebody from the list of - <a href="commercial-support.html">commercial support</a>. - <br/><br/> - </p> - </section> - <section name="SIP-Transport Integration"> - <p>You need Apache OpenMeetings <strong>version 4.0+</strong> to apply this guide!</p> - <p>You need Asterisk <strong>version 13+</strong> to apply this guide!</p> - <p>Here is instruction how-to set up red5sip transport integration with OpenMeetings on Ubuntu 16.04.</p> - </section> - <section name="Prerequisites"> - <div> - Run the commands - <source> -<![CDATA[ -sudo apt update && sudo apt upgrade -]]> - </source> - </div> - </section> - <section name="Building and setting up Asterisk"> - <div> - Run the commands - <source> -<![CDATA[ -sudo mkdir /usr/src/asterisk && cd /usr/src/asterisk -sudo wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-13.17.0.tar.gz -sudo tar -xvzf asterisk-13.17.0.tar.gz -cd ./asterisk-13.17.0 -sudo make clean -sudo contrib/scripts/install_prereq install -sudo ./configure -sudo make menuconfig -]]> - </source> - Make sure you have selected <tt>Add-ons -> res_config_mysql</tt>, Press F12 to save - <source> -<![CDATA[ -sudo make -sudo make install -sudo make samples -sudo make config -sudo service asterisk start -]]> - </source> - </div> - </section> - <section name="Configure Asterisk"> - <div> - Enable asterisk MySQL module:<br /><br /> - Modify "[modules]" section of <tt>/etc/asterisk/modules.conf</tt> as follows:<br /> - <strong>Add/uncomment the following lines</strong> - <source> -<![CDATA[ -preload => res_config_mysql.so -]]> - </source> - </div><br /> - <div> - Configure MySQL module:<br /><br /> - Set valid data for MySQL in <tt>/etc/asterisk/res_config_mysql.conf</tt> :<br /> - <strong>Example</strong> - <source> -<![CDATA[ -[general] -dbhost = 127.0.0.1 -dbname = openmeetings -dbuser = root -dbpass = -dbport = 3306 -dbsock = /var/lib/mysql/mysql.sock -dbcharset = utf8 -requirements=warn -]]> - </source> - </div><br /> - <div> - Modify <tt>/etc/asterisk/sip.conf</tt><br /> - <strong>Add/uncomment the following line</strong>:<br /> - <source> -<![CDATA[ -videosupport=yes -rtcachefriends=yes -]]> - </source> - <strong>Increase maxexpiry value to 43200</strong>:<br /> - <source> -<![CDATA[ -maxexpiry=43200 -]]> - </source> - <strong>Add user for the "SIP Transport"</strong>:<br /> - <source> -<![CDATA[ -[red5sip_user] -type=friend -secret=12345 -disallow=all -allow=ulaw -allow=h263 -host=dynamic -nat=force_rport,comedia -context=rooms-red5sip -]]> - </source> - </div><br /> - <div> - Add next lines into the <tt>/etc/asterisk/extconfig.conf</tt>: - <source> -<![CDATA[ -[settings] -sippeers => mysql,general,sipusers -]]> - </source> - </div><br /> - <div> - Modify <tt>/etc/asterisk/extensions.conf</tt><br /> - <strong>Add the following section</strong>:<br /> - <source> -<![CDATA[ -; ***************************************************** -; The below dial plan is used to dial into a Openmeetings Conference room -; The first line DB_EXISTS(openmeetings/room/ does not belong to the openmeetings application -; but is the name of astDB containing the astDB family/key pair and values -; To Check if your astDB has been created do the following in a terminal window type the following: -; asterisk –rx “database show” -; If you do not receive an output with that resembles openmeetings/rooms/400## where “##” will equal -; the extension assigned when you created your room -; If you do not receive the above output check your parameters in -; /opt/om/webapps/openmeetings/WEB-INF/classes/applicationContext.xml -; Go back into the Administrator Panel and remove the PIN number in each room save the record with -; no PIN number and then re-enter the pin again resave the record. -; ***************************************************** - -[rooms] -exten => _400X!,1,GotoIf($[${DB_EXISTS(openmeetings/rooms/${EXTEN})}]?ok:notavail) -exten => _400X!,n(ok),SET(PIN=${DB(openmeetings/rooms/${EXTEN})}) -exten => _400X!,n,Set(CONFBRIDGE(user,template)=sip_user) -exten => _400X!,n,Set(CONFBRIDGE(user,pin)=${PIN}) -exten => _400X!,n(ok),Confbridge(${EXTEN},default_bridge,) -exten => _400X!,n,Hangup -exten => _400X!,n(notavail),Answer() -exten => _400X!,n,Playback(invalid) -exten => _400X!,n,Hangup - -[rooms-originate] -exten => _400X!,1,Confbridge(${EXTEN},default_bridge,sip_user) -exten => _400X!,n,Hangup - -[rooms-out] -; ***************************************************** -; Extensions for outgoing calls from Openmeetings room. -; ***************************************************** - -[rooms-red5sip] -exten => _400X!,1,GotoIf($[${DB_EXISTS(openmeetings/rooms/${EXTEN})}]?ok:notavail) -exten => _400X!,n(ok),Confbridge(${EXTEN},default_bridge,red5sip_user) -exten => _400X!,n(notavail),Hangup -]]> - </source> - </div><br /> - <div> - Modify <tt>/etc/asterisk/confbridge.conf</tt><br /> - <strong>Add/Modify the following secions</strong>:<br /> - <source> -<![CDATA[ -[general] - -[red5sip_user] -type=user -marked=yes -dsp_drop_silence=yes -denoise=true - -[sip_user] -type=user -end_marked=yes -wait_marked=yes -music_on_hold_when_empty=yes -dsp_drop_silence=yes -denoise=true - -[default_bridge] -type=bridge -video_mode=follow_talker -]]> - </source> - </div><br /> - <div> - To enable Asterisk Manager API modify <tt>/etc/asterisk/manager.conf</tt><br /> - <strong>Add/Modify the following sections</strong>:<br /> - <source> -<![CDATA[ -[general] -enabled = yes -webenabled = no -port = 5038 -bindaddr = 127.0.0.1 - -[openmeetings] -secret = 12345 -deny=0.0.0.0/0.0.0.0 -permit=127.0.0.1/255.255.255.0 -read = all -write = all -]]> - </source> - </div><br /> - <div> - Update OpenMeetings with credentials for Asterisk manager. - Modify <tt>/opt/om/webapps/openmeetings/WEB-INF/classes/applicationContext.xml</tt><br /> - find <strong><bean id="sipDao" class="org.apache.openmeetings.db.dao.room.SipDao"></strong> - uncomment its parameters and set it to your custom values.<br/> - set value for <tt>uid</tt> property to unique secret value (can be generated here <a href="https://www.uuidtools.com">https://www.uuidtools.com</a>) - and sync it with <tt>settings.properties</tt> of red5sip (see below) - <p style="font-size: larger; color: blue;"> - IMPORTANT: this step should be done <strong>BEFORE</strong> system install/restore - otherwise all SIP related room information will be lost - </p> - </div><br /> - <div> - Restart asterisk: - <source> -<![CDATA[ -service asterisk restart -]]> - </source> - </div><br /> - </section> - - <section name="Setup red5sip transport"> - <ul> - <li>Download red5sip from <tt>https://github.com/openmeetings/red5sip</tt> - <source> -<![CDATA[ -git clone https://github.com/openmeetings/red5sip.git -]]> - </source> - </li> - <li>Build with Apache Maven - <source> -<![CDATA[ -cd red5sip -mvn clean package -]]> - </source> - </li> - <li>All necessary files will be available in <tt>target</tt> folder, copy/move it to /opt/red5sip/</li> - <li>Insert proper values to the <tt>/opt/red5sip/settings.properties</tt> - <source> -<![CDATA[ -red5.host=127.0.0.1 # red5 server address -om.context=openmeetings # Openmeetings context -red5.codec=asao -red5.codec.rate=22 # should correlate with mic setting in Admin->Config `flash.mic.rate` -sip.obproxy=127.0.0.1 # asterisk adderss -sip.phone=red5sip_user # sip phone number -sip.authid=red5sip_user # sip auth id -sip.secret=12345 # sip password -sip.realm=asterisk # sip realm -sip.proxy=127.0.0.1 # address of sip proxy -rooms.forceStart=no # TBD -uid=87dddad4-9ca5-475b-860f-2e0825d02b76 #can be generated here: https://www.uuidtools.com/ -rooms=1 # TBD (not in use) -]]> - </source> - </li> - <li>Set correct permissions on red5sip files: - <source> -<![CDATA[ -sudo chown -R nobody:nogroup /opt/red5sip -]]> - </source> - </li> - <li>Add red5sip to autostart: - <source> -<![CDATA[ -sudo cp /opt/red5sip/red5sip /etc/init.d/ -sudo chmod a+x /etc/init.d/red5sip -sudo update-rc.d red5sip defaults -]]> - </source> - </li> - <li>Start openmeetings - <source> -<![CDATA[ -service red5 start -]]> - </source> - </li> - <li> - Enable <tt>SIP</tt> in openmeetings: <br/> - <tt>Administration->Configuration->red5sip.enable == yes</tt> - </li> - <li> - Enable SIP for particular room(s): <br/> - <tt>Administration->Conference rooms->Room->Enable SIP transport in the room == checked</tt><br/> - (SIP number will be assigned to room if everything is OK) - </li> - <li>Start red5sip - <source> -<![CDATA[ -service red5sip start -]]> - </source> - </li> - </ul> - </section> - </body> -</document> diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/notifier/MailNotifier.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/notifier/MailNotifier.java index 3be75b2..1aa6bed 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/notifier/MailNotifier.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/notifier/MailNotifier.java @@ -26,11 +26,11 @@ import javax.annotation.PostConstruct; import org.apache.openmeetings.core.notifier.INotifier; import org.apache.openmeetings.core.notifier.NotifierService; -import org.apache.openmeetings.db.dao.room.IInvitationManager; import org.apache.openmeetings.db.entity.calendar.Appointment; import org.apache.openmeetings.db.entity.room.Invitation; import org.apache.openmeetings.db.entity.room.Invitation.MessageType; import org.apache.openmeetings.db.entity.user.User; +import org.apache.openmeetings.db.manager.IInvitationManager; import org.apache.openmeetings.service.mail.template.subject.AppointmentReminderTemplate; import org.apache.openmeetings.service.mail.template.subject.SubjectEmailTemplate; import org.springframework.beans.factory.annotation.Autowired; diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/room/InvitationManager.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/room/InvitationManager.java index 34ae0bc..159c6ea 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/room/InvitationManager.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/room/InvitationManager.java @@ -28,7 +28,6 @@ import java.util.TimeZone; import org.apache.openmeetings.IApplication; import org.apache.openmeetings.core.mail.MailHandler; -import org.apache.openmeetings.db.dao.room.IInvitationManager; import org.apache.openmeetings.db.dao.room.InvitationDao; import org.apache.openmeetings.db.entity.basic.MailMessage; import org.apache.openmeetings.db.entity.calendar.Appointment; @@ -40,6 +39,7 @@ import org.apache.openmeetings.db.entity.room.Invitation.Valid; import org.apache.openmeetings.db.entity.room.Room; import org.apache.openmeetings.db.entity.user.User; import org.apache.openmeetings.db.entity.user.User.Type; +import org.apache.openmeetings.db.manager.IInvitationManager; import org.apache.openmeetings.service.mail.template.InvitationTemplate; import org.apache.openmeetings.service.mail.template.subject.CanceledAppointmentTemplate; import org.apache.openmeetings.service.mail.template.subject.CreatedAppointmentTemplate; diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AbstractJob.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AbstractJob.java similarity index 97% rename from openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AbstractJob.java rename to openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AbstractJob.java index f1b641b..25db755 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AbstractJob.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AbstractJob.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.service.quartz.scheduler; +package org.apache.openmeetings.service.scheduler; import static org.apache.openmeetings.util.OpenmeetingsVariables.isInitComplete; diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AtomReader.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AtomReader.java similarity index 98% rename from openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AtomReader.java rename to openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AtomReader.java index ca3e46e..580b1ab 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/AtomReader.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/AtomReader.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.service.quartz.scheduler; +package org.apache.openmeetings.service.scheduler; import static org.apache.openmeetings.core.rss.LoadAtomRssFeed.getFeedConnection; diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/CleanupJob.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/CleanupJob.java similarity index 90% rename from openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/CleanupJob.java rename to openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/CleanupJob.java index 4ced109..5a8ba8e 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/CleanupJob.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/CleanupJob.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.service.quartz.scheduler; +package org.apache.openmeetings.service.scheduler; import static org.apache.openmeetings.util.OmFileHelper.EXTENSION_MP4; import static org.apache.openmeetings.util.OmFileHelper.TEST_SETUP_PREFIX; @@ -33,12 +33,19 @@ import org.apache.openmeetings.db.entity.user.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +@Component("cleanupJob") public class CleanupJob extends AbstractJob { private static Logger log = LoggerFactory.getLogger(CleanupJob.class); + @Value("${job.cleanup.session.timeout}") private long sessionTimeout = 30 * 60 * 1000L; + @Value("${job.cleanup.test.setup.timeout}") private long testSetupTimeout = 60 * 60 * 1000L; // 1 hour + @Value("${job.cleanup.reset.hash.ttl}") private long resetHashTtl = 24 * 60 * 60 * 1000L; // 1 day + @Value("${job.cleanup.conf.log.ttl}") private long confLogTtl = 7 * 24 * 60 * 60 * 1000L; // 7 days @Autowired @@ -48,22 +55,6 @@ public class CleanupJob extends AbstractJob { @Autowired private ConferenceLogDao confLogDao; - public void setSessionTimeout(long sessionTimeout) { - this.sessionTimeout = sessionTimeout; - } - - public void setTestSetupTimeout(long testSetupTimeout) { - this.testSetupTimeout = testSetupTimeout; - } - - public void setResetHashTtl(long resetHashTtl) { - this.resetHashTtl = resetHashTtl; - } - - public void setConfLogTtl(long confLogTtl) { - this.confLogTtl = confLogTtl; - } - public void cleanTestSetup() { log.trace("CleanupJob.cleanTestSetup"); final long now = System.currentTimeMillis(); diff --git a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/ReminderJob.java b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/ReminderJob.java similarity index 98% rename from openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/ReminderJob.java rename to openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/ReminderJob.java index bd1e32a..9fadd6a 100644 --- a/openmeetings-service/src/main/java/org/apache/openmeetings/service/quartz/scheduler/ReminderJob.java +++ b/openmeetings-service/src/main/java/org/apache/openmeetings/service/scheduler/ReminderJob.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.openmeetings.service.quartz.scheduler; +package org.apache.openmeetings.service.scheduler; import static org.apache.openmeetings.core.rss.LoadAtomRssFeed.setRss; import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DASHBOARD_RSS_FEED1; diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/ConnectionsPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/ConnectionsPanel.java index a57b704..f2bad46 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/ConnectionsPanel.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/ConnectionsPanel.java @@ -24,11 +24,10 @@ import static org.apache.openmeetings.web.common.confirmation.ConfirmationBehavi import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.openmeetings.core.remote.KurentoHandler; import org.apache.openmeetings.core.remote.StreamProcessor; @@ -76,14 +75,11 @@ public class ConnectionsPanel extends AdminBasePanel { private static final long serialVersionUID = 1L; private List<IDataProviderEntity> getConnections() { - List<IDataProviderEntity> l = new ArrayList<>(); - l.addAll(cm.list()); - Collection<KStreamDto> streams = streamProcessor.getStreams() + return Stream.concat(cm.stream() + , streamProcessor.getStreams() .stream() .map(KStreamDto::new) - .collect(Collectors.toList()); - l.addAll(streams); - return l; + ).collect(Collectors.toList()); } @Override diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/rooms/RoomForm.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/rooms/RoomForm.java index 128f26f..aa73236 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/rooms/RoomForm.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/rooms/RoomForm.java @@ -434,8 +434,7 @@ public class RoomForm extends AdminBaseForm<Room> { void updateClients(AjaxRequestTarget target) { long roomId = getModelObject().getId() != null ? getModelObject().getId() : 0; - final List<Client> clientsInRoom = cm.listByRoom(roomId); - clients.setDefaultModelObject(clientsInRoom); + clients.setDefaultModelObject(cm.streamByRoom(roomId).collect(Collectors.toList())); target.add(clientsContainer); } 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 ac4c389..13e0c97 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 @@ -39,10 +39,12 @@ import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; import javax.websocket.WebSocketContainer; import org.apache.openmeetings.IApplication; +import org.apache.openmeetings.core.sip.SipManager; import org.apache.openmeetings.core.util.ChatWebSocketHelper; import org.apache.openmeetings.core.util.WebSocketHelper; import org.apache.openmeetings.db.dao.basic.ConfigurationDao; @@ -60,6 +62,7 @@ import org.apache.openmeetings.db.entity.room.RoomGroup; import org.apache.openmeetings.db.entity.user.GroupUser; import org.apache.openmeetings.db.entity.user.User; import org.apache.openmeetings.db.entity.user.User.Type; +import org.apache.openmeetings.db.util.ApplicationHelper; import org.apache.openmeetings.db.util.ws.RoomMessage; import org.apache.openmeetings.db.util.ws.TextRoomMessage; import org.apache.openmeetings.util.OmFileHelper; @@ -185,6 +188,8 @@ public class Application extends AuthenticatedWebApplication implements IApplica private WhiteboardManager wbManager; @Autowired private AppointmentDao appointmentDao; + @Autowired + private SipManager sipManager; @Override protected void init() { @@ -348,6 +353,11 @@ public class Application extends AuthenticatedWebApplication implements IApplica recordingDao.resetProcessingStatus(); //we are starting so all processing recordings are now errors userManager.initHttpClient(); setInitComplete(true); + CompletableFuture.runAsync(() -> { + ThreadContext.setApplication(Application.this); + ApplicationHelper.ensureRequestCycle(Application.this); + sipManager.setUserPicture(u -> ProfileImageResourceReference.getUrl(RequestCycle.get(), u)); + }); } catch (Exception err) { log.error("[appStart]", err); } diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/ClientManager.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/ClientManager.java index 317f9ee..4dfedcc 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/ClientManager.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/ClientManager.java @@ -23,21 +23,21 @@ import static org.apache.openmeetings.web.app.WebSession.getUserId; import static org.apache.openmeetings.web.pages.auth.SignInPage.TOKEN_PARAM; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.openmeetings.core.remote.KurentoHandler; +import org.apache.openmeetings.core.sip.SipManager; import org.apache.openmeetings.db.dao.log.ConferenceLogDao; import org.apache.openmeetings.db.entity.basic.Client; import org.apache.openmeetings.db.entity.log.ConferenceLog; @@ -78,6 +78,10 @@ public class ClientManager implements IClientManager { private Application app; @Autowired private KurentoHandler kHandler; + @Autowired + private SipManager sipManager; + @Autowired + private TimerService timerService; private IMap<String, Client> map() { return app.hazelcast.getMap(ONLINE_USERS_KEY); @@ -170,14 +174,12 @@ public class ClientManager implements IClientManager { if (roomId != null) { IMap<Long, Set<String>> rooms = rooms(); rooms.lock(roomId); - Set<String> clients = rooms.get(roomId); - if (clients != null) { - clients.remove(c.getUid()); - rooms.put(roomId, clients); - onlineRooms.put(roomId, clients); - } + Set<String> clients = rooms.getOrDefault(roomId, ConcurrentHashMap.newKeySet()); + clients.remove(c.getUid()); + rooms.put(roomId, clients); + onlineRooms.put(roomId, clients); rooms.unlock(roomId); - if (clients == null || clients.isEmpty()) { + if (clients.isEmpty()) { String serverId = c.getServerId(); IMap<String, ServerInfo> servers = servers(); servers.lock(serverId); @@ -258,8 +260,7 @@ public class ClientManager implements IClientManager { log.debug("Adding online room client: {}, room: {}", c.getUid(), roomId); IMap<Long, Set<String>> rooms = rooms(); rooms.lock(roomId); - rooms.putIfAbsent(roomId, ConcurrentHashMap.newKeySet()); - Set<String> set = rooms.get(roomId); + Set<String> set = rooms.getOrDefault(roomId, ConcurrentHashMap.newKeySet()); set.add(c.getUid()); final int count = set.size(); rooms.put(roomId, set); @@ -268,6 +269,7 @@ public class ClientManager implements IClientManager { String serverId = c.getServerId(); addRoomToServer(serverId, r); update(c); + timerService.scheduleSipCheck(r); return count; } @@ -296,8 +298,8 @@ public class ClientManager implements IClientManager { } @Override - public List<Client> list() { - return new ArrayList<>(map().values()); + public Stream<Client> stream() { + return map().values().stream(); } @Override @@ -306,50 +308,24 @@ public class ClientManager implements IClientManager { } @Override - public List<Client> listByRoom(Long roomId) { - return listByRoom(roomId, null); - } - - public List<Client> listByRoom(Long roomId, Predicate<Client> filter) { - List<Client> clients = new ArrayList<>(); - if (roomId != null) { - Set<String> uids = onlineRooms.get(roomId); - if (uids != null) { - for (String uid : uids) { - Client c = get(uid); - if (c != null && (filter == null || filter.test(c))) { - clients.add(c); - } - } - } - } - return clients; - } - - public Set<Long> listRoomIds(Long userId) { - Set<Long> result = new HashSet<>(); - for (Entry<Long, Set<String>> me : onlineRooms.entrySet()) { - for (String uid : me.getValue()) { - Client c = get(uid); - if (c != null && c.sameUserId(userId)) { - result.add(me.getKey()); - } - } - } - return result; + public Stream<Client> streamByRoom(Long roomId) { + return Optional.ofNullable(roomId) + .map(id -> onlineRooms.getOrDefault(id, Set.of())) + .stream() + .flatMap(Set::stream) + .map(uid -> get(uid)) + .filter(Objects::nonNull); } public boolean isInRoom(long roomId, long userId) { - Set<String> clients = onlineRooms.get(roomId); - if (clients != null) { - for (String uid : clients) { - Client c = get(uid); - if (c != null && c.sameUserId(userId)) { - return true; - } - } - } - return false; + return Optional.of(roomId) + .map(id -> onlineRooms.getOrDefault(id, Set.of())) + .stream() + .flatMap(Set::stream) + .map(uid -> get(uid)) + .filter(c -> c != null && c.sameUserId(userId)) + .findAny() + .isPresent(); } private List<Client> getByKeys(Long userId, String sessionId) { diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/TimerService.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/TimerService.java index 906426f..799b5a1 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/TimerService.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/TimerService.java @@ -21,13 +21,17 @@ package org.apache.openmeetings.web.app; import static java.util.concurrent.CompletableFuture.delayedExecutor; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import javax.annotation.PostConstruct; +import org.apache.openmeetings.core.sip.SipManager; import org.apache.openmeetings.core.util.WebSocketHelper; +import org.apache.openmeetings.db.entity.basic.Client; import org.apache.openmeetings.db.entity.room.Room; import org.apache.openmeetings.db.entity.room.Room.Right; import org.apache.openmeetings.db.entity.user.User; @@ -42,15 +46,19 @@ import org.springframework.stereotype.Service; public class TimerService { private static final Logger log = LoggerFactory.getLogger(TimerService.class); private int modCheckInterval = 5; + private int sipCheckInterval = 2; private final User sysUser = new User(); private final Map<Long, CompletableFuture<Object>> modCheckMap = new ConcurrentHashMap<>(); + private final Map<Long, CompletableFuture<Object>> sipCheckMap = new ConcurrentHashMap<>(); @Autowired private ClientManager cm; + @Autowired + private SipManager sipManager; @PostConstruct private void init() { - sysUser.setId(-1L); + sysUser.setId(-5L); sysUser.setDisplayName("System"); } @@ -59,19 +67,64 @@ public class TimerService { roomId , new CompletableFuture<>().completeAsync(() -> { log.warn("Moderator room check {}", roomId); - if (cm.listByRoom(roomId).isEmpty()) { + if (cm.streamByRoom(roomId).findAny().isEmpty()) { modCheckMap.remove(roomId); } else { - WebSocketHelper.sendRoom(new TextRoomMessage(roomId, sysUser, RoomMessage.Type.MODERATOR_IN_ROOM, "" + !cm.listByRoom(roomId, c -> c.hasRight(Right.MODERATOR)).isEmpty())); + WebSocketHelper.sendRoom(new TextRoomMessage(roomId, sysUser, RoomMessage.Type.MODERATOR_IN_ROOM + , "" + !cm.streamByRoom(roomId).filter(c -> c.hasRight(Right.MODERATOR)).findAny().isEmpty())); doModCheck(roomId); } return null; }, delayedExecutor(modCheckInterval, TimeUnit.SECONDS))); } + private void doSipCheck(Long roomId) { + sipCheckMap.put( + roomId + , new CompletableFuture<>().completeAsync(() -> { + log.warn("Sip room check {}", roomId); + Optional<Client> sipClient = cm.streamByRoom(roomId).filter(Client::isSip).findAny(); + cm.streamByRoom(roomId).filter(Predicate.not(Client::isSip)).findAny().ifPresentOrElse(c -> { + updateSipLastName(sipClient, c.getRoom()); + doSipCheck(roomId); + }, () -> { + log.warn("No more clients in the room {}", roomId); + sipCheckMap.remove(roomId); + sipClient.ifPresent(cm::exit); + }); + return null; + }, delayedExecutor(sipCheckInterval, TimeUnit.SECONDS))); + } + + private void updateSipLastName(Optional<Client> sipClient, Room r) { + final String newLastName = "(" + sipManager.countUsers(r.getConfno()) + ")"; + sipClient.ifPresentOrElse(c -> { + if (!newLastName.equals(c.getUser().getLastname())) { + c.getUser().setLastname(newLastName).resetDisplayName(); + cm.update(c); + WebSocketHelper.sendRoom(new TextRoomMessage(r.getId(), c, RoomMessage.Type.RIGHT_UPDATED, c.getUid())); + } + }, () -> { + User sipUser = sipManager.getSipUser(r); + sipUser.setLastname(newLastName).resetDisplayName(); + Client c = new Client("-- unique - sip - session --", 1, sipUser, sipUser.getPictureUri()); + cm.add(c); + c.setRoom(r); + cm.addToRoom(c); + WebSocketHelper.sendRoom(new TextRoomMessage(r.getId(), c, RoomMessage.Type.ROOM_ENTER, c.getUid())); + }); + } + public void scheduleModCheck(Room r) { - if (r.isModerated() && r.isWaitModerator() && !cm.listByRoom(r.getId()).isEmpty() && !modCheckMap.containsKey(r.getId())) { + if (r.isModerated() && r.isWaitModerator() && !modCheckMap.containsKey(r.getId())) { doModCheck(r.getId()); } } + + public void scheduleSipCheck(Room r) { + // sip allowed and configured + if (sipManager.getSipUser(r) != null && !sipCheckMap.containsKey(r.getId())) { + doSipCheck(r.getId()); + } + } } diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/UserManager.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/UserManager.java index 53265d5..76a8dcf 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/UserManager.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/UserManager.java @@ -223,9 +223,7 @@ public class UserManager implements IUserManager { @Override public boolean kickUsersByRoomId(Long roomId) { try { - for (Client c : cm.listByRoom(roomId)) { - Application.kickUser(c); - } + cm.streamByRoom(roomId).forEach(Application::kickUser); return true; } catch (Exception err) { log.error("[kickUsersByRoomId]", err); @@ -235,7 +233,7 @@ public class UserManager implements IUserManager { @Override public boolean kickExternal(Long roomId, String externalType, String externalId) { - boolean result = false; + Boolean result = false; try { if (roomId == null) { return result; 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 73f9049..4a4ae17 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 @@ -44,7 +44,6 @@ import org.apache.openmeetings.db.dao.calendar.AppointmentDao; import org.apache.openmeetings.db.dao.file.FileItemDao; import org.apache.openmeetings.db.dao.user.UserDao; import org.apache.openmeetings.db.entity.basic.Client; -import org.apache.openmeetings.db.entity.basic.Client.StreamDesc; import org.apache.openmeetings.db.entity.calendar.Appointment; import org.apache.openmeetings.db.entity.calendar.MeetingMember; import org.apache.openmeetings.db.entity.file.BaseFileItem; @@ -167,9 +166,9 @@ public class RoomPanel extends BasePanel { sidebar.setFilesActive(target); } if (Room.Type.PRESENTATION != r.getType()) { - List<Client> mods = cm.listByRoom(r.getId(), cl -> cl.hasRight(Room.Right.MODERATOR)); - log.debug("RoomPanel::roomEnter, mods IS EMPTY ? {}, is MOD ? {}", mods.isEmpty(), c.hasRight(Room.Right.MODERATOR)); - if (mods.isEmpty()) { + boolean modsEmpty = noModerators(); + log.debug("RoomPanel::roomEnter, mods IS EMPTY ? {}, is MOD ? {}", modsEmpty, c.hasRight(Room.Right.MODERATOR)); + if (modsEmpty) { showIdeaAlert(target, getString(r.isModerated() ? "641" : "498")); } } @@ -182,11 +181,10 @@ public class RoomPanel extends BasePanel { private void initVideos(AjaxRequestTarget target) { StringBuilder sb = new StringBuilder(); JSONArray streams = new JSONArray(); - for (Client c : cm.listByRoom(getRoom().getId())) { - for (StreamDesc sd : c.getStreams()) { - streams.put(sd.toJson()); - } - } + cm.streamByRoom(getRoom().getId()) + .map(Client::getStreams) + .flatMap(List::stream) + .forEach(sd -> streams.put(sd.toJson())); if (streams.length() > 0) { sb.append("VideoManager.play(").append(streams).append(", ").append(kHandler.getTurnServers(getClient())).append(");"); } @@ -312,7 +310,7 @@ public class RoomPanel extends BasePanel { add(roomClosed = new RedirectMessageDialog("room-closed", "1098", r.isClosed(), r.getRedirectURL())); if (r.isClosed()) { room.setVisible(false); - } else if (cm.listByRoom(r.getId()).size() >= r.getCapacity()) { + } else if (cm.streamByRoom(r.getId()).count() >= r.getCapacity()) { accessDenied = new ExpiredMessageDialog(ACCESS_DENIED_ID, getString("99"), menu); room.setVisible(false); } else if (r.getId().equals(WebSession.get().getRoomId())) { @@ -397,7 +395,7 @@ public class RoomPanel extends BasePanel { } if (r.isModerated() && r.isWaitModerator() && !c.hasRight(Right.MODERATOR) - && cm.listByRoom(r.getId(), cl -> cl.hasRight(Right.MODERATOR)).isEmpty()) + && noModerators()) { room.setVisible(false); createWaitModerator(true); @@ -620,13 +618,9 @@ public class RoomPanel extends BasePanel { if (streamProcessor.isRecording(r.getId())) { handler.appendJavaScript("if (typeof(WbArea) === 'object') {WbArea.setRecStarted(true);}"); } else if (streamProcessor.recordingAllowed(getClient())) { - boolean hasStreams = false; - for (Client cl : cm.listByRoom(r.getId())) { - if (!cl.getStreams().isEmpty()) { - hasStreams = true; - break; - } - } + boolean hasStreams = cm.streamByRoom(r.getId()) + .filter(cl -> !cl.getStreams().isEmpty()) + .findAny().isPresent(); handler.appendJavaScript(String.format("if (typeof(WbArea) === 'object') {WbArea.setRecStarted(false);WbArea.setRecEnabled(%s);}", hasStreams)); } } @@ -641,12 +635,9 @@ public class RoomPanel extends BasePanel { } public static boolean hasRight(ClientManager cm, long userId, long roomId, Right r) { - for (Client c : cm.listByRoom(roomId)) { - if (c.sameUserId(userId) && c.hasRight(r)) { - return true; - } - } - return false; + return cm.streamByRoom(roomId) + .filter(c -> c.sameUserId(userId) && c.hasRight(r)) + .findAny().isPresent(); } @Override @@ -699,8 +690,7 @@ public class RoomPanel extends BasePanel { public void requestRight(Right right, IPartialPageRequestHandler handler) { RoomMessage.Type reqType = null; - List<Client> mods = cm.listByRoom(r.getId(), c -> c.hasRight(Room.Right.MODERATOR)); - if (mods.isEmpty()) { + if (noModerators()) { if (r.isModerated()) { showIdeaAlert(handler, getString("696")); return; @@ -881,7 +871,7 @@ public class RoomPanel extends BasePanel { private CharSequence createAddClientJs(Client c) { JSONArray arr = new JSONArray(); - cm.listByRoom(r.getId()).stream().forEach(cl -> arr.put(cl.toJson(c.getUid().equals(cl.getUid())))); + cm.streamByRoom(r.getId()).forEach(cl -> arr.put(cl.toJson(c.getUid().equals(cl.getUid())))); return new StringBuilder() .append("Room.addClient(") .append(arr.toString(new NullStringer())) @@ -909,4 +899,11 @@ public class RoomPanel extends BasePanel { } return res; } + + private boolean noModerators() { + return cm.streamByRoom(r.getId()) + .filter(cl -> cl.hasRight(Room.Right.MODERATOR)) + .findAny() + .isEmpty(); + } } diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/SipDialerDialog.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/SipDialerDialog.java index eb31b18..e54a13a 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/SipDialerDialog.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/SipDialerDialog.java @@ -18,7 +18,7 @@ */ package org.apache.openmeetings.web.room.menu; -import org.apache.openmeetings.db.dao.room.SipDao; +import org.apache.openmeetings.core.sip.SipManager; import org.apache.openmeetings.web.common.OmModalCloseButton; import org.apache.openmeetings.web.room.RoomPanel; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -41,7 +41,7 @@ public class SipDialerDialog extends Modal<String> { private final TextField<String> number = new TextField<>("number", Model.of("")); private final RoomPanel room; @SpringBean - private SipDao sipDao; + private SipManager sipDao; public SipDialerDialog(String id, RoomPanel room) { super(id); diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbWebSocketHelper.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbWebSocketHelper.java index c7b8232..df58970 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbWebSocketHelper.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbWebSocketHelper.java @@ -18,6 +18,7 @@ */ package org.apache.openmeetings.web.room.wb; +import static org.apache.openmeetings.core.util.WebSocketHelper.alwaysTrue; import static org.apache.openmeetings.core.util.WebSocketHelper.publish; import static org.apache.openmeetings.core.util.WebSocketHelper.sendRoom; import static org.apache.openmeetings.util.OpenmeetingsVariables.PARAM_SRC; @@ -74,7 +75,7 @@ public class WbWebSocketHelper { if (publish) { publish(new WsMessageWb(roomId, meth, obj, null)); } - sendWb(roomId, meth, obj, null); + sendWb(roomId, meth, obj, alwaysTrue()); } public static void sendWbOthers(Long roomId, WbAction meth, JSONObject obj, final String uid) { diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java index 9aca029..9791449 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java @@ -38,7 +38,6 @@ import java.util.List; import org.apache.openmeetings.core.mail.MailHandler; import org.apache.openmeetings.db.dao.basic.ConfigurationDao; import org.apache.openmeetings.db.dao.calendar.AppointmentDao; -import org.apache.openmeetings.db.dao.room.IInvitationManager; import org.apache.openmeetings.db.dao.room.RoomDao; import org.apache.openmeetings.db.dao.user.PrivateMessageDao; import org.apache.openmeetings.db.dao.user.UserDao; @@ -50,6 +49,7 @@ import org.apache.openmeetings.db.entity.room.Room; import org.apache.openmeetings.db.entity.user.PrivateMessage; import org.apache.openmeetings.db.entity.user.User; import org.apache.openmeetings.db.entity.user.User.Type; +import org.apache.openmeetings.db.manager.IInvitationManager; import org.apache.openmeetings.util.CalendarHelper; import org.apache.openmeetings.web.app.Application; import org.apache.openmeetings.web.app.WebSession; diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomListPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomListPanel.java index cd4dfd4..3576fc8 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomListPanel.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomListPanel.java @@ -70,7 +70,7 @@ public class RoomListPanel extends Panel { final WebMarkupContainer info = new WebMarkupContainer("info"); roomContainer.add(info.setOutputMarkupId(true) .add(AttributeModifier.append(ATTR_TITLE, getString(String.format("room.type.%s.desc", r.getType().name()))))); - final Label curUsers = new Label("curUsers", new Model<>(cm.listByRoom(r.getId()).size())); + final Label curUsers = new Label("curUsers", new Model<>(cm.streamByRoom(r.getId()).count())); roomContainer.add(curUsers.setOutputMarkupId(true)); roomContainer.add(new Label("totalUsers", r.getCapacity())); item.add(new WebMarkupContainer("btn").add(new Label("label", label)).add(new RoomEnterBehavior(r.getId()) { @@ -95,7 +95,7 @@ public class RoomListPanel extends Panel { @Override public void onClick(AjaxRequestTarget target) { - target.add(curUsers.setDefaultModelObject(cm.listByRoom(r.getId()).size())); + target.add(curUsers.setDefaultModelObject(cm.streamByRoom(r.getId()).count())); onRefreshClick(target, r); } }.add(AttributeModifier.append(ATTR_TITLE, new ResourceModel("lbl.refresh")))); diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomsPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomsPanel.java index f110da7..4760969 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomsPanel.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/rooms/RoomsPanel.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.List; +import java.util.stream.Collectors; import org.apache.openmeetings.db.dao.room.RoomDao; import org.apache.openmeetings.db.dao.user.UserDao; @@ -128,7 +129,7 @@ public class RoomsPanel extends UserPanel { } void updateRoomDetails(AjaxRequestTarget target) { - clients.setDefaultModelObject(cm.listByRoom(roomId)); + clients.setDefaultModelObject(cm.streamByRoom(roomId).collect(Collectors.toList())); Room room = roomDao.get(roomId); roomIdLbl.setDefaultModelObject(room.getId()); roomNameLbl.setDefaultModelObject(room.getName()); 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 0edbe2b..e8391ad 100644 --- a/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml +++ b/openmeetings-web/src/main/webapp/WEB-INF/classes/applicationContext.xml @@ -40,18 +40,9 @@ <context:annotation-config /> <context:component-scan base-package="org.apache.openmeetings" /> - <!-- - 5000 == 5 sec - 300000 == 5 min - 900000 == 15 min - 1800000 == 30 min - 3600000 == 1 hour - 86400000 == 1 day - 604800000 == 7 days - --> - <bean id="cleanupJob" class="org.apache.openmeetings.service.quartz.scheduler.CleanupJob" - p:sessionTimeout="1800000" p:testSetupTimeout="3600000" p:resetHashTtl="86400000" - p:confLogTtl="604800000" /> + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" + p:location="classpath:openmeetings.properties" /> + <!-- sessions clean-up --> <bean id="cleanSessionsJobDetails" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" p:targetObject-ref="cleanupJob" p:targetMethod="cleanSessions" p:concurrent="false" /> @@ -124,46 +115,10 @@ </bean> <!-- End of Services --> - <bean class="org.apache.openmeetings.db.dao.room.SipConfig"> - <!-- Should be uncommented and updated with real values for Asterisk- - <property name="sipHostname" value="192.168.1.102"/> - <property name="managerPort" value="5038"/> - <property name="managerUser" value="openmeetings"/> - <property name="managerPass" value="12345"/> - <property name="managerTimeout" value="10000"/> - - <property name="localWsPort" value="6666"/> - <property name="localWsHost" value="192.168.1.211"/> - <property name="wsPort" value="8088"/> - <property name="omSipUser" value="omsip_user"/> - <property name="omSipPasswd" value="12345"/> - - <property name="uid" value="87dddad4-9ca5-475b-860f-2e0825d02b76"/> - - --> - </bean> - <!-- Thread Executor --> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="queueCapacity" value="25" /> </bean> - - <!-- Kurento --> - <!-- please ensure `p:kuid` below is unique, better to regenerate it from time to time --> - <!-- `p:ignoredKuids` can be space and/or comma separated --> - <bean id="kurentoHandler" class="org.apache.openmeetings.core.remote.KurentoHandler" - p:kurentoWsUrl="ws://127.0.0.1:8888/kurento" - p:checkTimeout="10000" - p:watchThreadCount="10" - p:turnUrl="" - p:turnUser="" - p:turnSecret="" - p:turnMode="rest" - p:turnTtl="60" - p:objCheckTimeout="200" - p:flowoutTimeout="5" - p:kuid="df992960-e7b0-11ea-9acd-337fb30dd93d" - p:ignoredKuids="" - /> </beans> diff --git a/openmeetings-web/src/main/webapp/WEB-INF/classes/openmeetings.properties b/openmeetings-web/src/main/webapp/WEB-INF/classes/openmeetings.properties new file mode 100644 index 0000000..5f566d8 --- /dev/null +++ b/openmeetings-web/src/main/webapp/WEB-INF/classes/openmeetings.properties @@ -0,0 +1,65 @@ +# +# 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. +# +################## Timeouts ################## +# 5000 == 5 sec +# 300000 == 5 min +# 900000 == 15 min +# 1800000 == 30 min +# 3600000 == 1 hour +# 86400000 == 1 day +# 604800000 == 7 days +job.cleanup.session.timeout=1800000 +job.cleanup.test.setup.timeout=3600000 +job.cleanup.reset.hash.ttl=86400000 +job.cleanup.conf.log.ttl=604800000 + +################## Kurento ################## +kurento.ws.url=ws://127.0.0.1:8888/kurento +kurento.turn.url= +kurento.turn.user= +kurento.turn.secret= +kurento.turn.mode=rest +## minutes +kurento.turn.ttl=60 +## milliseconds +kurento.check.timeout=10000 +## milliseconds +kurento.object.check.timeout=200 +kurento.watch.thread.count=10 +kurento.flowout.timeout=5 +## please ensure this one is unique, better to regenerate it from time to time +## can be generated for ex. here https://www.uuidtools.com +kurento.kuid=df992960-e7b0-11ea-9acd-337fb30dd93d +## this list can be space and/or comma separated +kurento.ignored.kuids= + +################## SIP ################## +### Should be uncommented and updated with real values for Asterisk ### +#sip.hostname=192.168.1.102 +#sip.manager.port=5038 +#sip.manager.user=openmeetings +#sip.manager.password=12345 +#sip.manager.timeout=10000 + +#sip.ws.local.port=6666 +## 127.0.0.1 is NOT working here +#sip.ws.local.host=192.168.1.211 +#sip.ws.remote.port=8088 +#sip.ws.remote.user=omsip_user +#sip.ws.remote.password=12345 diff --git a/openmeetings-web/src/test/java/org/apache/openmeetings/service/quartz/TestJob.java b/openmeetings-web/src/test/java/org/apache/openmeetings/service/quartz/TestJob.java index 01be361..58edf05 100644 --- a/openmeetings-web/src/test/java/org/apache/openmeetings/service/quartz/TestJob.java +++ b/openmeetings-web/src/test/java/org/apache/openmeetings/service/quartz/TestJob.java @@ -23,8 +23,8 @@ import static org.apache.openmeetings.util.OpenmeetingsVariables.setInitComplete import org.apache.openmeetings.AbstractWicketTester; import org.apache.openmeetings.db.entity.basic.Configuration; -import org.apache.openmeetings.service.quartz.scheduler.CleanupJob; -import org.apache.openmeetings.service.quartz.scheduler.ReminderJob; +import org.apache.openmeetings.service.scheduler.CleanupJob; +import org.apache.openmeetings.service.scheduler.ReminderJob; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/RoomWebService.java b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/RoomWebService.java index dd4a83c..d704577 100644 --- a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/RoomWebService.java +++ b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/RoomWebService.java @@ -22,6 +22,7 @@ import static org.apache.openmeetings.webservice.Constants.TNS; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import javax.jws.WebMethod; import javax.jws.WebParam; @@ -46,7 +47,6 @@ import org.apache.openmeetings.db.dto.basic.ServiceResult.Type; import org.apache.openmeetings.db.dto.room.InvitationDTO; import org.apache.openmeetings.db.dto.room.RoomDTO; import org.apache.openmeetings.db.dto.user.UserDTO; -import org.apache.openmeetings.db.entity.basic.Client; import org.apache.openmeetings.db.entity.room.Invitation; import org.apache.openmeetings.db.entity.room.Invitation.MessageType; import org.apache.openmeetings.db.entity.room.Room; @@ -349,7 +349,7 @@ public class RoomWebService extends BaseWebService { @GET @Path("/count/{roomid}") public ServiceResult count(@WebParam(name="sid") @QueryParam("sid") String sid, @WebParam(name="roomid") @PathParam("roomid") Long roomId) { - return performCall(sid, User.Right.SOAP, sd -> new ServiceResult(String.valueOf(clientManager.listByRoom(roomId).size()), Type.SUCCESS)); + return performCall(sid, User.Right.SOAP, sd -> new ServiceResult(String.valueOf(clientManager.streamByRoom(roomId).count()), Type.SUCCESS)); } /** @@ -364,11 +364,9 @@ public class RoomWebService extends BaseWebService { @Path("/users/{roomid}") public List<UserDTO> users(@WebParam(name="sid") @QueryParam("sid") String sid, @WebParam(name="roomid") @PathParam("roomid") Long roomId) { return performCall(sid, User.Right.SOAP, sd -> { - List<UserDTO> result = new ArrayList<>(); - for (Client c : clientManager.listByRoom(roomId)) { - result.add(new UserDTO(c.getUser())); - } - return result; + return clientManager.streamByRoom(roomId) + .map(c -> new UserDTO(c.getUser())) + .collect(Collectors.toList()); }); } diff --git a/pom.xml b/pom.xml index 60b4cf4..959ee7e 100644 --- a/pom.xml +++ b/pom.xml @@ -616,18 +616,6 @@ </exclusions> </dependency> <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-inline</artifactId> - <version>${mockito.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-junit-jupiter</artifactId> - <version>${mockito.version}</version> - <scope>test</scope> - </dependency> - <dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> @@ -644,16 +632,33 @@ <version>4.3.0</version> </dependency> <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-params</artifactId> - <version>${junit.version}</version> - <scope>test</scope> + <groupId>org.asteriskjava</groupId> + <artifactId>asterisk-java</artifactId> + <version>${asterisk-java.version}</version> </dependency> <dependency> <groupId>javax.sip</groupId> <artifactId>jain-sip-ri</artifactId> <version>${jain-sip.version}</version> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-inline</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> </dependencies> </dependencyManagement> <dependencies>