/**
* 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.
*/
package org.ifsoft.rayo;
import org.dom4j.*;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.muc.spi.*;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.http.HttpBindManager;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.handler.IQHandler;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.JID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.component.AbstractComponent;
import org.xmpp.jnodes.*;
import org.xmpp.jnodes.nio.LocalIPResolver;
import org.xmpp.packet.*;
import java.util.*;
import java.util.concurrent.*;
import java.text.ParseException;
import java.net.*;
import com.rayo.core.*;
import com.rayo.core.verb.*;
import com.rayo.core.validation.*;
import com.rayo.core.xml.providers.*;
import com.sun.voip.server.*;
import com.sun.voip.*;
import org.voicebridge.*;
import com.jcumulus.server.rtmfp.ServerPipelineFactory;
import com.jcumulus.server.rtmfp.Sessions;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
public class RayoComponent extends AbstractComponent
implements TreatmentDoneListener,
CallEventListener {
private static final Logger Log = LoggerFactory.getLogger(RayoComponent.class);
private static final String RAYO_CORE = "urn:xmpp:rayo:1";
private static final String RAYO_RECORD = "urn:xmpp:rayo:record:1";
private static final String RAYO_SAY = "urn:xmpp:tropo:say:1";
private static final String RAYO_HANDSET = "urn:xmpp:rayo:handset:1";
private static final String HOST = "host";
private static final String LOCAL_PORT = "localport";
private static final String REMOTE_PORT = "remoteport";
private static final String ID = "id";
private static final String URI = "uri";
private static final String defaultIncomingConferenceId = "IncomingCallsConference";
public static RayoComponent self;
private final RayoPlugin plugin;
private RayoProvider rayoProvider = null;
private RecordProvider recordProvider = null;
private SayProvider sayProvider = null;
private HandsetProvider handsetProvider = null;
private static ConnectionlessBootstrap bootstrap = null;
public static Channel channel = null;
private static Sessions sessions;
public RayoComponent(final RayoPlugin plugin)
{
self = this;
this.plugin = plugin;
}
public void doStart()
{
Log.info("RayoComponent initialize " + jid);
XMPPServer server = XMPPServer.getInstance();
server.getIQDiscoInfoHandler().addServerFeature(RAYO_CORE);
rayoProvider = new RayoProvider();
rayoProvider.setValidator(new Validator());
server.getIQDiscoInfoHandler().addServerFeature(RAYO_RECORD);
recordProvider = new RecordProvider();
recordProvider.setValidator(new Validator());
server.getIQDiscoInfoHandler().addServerFeature(RAYO_SAY);
sayProvider = new SayProvider();
sayProvider.setValidator(new Validator());
server.getIQDiscoInfoHandler().addServerFeature(RAYO_HANDSET);
handsetProvider = new HandsetProvider();
handsetProvider.setValidator(new Validator());
createIQHandlers();
try{
Log.info("Starting jCumulus.....");
sessions = new Sessions();
ExecutorService executorservice = Executors.newCachedThreadPool();
NioDatagramChannelFactory niodatagramchannelfactory = new NioDatagramChannelFactory(executorservice);
bootstrap = new ConnectionlessBootstrap(niodatagramchannelfactory);
OrderedMemoryAwareThreadPoolExecutor orderedmemoryawarethreadpoolexecutor = new OrderedMemoryAwareThreadPoolExecutor(10, 0x100000L, 0x40000000L, 100L, TimeUnit.MILLISECONDS, Executors.defaultThreadFactory());
bootstrap.setPipelineFactory(new ServerPipelineFactory(sessions, orderedmemoryawarethreadpoolexecutor));
bootstrap.setOption("reuseAddress", Boolean.valueOf(true));
bootstrap.setOption("sendBufferSize", Integer.valueOf(1215));
bootstrap.setOption("receiveBufferSize", Integer.valueOf(2048));
bootstrap.setOption("receiveBufferSizePredictorFactory", new FixedReceiveBufferSizePredictorFactory(2048));
InetSocketAddress inetsocketaddress = new InetSocketAddress(JiveGlobals.getIntProperty("voicebridge.rtmfp.port", 1935));
Log.info("Listening on " + inetsocketaddress.getPort() + " port");
channel = bootstrap.bind(inetsocketaddress);
} catch (Exception e) {
Log.error("jCumulus startup failure");
e.printStackTrace();
}
}
public void doStop()
{
Log.info("RayoComponent shutdown ");
XMPPServer server = XMPPServer.getInstance();
server.getIQDiscoInfoHandler().removeServerFeature(RAYO_CORE);
server.getIQDiscoInfoHandler().removeServerFeature(RAYO_RECORD);
server.getIQDiscoInfoHandler().removeServerFeature(RAYO_SAY);
server.getIQDiscoInfoHandler().removeServerFeature(RAYO_HANDSET);
destroyIQHandlers();
Log.info("jCumulus stopping...");
channel.close();
bootstrap.releaseExternalResources();
}
public String getName() {
return "rayo";
}
public String getDescription() {
return "XEP-0327: Rayo";
}
@Override
protected String[] discoInfoFeatureNamespaces() {
return new String[]{RAYO_CORE};
}
@Override
protected String discoInfoIdentityCategoryType() {
return "rayo";
}
@Override
synchronized protected IQ handleIQGet(IQ iq) throws Exception {
Log.info("RayoComponent handleIQGet \n" + iq.toString());
final Element element = iq.getChildElement();
final String namespace = element.getNamespaceURI();
try {
if (RAYO_HANDSET.equals(namespace)) {
IQ reply = null;
Object object = handsetProvider.fromXML(element);
if (object instanceof OnHookCommand) {
OnHookCommand command = (OnHookCommand) object;
reply = handleOnOffHookCommand(command, iq);
} else if (object instanceof OffHookCommand) {
OffHookCommand command = (OffHookCommand) object;
reply = handleOnOffHookCommand(command, iq);
} else if (object instanceof MuteCommand) {
reply = handleMuteCommand((MuteCommand) object, iq);
} else if (object instanceof UnmuteCommand) {
reply = handleMuteCommand((UnmuteCommand) object, iq);
} else if (object instanceof HoldCommand) {
reply = handleHoldCommand((HoldCommand) object, iq);
} else if (object instanceof PrivateCommand) {
reply = handlePrivateCommand(object, iq);
} else if (object instanceof PublicCommand) {
reply = handlePrivateCommand(object, iq);
} else if (object instanceof CreateSpeakerCommand) {
reply = handleCreateSpeakerCommand(object, iq);
} else if (object instanceof DestroySpeakerCommand) {
reply = handleDestroySpeakerCommand(object, iq);
} else if (object instanceof PutOnSpeakerCommand) {
reply = handleOnOffSpeakerCommand(object, iq, true);
} else if (object instanceof TakeOffSpeakerCommand) {
reply = handleOnOffSpeakerCommand(object, iq, false);
} else if (object instanceof TalkCommand) {
reply = handleOnOffTalkCommand(object, iq, false);
} else if (object instanceof UntalkCommand) {
reply = handleOnOffTalkCommand(object, iq, true);
}
return reply;
}
if (RAYO_RECORD.equals(namespace)) {
IQ reply = null;
Object object = recordProvider.fromXML(element);
if (object instanceof Record) {
reply = handleRecord((Record) object, iq);
} else if (object instanceof PauseCommand) {
reply = handlePauseRecordCommand(true, iq);
} else if (object instanceof ResumeCommand) {
reply = handlePauseRecordCommand(false, iq);
}
return reply;
}
if (RAYO_SAY.equals(namespace)) {
IQ reply = null;
Object object = sayProvider.fromXML(element);
if (object instanceof Say) {
reply = handleSay((Say) object, iq);
} else if (object instanceof PauseCommand) {
reply = handlePauseSayCommand(true, iq);
} else if (object instanceof ResumeCommand) {
reply = handlePauseSayCommand(false, iq);
}
return reply;
}
if (RAYO_CORE.equals(namespace)) {
IQ reply = null;
Object object = rayoProvider.fromXML(element);
if (object instanceof JoinCommand) {
reply = handleJoinCommand((JoinCommand) object, iq);
} else if (object instanceof UnjoinCommand) {
reply = handleUnjoinCommand((UnjoinCommand) object, iq);
} else if (object instanceof AcceptCommand) {
reply = handleAcceptCommand((AcceptCommand) object, iq);
} else if (object instanceof AnswerCommand) {
reply = handleAnswerCommand((AnswerCommand) object, iq);
} else if (object instanceof HangupCommand) {
reply = handleHangupCommand(iq);
} else if (object instanceof RejectCommand) {
// implemented as hangup on client
} else if (object instanceof RedirectCommand) {
RedirectCommand redirect = (RedirectCommand) object;
DialCommand dial = new DialCommand();
dial.setTo(redirect.getTo());
dial.setFrom(new URI("xmpp:" + iq.getFrom()));
dial.setHeaders(redirect.getHeaders());
reply = handleDialCommand((DialCommand) dial, iq, true);
} else if (object instanceof DialCommand) {
reply = handleDialCommand((DialCommand) object, iq, false);
} else if (object instanceof StopCommand) {
} else if (object instanceof DtmfCommand) {
reply = handleDtmfCommand((DtmfCommand) object, iq);
} else if (object instanceof DestroyMixerCommand) {
}
return reply;
}
return null; // feature not implemented.
} catch (Exception e) {
e.printStackTrace();
final IQ reply = IQ.createResultIQ(iq);
reply.setError(PacketError.Condition.internal_server_error);
return reply;
}
}
private IQ handleHoldCommand(Object object, IQ iq)
{
Log.info("RayoComponent handleHoldCommand");
IQ reply = IQ.createResultIQ(iq);
String callId = iq.getTo().getNode(); // far party
CallHandler handler = CallHandler.findCall(callId);
if (handler != null)
{
handler.getCallParticipant().setHeld(true);
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleMuteCommand(Object object, IQ iq)
{
Log.info("RayoComponent handleMuteCommand");
boolean muted = object instanceof MuteCommand;
IQ reply = IQ.createResultIQ(iq);
String callId = JID.escapeNode(iq.getFrom().toString()); // handset
CallHandler handler = CallHandler.findCall(callId);
if (handler != null)
{
handler.setMuted(muted);
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(handler.getCallParticipant().getConferenceId());
ArrayList memberList = conferenceManager.getMemberList();
synchronized (memberList)
{
for (int i = 0; i < memberList.size(); i++)
{
ConferenceMember member = (ConferenceMember) memberList.get(i);
CallHandler callHandler = member.getCallHandler();
CallParticipant cp = callHandler.getCallParticipant();
String target = cp.getCallOwner();
Log.info( "RayoComponent handleMuteCommand route event to " + target);
if (target != null)
{
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(target);
if (muted)
{
MutedEvent event = new MutedEvent();
presence.getElement().add(handsetProvider.toXML(event));
} else {
UnmutedEvent event = new UnmutedEvent();
presence.getElement().add(handsetProvider.toXML(event));
}
sendPacket(presence);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handlePrivateCommand(Object object, IQ iq)
{
Log.info("RayoComponent handlePrivateCommand");
boolean privateCall = object instanceof PrivateCommand;
IQ reply = IQ.createResultIQ(iq);
String callId = JID.escapeNode(iq.getFrom().toString()); // handset
CallHandler handler = CallHandler.findCall(callId);
if (handler != null)
{
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(handler.getCallParticipant().getConferenceId());
conferenceManager.setPrivateCall(privateCall);
ArrayList memberList = conferenceManager.getMemberList();
synchronized (memberList)
{
for (int i = 0; i < memberList.size(); i++)
{
ConferenceMember member = (ConferenceMember) memberList.get(i);
CallHandler callHandler = member.getCallHandler();
CallParticipant cp = callHandler.getCallParticipant();
String target = cp.getCallOwner();
Log.info( "RayoComponent handlePrivateCommand route event to " + target);
if (target != null)
{
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(target);
if (privateCall)
{
PrivateEvent event = new PrivateEvent();
presence.getElement().add(handsetProvider.toXML(event));
} else {
PublicEvent event = new PublicEvent();
presence.getElement().add(handsetProvider.toXML(event));
}
sendPacket(presence);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleOnOffHookCommand(Object object, IQ iq)
{
Log.info("RayoComponent handleOnOffHookCommand");
IQ reply = IQ.createResultIQ(iq);
String handsetId = JID.escapeNode(iq.getFrom().toString());
if (object instanceof OnHookCommand)
{
CallHandler handler = CallHandler.findCall(handsetId);
if (handler != null)
{
handleOnOffHook(handsetId, object, plugin.getRelayChannel(handsetId), reply);
} else {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
final Handset handset = ((OffHookCommand) object).getHandset();
if (handset.sipuri == null) // webrtc handset
{
final RelayChannel channel = plugin.createRelayChannel(iq.getFrom(), handset);
if (channel != null)
{
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(HOST, LocalIPResolver.getLocalIP());
childElement.addAttribute(LOCAL_PORT, Integer.toString(channel.getPortA()));
childElement.addAttribute(REMOTE_PORT, Integer.toString(channel.getPortB()));
childElement.addAttribute(ID, channel.getAttachment());
childElement.addAttribute(URI, "xmpp:" + channel.getAttachment() + "@" + getDomain() + "/webrtc");
Log.debug("Created WebRTC handset channel {}:{}, {}:{}, {}:{}", new Object[]{HOST, LocalIPResolver.getLocalIP(), LOCAL_PORT, Integer.toString(channel.getPortA()), REMOTE_PORT, Integer.toString(channel.getPortB())});
handleOnOffHook(handsetId, object, channel, reply);
} else {
reply.setError(PacketError.Condition.internal_server_error);
}
} else { // SIP handset
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, handsetId);
childElement.addAttribute(URI, handset.sipuri);
Log.info("Created SIP handset channel " + handset.sipuri);
handleOnOffHook(handsetId, object, null, reply);
}
}
return reply;
}
private IQ handleOnOffTalkCommand(Object object, IQ iq, boolean mute)
{
Log.info("RayoComponent handleOnOffTalkCommand");
IQ reply = IQ.createResultIQ(iq);
String callId = iq.getTo().getNode();
String speakerId = JID.escapeNode(iq.getFrom().toBareJID() + "/speaker");
String bridgeCallId = "call-" + callId + speakerId;
String bridgeSpeakerId = "spkr-" + speakerId + callId;
CallHandler callHandler = CallHandler.findCall(bridgeCallId);
CallHandler callHandler2 = CallHandler.findCall(bridgeSpeakerId);
if (callHandler != null)
{
CallHandler spkrHandler = CallHandler.findCall(speakerId);
if (spkrHandler != null)
{
MemberReceiver memberReceiver = spkrHandler.getMemberReceiver();
MemberSender memberSender = callHandler.getMemberSender();
if (!mute)
{
memberReceiver.setChannel(new SpeakerChannel(callHandler.getMemberReceiver()));
} else {
memberReceiver.setChannel(null);
}
CallParticipant cp = spkrHandler.getCallParticipant();
cp.setMuted(mute); // mic on/off
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleOnOffSpeakerCommand(Object object, IQ iq, boolean flag)
{
Log.info("RayoComponent handleOnOffSpeakerCommand");
IQ reply = IQ.createResultIQ(iq);
String callId = iq.getTo().getNode();
String speakerId = JID.escapeNode(iq.getFrom().toBareJID() + "/speaker");
CallHandler callHandler = CallHandler.findCall(callId);
CallHandler spkrHandler = CallHandler.findCall(speakerId);
if (callHandler != null)
{
if (spkrHandler != null)
{
Log.info("RayoComponent handleOnOffSpeakerCommand, found call " + callId);
bridgeMixers(spkrHandler, callHandler, flag, iq.getFrom());
}
} else { // not call, we use callId for mixer name
ConferenceManager cm = ConferenceManager.getConference(callId, "PCMU/8000/1", callId, false);
if (spkrHandler != null)
{
Log.info("RayoComponent handleOnOffSpeakerCommand, found conference " + callId);
CallParticipant sp = spkrHandler.getCallParticipant();
String spkrMixer = sp.getConferenceId();
String callMixer = callId;
bridgeMixers(spkrMixer, speakerId, callMixer, callId, flag, iq.getFrom());
}
}
return reply;
}
private void bridgeMixers(CallHandler spkrHandler, CallHandler callHandler, boolean flag, JID from)
{
Log.info("RayoComponent bridgeMixers");
CallParticipant sp = spkrHandler.getCallParticipant();
CallParticipant cp = callHandler.getCallParticipant();
String callMixer = cp.getConferenceId();
String spkrMixer = sp.getConferenceId();
bridgeMixers(spkrMixer, sp.getCallId(), callMixer, cp.getCallId(), flag, from);
}
synchronized private void bridgeMixers(String spkrMixer, String speakerId, String callMixer, String callId, boolean flag, JID from)
{
Log.info("RayoComponent bridgeMixers " + speakerId + " " + callMixer + " " + callId + " " + flag);
String bridgeSpeakerId = "spkr-" + speakerId + callId;
String bridgeCallId = "call-" + callId + speakerId;
CallHandler bridge1 = CallHandler.findCall(bridgeSpeakerId);
if (bridge1 != null) bridge1.cancelRequest("Speaker terminated");
CallHandler bridge2 = CallHandler.findCall(bridgeCallId);
if (bridge2 != null) bridge2.cancelRequest("Speaker terminated");
if (flag)
{
synchronized (this)
{
CallParticipant bp1 = new CallParticipant();
bp1.setCallId(bridgeSpeakerId);
bp1.setConferenceId(spkrMixer);
bp1.setPhoneNumber(speakerId);
bp1.setDisplayName("SPKR");
bp1.setVoiceDetection(false);
bp1.setProtocol("Speaker");
bridge1 = new OutgoingCallHandler(this, bp1);
CallParticipant bp2 = new CallParticipant();
bp2.setCallId(bridgeCallId);
bp2.setConferenceId(callMixer);
bp2.setPhoneNumber(speakerId);
bp2.setDisplayName("CALL");
bp2.setVoiceDetection(true);
bp2.setCallOwner(from.toString());
bp2.setProtocol("Speaker");
bp2.setOtherCall(bridge1);
bridge2 = new OutgoingCallHandler(this, bp2);
bridge1.start();
try {
Thread.sleep(3000);
} catch (Exception e) {}
bridge2.start();
}
}
}
private IQ handleDestroySpeakerCommand(Object object, IQ iq)
{
Log.info("RayoComponent handleDestroySpeakerCommand");
IQ reply = IQ.createResultIQ(iq);
DestroySpeakerCommand speaker = (DestroySpeakerCommand) object;
try {
String speakerId = JID.escapeNode(iq.getFrom().toBareJID() + "/speaker");
CallHandler handler = CallHandler.findCall(speakerId);
if (handler != null)
{
killSpeaker(handler);
}
} catch (Exception e) {
e.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
return reply;
}
private void killSpeaker(CallHandler handler)
{
Log.info("RayoComponent killSpeaker");
try {
handler.cancelRequest("Speaker is destroyed");
CallParticipant cp = handler.getCallParticipant();
String confId = cp.getConferenceId();
handler = null;
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(confId);
ArrayList memberList = conferenceManager.getMemberList();
synchronized (memberList)
{
for (int i = 0; i < memberList.size(); i++)
{
CallHandler participant = ((ConferenceMember) memberList.get(i)).getCallHandler();
if (participant != null)
{
participant.cancelRequest("Speaker is destroyed");
participant = null;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private IQ handleCreateSpeakerCommand(Object object, IQ iq)
{
Log.info("RayoComponent handleCreateSpeakerCommand");
IQ reply = IQ.createResultIQ(iq);
CreateSpeakerCommand speaker = (CreateSpeakerCommand) object;
try {
String speakerId = JID.escapeNode(iq.getFrom().toBareJID() + "/speaker");
String label = iq.getFrom().getNode();
CallHandler handler = CallHandler.findCall(speakerId);
if (handler != null)
{
//killSpeaker(handler);
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, speakerId);
childElement.addAttribute(URI, "xmpp:" + iq.getFrom().toBareJID() + "/speaker");
return reply;
}
String mediaPreference = "PCMU/8000/1";
if (speaker.codec == null || "OPUS".equals(speaker.codec))
mediaPreference = "PCM/48000/2";
CallParticipant cp = new CallParticipant();
cp.setCallId(speakerId);
cp.setConferenceId(speaker.mixer);
cp.setDisplayName("rayo-speaker-" + System.currentTimeMillis());
cp.setName(cp.getDisplayName());
cp.setVoiceDetection(true);
cp.setCallOwner(iq.getFrom().toString());
cp.setPhoneNumber(speaker.sipuri);
cp.setAutoAnswer(true);
cp.setProtocol("SIP");
cp.setMuted(true); // set mic off
ConferenceManager cm = ConferenceManager.getConference(speaker.mixer, mediaPreference, label, false);
OutgoingCallHandler callHandler = new OutgoingCallHandler(this, cp);
callHandler.start();
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, speakerId);
childElement.addAttribute(URI, "xmpp:" + iq.getFrom().toBareJID() + "/speaker");
} catch (Exception e) {
e.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
return reply;
}
private void handleOnOffHook(String handsetId, Object object, RelayChannel channel, IQ reply)
{
final boolean flag = object instanceof OnHookCommand;
Log.info("RayoComponent handleOnOffHook " + flag);
try {
CallHandler handler = CallHandler.findCall(handsetId);
if (handler != null)
{
handler.cancelRequest("Reseting handset to " + (flag ? "on" : "off") + "hook");
handler = null;
}
if (!flag) // offhook
{
Handset handset = ((OffHookCommand) object).getHandset();
String mediaPreference = "PCMU/8000/1";
if (handset.codec == null || "OPUS".equals(handset.codec))
mediaPreference = "PCM/48000/2";
CallParticipant cp = new CallParticipant();
cp.setCallId(handsetId);
cp.setConferenceId(handset.mixer);
cp.setDisplayName("rayo-handset-" + System.currentTimeMillis());
cp.setName(cp.getDisplayName());
cp.setVoiceDetection(true);
cp.setCallOwner(JID.unescapeNode(handsetId));
String label = (new JID(cp.getCallOwner())).getNode();
if (handset.group != null && ! "".equals(handset.group))
{
label = handset.group;
}
ConferenceManager cm = ConferenceManager.getConference(handset.mixer, mediaPreference, label, false);
if (handset.callId != null && "".equals(handset.callId) == false)
{
cm.setCallId(handset.callId); // set answering far party call id for mixer
}
if (handset.group != null && ! "".equals(handset.group))
{
cm.setGroupName(handset.group);
}
if (cm.isPrivateCall() == false || cm.getMemberList().size() < 2)
{
if (channel == null)
{
if (handset.sipuri.indexOf("sip:") == 0)
{
cp.setPhoneNumber(handset.sipuri);
cp.setAutoAnswer(true);
cp.setProtocol("SIP");
} else if (handset.sipuri.indexOf("rtmfp:") == 0) {
String[] tokens = handset.sipuri.split(":");
if (tokens.length == 3)
{
cp.setProtocol("Rtmfp");
cp.setRtmfpSendStream(tokens[1]);
cp.setRtmfpRecieveStream(tokens[2]);
cp.setAutoAnswer(true);
} else {
reply.setError(PacketError.Condition.not_allowed);
return;
}
} else {
reply.setError(PacketError.Condition.not_allowed);
return;
}
} else {
cp.setMediaPreference(mediaPreference);
cp.setChannel(channel);
cp.setProtocol("WebRtc");
}
OutgoingCallHandler callHandler = new OutgoingCallHandler(this, cp);
callHandler.start();
if (channel != null)
{
channel.setCallHandler(callHandler);
}
} else {
reply.setError(PacketError.Condition.not_allowed);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private IQ handleRecord(Record command, IQ iq)
{
Log.info("RayoComponent handleRecord " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
final String callId = JID.escapeNode(iq.getFrom().toString());
final String uri = command.getTo().toString();
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler != null)
{
try {
final String fileName = uri.substring(5); // expecting file: prefix
callHandler.getCallParticipant().setRecordDirectory(System.getProperty("com.sun.voip.server.Bridge.soundsDirectory", "."));
callHandler.getMemberReceiver().setRecordFromMember(true, fileName, "au");
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, fileName);
childElement.addAttribute(URI, (String) uri);
} catch (Exception e1) {
e1.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handlePauseRecordCommand(boolean flag, IQ iq)
{
Log.info("RayoComponent handlePauseRecordCommand " + iq.getFrom() + " " + iq.getTo());
IQ reply = IQ.createResultIQ(iq);
final String callId = JID.escapeNode(iq.getFrom().toString());
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler != null)
{
try {
CallParticipant cp = callHandler.getCallParticipant();
String fileName = cp.getFromRecordingFile();
cp.setRecordDirectory(System.getProperty("com.sun.voip.server.Bridge.soundsDirectory", "."));
callHandler.getMemberReceiver().setRecordFromMember(flag, fileName, "au");
} catch (Exception e1) {
e1.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleSay(Say command, IQ iq)
{
Log.info("RayoComponent handleSay " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
final String entityId = iq.getTo().getNode();
final String treatmentId = command.getPrompt().getText();
CallHandler callHandler = CallHandler.findCall(entityId);
if (callHandler != null)
{
try {
callHandler.playTreatmentToCall(treatmentId, this);
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, treatmentId);
childElement.addAttribute(URI, (String) "xmpp:" + entityId + "@" + getDomain() + "/" + treatmentId);
} catch (Exception e1) {
e1.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
} else { // not call, lets try mixer
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(entityId);
try {
conferenceManager.addTreatment(treatmentId);
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(ID, treatmentId);
childElement.addAttribute(URI, (String) "xmpp:" + entityId + "@" + getDomain() + "/" + treatmentId);
} catch (Exception e2) {
e2.printStackTrace();
reply.setError(PacketError.Condition.not_allowed);
}
} catch (ParseException e1) {
reply.setError(PacketError.Condition.item_not_found);
}
}
return reply;
}
private IQ handlePauseSayCommand(boolean flag, IQ iq)
{
Log.info("RayoComponent handlePauseSayCommand " + iq.getFrom() + " " + iq.getTo());
IQ reply = IQ.createResultIQ(iq);
final JID entityId = getJID(iq.getTo().getNode());
if (entityId != null)
{
final String treatmentId = entityId.getResource();
final String callId = entityId.getNode();
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler != null)
{
callHandler.getMember().pauseTreatment(treatmentId, flag);
} else { // not call, lets try mixer
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(callId);
conferenceManager.getWGManager().pauseConferenceTreatment(treatmentId, flag);
} catch (ParseException e1) {
reply.setError(PacketError.Condition.item_not_found);
}
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleAcceptCommand(AcceptCommand command, IQ iq)
{
Map<String, String> headers = command.getHeaders();
String callId = iq.getTo().getNode(); // destination JID escaped
String callerId = headers.get("caller_id"); // source JID
String mixer = headers.get("mixer_name");
Log.info("RayoComponent handleAcceptCommand " + callerId + " " + callId + " " + mixer);
IQ reply = IQ.createResultIQ(iq);
JID callJID = getJID(callId);
if (callJID != null) // only for XMPP calls
{
if (mixer != null)
{
headers.put("call_protocol", "XMPP");
callerId = callerId.substring(5); // remove xmpp: prefix
Presence presence = new Presence();
presence.setFrom(iq.getTo());
presence.setTo(callerId);
setRingingState(presence, ConferenceManager.isTransferCall(mixer), headers);
sendPacket(presence);
} else reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleAnswerCommand(AnswerCommand command, IQ iq)
{
Map<String, String> headers = command.getHeaders();
IQ reply = IQ.createResultIQ(iq);
String callId = iq.getTo().getNode(); // destination JID escaped
String callerId = headers.get("caller_id"); // source JID
Log.info("RayoComponent AnswerCommand " + callerId + " " + callId);
if (callerId != null)
{
JID callJID = getJID(callId);
CallHandler callHandler = null;
CallHandler handsetHandler = null;
if (callJID != null) // XMPP call
{
callerId = callerId.substring(5); // remove xmpp: prefix
headers.put("call_protocol", "XMPP");
headers.put("call_owner", callerId);
headers.put("call_action", "join");
try {
callHandler = CallHandler.findCall(callId);
handsetHandler = CallHandler.findCall(JID.escapeNode(callerId));
if (handsetHandler != null)
{
CallParticipant hp = handsetHandler.getCallParticipant();
Presence presence1 = new Presence(); //to caller
presence1.setFrom(iq.getTo());
presence1.setTo(callerId);
setAnsweredState(presence1, ConferenceManager.isTransferCall(hp.getConferenceId()), headers);
sendPacket(presence1);
}
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
e.printStackTrace();
}
} else {
callHandler = CallHandler.findCall(callId); // SIP call;
handsetHandler = CallHandler.findCall(JID.escapeNode(iq.getFrom().toString()));
}
if (callHandler != null && handsetHandler != null)
{
CallParticipant cp = callHandler.getCallParticipant();
CallParticipant hp = handsetHandler.getCallParticipant();
Log.info("RayoComponent handleAnswerCommand found call handlers " + cp.getCallId() + " " + hp.getCallId());
try {
long start = System.currentTimeMillis();
cp.setStartTimestamp(start);
cp.setHandset(hp);
hp.setFarParty(cp);
hp.setStartTimestamp(start);
cp.setHeaders(headers);
String recording = cp.getConferenceId() + "-" + cp.getStartTimestamp() + ".au";
ConferenceManager.recordConference(cp.getConferenceId(), true, recording, "au");
String destination = iq.getFrom().getNode();
String source = cp.getName();
if (callJID != null)
{
source = (new JID(callerId)).getNode();
Config.createCallRecord(source, recording, "xmpp:" + iq.getFrom(), cp.getStartTimestamp(), 0, "dialed") ;
Config.createCallRecord(destination, recording, "xmpp:" + callerId, cp.getStartTimestamp(), 0, "received");
sendMessage(new JID(callerId), iq.getFrom(), "Call started", recording, "chat");
} else { // incoming SIP
Config.createCallRecord(destination, recording, "sip:" + cp.getPhoneNumber(), cp.getStartTimestamp(), 0, "received") ;
sendMessage(iq.getFrom(), new JID(cp.getCallId() + "@" + getDomain()), "Call started", recording, "chat");
}
} catch (ParseException e1) {
reply.setError(PacketError.Condition.internal_server_error);
}
} else reply.setError(PacketError.Condition.item_not_found);
} else reply.setError(PacketError.Condition.item_not_found);
return reply;
}
private IQ handleHangupCommand(IQ iq)
{
String callId = iq.getTo().getNode();
Log.info("RayoComponent handleHangupCommand " + iq.getFrom() + " " + callId);
IQ reply = IQ.createResultIQ(iq);
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler != null)
{
Log.info("RayoComponent handleHangupCommand found callhandler " + callId);
CallParticipant cp = callHandler.getCallParticipant();
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(cp.getConferenceId());
Log.info("RayoComponent handleHangupCommand one person left, cancel call " + conferenceManager.getMemberList().size());
if (conferenceManager.getMemberList().size() <= 2)
{
CallHandler.hangup(callId, "User requested call termination");
}
} catch (Exception e) {}
} else {
//reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private JID getJID(String jid)
{
if (jid != null)
{
jid = JID.unescapeNode(jid);
if (jid.indexOf("@") == -1 || jid.indexOf("/") == -1) return null;
try {
return new JID(jid);
} catch (Exception e) {
return null;
}
} else return null;
}
private IQ handleDtmfCommand(DtmfCommand command, IQ iq)
{
Log.info("RayoComponent handleDtmfCommand " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
try {
CallHandler callHandler = CallHandler.findCall(iq.getTo().getNode());
callHandler.dtmfKeys(command.getTones());
} catch (NoSuchElementException e) {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleJoinCommand(JoinCommand command, IQ iq)
{
Log.info("RayoComponent handleJoinCommand " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
String mixer = null;
if (command.getType() == JoinDestinationType.CALL) {
// TODO join.getTo()
} else {
mixer = command.getTo();
}
if (mixer != null)
{
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(mixer);
if (CallHandler.findCall("colibri-" + mixer) == null) // other participant than colibri
{
if (conferenceManager.getMemberList().size() == 1) // handset already in call
{
String recording = mixer + "-" + System.currentTimeMillis() + ".au";
conferenceManager.recordConference(true, recording, "au");
sendMucMessage(mixer, recording, iq.getFrom(), "started voice recording");
}
}
sendMucMessage(mixer, null, iq.getFrom(), iq.getFrom().getNode() + " joined voice conversation");
} catch (ParseException pe) { // colibri joining as first participant
try {
ConferenceManager conferenceManager = ConferenceManager.getConference(mixer, "PCM/48000/2", mixer, false);
String recording = mixer + "-" + System.currentTimeMillis() + ".au";
conferenceManager.recordConference(true, recording, "au");
sendMucMessage(mixer, recording, iq.getFrom(), "started voice recording");
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
}
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.feature_not_implemented);
}
return reply;
}
private IQ handleUnjoinCommand(UnjoinCommand command, IQ iq)
{
Log.info("RayoComponent handleUnjoinCommand " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
String mixer = null;
if (command.getType() == JoinDestinationType.CALL) {
// TODO join.getFrom()
} else {
mixer = command.getFrom();
}
if (mixer != null)
{
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(mixer);
if (conferenceManager.getMemberList().size() == 1)
{
conferenceManager.recordConference(false, null, null);
sendMucMessage(mixer, null, iq.getFrom(), "stopped voice recording");
}
sendMucMessage(mixer, null, iq.getFrom(), iq.getFrom().getNode() + " left voice conversation");
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.feature_not_implemented);
}
return reply;
}
private void attachVideobridge(String conferenceId, JID participant, String mediaPreference)
{
//if (XMPPServer.getInstance().getPluginManager().getPlugin("jitsivideobridge") != null)
//{
Log.info("attachVideobridge Found Jitsi Videobridge, attaching.." + conferenceId);
if (XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").hasChatRoom(conferenceId)) {
MUCRoom room = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").getChatRoom(conferenceId);
if (room != null)
{
for (MUCRole role : room.getOccupants())
{
if (participant.toBareJID().equals(role.getUserAddress().toBareJID()))
{
Log.info("attachVideobridge Found participant " + participant.toBareJID());
try {
CallParticipant vp = new CallParticipant();
vp.setCallId("colibri-" + conferenceId);
vp.setCallOwner(participant.toString());
vp.setProtocol("Videobridge");
vp.setPhoneNumber(participant.getNode());
vp.setMediaPreference(mediaPreference);
vp.setConferenceId(conferenceId);
OutgoingCallHandler videoBridgeHandler = new OutgoingCallHandler(null, vp);
videoBridgeHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
}
//}
}
private void detachVideobridge(String conferenceId)
{
try {
Log.info("Jitsi Videobridge, detaching.." + conferenceId);
CallHandler callHandler = CallHandler.findCall("colibri-" + conferenceId);
if (callHandler != null)
{
CallHandler.hangup("colibri-" + conferenceId, "Detaching from Jitsi Videobridge");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isMixerMuc(String mixer)
{
Log.info("RayoComponent isMixerMuc " + mixer);
boolean isMuc = false;
try {
if (XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").hasChatRoom(mixer)) {
isMuc = null != XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").getChatRoom(mixer);
}
} catch (Exception e) {}
return isMuc;
}
private void sendMucMessage(String mixer, String recording, JID participant, String message)
{
if (isMixerMuc(mixer)) // not working properly. sending only to single person
{
sendMessage(new JID(mixer + "@conference." + getDomain()), participant, message, recording, "groupchat");
}
}
private IQ handleDialCommand(DialCommand command, IQ iq, boolean transferCall)
{
Log.info("RayoComponent handleHandsetDialCommand " + iq.getFrom());
IQ reply = IQ.createResultIQ(iq);
Map<String, String> headers = command.getHeaders();
String from = command.getFrom().toString();
String to = command.getTo().toString();
boolean toPhone = to.indexOf("sip:") == 0 || to.indexOf("tel:") == 0;
boolean toXmpp = to.indexOf("xmpp:") == 0;
String callerName = headers.get("caller_name");
String calledName = headers.get("called_name");
String handsetId = iq.getFrom().toString();
JoinCommand join = command.getJoin();
if (join != null)
{
if (join.getType() == JoinDestinationType.CALL) {
// TODO join.getTo()
} else {
}
reply.setError(PacketError.Condition.feature_not_implemented);
} else {
if (callerName == null)
{
callerName = iq.getFrom().getNode();
headers.put("caller_name", callerName);
}
if (toPhone)
{
if (calledName == null)
{
calledName = to;
headers.put("called_name", calledName);
}
CallParticipant cp = new CallParticipant();
cp.setVoiceDetection(true);
cp.setCallOwner(handsetId);
cp.setProtocol("SIP");
cp.setDisplayName(callerName);
cp.setPhoneNumber(to);
cp.setName(calledName);
cp.setHeaders(headers);
reply = doPhoneAndPcCall(JID.escapeNode(handsetId), cp, reply, transferCall);
} else if (toXmpp){
headers.put("call_protocol", "XMPP");
JID destination = getJID(to.substring(5));
if (destination != null)
{
String source = JID.escapeNode(handsetId);
CallHandler handsetHandler = CallHandler.findCall(source);
if (handsetHandler != null)
{
CallParticipant hp = handsetHandler.getCallParticipant();
headers.put("mixer_name", hp.getConferenceId());
headers.put("codec_name", "PCM/48000/2".equals(hp.getMediaPreference()) ? "OPUS" : "PCMU");
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(hp.getConferenceId());
conferenceManager.setTransferCall(transferCall);
} catch (Exception e) {}
if (findUser(destination.getNode()) != null)
{
routeXMPPCall(reply, destination, source, calledName, headers, hp.getConferenceId());
} else {
int count = 0;
try {
Group group = GroupManager.getInstance().getGroup(destination.getNode());
for (JID memberJID : group.getMembers())
{
if (iq.getFrom().toBareJID().equals(memberJID.toBareJID()) == false)
{
Collection<ClientSession> sessions = SessionManager.getInstance().getSessions(memberJID.getNode());
for (ClientSession session : sessions)
{
routeXMPPCall(reply, session.getAddress(), source, calledName, headers, hp.getConferenceId());
count++;
}
}
}
} catch (GroupNotFoundException e) {
if (XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").hasChatRoom(destination.getNode())) {
MUCRoom room = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").getChatRoom(destination.getNode());
if (room != null)
{
for (MUCRole role : room.getOccupants())
{
if (iq.getFrom().toBareJID().equals(role.getUserAddress().toBareJID()) == false)
{
routeXMPPCall(reply, role.getUserAddress(), source, calledName, headers, hp.getConferenceId());
count++;
}
}
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
}
if (count == 0)
{
reply.setError(PacketError.Condition.item_not_found);
}
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.feature_not_implemented);
}
}
return reply;
}
private void routeXMPPCall(IQ reply, JID destination, String source, String calledName, Map<String, String> headers, String mixer)
{
String callId = JID.escapeNode(destination.toString());
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(destination);
OfferEvent offer = new OfferEvent(null);
try {
offer.setFrom(new URI("xmpp:" + JID.unescapeNode(source)));
offer.setTo(new URI("xmpp:" + destination));
} catch (URISyntaxException e) {
reply.setError(PacketError.Condition.feature_not_implemented);
return;
}
if (calledName == null)
{
calledName = presence.getTo().getNode();
headers.put("called_name", calledName);
}
offer.setHeaders(headers);
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(URI, (String) "xmpp:" + presence.getFrom());
childElement.addAttribute(ID, (String) callId);
presence.getElement().add(rayoProvider.toXML(offer));
sendPacket(presence);
}
private IQ doPhoneAndPcCall(String handsetId, CallParticipant cp, IQ reply, boolean transferCall)
{
Log.info("RayoComponent doPhoneAndPcCall " + handsetId);
CallHandler handsetHandler = CallHandler.findCall(handsetId);
if (handsetHandler != null)
{
try {
setMixer(handsetHandler, reply, cp, transferCall);
OutgoingCallHandler outgoingCallHandler = new OutgoingCallHandler(this, cp);
//outgoingCallHandler.setOtherCall(handsetHandler);
//handsetHandler.setOtherCall(outgoingCallHandler);
outgoingCallHandler.start();
final Element childElement = reply.setChildElement("ref", RAYO_CORE);
childElement.addAttribute(URI, (String) "xmpp:" + cp.getCallId() + "@" + getDomain());
childElement.addAttribute(ID, (String) cp.getCallId());
} catch (Exception e) {
e.printStackTrace();
reply.setError(PacketError.Condition.internal_server_error);
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private void setMixer(CallHandler handsetHandler, IQ reply, CallParticipant cp, boolean transferCall)
{
CallParticipant hp = handsetHandler.getCallParticipant();
try {
hp.setFarParty(cp);
cp.setHandset(hp);
long start = System.currentTimeMillis();
cp.setStartTimestamp(start);
hp.setStartTimestamp(start);
String mixer = hp.getConferenceId();
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(mixer);
cp.setConferenceId(mixer);
cp.setCallId(mixer);
cp.setMediaPreference(hp.getMediaPreference());
conferenceManager.setCallId(mixer);
conferenceManager.setTransferCall(transferCall);
String recording = mixer + "-" + cp.getStartTimestamp() + ".au";
conferenceManager.recordConference(true, recording, "au");
Config.createCallRecord(cp.getDisplayName(), recording, cp.getPhoneNumber(), cp.getStartTimestamp(), 0, "dialed") ;
sendMessage(new JID(cp.getCallOwner()), new JID(cp.getCallId() + "@" + getDomain()), "Call started", recording, "chat");
} catch (ParseException e1) {
reply.setError(PacketError.Condition.internal_server_error);
}
}
@Override
public String getDomain() {
return XMPPServer.getInstance().getServerInfo().getXMPPDomain();
}
public HandsetProvider getHandsetProvider() {
return handsetProvider;
}
public void treatmentDoneNotification(TreatmentManager treatmentManager)
{
Log.info("RayoComponent treatmentDoneNotification " + treatmentManager.getId());
}
public void callEventNotification(com.sun.voip.CallEvent callEvent)
{
Log.info("RayoComponent callEventNotification " + callEvent);
JID from = getJID(callEvent.getCallInfo());
if (from != null)
{
String myEvent = com.sun.voip.CallEvent.getEventString(callEvent.getEvent());
String callState = callEvent.getCallState().toString();
try {
CallHandler callHandler = CallHandler.findCall(callEvent.getCallId());
if (callHandler != null)
{
Log.info("RayoComponent callEventNotification found call handler " + callHandler);
CallParticipant cp = callHandler.getCallParticipant();
CallParticipant hp = cp.getHandset();
if (cp != null)
{
Log.info("RayoComponent callEventNotification found call paticipant " + cp);
Map<String, String> headers = cp.getHeaders();
headers.put("mixer_name", callEvent.getConferenceId());
headers.put("call_protocol", cp.getProtocol());
Presence presence = new Presence();
presence.setFrom(callEvent.getCallId() + "@" + getDomain());
presence.setTo(from);
if ("001 STATE CHANGED".equals(myEvent))
{
if ("100 INVITED".equals(callState)) {
if (cp.isAutoAnswer() == false) // SIP handset, no ringing event
{
setRingingState(presence, ConferenceManager.isTransferCall(callEvent.getConferenceId()), headers);
sendPacket(presence);
}
} else if ("200 ESTABLISHED".equals(callState)) {
} else if ("299 ENDED".equals(callState)) {
/*
if (callEvent.getCallId().indexOf("2fspeaker") > -1 && callEvent.getInfo().indexOf("Reason='System shutdown'") == -1)
{
CallParticipant cp2 = new CallParticipant();
cp2.setCallId(cp.getCallId());
cp2.setConferenceId(cp.getConferenceId());
cp2.setDisplayName(cp.getDisplayName());
cp2.setName(cp.getDisplayName());
cp2.setCallOwner(cp.getCallOwner());
cp2.setPhoneNumber(cp.getPhoneNumber());
cp2.setVoiceDetection(true);
cp2.setAutoAnswer(true);
cp2.setProtocol("SIP");
cp2.setMuted(true); // set mic off
OutgoingCallHandler callHandlerNew = new OutgoingCallHandler(this, cp2);
callHandlerNew.start();
}
*/
}
} else if ("250 STARTED SPEAKING".equals(myEvent)) {
broadcastSpeaking(true, callEvent.getCallId(), callEvent.getConferenceId(), from);
} else if ("259 STOPPED SPEAKING".equals(myEvent)) {
broadcastSpeaking(false, callEvent.getCallId(), callEvent.getConferenceId(), from);
} else if ("269 DTMF".equals(myEvent)) {
presence.getElement().add(rayoProvider.toXML(new DtmfEvent(callEvent.getCallId(), callEvent.getDtmfKey())));
sendPacket(presence);
} else if ("230 TREATMENT DONE".equals(myEvent)) {
presence.setFrom(callEvent.getCallId() + "@" + getDomain() + "/" + callEvent.getTreatmentId());
SayCompleteEvent complete = new SayCompleteEvent();
complete.setReason(SayCompleteEvent.Reason.valueOf("SUCCESS"));
presence.getElement().add(sayProvider.toXML(complete));
sendPacket(presence);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void broadcastSpeaking(Boolean startSpeaking, String callId, String conferenceId, JID from)
{
Log.info( "RayoComponent broadcastSpeaking " + startSpeaking + " " + callId + " " + conferenceId + " " + from);
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(conferenceId);
ArrayList memberList = conferenceManager.getMemberList();
//sendMucMessage(conferenceId, null, from, from.getNode() + (startSpeaking ? " started" : " stopped") + " speaking");
synchronized (memberList)
{
for (int i = 0; i < memberList.size(); i++)
{
ConferenceMember member = (ConferenceMember) memberList.get(i);
CallHandler callHandler = member.getCallHandler();
if (callHandler != null)
{
CallParticipant cp = callHandler.getCallParticipant();
String target = cp.getCallOwner();
Log.info( "RayoComponent broadcastSpeaking checking " + target);
if (target != null && target.equals(from.toString()) == false)
{
Presence presence = new Presence();
presence.setFrom(conferenceId + "@" + getDomain());
presence.setTo(target);
if (startSpeaking)
{
StartedSpeakingEvent speaker = new StartedSpeakingEvent();
speaker.setSpeakerId(JID.escapeNode(from.toString()));
presence.getElement().add(rayoProvider.toXML(speaker));
} else {
StoppedSpeakingEvent speaker = new StoppedSpeakingEvent();
speaker.setSpeakerId(JID.escapeNode(from.toString()));
presence.getElement().add(rayoProvider.toXML(speaker));
}
sendPacket(presence);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void finishCallRecord(CallParticipant cp)
{
Log.info( "RayoComponent finishCallRecord " + cp.getStartTimestamp());
if (cp.getStartTimestamp() > 0)
{
cp.setEndTimestamp(System.currentTimeMillis());
Config.updateCallRecord(cp.getStartTimestamp(), (int)((cp.getEndTimestamp() - cp.getStartTimestamp()) / 1000));
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(cp.getConferenceId());
conferenceManager.recordConference(false, null, null);
String target = cp.getCallOwner();
JID destination = getJID(conferenceManager.getCallId());
if (destination == null)
{
destination = new JID(conferenceManager.getCallId() + "@" + getDomain());
}
if (target == null)
{
if (cp.getHandset() != null)
{
target = cp.getHandset().getCallOwner();
}
}
if (target != null)
{
try {
if (target.equals(destination.toString()) == false)
{
sendMessage(new JID(target), destination, "Call ended", null, "chat");
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {}
cp.setStartTimestamp(0);
}
}
private void sendMessage(JID from, JID to, String body, String fileName, String type)
{
Log.info( "RayoComponent sendMessage " + from + " " + to + " " + body + " " + fileName);
int port = HttpBindManager.getInstance().getHttpBindUnsecurePort();
Message packet = new Message();
packet.setTo(to);
packet.setFrom(from);
packet.setType("chat".equals(type) ? Message.Type.chat : Message.Type.groupchat);
if (fileName != null)
{
String url = "http://" + getDomain() + ":" + port + "/rayo/recordings/" + fileName;
packet.setThread(url);
body = body + " " + url;
}
packet.setBody(body);
sendPacket(packet);
}
public void sendPacket(Packet packet)
{
try {
ComponentManagerFactory.getComponentManager().sendPacket(this, packet);
} catch (Exception e) {
Log.error("RayoComponent sendPacket " + e);
e.printStackTrace();
}
}
public void notifyConferenceMonitors(ConferenceEvent conferenceEvent)
{
Log.info( "RayoComponent notifyConferenceMonitors " + conferenceEvent.toString());
if (defaultIncomingConferenceId.equals(conferenceEvent.getConferenceId())) return;
ConferenceManager conferenceManager = null;
try {
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT) || conferenceEvent.equals(ConferenceEvent.MEMBER_JOINED))
{
Log.info("RayoComponent notifyConferenceMonitors looking for call " + conferenceEvent.getCallId() + " " + conferenceEvent.getMemberCount());
try {
conferenceManager = ConferenceManager.findConferenceManager(conferenceEvent.getConferenceId());
} catch (Exception e) {}
if (conferenceManager != null)
{
String groupName = conferenceManager.getGroupName();
String callId = conferenceManager.getCallId();
if (callId == null) callId = conferenceEvent.getConferenceId(); // special case of SIP incoming
CallHandler farParty = CallHandler.findCall(callId);
CallHandler callHandler = CallHandler.findCall(conferenceEvent.getCallId());
if (callHandler != null)
{
Log.info("RayoComponent notifyConferenceMonitors found call handler " + callHandler + " " + farParty);
CallParticipant callParticipant = callHandler.getCallParticipant();
ArrayList memberList = conferenceManager.getMemberList();
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT) && callId.equals(conferenceEvent.getCallId()))
{
if (farParty != null && farParty.getCallParticipant().isHeld() == false) // far party left
{
synchronized (memberList)
{
for (int i = 0; i < memberList.size(); i++)
{
CallHandler participant = ((ConferenceMember) memberList.get(i)).getCallHandler();
participant.cancelRequest("Far Party has left");
}
}
}
}
int memberCount = memberList.size();
/*
When mixer is an muc, assume a conference call just sent join/unjoin
When mixer is a group, assume a third party call, inform group members
*/
if (groupName == null)
{
if (isMixerMuc(conferenceEvent.getConferenceId()))
{
MUCRoom room = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService("conference").getChatRoom(conferenceEvent.getConferenceId());
Log.info("RayoComponent notifyConferenceMonitors routing to room occupants of " + conferenceEvent.getConferenceId());
for ( MUCRole role : room.getOccupants())
{
String jid = role.getUserAddress().toString();
Log.info("RayoComponent notifyConferenceMonitors routing to room occupant " + jid);
Presence presence = new Presence();
presence.setFrom(conferenceEvent.getCallId() + "@" + getDomain());
presence.setTo(jid);
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT))
{
UnjoinedEvent event = new UnjoinedEvent(null, conferenceEvent.getConferenceId(), JoinDestinationType.MIXER);
presence.getElement().add(rayoProvider.toXML(event));
} else {
JoinedEvent event = new JoinedEvent(null, conferenceEvent.getConferenceId(), JoinDestinationType.MIXER);
presence.getElement().add(rayoProvider.toXML(event));
}
sendPacket(presence);
}
} else {
Log.info("RayoComponent notifyConferenceMonitors routing to owner " + callParticipant.getCallOwner() + " " + memberCount);
routeJoinEvent(callParticipant.getCallOwner(), callParticipant, conferenceEvent, memberCount, groupName, callId, farParty, conferenceManager);
}
} else {
Group group = GroupManager.getInstance().getGroup(groupName);
for (JID memberJID : group.getMembers())
{
Collection<ClientSession> sessions = SessionManager.getInstance().getSessions(memberJID.getNode());
for (ClientSession session : sessions)
{
routeJoinEvent(session.getAddress().toString(), callParticipant, conferenceEvent, memberCount, groupName, callId, farParty, conferenceManager);
}
}
}
if (memberCount == 0 && conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT))
{
conferenceManager.recordConference(false, null, null);
conferenceManager.endConference(conferenceEvent.getConferenceId());
CallParticipant heldCall = conferenceManager.getHeldCall();
if (heldCall != null)
{
JID target = getJID(heldCall.getCallId());
if (target != null)
{
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(target);
presence.getElement().add(rayoProvider.toXML(new EndEvent(null, EndEvent.Reason.valueOf("HANGUP"), callParticipant.getHeaders())));
sendPacket(presence);
}
}
} else if (memberCount == 2) {
conferenceManager.setTransferCall(false); // reset after informing on redirect
}
}
}
}
} catch (Exception e) {
Log.error( "RayoComponent Error in notifyConferenceMonitors " + e);
e.printStackTrace();
}
}
private void routeJoinEvent(String callee, CallParticipant callParticipant, ConferenceEvent conferenceEvent, int memberCount, String groupName, String callId, CallHandler farParty, ConferenceManager conferenceManager)
{
Log.info( "RayoComponent routeJoinEvent " + callee + " " + callId + " " + groupName + " " + memberCount + " " + farParty);
if (callee == null) return;
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(callee);
Map<String, String> headers = callParticipant.getHeaders();
headers.put("call_owner", callParticipant.getCallOwner());
headers.put("call_action", conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT) ? "leave" : "join");
headers.put("call_protocol", callParticipant.getProtocol());
headers.put("mixer_name", conferenceEvent.getConferenceId());
headers.put("group_name", groupName);
if (memberCount > 2) // conferencing state
{
Log.info( "RayoComponent routeJoinEvent conferenced state " + memberCount);
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT))
{
UnjoinedEvent event = new UnjoinedEvent(null, conferenceEvent.getConferenceId(), JoinDestinationType.MIXER);
presence.getElement().add(rayoProvider.toXML(event));
} else {
JoinedEvent event = new JoinedEvent(null, conferenceEvent.getConferenceId(), JoinDestinationType.MIXER);
presence.getElement().add(rayoProvider.toXML(event));
}
sendPacket(presence);
} else {
if (memberCount == 2) // caller with callee only
{
Log.info( "RayoComponent routeJoinEvent answered state " + callId + " " + conferenceEvent.getCallId());
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT)) // previously conferenced
{
Log.info( "RayoComponent routeJoinEvent someone left ");
if (callId.equals(conferenceEvent.getCallId()) == false) // handset leaving
{
Log.info( "RayoComponent routeJoinEvent handset leaving ");
setAnsweredState(presence, conferenceManager.isTransferCall(), headers);
sendPacket(presence);
} else {
Log.info( "RayoComponent routeJoinEvent far party leaving ");
}
} else {
Log.info( "RayoComponent routeJoinEvent someone joined ");
if (callId.equals(conferenceEvent.getCallId())) // far party joined
{
Log.info( "RayoComponent routeJoinEvent far party joined ");
setAnsweredState(presence, conferenceManager.isTransferCall(), headers);
sendPacket(presence);
} else { // handset joined
Log.info( "RayoComponent routeJoinEvent handset joined ");
if (farParty != null)
{
CallParticipant fp = farParty.getCallParticipant();
if (fp.isHeld())
{
Log.info( "RayoComponent routeJoinEvent on hold ");
fp.setHeld(false);
conferenceManager.setHeldCall(null);
setAnsweredState(presence, conferenceManager.isTransferCall(), headers);
sendPacket(presence);
} else {
Log.info( "RayoComponent routeJoinEvent not held " + fp.getProtocol() + " " + fp);
if ("WebRtc".equals(fp.getProtocol()) == false)
{
Log.info( "RayoComponent routeJoinEvent handset joing sip call");
setAnsweredState(presence, conferenceManager.isTransferCall(), headers);
sendPacket(presence);
}
}
}
}
}
} else if (memberCount == 1) { // callee or caller
if (conferenceEvent.equals(ConferenceEvent.MEMBER_LEFT))
{
Log.info( "RayoComponent routeJoinEvent only one person left");
if (callId.equals(conferenceEvent.getCallId()) == false) // handset leaving
{
if (farParty != null)
{
Log.info( "RayoComponent routeJoinEvent handset leaving call " + farParty.getCallParticipant());
CallParticipant fp = farParty.getCallParticipant();
if (callParticipant.isAutoAnswer()) fp.setHeld(true); // sip phone as handset hangup
if (fp.isHeld())
{
Log.info( "RayoComponent routeJoinEvent call held with " + callParticipant);
presence.getElement().add(handsetProvider.toXML(new OnHoldEvent()));
sendPacket(presence);
conferenceManager.setHeldCall(callParticipant);
}
}
} else { // far party leaving
Log.info( "RayoComponent routeJoinEvent far party leaving call " + callParticipant);
if (callParticipant.isHeld())
{
Log.info( "RayoComponent routeJoinEvent call held with " + farParty);
presence.getElement().add(handsetProvider.toXML(new OnHoldEvent()));
sendPacket(presence);
conferenceManager.setHeldCall(farParty.getCallParticipant());
} else {
finishCallRecord(callParticipant);
presence.getElement().add(rayoProvider.toXML(new EndEvent(null, EndEvent.Reason.valueOf("HANGUP"), headers)));
sendPacket(presence);
}
}
}
} else { // nobody left, call ended, signal last handset
presence.getElement().add(rayoProvider.toXML(new EndEvent(null, EndEvent.Reason.valueOf("HANGUP"), headers)));
sendPacket(presence);
finishCallRecord(callParticipant);
}
}
}
private void setAnsweredState(Presence presence, boolean isTransfer, Map<String, String> headers)
{
if (isTransfer)
{
presence.getElement().add(handsetProvider.toXML(new TransferredEvent()));
} else {
presence.getElement().add(rayoProvider.toXML(new AnsweredEvent(null, headers)));
}
}
private void setRingingState(Presence presence, boolean isTransfer, Map<String, String> headers)
{
if (isTransfer)
{
presence.getElement().add(handsetProvider.toXML(new TransferringEvent()));
} else {
presence.getElement().add(rayoProvider.toXML(new RingingEvent(null, headers)));
}
}
private JID findUser(String username)
{
Collection<ClientSession> sessions = SessionManager.getInstance().getSessions();
JID foundUser = null;
for (ClientSession session : sessions)
{
try{
String userId = session.getAddress().getNode();
if (username.equals(userId))
{
Log.info("Incoming SIP, findUser " + session.getAddress());
foundUser = session.getAddress();
break;
}
} catch (Exception e) { }
}
return foundUser;
}
public boolean routeIncomingSIP(CallParticipant cp)
{
boolean canRoute = false;
Group group = null;
JID foundUser = findUser(cp.getToPhoneNumber());
if (foundUser != null)
canRoute = true;
else {
try {
group = GroupManager.getInstance().getGroup(cp.getToPhoneNumber());
canRoute = true;
} catch (GroupNotFoundException e) {
}
}
Log.info("Incoming SIP, call route to entity " + cp.getToPhoneNumber() + " " + canRoute);
if (canRoute)
{
String callId = "rayo-incoming-" + System.currentTimeMillis();
cp.setCallId(callId);
cp.setConferenceId(callId);
if (cp.getMediaPreference() == null) cp.setMediaPreference("PCMU/8000/1"); // regular phone
ConferenceManager conferenceManager = ConferenceManager.getConference(callId, cp.getMediaPreference(), cp.getToPhoneNumber(), false);
conferenceManager.setCallId(callId);
Map<String, String> headers = cp.getHeaders();
headers.put("mixer_name", callId);
headers.put("call_protocol", "SIP");
headers.put("codec_name", "PCM/48000/2".equals(cp.getMediaPreference()) ? "OPUS" : "PCMU");
headers.put("group_name", cp.getToPhoneNumber());
if (foundUser != null) // send this call to specific user
{
cp.setCallOwner(foundUser.toString());
routeSIPCall(foundUser, cp, callId, headers);
} else {
conferenceManager.setGroupName(cp.getToPhoneNumber());
for (JID memberJID : group.getMembers())
{
Collection<ClientSession> sessions = SessionManager.getInstance().getSessions(memberJID.getNode());
for (ClientSession session : sessions)
{
routeSIPCall(session.getAddress(), cp, callId, headers);
}
}
}
}
return canRoute;
}
public void routeSIPCall(JID callee, CallParticipant cp, String callId, Map<String, String> headers)
{
Log.info("routeSIPCall to user " + callee);
if (callee != null) // send this call to user
{
Presence presence = new Presence();
presence.setFrom(callId + "@" + getDomain());
presence.setTo(callee);
OfferEvent offer = new OfferEvent(null);
try {
offer.setTo(new URI("xmpp:" + callee.toString()));
offer.setFrom(new URI("sip:" + cp.getPhoneNumber()));
} catch (URISyntaxException e) {
Log.error("SIP phone nos not URI " + cp.getPhoneNumber() + " " + callee);
}
headers.put("called_name", callee.getNode());
headers.put("caller_name", cp.getName());
offer.setHeaders(headers);
presence.getElement().add(rayoProvider.toXML(offer));
sendPacket(presence);
}
}
private IQHandler onHookIQHandler = null;
private IQHandler offHookIQHandler = null;
private IQHandler privateIQHandler = null;
private IQHandler publicIQHandler = null;
private IQHandler muteIQHandler = null;
private IQHandler unmuteIQHandler = null;
private IQHandler holdIQHandler = null;
private IQHandler sayIQHandler = null;
private IQHandler pauseSayIQHandler = null;
private IQHandler resumeSayIQHandler = null;
private IQHandler recordIQHandler = null;
private IQHandler pauseRecordIQHandler = null;
private IQHandler resumeRecordIQHandler = null;
private IQHandler acceptIQHandler = null;
private IQHandler answerIQHandler = null;
private IQHandler dialIQHandler = null;
private IQHandler hangupIQHandler = null;
private IQHandler redirectIQHandler = null;
private IQHandler dtmfIQHandler = null;
private void createIQHandlers()
{
XMPPServer server = XMPPServer.getInstance();
onHookIQHandler = new OnHookIQHandler(); server.getIQRouter().addHandler(onHookIQHandler);
offHookIQHandler = new OffHookIQHandler(); server.getIQRouter().addHandler(offHookIQHandler);
privateIQHandler = new PrivateIQHandler(); server.getIQRouter().addHandler(privateIQHandler);
publicIQHandler = new PublicIQHandler(); server.getIQRouter().addHandler(publicIQHandler);
muteIQHandler = new MuteIQHandler(); server.getIQRouter().addHandler(muteIQHandler);
unmuteIQHandler = new UnmuteIQHandler(); server.getIQRouter().addHandler(unmuteIQHandler);
holdIQHandler = new HoldIQHandler(); server.getIQRouter().addHandler(holdIQHandler);
recordIQHandler = new RecordIQHandler(); server.getIQRouter().addHandler(recordIQHandler);
pauseRecordIQHandler = new PauseRecordIQHandler(); server.getIQRouter().addHandler(pauseRecordIQHandler);
resumeRecordIQHandler = new ResumeRecordIQHandler(); server.getIQRouter().addHandler(resumeRecordIQHandler);
sayIQHandler = new SayIQHandler(); server.getIQRouter().addHandler(sayIQHandler);
pauseSayIQHandler = new PauseSayIQHandler(); server.getIQRouter().addHandler(pauseSayIQHandler);
resumeSayIQHandler = new ResumeSayIQHandler(); server.getIQRouter().addHandler(resumeSayIQHandler);
acceptIQHandler = new AcceptIQHandler(); server.getIQRouter().addHandler(acceptIQHandler);
answerIQHandler = new AnswerIQHandler(); server.getIQRouter().addHandler(answerIQHandler);
dialIQHandler = new DialIQHandler(); server.getIQRouter().addHandler(dialIQHandler);
hangupIQHandler = new HangupIQHandler(); server.getIQRouter().addHandler(hangupIQHandler);
redirectIQHandler = new RedirectIQHandler(); server.getIQRouter().addHandler(redirectIQHandler);
dtmfIQHandler = new DtmfIQHandler(); server.getIQRouter().addHandler(dtmfIQHandler);
}
private void destroyIQHandlers()
{
XMPPServer server = XMPPServer.getInstance();
if (onHookIQHandler != null) {server.getIQRouter().removeHandler(onHookIQHandler); onHookIQHandler = null;}
if (offHookIQHandler != null) {server.getIQRouter().removeHandler(offHookIQHandler); offHookIQHandler = null;}
if (privateIQHandler != null) {server.getIQRouter().removeHandler(privateIQHandler); privateIQHandler = null;}
if (publicIQHandler != null) {server.getIQRouter().removeHandler(publicIQHandler); publicIQHandler = null;}
if (muteIQHandler != null) {server.getIQRouter().removeHandler(muteIQHandler); muteIQHandler = null;}
if (unmuteIQHandler != null) {server.getIQRouter().removeHandler(unmuteIQHandler); unmuteIQHandler = null;}
if (holdIQHandler != null) {server.getIQRouter().removeHandler(holdIQHandler); holdIQHandler = null;}
if (sayIQHandler != null) {server.getIQRouter().removeHandler(sayIQHandler); sayIQHandler = null;}
if (pauseSayIQHandler != null) {server.getIQRouter().removeHandler(pauseSayIQHandler); pauseSayIQHandler = null;}
if (resumeSayIQHandler != null) {server.getIQRouter().removeHandler(resumeSayIQHandler); resumeSayIQHandler = null;}
if (acceptIQHandler != null) {server.getIQRouter().removeHandler(acceptIQHandler); acceptIQHandler = null;}
if (answerIQHandler != null) {server.getIQRouter().removeHandler(answerIQHandler); answerIQHandler = null;}
if (dialIQHandler != null) {server.getIQRouter().removeHandler(dialIQHandler); dialIQHandler = null;}
if (hangupIQHandler != null) {server.getIQRouter().removeHandler(hangupIQHandler); hangupIQHandler = null;}
if (redirectIQHandler != null) {server.getIQRouter().removeHandler(redirectIQHandler); redirectIQHandler = null;}
if (dtmfIQHandler != null) {server.getIQRouter().removeHandler(dtmfIQHandler); dtmfIQHandler = null;}
}
private class OnHookIQHandler extends IQHandler
{
public OnHookIQHandler() { super("Rayo: XEP 0327 - Onhook");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) {return null;} }
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("onhook", RAYO_HANDSET); }
}
private class OffHookIQHandler extends IQHandler
{
public OffHookIQHandler() { super("Rayo: XEP 0327 - Offhook");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("offhook", RAYO_HANDSET); }
}
private class PrivateIQHandler extends IQHandler
{
public PrivateIQHandler() { super("Rayo: XEP 0327 - Private");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("private", RAYO_HANDSET); }
}
private class PublicIQHandler extends IQHandler
{
public PublicIQHandler() { super("Rayo: XEP 0327 - Public");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("public", RAYO_HANDSET); }
}
private class MuteIQHandler extends IQHandler
{
public MuteIQHandler() { super("Rayo: XEP 0327 - Mute");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("mute", RAYO_HANDSET); }
}
private class UnmuteIQHandler extends IQHandler
{
public UnmuteIQHandler() { super("Rayo: XEP 0327 - Unmute");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("unmute", RAYO_HANDSET); }
}
private class HoldIQHandler extends IQHandler
{
public HoldIQHandler() { super("Rayo: XEP 0327 - Hold");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("hold", RAYO_HANDSET); }
}
private class RecordIQHandler extends IQHandler
{
public RecordIQHandler() { super("Rayo: XEP 0327 - Record");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("record", RAYO_RECORD); }
}
private class PauseRecordIQHandler extends IQHandler
{
public PauseRecordIQHandler() { super("Rayo: XEP 0327 - Pause Record");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("pause", RAYO_RECORD); }
}
private class ResumeRecordIQHandler extends IQHandler
{
public ResumeRecordIQHandler() { super("Rayo: XEP 0327 - Resume Record");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("resume", RAYO_RECORD); }
}
private class SayIQHandler extends IQHandler
{
public SayIQHandler() { super("Rayo: XEP 0327 - Say (text to speech)");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("say", RAYO_SAY); }
}
private class PauseSayIQHandler extends IQHandler
{
public PauseSayIQHandler() { super("Rayo: XEP 0327 - Pause Say");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("pause", RAYO_SAY); }
}
private class ResumeSayIQHandler extends IQHandler
{
public ResumeSayIQHandler() { super("Rayo: XEP 0327 - Resume Say");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("resume", RAYO_SAY); }
}
private class AcceptIQHandler extends IQHandler
{
public AcceptIQHandler() { super("Rayo: XEP 0327 - Accept");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("accept", RAYO_CORE); }
}
private class AnswerIQHandler extends IQHandler
{
public AnswerIQHandler() { super("Rayo: XEP 0327 - Answer");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("answer", RAYO_CORE); }
}
private class DialIQHandler extends IQHandler
{
public DialIQHandler() { super("Rayo: XEP 0327 - Dial");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("dial", RAYO_CORE); }
}
private class HangupIQHandler extends IQHandler
{
public HangupIQHandler() { super("Rayo: XEP 0327 - Hangup");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("hangup", RAYO_CORE); }
}
private class RedirectIQHandler extends IQHandler
{
public RedirectIQHandler() { super("Rayo: XEP 0327 - Redirect");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("redirect", RAYO_CORE); }
}
private class DtmfIQHandler extends IQHandler
{
public DtmfIQHandler() { super("Rayo: XEP 0327 - DTMF");}
@Override public IQ handleIQ(IQ iq) {try {return handleIQGet(iq);} catch(Exception e) { return null;}}
@Override public IQHandlerInfo getInfo() { return new IQHandlerInfo("dtmf", RAYO_CORE); }
}
}