diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala index 571c4db2bd6ed088ea9783a0e50e14de9015df73..c5f0662066d8730f4da62c12e9094d3f885c1697 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala @@ -3,6 +3,13 @@ package org.bigbluebutton.core.apps.voice import org.bigbluebutton.core.running.MeetingActor import org.bigbluebutton.core2.message.handlers.RecordingStartedVoiceConfEvtMsgHdlr +object VoiceCallState { + val NOT_IN_CALL = "NOT_IN_CALL" + val IN_ECHO_TEST = "IN_ECHO_TEST" + val IN_CONFERENCE = "IN_CONFERENCE" + val CALL_STARTED = "CALL_STARTED" + val CALL_ENDED = "CALL_ENDED" +} trait VoiceApp2x extends UserJoinedVoiceConfEvtMsgHdlr with UserJoinedVoiceConfMessageHdlr with UserLeftVoiceConfEvtMsgHdlr @@ -11,6 +18,7 @@ trait VoiceApp2x extends UserJoinedVoiceConfEvtMsgHdlr with RecordingStartedVoiceConfEvtMsgHdlr with VoiceConfRunningEvtMsgHdlr with SyncGetVoiceUsersMsgHdlr + with VoiceConfCallStateEvtMsgHdlr with UserStatusVoiceConfEvtMsgHdlr { this: MeetingActor => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfCallStateEvtMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfCallStateEvtMsgHdlr.scala new file mode 100755 index 0000000000000000000000000000000000000000..b82ddc6468f934706fb7819c23338b217a8a5ed9 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfCallStateEvtMsgHdlr.scala @@ -0,0 +1,42 @@ +package org.bigbluebutton.core.apps.voice + +import org.bigbluebutton.common2.msgs.{ BbbClientMsgHeader, BbbCommonEnvCoreMsg, BbbCoreEnvelope, MessageTypes, Routing, VoiceCallStateEvtMsg, VoiceCallStateEvtMsgBody, VoiceConfCallStateEvtMsg } +import org.bigbluebutton.core.models.{ VoiceUserState, VoiceUsers } +import org.bigbluebutton.core.running.{ LiveMeeting, MeetingActor, OutMsgRouter } + +trait VoiceConfCallStateEvtMsgHdlr { + this: MeetingActor => + + val liveMeeting: LiveMeeting + val outGW: OutMsgRouter + + def handleVoiceConfCallStateEvtMsg(msg: VoiceConfCallStateEvtMsg): Unit = { + val routing = Routing.addMsgToClientRouting( + MessageTypes.BROADCAST_TO_MEETING, + liveMeeting.props.meetingProp.intId, + msg.body.voiceConf + ) + val envelope = BbbCoreEnvelope( + VoiceCallStateEvtMsg.NAME, + routing + ) + val header = BbbClientMsgHeader( + VoiceCallStateEvtMsg.NAME, + liveMeeting.props.meetingProp.intId, + msg.body.voiceConf + ) + + val body = VoiceCallStateEvtMsgBody( + meetingId = liveMeeting.props.meetingProp.intId, + voiceConf = msg.body.voiceConf, + clientSession = msg.body.callSession, + userId = msg.body.userId, + callerName = msg.body.callerName, + callState = msg.body.callState + ) + + val event = VoiceCallStateEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, event) + outGW.send(msgEvent) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index 7dd24a7fa959786fdb198491c8b14a4caaa9167a..2db88ad68a864743cf8573346cc29b3a23f8a8a3 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -152,6 +152,8 @@ class ReceivedJsonMsgHandlerActor( routeVoiceMsg[CheckRunningAndRecordingVoiceConfEvtMsg](envelope, jsonNode) case UserStatusVoiceConfEvtMsg.NAME => routeVoiceMsg[UserStatusVoiceConfEvtMsg](envelope, jsonNode) + case VoiceConfCallStateEvtMsg.NAME => + routeVoiceMsg[VoiceConfCallStateEvtMsg](envelope, jsonNode) // Breakout rooms case BreakoutRoomsListMsg.NAME => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index b6e32aab55b961116fe513bdb0aad2fd5b7d68c3..5ea402cddedb021d0cbdde7cdbd8b7cfb38a1173 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -384,6 +384,7 @@ class MeetingActor( state = updateInactivityTracker(state) updateVoiceUserLastActivity(m.body.voiceUserId) handleUserTalkingInVoiceConfEvtMsg(m) + case m: VoiceConfCallStateEvtMsg => handleVoiceConfCallStateEvtMsg(m) case m: RecordingStartedVoiceConfEvtMsg => handleRecordingStartedVoiceConfEvtMsg(m) case m: MuteUserCmdMsg => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala index c7b4b094865e1b0edd11770f392ee1f58556d7ce..f65e7bf7276f5d7050fccbb073220b95c23edf5d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala @@ -93,6 +93,8 @@ class AnalyticsActor extends Actor with ActorLogging { // Voice case m: UserMutedVoiceEvtMsg => logMessage(msg) + case m: VoiceConfCallStateEvtMsg => logMessage(msg) + case m: VoiceCallStateEvtMsg => logMessage(msg) // Breakout case m: BreakoutRoomEndedEvtMsg => logMessage(msg) diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java index 0d165a9a5c28a471fc4c9fc374ebd7d97b754b49..48012683bf1f00b429d9d723ff5ade3f1b359f84 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java @@ -100,6 +100,19 @@ public class FreeswitchConferenceEventListener implements ConferenceEventListene } else if (event instanceof VoiceUsersStatusEvent) { VoiceUsersStatusEvent evt = (VoiceUsersStatusEvent) event; vcs.voiceUsersStatus(evt.getRoom(), evt.confMembers, evt.confRecordings); + } else if (event instanceof VoiceCallStateEvent) { + VoiceCallStateEvent evt = (VoiceCallStateEvent) event; + vcs.voiceCallStateEvent(evt.getRoom(), + evt.callSession, + evt.clientSession, + evt.userId, + evt.callerName, + evt.callState, + evt.origCallerIdName, + evt.origCalledDest); + } else if (event instanceof FreeswitchStatusReplyEvent) { + FreeswitchStatusReplyEvent evt = (FreeswitchStatusReplyEvent) event; + vcs.freeswitchStatusReplyEvent(evt.jsonResponse); } } diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java index e91692493935e1a363ccd32eecd48d115657b02e..cd42bfbaa1822e6ade6aa53abb21add3adccd017 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java @@ -65,4 +65,14 @@ public interface IVoiceConferenceService { Boolean isRecording, java.util.List<ConfRecording> confRecording); + void voiceCallStateEvent(String conf, + String callSession, + String clientSession, + String userId, + String callerName, + String callState, + String origCallerIdName, + String origCalledDest); + + void freeswitchStatusReplyEvent(String json); } diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/FreeswitchStatusReplyEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/FreeswitchStatusReplyEvent.java new file mode 100755 index 0000000000000000000000000000000000000000..d8ae7f3541ac887a8ca29ef1389aceb318a44d1d --- /dev/null +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/FreeswitchStatusReplyEvent.java @@ -0,0 +1,11 @@ +package org.bigbluebutton.freeswitch.voice.events; + +public class FreeswitchStatusReplyEvent extends VoiceConferenceEvent { + + public final String jsonResponse; + + public FreeswitchStatusReplyEvent(String json) { + super("unused"); + this.jsonResponse = json; + } +} diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceCallStateEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceCallStateEvent.java new file mode 100755 index 0000000000000000000000000000000000000000..9d0a9277e66cc43d76b3222ab1eac93092c21c09 --- /dev/null +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceCallStateEvent.java @@ -0,0 +1,30 @@ +package org.bigbluebutton.freeswitch.voice.events; + +public class VoiceCallStateEvent extends VoiceConferenceEvent { + public final String callSession; + public final String clientSession; + public final String userId; + public final String callerName; + public final String callState; + public final String origCallerIdName; + public final String origCalledDest; + + public VoiceCallStateEvent( + String conf, + String callSession, + String clientSession, + String userId, + String callerName, + String callState, + String origCallerIdName, + String origCalledDest) { + super(conf); + this.callSession = callSession; + this.clientSession = clientSession; + this.userId = userId; + this.callerName = callerName; + this.callState = callState; + this.origCallerIdName = origCallerIdName; + this.origCalledDest = origCalledDest; + } +} diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java index 47a6b8e32ec5b213b19438f2dfbb4575550f8705..a194ffa16c99f10d67b1fb724ff9d34a12d0bc49 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java @@ -34,6 +34,7 @@ import org.bigbluebutton.freeswitch.voice.freeswitch.actions.*; import org.freeswitch.esl.client.inbound.Client; import org.freeswitch.esl.client.inbound.InboundConnectionFailure; import org.freeswitch.esl.client.manager.ManagerConnection; +import org.freeswitch.esl.client.transport.CommandResponse; import org.freeswitch.esl.client.transport.message.EslMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,10 +82,18 @@ public class ConnectionManager { if (!subscribed) { log.info("Subscribing for ESL events."); c.cancelEventSubscriptions(); - c.setEventSubscriptions("plain", "all"); - //c.addEventFilter(EVENT_NAME, "heartbeat"); - c.addEventFilter(EVENT_NAME, "custom"); - c.addEventFilter(EVENT_NAME, "background_job"); + CommandResponse response = c.setEventSubscriptions("plain", "all"); + if (response.isOk()) { + log.info("Subscribed to ESL events." + + " Command: [" + response.getCommand() + "] " + + " Response: [" + response.getReplyText() + "]"); + } + + //c.addEventFilter(EVENT_NAME, "HEARTBEAT"); + //c.addEventFilter(EVENT_NAME, "custom"); + //c.addEventFilter(EVENT_NAME, "background_job"); + c.addEventFilter(EVENT_NAME, "CHANNEL_EXECUTE"); + c.addEventFilter(EVENT_NAME, "CHANNEL_STATE"); subscribed = true; } else { // Let's check for status every minute. diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java index d18b994b2129e539882b6230648b18c26ac32599..fb204b984dd1e703bb7a6900c2de32146d2f299a 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java @@ -1,6 +1,7 @@ package org.bigbluebutton.freeswitch.voice.freeswitch; +import java.util.Iterator; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; @@ -52,6 +53,8 @@ public class ESLEventListener implements IEslEventListener { private static final Pattern GLOBAL_AUDION_PATTERN = Pattern.compile("(GLOBAL_AUDIO)_(.*)$"); private static final Pattern CALLERNAME_PATTERN = Pattern.compile("(.*)-bbbID-(.*)$"); private static final Pattern CALLERNAME_WITH_SESS_INFO_PATTERN = Pattern.compile("^(.*)_(\\d+)-bbbID-(.*)$"); + private static final Pattern CALLERNAME_LISTENONLY_PATTERN = Pattern.compile("^(.*)_(\\d+)-bbbID-LISTENONLY-(.*)$"); + private static final Pattern ECHO_TEST_DEST_PATTERN = Pattern.compile("^9196(\\d+)$"); @Override public void conferenceEventJoin(String uniqueId, String confName, int confSize, EslEvent event) { @@ -92,6 +95,22 @@ public class ESLEventListener implements IEslEventListener { voiceUserId = "v_" + memberId.toString(); } + String coreuuid = headers.get("Core-UUID"); + String clientSession = "0"; + String callState = "IN_CONFERENCE"; + String origCallerIdName = headers.get("Caller-Caller-ID-Name"); + String origCallerDestNumber = headers.get("Caller-Destination-Number"); + VoiceCallStateEvent csEvent = new VoiceCallStateEvent( + confName, + coreuuid, + clientSession, + voiceUserId, + callerIdName, + callState, + origCallerIdName, + origCallerDestNumber); + conferenceEventListener.handleConferenceEvent(csEvent); + String callerUUID = this.getMemberUUIDFromEvent(event); log.info("Caller joined: conf=" + confName + ",uuid=" + callerUUID + @@ -111,6 +130,8 @@ public class ESLEventListener implements IEslEventListener { speaking, "none"); conferenceEventListener.handleConferenceEvent(pj); + + } } @@ -243,13 +264,187 @@ public class ESLEventListener implements IEslEventListener { @Override public void eventReceived(EslEvent event) { - //System.out.println("ESL Event Listener received event=[" + event.getEventName() + "]" + - // event.getEventHeaders().toString()); - if (event.getEventName().equals("heartbeat")) { - log.info("Received heartbeat from FreeSWITCH"); -//// setChanged(); -// notifyObservers(event); -// return; +// System.out.println("*********** ESL Event Listener received event=[" + event.getEventName() + "]" + +// event.getEventHeaders().toString()); + + /** + Map<String, String> eventHeaders1 = event.getEventHeaders(); + StringBuilder sb = new StringBuilder(""); + sb.append("\n"); + for (Iterator it = eventHeaders1.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = (Map.Entry)it.next(); + sb.append(entry.getKey()); + sb.append(" => '"); + sb.append(entry.getValue()); + sb.append("'\n"); + } + + System.out.println("##### ===>>> " + sb.toString()); + System.out.println("<<<=== #####"); + **/ + + if (event.getEventName().equals("HEARTBEAT")) { + //log.info("Received heartbeat from FreeSWITCH"); + } else if (event.getEventName().equals( "CHANNEL_EXECUTE" )) { + Map<String, String> eventHeaders = event.getEventHeaders(); + + String application = (eventHeaders.get("Application") == null) ? "" : eventHeaders.get("Application"); + String channelCallState = (eventHeaders.get("Channel-Call-State") == null) ? "" : eventHeaders.get("Channel-Call-State"); + String varvBridge = (eventHeaders.get("variable_vbridge") == null) ? "" : eventHeaders.get("variable_vbridge"); + + if ("echo".equalsIgnoreCase(application) && !varvBridge.isEmpty()) { + String origCallerIdName = eventHeaders.get("Caller-Caller-ID-Name"); + String origCallerDestNumber = eventHeaders.get("Caller-Destination-Number"); + String coreuuid = eventHeaders.get("Core-UUID"); + + //System.out.println("******** uuid=" + coreuuid + " " + origCallerIdName + " is in echo test " + origCallerDestNumber + " vbridge=" + varvBridge); + + String voiceUserId = ""; + String callerName = origCallerIdName; + String clientSession = "0"; + String callState = "IN_ECHO_TEST"; + + Matcher callerListenOnly = CALLERNAME_LISTENONLY_PATTERN.matcher(origCallerIdName); + Matcher callWithSess = CALLERNAME_WITH_SESS_INFO_PATTERN.matcher(origCallerIdName); + if (callWithSess.matches()) { + voiceUserId = callWithSess.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callWithSess.group(3).trim(); + } else if (callerListenOnly.matches()) { + voiceUserId = callerListenOnly.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callerListenOnly.group(3).trim(); + } + + VoiceCallStateEvent csEvent = new VoiceCallStateEvent(varvBridge, + coreuuid, + clientSession, + voiceUserId, + callerName, + callState, + origCallerIdName, + origCallerDestNumber); + conferenceEventListener.handleConferenceEvent(csEvent); + + } else if ("RINGING".equalsIgnoreCase(channelCallState) && !varvBridge.isEmpty()) { + String origCallerIdName = eventHeaders.get("Caller-Caller-ID-Name"); + String origCallerDestNumber = eventHeaders.get("Caller-Destination-Number"); + String coreuuid = eventHeaders.get("Core-UUID"); + //System.out.println("******** uuid=" + coreuuid + " " + origCallerIdName + " is in ringing " + origCallerDestNumber + " vbridge=" + varvBridge); + + String voiceUserId = ""; + String callerName = origCallerIdName; + String clientSession = "0"; + String callState = "CALL_STARTED"; + + Matcher callerListenOnly = CALLERNAME_LISTENONLY_PATTERN.matcher(origCallerIdName); + Matcher callWithSess = CALLERNAME_WITH_SESS_INFO_PATTERN.matcher(origCallerIdName); + if (callWithSess.matches()) { + voiceUserId = callWithSess.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callWithSess.group(3).trim(); + } else if (callerListenOnly.matches()) { + voiceUserId = callerListenOnly.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callerListenOnly.group(3).trim(); + } + + VoiceCallStateEvent csEvent = new VoiceCallStateEvent(varvBridge, + coreuuid, + clientSession, + voiceUserId, + callerName, + callState, + origCallerIdName, + origCallerDestNumber); + conferenceEventListener.handleConferenceEvent(csEvent); + } + } else if (event.getEventName().equalsIgnoreCase("CHANNEL_STATE")) { + Map<String, String> eventHeaders = event.getEventHeaders(); + String channelCallState = (eventHeaders.get("Channel-Call-State") == null) ? "" : eventHeaders.get("Channel-Call-State"); + String channelState = (eventHeaders.get("Channel-State") == null) ? "" : eventHeaders.get("Channel-State"); + + if ("HANGUP".equalsIgnoreCase(channelCallState) && "CS_DESTROY".equalsIgnoreCase(channelState)) { + String origCallerIdName = eventHeaders.get("Caller-Caller-ID-Name"); + String origCallerDestNumber = eventHeaders.get("Caller-Destination-Number"); + String coreuuid = eventHeaders.get("Core-UUID"); + //System.out.println("******** uuid=" + coreuuid + " " + origCallerIdName + " is hanging up " + origCallerDestNumber); + + String voiceUserId = ""; + String callerName = origCallerIdName; + String clientSession = "0"; + String callState = "CALL_ENDED"; + + Matcher callerListenOnly = CALLERNAME_LISTENONLY_PATTERN.matcher(origCallerIdName); + Matcher callWithSess = CALLERNAME_WITH_SESS_INFO_PATTERN.matcher(origCallerIdName); + if (callWithSess.matches()) { + voiceUserId = callWithSess.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callWithSess.group(3).trim(); + } else if (callerListenOnly.matches()) { + voiceUserId = callerListenOnly.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callerListenOnly.group(3).trim(); + } + + String conf = origCallerDestNumber; + Matcher callerDestNumberMatcher = ECHO_TEST_DEST_PATTERN.matcher(origCallerDestNumber); + if (callerDestNumberMatcher.matches()) { + conf = callerDestNumberMatcher.group(1).trim(); + } + + VoiceCallStateEvent csEvent = new VoiceCallStateEvent(conf, + coreuuid, + clientSession, + voiceUserId, + callerName, + callState, + origCallerIdName, + origCallerDestNumber + ); + conferenceEventListener.handleConferenceEvent(csEvent); + + } else if ("RINGING".equalsIgnoreCase(channelCallState) && "CS_EXECUTE".equalsIgnoreCase(channelState)) { + String origCallerIdName = eventHeaders.get("Caller-Caller-ID-Name"); + String origCallerDestNumber = eventHeaders.get("Caller-Destination-Number"); + String coreuuid = eventHeaders.get("Core-UUID"); + //System.out.println("******** uuid=" + coreuuid + " " + origCallerIdName + " is ringing " + origCallerDestNumber); + + String voiceUserId = ""; + String callerName = origCallerIdName; + String clientSession = "0"; + String callState = "CALL_STARTED"; + + Matcher callerListenOnly = CALLERNAME_LISTENONLY_PATTERN.matcher(origCallerIdName); + Matcher callWithSess = CALLERNAME_WITH_SESS_INFO_PATTERN.matcher(origCallerIdName); + if (callWithSess.matches()) { + voiceUserId = callWithSess.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callWithSess.group(3).trim(); + } else if (callerListenOnly.matches()) { + voiceUserId = callerListenOnly.group(1).trim(); + clientSession = callWithSess.group(2).trim(); + callerName = callerListenOnly.group(3).trim(); + } + + String conf = origCallerDestNumber; + Matcher callerDestNumberMatcher = ECHO_TEST_DEST_PATTERN.matcher(origCallerDestNumber); + if (callerDestNumberMatcher.matches()) { + conf = callerDestNumberMatcher.group(1).trim(); + } + + VoiceCallStateEvent csEvent = new VoiceCallStateEvent(conf, + coreuuid, + clientSession, + voiceUserId, + callerName, + callState, + origCallerIdName, + origCallerDestNumber + ); + conferenceEventListener.handleConferenceEvent(csEvent); + } + } } diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/CheckFreeswitchStatusCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/CheckFreeswitchStatusCommand.java index d0d2aa67f04113bf15159a487845b929122d2996..2e8e4f912dd6c308a1f5262a715ecf1f4294e093 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/CheckFreeswitchStatusCommand.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/CheckFreeswitchStatusCommand.java @@ -3,6 +3,7 @@ package org.bigbluebutton.freeswitch.voice.freeswitch.actions; import com.google.gson.Gson; import org.apache.commons.lang3.StringUtils; import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener; +import org.bigbluebutton.freeswitch.voice.events.FreeswitchStatusReplyEvent; import org.freeswitch.esl.client.transport.message.EslMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,10 +27,11 @@ public class CheckFreeswitchStatusCommand extends FreeswitchCommand { } public void handleResponse(EslMessage response, ConferenceEventListener eventListener) { - Gson gson = new Gson(); log.info(gson.toJson(response.getBodyLines())); - + FreeswitchStatusReplyEvent statusEvent = new FreeswitchStatusReplyEvent( + gson.toJson(response.getBodyLines())); + eventListener.handleConferenceEvent(statusEvent); } } diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala index 2e186f1990b9cc84595d487cb386fd190a6931d5..07ff1be12d2b5158582f928dfe2ff8c963ea49bc 100755 --- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala +++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala @@ -273,4 +273,41 @@ class VoiceConferenceService(sender: RedisPublisher) extends IVoiceConferenceSer sender.publish(fromVoiceConfRedisChannel, json) } + def voiceCallStateEvent( + conf: String, + callSession: String, + clientSession: String, + userId: String, + callerName: String, + callState: String, + origCallerIdName: String, + origCalledDest: String + ): Unit = { + val header = BbbCoreVoiceConfHeader(VoiceConfCallStateEvtMsg.NAME, conf) + val body = VoiceConfCallStateEvtMsgBody( + voiceConf = conf, + callSession = callSession, + clientSession = clientSession, + userId = userId, + callerName = callerName, + callState = callState, + origCallerIdName = origCallerIdName, + origCalledDest = origCalledDest + ) + val envelope = BbbCoreEnvelope(VoiceConfCallStateEvtMsg.NAME, Map("voiceConf" -> conf)) + + val msg = new VoiceConfCallStateEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, msg) + + val json = JsonUtil.toJson(msgEvent) + sender.publish(fromVoiceConfRedisChannel, json) + } + + def freeswitchStatusReplyEvent(json: String): Unit = { + // Placeholder so we can add a /healthz check endpoint to + // monitor akka-fsesl (ralam feb 5, 2020) + //println("***** >>>>") + //println(json) + //println("<<<< *****") + } } diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala index 83f90ead4d36f88b390aaf659140a84c57adc6c8..4d92363940c0385590b99bdfbfa52981819b17e5 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala @@ -433,4 +433,40 @@ case class UserDisconnectedFromGlobalAudioMsgBody(userId: String, name: String) */ object SyncGetVoiceUsersRespMsg { val NAME = "SyncGetVoiceUsersRespMsg" } case class SyncGetVoiceUsersRespMsg(header: BbbClientMsgHeader, body: SyncGetVoiceUsersRespMsgBody) extends BbbCoreMsg -case class SyncGetVoiceUsersRespMsgBody(voiceUsers: Vector[VoiceConfUser]) \ No newline at end of file +case class SyncGetVoiceUsersRespMsgBody(voiceUsers: Vector[VoiceConfUser]) + +/** + * Received from FS call state events. + */ +object VoiceConfCallStateEvtMsg { val NAME = "VoiceConfCallStateEvtMsg" } +case class VoiceConfCallStateEvtMsg( + header: BbbCoreVoiceConfHeader, + body: VoiceConfCallStateEvtMsgBody +) extends VoiceStandardMsg +case class VoiceConfCallStateEvtMsgBody( + voiceConf: String, + callSession: String, + clientSession: String, + userId: String, + callerName: String, + callState: String, + origCallerIdName: String, + origCalledDest: String +) + +/** + * Sent to interested parties call state events. + */ +object VoiceCallStateEvtMsg { val NAME = "VoiceCallStateEvtMsg" } +case class VoiceCallStateEvtMsg( + header: BbbClientMsgHeader, + body: VoiceCallStateEvtMsgBody +) extends BbbCoreMsg +case class VoiceCallStateEvtMsgBody( + meetingId: String, + voiceConf: String, + clientSession: String, + userId: String, + callerName: String, + callState: String +) \ No newline at end of file diff --git a/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java b/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java index 482067ed8e4e2112c1945ed9316108e41029f593..dc5d0f6d46a9d83761d37a283015f96e37b94237 100755 --- a/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java +++ b/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java @@ -428,6 +428,7 @@ public class Client public void eventReceived( final EslEvent event ) { log.debug( "Event received [{}]", event ); + /* * Notify listeners in a different thread in order to: * - not to block the IO threads with potentially long-running listeners @@ -537,8 +538,10 @@ public class Client System.out.println("##### " + sb.toString()); **/ } + } else { + listener.eventReceived( event ); } - listener.eventReceived( event ); + } catch ( Throwable t ) { log.error( "Error caught notifying listener of event [" + event + ']', t ); }