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 5608cbf  [OPENMEETINGS-2239] another attempt to make 'softphone -> 
browser' work
5608cbf is described below

commit 5608cbfee7be52e625f0197f1dbad0d53f1421e9
Author: Maxim Solodovnik <solomax...@gmail.com>
AuthorDate: Tue Dec 22 21:40:51 2020 +0700

    [OPENMEETINGS-2239] another attempt to make 'softphone -> browser' work
---
 .../openmeetings/core/remote/AbstractStream.java   |  12 +-
 .../org/apache/openmeetings/core/remote/KRoom.java |  26 ++--
 .../apache/openmeetings/core/remote/KStream.java   | 140 ++++++++++++---------
 .../openmeetings/core/remote/KTestStream.java      |   4 +-
 .../openmeetings/core/sip/ISipCallbacks.java       |   4 +-
 .../apache/openmeetings/core/sip/SipManager.java   |  47 ++++---
 .../openmeetings/core/sip/SipStackProcessor.java   |  18 +--
 .../openmeetings/core/remote/BaseMockedTest.java   |   3 +-
 .../src/site/markdown/AsteriskIntegration.md       |   1 -
 .../web/admin/connection/KStreamDto.java           |  40 +++---
 .../apache/openmeetings/web/app/TimerService.java  |   3 +-
 .../org/apache/openmeetings/web/room/raw-room.js   |  28 +++--
 12 files changed, 181 insertions(+), 145 deletions(-)

diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/AbstractStream.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/AbstractStream.java
index cfc18d4..2dd7230 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/AbstractStream.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/AbstractStream.java
@@ -48,8 +48,16 @@ public abstract class AbstractStream {
 
        public abstract void release(boolean remove);
 
-       public static WebRtcEndpoint createWebRtcEndpoint(MediaPipeline 
pipeline) {
-               return new WebRtcEndpoint.Builder(pipeline).build();
+       public static WebRtcEndpoint createWebRtcEndpoint(MediaPipeline 
pipeline, Boolean send) {
+               WebRtcEndpoint.Builder builder = new 
WebRtcEndpoint.Builder(pipeline);
+               if (send != null) {
+                       if (send) {
+                               builder.sendonly();
+                       } else {
+                               builder.recvonly();
+                       }
+               }
+               return builder.build();
        }
 
        public static RecorderEndpoint createRecorderEndpoint(MediaPipeline 
pipeline, String path, MediaProfileSpecType profile) {
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
index 2062c5b..bc90f9b 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
@@ -1,7 +1,4 @@
 /*
- * (C) Copyright 2014 Kurento (http://kurento.org/)
- */
-/*
  * 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
@@ -52,15 +49,12 @@ import org.slf4j.LoggerFactory;
 import com.github.openjson.JSONObject;
 
 /**
- * Bean object dynamically created representing a conference room on the 
MediaServer
+ * Dynamically created object representing a conference room on the MediaServer
  *
  */
 public class KRoom {
        private static final Logger log = LoggerFactory.getLogger(KRoom.class);
 
-       /**
-        * Not injected by annotation but by constructor.
-        */
        private final StreamProcessor processor;
        private final RecordingChunkDao chunkDao;
        private final Room room;
@@ -104,8 +98,6 @@ public class KRoom {
                                .put("uid", stream.getUid())
                                .toString()
                        );
-               //FIXME TODO check close on stop sharing
-               //FIXME TODO permission can be removed, some listener might be 
required
        }
 
        public boolean isRecording() {
@@ -251,8 +243,22 @@ public class KRoom {
 
        public void updateSipCount(final long count) {
                if (count != sipCount) {
-                       sipCount = count;
                        processor.getByRoom(room.getId()).forEach(stream -> 
stream.addSipProcessor(count));
+                       if (sipCount == 0) {
+                               processor.getClientManager()
+                                       .streamByRoom(room.getId())
+                                       .filter(Client::isSip)
+                                       .findAny()
+                                       .ifPresent(c -> {
+                                               StreamDesc sd = 
c.addStream(StreamType.WEBCAM, Activity.AUDIO, Activity.VIDEO); // TODO check 
this
+                                               sd.setWidth(120).setHeight(90);
+                                               c.restoreActivities(sd);
+                                               KStream stream = join(sd, 
processor.getHandler());
+                                               stream.startBroadcast(sd, "", 
() -> {});
+                                               
processor.getClientManager().update(c);
+                                       });
+                       }
+                       sipCount = count;
                }
        }
 
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KStream.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KStream.java
index c7fb37a..ffd91e1 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KStream.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KStream.java
@@ -40,6 +40,7 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 
 import org.apache.openmeetings.core.sip.ISipCallbacks;
 import org.apache.openmeetings.core.sip.SipStackProcessor;
@@ -52,6 +53,7 @@ import 
org.apache.openmeetings.db.entity.record.RecordingChunk.Type;
 import org.apache.openmeetings.db.util.ws.RoomMessage;
 import org.apache.openmeetings.db.util.ws.TextRoomMessage;
 import org.apache.openmeetings.util.OmFileHelper;
+import org.kurento.client.BaseRtpEndpoint;
 import org.kurento.client.Continuation;
 import org.kurento.client.IceCandidate;
 import org.kurento.client.ListenerSubscription;
@@ -60,6 +62,7 @@ import org.kurento.client.MediaObject;
 import org.kurento.client.MediaPipeline;
 import org.kurento.client.MediaProfileSpecType;
 import org.kurento.client.MediaType;
+import org.kurento.client.OfferOptions;
 import org.kurento.client.RecorderEndpoint;
 import org.kurento.client.RtpEndpoint;
 import org.kurento.client.WebRtcEndpoint;
@@ -79,7 +82,7 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
        private MediaProfileSpecType profile;
        private MediaPipeline pipeline;
        private RecorderEndpoint recorder;
-       private WebRtcEndpoint outgoingMedia = null;
+       private BaseRtpEndpoint outgoingMedia = null;
        private RtpEndpoint rtpEndpoint;
        private Optional<SipStackProcessor> sipProcessor = Optional.empty();
        private final ConcurrentMap<String, WebRtcEndpoint> listeners = new 
ConcurrentHashMap<>();
@@ -143,7 +146,13 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                pipeline = kHandler.createPipiline(Map.of(TAG_ROOM, 
String.valueOf(getRoomId()), TAG_STREAM_UID, sd.getUid()), new 
Continuation<Void>() {
                        @Override
                        public void onSuccess(Void result) throws Exception {
-                               internalStartBroadcast(sd, sdpOffer);
+                               if (sipClient) {
+                                       addSipProcessor(1);
+                               } else {
+                                       outgoingMedia = 
createEndpoint(sd.getSid(), sd.getUid(), true);
+                                       internalStartBroadcast(sd, sdpOffer);
+                                       notifyOnNewStream(sd);
+                               }
                                then.run();
                        }
 
@@ -155,10 +164,10 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
        }
 
        private void internalStartBroadcast(final StreamDesc sd, final String 
sdpOffer) throws Exception {
-               outgoingMedia = createEndpoint(sd.getSid(), sd.getUid());
                outgoingMedia.addMediaSessionTerminatedListener(evt -> 
log.warn("Media stream terminated {}", sd));
                flowoutSubscription = 
outgoingMedia.addMediaFlowOutStateChangeListener(evt -> {
-                       log.info("Media Flow STATE :: {}, type {}, evt {}", 
evt.getState(), evt.getType(), evt.getMediaType());
+                       log.info("Media Flow OUT STATE :: {}, evt {}, source {}"
+                                       , evt.getState(), evt.getMediaType(), 
evt.getSource());
                        if (MediaFlowState.NOT_FLOWING == evt.getState()) {
                                log.warn("FlowOut Future is created");
                                flowoutFuture = Optional.of(new 
CompletableFuture<>().completeAsync(() -> {
@@ -173,12 +182,18 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                                dropFlowoutFuture();
                        }
                });
-               outgoingMedia.addMediaFlowInStateChangeListener(evt -> 
log.warn("Media FlowIn :: {}", evt));
-               addListener(sd.getSid(), sd.getUid(), sdpOffer);
-               addSipProcessor(kRoom.getSipCount());
+               outgoingMedia.addMediaFlowInStateChangeListener(evt -> 
log.warn("Media Flow IN :: {}, {}, {}"
+                               , evt.getState(), evt.getMediaType(), 
evt.getSource()));
+               if (!sipClient) {
+                       addListener(sd.getSid(), sd.getUid(), sdpOffer);
+                       addSipProcessor(kRoom.getSipCount());
+               }
                if (kRoom.isRecording()) {
                        startRecord();
                }
+       }
+
+       private void notifyOnNewStream(final StreamDesc sd) {
                Client c = sd.getClient();
                WebSocketHelper.sendRoom(new TextRoomMessage(c.getRoomId(), c, 
RoomMessage.Type.RIGHT_UPDATED, c.getUid()));
                if (hasAudio || hasVideo || hasScreen) {
@@ -213,11 +228,13 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                        return;
                }
 
-               final WebRtcEndpoint endpoint = getEndpointForUser(sid, uid);
+               final BaseRtpEndpoint endpoint = getEndpointForUser(sid, uid);
                final String sdpAnswer = endpoint.processOffer(sdpOffer);
 
-               log.debug("gather candidates");
-               endpoint.gatherCandidates(); // this one might throw Exception
+               if (endpoint instanceof WebRtcEndpoint) {
+                       log.debug("gather candidates");
+                       ((WebRtcEndpoint)endpoint).gatherCandidates(); // this 
one might throw Exception
+               }
                log.trace("USER {}: SdpAnswer is {}", this.uid, sdpAnswer);
                kHandler.sendClient(sid, newKurentoMsg()
                                .put("id", "videoResponse")
@@ -225,7 +242,7 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                                .put("sdpAnswer", sdpAnswer));
        }
 
-       private WebRtcEndpoint getEndpointForUser(String sid, String uid) {
+       private BaseRtpEndpoint getEndpointForUser(String sid, String uid) {
                if (uid.equals(this.uid)) {
                        log.debug("PARTICIPANT {}: configuring loopback", 
this.uid);
                        return outgoingMedia;
@@ -238,7 +255,7 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                        listener.release();
                }
                log.debug("PARTICIPANT {}: creating new endpoint for {}", uid, 
this.uid);
-               listener = createEndpoint(sid, uid);
+               listener = createEndpoint(sid, uid, false);
                listeners.put(uid, listener);
 
                log.debug("PARTICIPANT {}: obtained endpoint for {}", uid, 
this.uid);
@@ -266,14 +283,16 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                endpoint.addTag("uid", uid);
        }
 
-       private RtpEndpoint getRtpEndpoint(MediaPipeline pipeline) {
-               RtpEndpoint endpoint = new 
RtpEndpoint.Builder(pipeline).build();
+       private RtpEndpoint getRtpEndpoint(MediaPipeline pipeline, String 
direction) {
+               RtpEndpoint endpoint = new RtpEndpoint.Builder(pipeline)
+                               //.withProperties(Properties.of(direction, 
Boolean.TRUE))
+                               .build();
                setTags(endpoint, uid);
                return endpoint;
        }
 
-       private WebRtcEndpoint createEndpoint(String sid, String uid) {
-               WebRtcEndpoint endpoint = createWebRtcEndpoint(pipeline);
+       private WebRtcEndpoint createEndpoint(String sid, String uid, boolean 
send) {
+               WebRtcEndpoint endpoint = createWebRtcEndpoint(pipeline, send);
                setTags(endpoint, uid);
 
                endpoint.addIceCandidateFoundListener(evt -> 
kHandler.sendClient(sid
@@ -475,10 +494,10 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
 
        public void addCandidate(IceCandidate candidate, String uid) {
                if (this.uid.equals(uid)) {
-                       if (outgoingMedia == null) {
+                       if (outgoingMedia == null || !(outgoingMedia instanceof 
WebRtcEndpoint)) {
                                return;
                        }
-                       outgoingMedia.addIceCandidate(candidate);
+                       
((WebRtcEndpoint)outgoingMedia).addIceCandidate(candidate);
                } else {
                        WebRtcEndpoint endpoint = listeners.get(uid);
                        log.debug("Add candidate for {}, listener found ? {}", 
uid, endpoint != null);
@@ -488,46 +507,14 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                }
        }
 
-       void addSipProcessor(long count) {
-               if (count > 0) {
-                       if (sipProcessor.isEmpty()) {
-                               try {
-                                       sipProcessor = 
kHandler.getSipManager().createSipStackProcessor(
-                                                       randomUUID().toString()
-                                                       , kRoom.getRoom()
-                                                       , this);
-                                       
sipProcessor.ifPresent(SipStackProcessor::register);
-                               } catch (Exception e) {
-                                       log.error("Unexpected error while 
creating SipProcessor", e);
-                               }
-                       }
-               } else {
-                       releaseRtp();
-               }
-       }
-
        private static JSONObject convert(com.google.gson.JsonObject o) {
                return new JSONObject(o.toString());
        }
 
-       @Override
-       public String getSid() {
-               return sid;
-       }
-
-       @Override
-       public String getUid() {
-               return uid;
-       }
-
        public Date getConnectedSince() {
                return connectedSince;
        }
 
-       public KRoom getKRoom() {
-               return kRoom;
-       }
-
        public Long getRoomId() {
                return kRoom.getRoom().getId();
        }
@@ -548,10 +535,6 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                return recorder;
        }
 
-       public WebRtcEndpoint getOutgoingMedia() {
-               return outgoingMedia;
-       }
-
        public Long getChunkId() {
                return chunkId;
        }
@@ -571,26 +554,61 @@ public class KStream extends AbstractStream implements 
ISipCallbacks {
                                + flowoutFuture + ", chunkId=" + chunkId + ", 
type=" + type + ", sid=" + sid + ", uid=" + uid + "]";
        }
 
+       void addSipProcessor(long count) {
+               if (count > 0) {
+                       if (sipProcessor.isEmpty()) {
+                               try {
+                                       sipProcessor = 
kHandler.getSipManager().createSipStackProcessor(
+                                                       randomUUID().toString()
+                                                       , kRoom.getRoom()
+                                                       , this);
+                                       
sipProcessor.ifPresent(SipStackProcessor::register);
+                               } catch (Exception e) {
+                                       log.error("Unexpected error while 
creating SipProcessor", e);
+                               }
+                       }
+               } else {
+                       if (sipClient) {
+                               release();
+                       } else {
+                               releaseRtp();
+                       }
+               }
+       }
+
        @Override
        public void onRegisterOk() {
-               if (sipClient) {
-
-               } else {
-                       rtpEndpoint = getRtpEndpoint(pipeline);
+               rtpEndpoint = getRtpEndpoint(pipeline, sipClient ? "recvonly" : 
"sendonly");
+               OfferOptions options = new OfferOptions();
+               options.setOfferToReceiveAudio(hasAudio);
+               options.setOfferToReceiveVideo(hasVideo);
+               String offer = null;
+               if (!sipClient) {
+                       offer = rtpEndpoint.generateOffer(options);
                        if (hasAudio) {
                                outgoingMedia.connect(rtpEndpoint, 
MediaType.AUDIO);
                        }
                        if (hasVideo) {
                                outgoingMedia.connect(rtpEndpoint, 
MediaType.VIDEO);
                        }
-                       sipProcessor.get().invite(kRoom.getRoom(), 
rtpEndpoint.generateOffer());
                }
+               sipProcessor.get().invite(kRoom.getRoom(), offer);
        }
 
        @Override
-       public void onInviteOk(String sdp) {
+       public void onInviteOk(String sdp, Consumer<String> answerConsumer) {
                if (sipClient) {
-
+                       String answer = rtpEndpoint.processOffer(sdp);
+                       answerConsumer.accept(answer);
+                       log.debug(answer);
+                       StreamDesc sd = 
kHandler.getStreamProcessor().getBySid(sid).getStream(uid);
+                       try {
+                               outgoingMedia = rtpEndpoint;
+                               internalStartBroadcast(sd, sdp);
+                               notifyOnNewStream(sd);
+                       } catch (Exception e) {
+                               log.error("Unexpected error");
+                       }
                } else {
                        rtpEndpoint.processAnswer(sdp);
                }
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestStream.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestStream.java
index 6949528..741c1f6 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestStream.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestStream.java
@@ -72,7 +72,7 @@ public class KTestStream extends AbstractStream {
        }
 
        private void startTestRecording(IWsClient c, JSONObject msg) {
-               webRtcEndpoint = createWebRtcEndpoint(pipeline);
+               webRtcEndpoint = createWebRtcEndpoint(pipeline, null);
                webRtcEndpoint.connect(webRtcEndpoint);
 
                MediaProfileSpecType profile = getProfile(msg);
@@ -134,7 +134,7 @@ public class KTestStream extends AbstractStream {
 
        public void play(final IWsClient inClient, JSONObject msg) {
                createPipeline(() -> {
-                       webRtcEndpoint = createWebRtcEndpoint(pipeline);
+                       webRtcEndpoint = createWebRtcEndpoint(pipeline, true);
                        player = createPlayerEndpoint(pipeline, recPath);
                        player.connect(webRtcEndpoint);
                        webRtcEndpoint.addMediaSessionStartedListener(evt -> {
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/ISipCallbacks.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/ISipCallbacks.java
index a04f275..b476c8a 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/ISipCallbacks.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/ISipCallbacks.java
@@ -18,7 +18,9 @@
  */
 package org.apache.openmeetings.core.sip;
 
+import java.util.function.Consumer;
+
 public interface ISipCallbacks {
        void onRegisterOk();
-       void onInviteOk(String sdp);
+       void onInviteOk(String sdp, Consumer<String> answerConsumer);
 }
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
index ac8fc06..a95e419 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
@@ -26,6 +26,7 @@ import java.util.Optional;
 import java.util.function.Function;
 
 import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 
 import org.apache.openmeetings.db.entity.room.Room;
 import org.apache.openmeetings.db.entity.user.User;
@@ -35,6 +36,7 @@ import org.apache.wicket.util.string.Strings;
 import org.asteriskjava.manager.DefaultManagerConnection;
 import org.asteriskjava.manager.ManagerConnection;
 import org.asteriskjava.manager.ManagerConnectionFactory;
+import org.asteriskjava.manager.ManagerConnectionState;
 import org.asteriskjava.manager.ResponseEvents;
 import org.asteriskjava.manager.action.ConfbridgeListAction;
 import org.asteriskjava.manager.action.DbDelAction;
@@ -85,6 +87,7 @@ public class SipManager implements ISipManager {
        private int maxLocalWsPort = 7666;
 
        private ManagerConnectionFactory factory;
+       private ManagerConnection con;
        private String sipUserPicture;
        private BitSet ports;
 
@@ -100,13 +103,23 @@ public class SipManager implements ISipManager {
                }
        }
 
-       private ManagerConnection getConnection() {
-               DefaultManagerConnection con = 
(DefaultManagerConnection)factory.createManagerConnection();
-               con.setDefaultEventTimeout(managerTimeout);
-               con.setDefaultResponseTimeout(managerTimeout);
-               con.setSocketReadTimeout((int)managerTimeout);
-               con.setSocketTimeout((int)managerTimeout);
-               return con;
+       @PreDestroy
+       public void destroy() {
+               if (con != null) {
+                       con.logoff();
+               }
+       }
+
+       private void connectManager() throws Exception {
+               if (con == null || ManagerConnectionState.CONNECTED != 
con.getState()) {
+                       DefaultManagerConnection defCon = 
(DefaultManagerConnection)factory.createManagerConnection();
+                       defCon.setDefaultEventTimeout(managerTimeout);
+                       defCon.setDefaultResponseTimeout(managerTimeout);
+                       defCon.setSocketReadTimeout((int)managerTimeout);
+                       defCon.setSocketTimeout((int)managerTimeout);
+                       con = defCon;
+                       con.login("on");
+               }
        }
 
        private ManagerResponse exec(ManagerAction action) {
@@ -114,9 +127,8 @@ public class SipManager implements ISipManager {
                        log.warn("There is no Asterisk configured");
                        return null;
                }
-               ManagerConnection con = getConnection();
                try {
-                       con.login();
+                       connectManager();
                        ManagerResponse r = con.sendAction(action);
                        if (r != null) {
                                log.debug("{}", r);
@@ -124,12 +136,6 @@ public class SipManager implements ISipManager {
                        return (r instanceof ManagerError) ? null : r;
                } catch (Exception e) {
                        log.error("Error while executing ManagerAction: {}", 
action, e);
-               } finally {
-                       try {
-                               con.logoff();
-                       } catch (Exception e) {
-                               // no-op
-                       }
                }
                return null;
        }
@@ -139,22 +145,15 @@ public class SipManager implements ISipManager {
                        log.warn("There is no Asterisk configured");
                        return null;
                }
-               ManagerConnection con = getConnection();
                try {
-                       con.login("on");
+                       connectManager();
                        ResponseEvents r = 
con.sendEventGeneratingAction(action);
                        if (r != null) {
-                               log.debug("{}", r.getResponse());
+                               log.trace("{}", r.getResponse());
                        }
                        return (r == null || r.getResponse() instanceof 
ManagerError) ? null : r;
                } catch (Exception e) {
                        log.error("Error while executing EventGeneratingAction: 
{}", action, e);
-               } finally {
-                       try {
-                               con.logoff();
-                       } catch (Exception e) {
-                               // no-op
-                       }
                }
                return null;
        }
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipStackProcessor.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipStackProcessor.java
index 31a1941..dc22235 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipStackProcessor.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipStackProcessor.java
@@ -198,8 +198,7 @@ public class SipStackProcessor implements SipListenerExt {
                                        callbacks.onRegisterOk();
                                } else if (INVITE.equals(prevReq.getMethod())) {
                                        dialog = evt.getDialog();
-                                       ack(evt);
-                                       callbacks.onInviteOk(new 
String((byte[])resp.getContent()));
+                                       callbacks.onInviteOk(new 
String((byte[])resp.getContent()), answer -> ack(evt, answer));
                                } else if (BYE.equals(prevReq.getMethod())) {
                                        doDestroy();
                                }
@@ -212,12 +211,13 @@ public class SipStackProcessor implements SipListenerExt {
                }
        }
 
-       private void ack(ResponseEvent evt) {
+       private void ack(ResponseEvent evt, String answer) {
                try {
                        Response resp = evt.getResponse();
                        Dialog dlg = evt.getDialog();
                        CSeqHeader cseqHead = 
(CSeqHeader)resp.getHeader(CSeqHeader.NAME);
                        Request ack = dlg.createAck(cseqHead.getSeqNumber());
+                       addSdp(ack, answer);
                        dlg.sendAck(ack);
                } catch (Exception e) {
                        log.error("ack {}", evt, e);
@@ -336,6 +336,13 @@ public class SipStackProcessor implements SipListenerExt {
                                });
        }
 
+       private void addSdp(Request req, String sdp) throws Exception {
+               if (sdp != null) {
+                       
req.addHeader(headerFactory.createContentLengthHeader(sdp.length()));
+                       req.setContent(sdp, 
headerFactory.createContentTypeHeader("application", "sdp"));
+               }
+       }
+
        public void invite(Room r, String sdp) {
                final String sipNumber = getSipNumber(r);
                if (sipNumber == null) {
@@ -349,10 +356,7 @@ public class SipStackProcessor implements SipListenerExt {
                                , req -> {
                                        try {
                                                addAllow(req);
-                                               if (sdp != null) {
-                                                       
req.addHeader(headerFactory.createContentLengthHeader(sdp.length()));
-                                                       req.setContent(sdp, 
headerFactory.createContentTypeHeader("application", "sdp"));
-                                               }
+                                               addSdp(req, sdp);
                                        } catch (Exception e) {
                                                log.error("fail patch invite 
request", e);
                                        }
diff --git 
a/openmeetings-core/src/test/java/org/apache/openmeetings/core/remote/BaseMockedTest.java
 
b/openmeetings-core/src/test/java/org/apache/openmeetings/core/remote/BaseMockedTest.java
index 7402754..3565a64 100644
--- 
a/openmeetings-core/src/test/java/org/apache/openmeetings/core/remote/BaseMockedTest.java
+++ 
b/openmeetings-core/src/test/java/org/apache/openmeetings/core/remote/BaseMockedTest.java
@@ -20,6 +20,7 @@
 package org.apache.openmeetings.core.remote;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
@@ -94,7 +95,7 @@ public class BaseMockedTest {
                                        return null;
                                }
                        });
-                       streamMock.when(() -> 
AbstractStream.createWebRtcEndpoint(any(MediaPipeline.class))).thenReturn(mock(WebRtcEndpoint.class));
+                       streamMock.when(() -> 
AbstractStream.createWebRtcEndpoint(any(MediaPipeline.class), 
anyBoolean())).thenReturn(mock(WebRtcEndpoint.class));
                        streamMock.when(() -> 
AbstractStream.createRecorderEndpoint(any(MediaPipeline.class), anyString(), 
any(MediaProfileSpecType.class))).thenReturn(mock(RecorderEndpoint.class));
                        streamMock.when(() -> 
AbstractStream.createPlayerEndpoint(any(MediaPipeline.class), 
anyString())).thenReturn(mock(PlayerEndpoint.class));
 
diff --git a/openmeetings-server/src/site/markdown/AsteriskIntegration.md 
b/openmeetings-server/src/site/markdown/AsteriskIntegration.md
index 0b98140..c6459d4 100644
--- a/openmeetings-server/src/site/markdown/AsteriskIntegration.md
+++ b/openmeetings-server/src/site/markdown/AsteriskIntegration.md
@@ -138,7 +138,6 @@ encryption=no
 avpf=yes
 icesupport=yes
 directmedia=no
-disallow=all
 allow=!all,ulaw,opus,vp8
 ```
 
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/KStreamDto.java
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/KStreamDto.java
index 90cc2b7..75265a7 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/KStreamDto.java
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/connection/KStreamDto.java
@@ -37,30 +37,26 @@ import 
org.apache.openmeetings.db.entity.record.RecordingChunk.Type;
 public class KStreamDto implements IDataProviderEntity {
        private static final long serialVersionUID = 1L;
 
-       private String sid;
-       private String uid;
-       private Long roomId;
-       private Date connectedSince;
-       private StreamType streamType;
-       private String profile;
-       private String recorder;
-       private Long chunkId;
-       private Type type;
+       private final String sid;
+       private final String uid;
+       private final Long roomId;
+       private final Date connectedSince;
+       private final StreamType streamType;
+       private final String profile;
+       private final String recorder;
+       private final Long chunkId;
+       private final Type type;
 
        public KStreamDto(KStream kStream) {
-               this.sid = kStream.getSid();
-               this.uid = kStream.getUid();
-               this.roomId = kStream.getRoomId();
-               this.connectedSince = kStream.getConnectedSince();
-               this.streamType = kStream.getStreamType();
-               this.profile = kStream.getProfile().toString();
-               this.recorder = (kStream.getRecorder() == null) ? null : 
kStream.getRecorder().toString();
-               this.chunkId = kStream.getChunkId();
-               this.type = kStream.getType();
-       }
-
-       public static long getSerialversionuid() {
-               return serialVersionUID;
+               sid = kStream.getSid();
+               uid = kStream.getUid();
+               roomId = kStream.getRoomId();
+               connectedSince = kStream.getConnectedSince();
+               streamType = kStream.getStreamType();
+               profile = kStream.getProfile().toString();
+               recorder = (kStream.getRecorder() == null) ? null : 
kStream.getRecorder().toString();
+               chunkId = kStream.getChunkId();
+               type = kStream.getType();
        }
 
        public String getSid() {
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 422755a..6829c0f 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
@@ -102,7 +102,6 @@ public class TimerService {
        private void updateSipLastName(Optional<Client> sipClient, Room r) {
                long count = sipManager.countUsers(r.getConfno());
                final String newLastName = "(" + count + ")";
-               kHandler.updateSipCount(r, count);
                sipClient.ifPresentOrElse(c -> {
                        if (!newLastName.equals(c.getUser().getLastname())) {
                                
c.getUser().setLastname(newLastName).resetDisplayName();
@@ -113,11 +112,13 @@ public class TimerService {
                        User sipUser = sipManager.getSipUser(r);
                        sipUser.setLastname(newLastName).resetDisplayName();
                        Client c = new Client("-- unique - sip - session --", 
1, sipUser, sipUser.getPictureUri());
+                       c.allow(Right.VIDEO, Right.AUDIO);
                        cm.add(c);
                        c.setRoom(r);
                        cm.addToRoom(c);
                        WebSocketHelper.sendRoom(new TextRoomMessage(r.getId(), 
c, RoomMessage.Type.ROOM_ENTER, c.getUid()));
                });
+               kHandler.updateSipCount(r, count);
        }
 
        public void scheduleModCheck(Room r) {
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
index b54fbf6..0d349c2 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
@@ -440,25 +440,27 @@ var Room = (function() {
                        .css('background-image', 'url(' + c.user.pictureUri + 
')')
                        .find('.user.name').text(c.user.displayName);
 
-               const actions = le.find('.user.actions');
-               __rightVideoIcon(c, actions);
-               __rightAudioIcon(c, actions);
-               __rightOtherIcons(c, actions);
-               __activityIcon(actions, '.kick'
-                       , () => !self && _hasRight('MODERATOR') && 
!_hasRight('SUPER_MODERATOR', c.rights)
-                       , null
-                       , {
-                               confirmationEvent: 'om-kick'
-                               , placement: Settings.isRtl ? 'left' : 'right'
-                               , onConfirm: () => OmUtil.roomAction({action: 
'kick', uid: c.uid})
-                       });
-               __activityIcon(actions, '.private-chat'
+               if (c.user.id !== -1) {
+                       const actions = le.find('.user.actions');
+                       __rightVideoIcon(c, actions);
+                       __rightAudioIcon(c, actions);
+                       __rightOtherIcons(c, actions);
+                       __activityIcon(actions, '.kick'
+                               , () => !self && _hasRight('MODERATOR') && 
!_hasRight('SUPER_MODERATOR', c.rights)
+                               , null
+                               , {
+                                       confirmationEvent: 'om-kick'
+                                       , placement: Settings.isRtl ? 'left' : 
'right'
+                                       , onConfirm: () => 
OmUtil.roomAction({action: 'kick', uid: c.uid})
+                               });
+                       __activityIcon(actions, '.private-chat'
                                , () => options.userId !== c.user.id && 
$('#chatPanel').is(':visible')
                                , function() {
                                        Chat.addTab('chatTab-u' + c.user.id, 
c.user.displayName);
                                        Chat.open();
                                        $('#chatMessage 
.wysiwyg-editor').click();
                                });
+               }
                if (self) {
                        options.rights = c.rights;
                        _setQuickPollRights();

Reply via email to