- when freeswitch initiates hanging up of global audio call, we need to hangup all

listen only callers. If not, the globak audio stream is destroyed and not re-recreated
   resulting in no audio for listen only.
This commit is contained in:
Richard Alam 2019-01-24 12:55:33 -08:00
parent 88df7450a5
commit d34ee2a90e
6 changed files with 53 additions and 11 deletions

0
bbb-fsesl-client/deploy.sh Normal file → Executable file
View File

View File

@ -63,6 +63,7 @@ public class CallAgent extends CallListenerAdapter implements CallStreamObserver
private String _destination; private String _destination;
private Boolean listeningToGlobal = false; private Boolean listeningToGlobal = false;
private IMessagingService messagingService; private IMessagingService messagingService;
private ForceHangupGlobalAudioUsersListener forceHangupGlobalAudioUsersListener;
private enum CallState { private enum CallState {
UA_IDLE(0), UA_INCOMING_CALL(1), UA_OUTGOING_CALL(2), UA_ONCALL(3); UA_IDLE(0), UA_INCOMING_CALL(1), UA_OUTGOING_CALL(2), UA_ONCALL(3);
@ -404,15 +405,23 @@ public class CallAgent extends CallListenerAdapter implements CallStreamObserver
/** Callback function called when arriving a BYE request */ /** Callback function called when arriving a BYE request */
public void onCallClosing(Call call, Message bye) { public void onCallClosing(Call call, Message bye) {
log.info("Received a BYE from the other end telling us to hangup."); log.info("Received a BYE from the other end telling us to hangup.");
if (!isCurrentCall(call)) return; if (!isCurrentCall(call)) return;
closeVoiceStreams(); closeVoiceStreams();
notifyListenersOfOnCallClosed(); notifyListenersOfOnCallClosed();
callState = CallState.UA_IDLE;
// Reset local sdp for next call. // FreeSWITCH initiated hangup of call. Hangup all listen only users.
initSessionDescriptor(); // ralam jan 24, 2019
if (forceHangupGlobalAudioUsersListener != null) {
log.info("Forcing hangup for listen only users of of voice conf {}.", getDestination());
forceHangupGlobalAudioUsersListener.forceHangupGlobalAudioUsers(getDestination());
}
callState = CallState.UA_IDLE;
// Reset local sdp for next call.
initSessionDescriptor();
} }
@ -452,6 +461,10 @@ public class CallAgent extends CallListenerAdapter implements CallStreamObserver
return this.call == call; return this.call == call;
} }
public void setForceHangupGlobalAudioUsersListener(ForceHangupGlobalAudioUsersListener listener) {
forceHangupGlobalAudioUsersListener = listener;
}
public void setCallStreamFactory(CallStreamFactory csf) { public void setCallStreamFactory(CallStreamFactory csf) {
this.callStreamFactory = csf; this.callStreamFactory = csf;
} }

View File

@ -0,0 +1,5 @@
package org.bigbluebutton.voiceconf.sip;
public interface ForceHangupGlobalAudioUsersListener {
void forceHangupGlobalAudioUsers(String voiceConf);
}

View File

@ -1,6 +1,7 @@
package org.bigbluebutton.voiceconf.sip; package org.bigbluebutton.voiceconf.sip;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.red5.app.sip.codecs.Codec; import org.red5.app.sip.codecs.Codec;
@ -80,6 +81,13 @@ public class GlobalCall {
return null; return null;
} }
public static synchronized Collection<ListenOnlyUser> getAllListenOnlyUsers(String voiceConf) {
if (voiceConfToListenOnlyUsersMap.containsKey(voiceConf)) {
return voiceConfToListenOnlyUsersMap.get(voiceConf).getAllListenOnlyUsers();
}
return null;
}
public static Codec getRoomCodec(String roomName) { public static Codec getRoomCodec(String roomName) {
return roomToCodecMap.get(roomName); return roomToCodecMap.get(roomName);
} }

View File

@ -36,7 +36,7 @@ import org.red5.server.api.stream.IBroadcastStream;
* @author Richard Alam * @author Richard Alam
* *
*/ */
public class SipPeer implements SipRegisterAgentListener { public class SipPeer implements SipRegisterAgentListener, ForceHangupGlobalAudioUsersListener {
private static Logger log = Red5LoggerFactory.getLogger(SipPeer.class, "sip"); private static Logger log = Red5LoggerFactory.getLogger(SipPeer.class, "sip");
private ClientConnectionManager clientConnManager; private ClientConnectionManager clientConnManager;
@ -130,6 +130,7 @@ public class SipPeer implements SipRegisterAgentListener {
SipPeerProfile callerProfile = SipPeerProfile.copy(registeredProfile); SipPeerProfile callerProfile = SipPeerProfile.copy(registeredProfile);
CallAgent ca = new CallAgent(this.clientRtpIp, sipProvider, callerProfile, audioconfProvider, clientId, messagingService); CallAgent ca = new CallAgent(this.clientRtpIp, sipProvider, callerProfile, audioconfProvider, clientId, messagingService);
ca.setClientConnectionManager(clientConnManager); ca.setClientConnectionManager(clientConnManager);
ca.setForceHangupGlobalAudioUsersListener(this);
ca.setCallStreamFactory(callStreamFactory); ca.setCallStreamFactory(callStreamFactory);
callManager.add(ca); callManager.add(ca);
@ -230,6 +231,15 @@ public class SipPeer implements SipRegisterAgentListener {
registered = false; registered = false;
} }
public void forceHangupGlobalAudioUsers(String voiceConf) {
Collection<ListenOnlyUser> listenOnlyUsers = GlobalCall.getAllListenOnlyUsers(voiceConf);
Iterator iter = listenOnlyUsers.iterator();
while (iter.hasNext()) {
ListenOnlyUser listenOnlyUser = (ListenOnlyUser) iter.next();
hangup(listenOnlyUser.clientId, true);
}
}
public void setCallStreamFactory(CallStreamFactory csf) { public void setCallStreamFactory(CallStreamFactory csf) {
callStreamFactory = csf; callStreamFactory = csf;
} }

View File

@ -1,5 +1,7 @@
package org.bigbluebutton.voiceconf.sip; package org.bigbluebutton.voiceconf.sip;
import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -23,4 +25,8 @@ public class VoiceConfToListenOnlyUsersMap {
public int numUsers() { public int numUsers() {
return listenOnlyUsers.size(); return listenOnlyUsers.size();
} }
public Collection<ListenOnlyUser> getAllListenOnlyUsers() {
return listenOnlyUsers.values();
}
} }