/* * Jicofo, the Jitsi Conference Focus. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jitsi.jicofo.recording; import net.java.sip.communicator.impl.protocol.jabber.extensions.jirecon.*; import org.jitsi.jicofo.*; import org.jitsi.protocol.xmpp.*; import org.jitsi.util.*; import org.jivesoftware.smack.packet.*; /** * Class implements {@link Recorder} using Jirecon recorder container. * * @author Pawel Domas */ public class JireconRecorder extends Recorder { /** * The logger. */ private final static Logger logger = Logger.getLogger(JireconRecorder.class); /** * The name of the property which specifies the token used to authenticate * requests to enable media recording. */ static final String MEDIA_RECORDING_TOKEN_PNAME = "org.jitsi.videobridge.MEDIA_RECORDING_TOKEN"; /** * FIXME: not sure about that * Our room JID in form of room_name@muc_component/focus_nickname */ private final String mucRoomJid; /** * Recording authentication token. */ private final String token; /** * Recording status of the Jirecon component. */ private JireconIq.Status status = JireconIq.Status.UNDEFINED; /** * Recording session identifier assigned by Jirecon. */ private String recordingId; /** * Creates new instance of <tt>JireconRecorder</tt>. * @param mucRoomJid focus room jid in form of * "room_name@muc_component/focus_nickname". * @param recorderComponentJid recorder component address. * @param xmpp {@link OperationSetDirectSmackXmpp} instance for current * XMPP connection. */ public JireconRecorder(String mucRoomJid, String recorderComponentJid, OperationSetDirectSmackXmpp xmpp) { super(recorderComponentJid, xmpp); this.mucRoomJid = mucRoomJid; this.token = FocusBundleActivator.getConfigService() .getString(MEDIA_RECORDING_TOKEN_PNAME); } /** * {@inheritDoc} */ @Override public boolean isRecording() { return JireconIq.Status.INITIATING == status || JireconIq.Status.STARTED == status; } /** * {@inheritDoc} */ @Override public boolean setRecording( String from, String token, boolean doRecord, String path) { if (!StringUtils.isNullOrEmpty(this.token) && !this.token.equals(token)) { return false; } if (!isRecording() && doRecord) { // Send start recording IQ JireconIq recording = new JireconIq(); recording.setTo(recorderComponentJid); recording.setType(IQ.Type.SET); recording.setFrom(from); recording.setMucJid(mucRoomJid); recording.setAction(JireconIq.Action.START); recording.setOutput(path); Packet reply = xmpp.getXmppConnection().sendPacketAndGetReply(recording); if (reply instanceof JireconIq) { JireconIq recResponse = (JireconIq) reply; if (JireconIq.Status.INITIATING.equals(recResponse.getStatus())) { recordingId = recResponse.getRid(); logger.info("Received recording ID: " + recordingId); status = JireconIq.Status.INITIATING; } else { logger.error( "Unexpected status received: " + recResponse.toXML()); } } else { logger.error("Unexpected response: " + reply.toXML()); } } else if (isRecording() && !doRecord) { // Send stop recording IQ JireconIq recording = new JireconIq(); recording.setTo(recorderComponentJid); recording.setType(IQ.Type.SET); recording.setFrom(from); recording.setRid(recordingId); recording.setMucJid(mucRoomJid); recording.setAction(JireconIq.Action.STOP); xmpp.getXmppConnection().sendPacket(recording); status = JireconIq.Status.STOPPING; } return true; } /** * Accepts Jirecon packets. * * {@inheritDoc} */ @Override public boolean accept(Packet packet) { return packet instanceof JireconIq; } /** * Jirecon packets processing logic. * * {@inheritDoc} */ @Override public void processPacket(Packet packet) { JireconIq recording = (JireconIq) packet; if (JireconIq.Action.INFO != recording.getAction() && IQ.Type.RESULT == recording.getType() || StringUtils.isNullOrEmpty(recording.getRid())) { logger.warn("Discarded: " + recording.toXML()); return; } if (!recording.getRid().equals(recordingId)) { logger.warn( "Received IQ for unknown session: " + recording.toXML()); return; } if (status != recording.getStatus()) { status = recording.getStatus(); logger.info("Recording " + recordingId + " status: " + status); if (status == JireconIq.Status.STOPPED) { logger.info("Recording STOPPED: " + recordingId); recordingId = null; } } else { logger.info("Ignored status change: " + recording.toXML()); } } }