aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2012-02-01 12:38:14 +0000
committerDamian Minkov <damencho@jitsi.org>2012-02-01 12:38:14 +0000
commit8e66e5a9db51c6f68d04575c9bafb9648be63f2d (patch)
treee43b59a71e4baa51c4cae3b96d1b527102dd5b91 /src/net/java/sip/communicator/impl
parentee69f66fe49880758a639a3336df1b32e7175c5d (diff)
downloadjitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.zip
jitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.tar.gz
jitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.tar.bz2
Implements receiving of sip INFO dtmf tones.
Diffstat (limited to 'src/net/java/sip/communicator/impl')
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java9
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java63
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java10
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java178
4 files changed, 258 insertions, 2 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java
index c8ad9d9..9bd2878 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java
@@ -134,4 +134,13 @@ public class OperationSetDTMFSipImpl
return false;
}
+
+ /**
+ * Returns DTMFInfo mode implementation.
+ * @return DTMFInfo mode implementation.
+ */
+ DTMFInfo getDtmfModeInfo()
+ {
+ return dtmfModeInfo;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java
new file mode 100644
index 0000000..506ecbb
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.protocol.sip;
+
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+
+/**
+ * An <tt>OperationSet</tt> that allows us to receive DMF tones through
+ * this protocol provider.
+ *
+ * @author Damian Minkov
+ */
+public class OperationSetIncomingDTMFSipImpl
+ implements OperationSetIncomingDTMF
+{
+ /**
+ * The parent provider.
+ */
+ private ProtocolProviderServiceSipImpl provider;
+
+ /**
+ * The send DTMF operation set holding dtmf implementations.
+ */
+ private OperationSetDTMFSipImpl opsetDTMFSip;
+
+ /**
+ * Creates operation set.
+ * @param provider the parent provider
+ * @param opsetDTMFSip the dtmf implementation.
+ */
+ OperationSetIncomingDTMFSipImpl(ProtocolProviderServiceSipImpl provider,
+ OperationSetDTMFSipImpl opsetDTMFSip)
+ {
+ this.provider = provider;
+
+ this.opsetDTMFSip = opsetDTMFSip;
+ }
+
+ /**
+ * Registers the specified DTMFListener with this provider so that it could
+ * be notified when incoming DTMF tone is received.
+ * @param listener the listener to register with this provider.
+ *
+ */
+ public void addDTMFListener(DTMFListener listener)
+ {
+ this.opsetDTMFSip.getDtmfModeInfo().addDTMFListener(listener);
+ }
+
+ /**
+ * Removes the specified listener from the list of DTMF listeners.
+ * @param listener the listener to unregister.
+ */
+ public void removeDTMFListener(DTMFListener listener)
+ {
+ this.opsetDTMFSip.getDtmfModeInfo().removeDTMFListener(listener);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
index c4e224d..4eeadf7 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
@@ -443,9 +443,15 @@ public class ProtocolProviderServiceSipImpl
new OperationSetTelephonyConferencingSipImpl(this));
// init DTMF (from JM Heitz)
+ OperationSetDTMFSipImpl operationSetDTMFSip
+ = new OperationSetDTMFSipImpl(this);
addSupportedOperationSet(
- OperationSetDTMF.class,
- new OperationSetDTMFSipImpl(this));
+ OperationSetDTMF.class, operationSetDTMFSip);
+
+ addSupportedOperationSet(
+ OperationSetIncomingDTMF.class,
+ new OperationSetIncomingDTMFSipImpl(
+ this, operationSetDTMFSip));
boolean isDesktopStreamingDisabled
= SipActivator.getConfigurationService()
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java b/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java
index 1c29751..612030f 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java
@@ -8,6 +8,7 @@ package net.java.sip.communicator.impl.protocol.sip.dtmf;
import gov.nist.javax.sip.header.*;
+import java.io.*;
import java.text.*;
import java.util.*;
@@ -17,6 +18,7 @@ import javax.sip.message.*;
import net.java.sip.communicator.impl.protocol.sip.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
@@ -59,6 +61,12 @@ public class DTMFInfo
private final ProtocolProviderServiceSipImpl pps;
/**
+ * A list of listeners registered for dtmf tone events.
+ */
+ private final List<DTMFListener> dtmfListeners =
+ new LinkedList<DTMFListener>();
+
+ /**
* Constructor
*
* @param pps the SIP Protocol provider service
@@ -277,4 +285,174 @@ public class DTMFInfo
}
return processed;
}
+
+ /*
+ * Receives dtmf info requests.
+ */
+ public boolean processRequest(RequestEvent requestEvent)
+ {
+ Request request = requestEvent.getRequest();
+
+ ContentTypeHeader contentTypeHeader
+ = (ContentTypeHeader)
+ request.getHeader(ContentTypeHeader.NAME);
+
+ if ((contentTypeHeader != null)
+ && CONTENT_TYPE.equalsIgnoreCase(
+ contentTypeHeader.getContentType())
+ && CONTENT_SUB_TYPE.equalsIgnoreCase(
+ contentTypeHeader.getContentSubType()))
+ {
+ try
+ {
+ byte[] value;
+ Object valueObj = request.getContent();
+
+ if(valueObj instanceof String)
+ value = ((String)valueObj).getBytes("UTF-8");
+ else if(valueObj instanceof byte[])
+ value = (byte[])valueObj;
+ else
+ {
+ logger.error("Unknown content type");
+ return false;
+ }
+
+ Properties prop = new Properties();
+ prop.load(new ByteArrayInputStream(value));
+
+ String signal = prop.getProperty("Signal");
+ String durationStr = prop.getProperty("Duration");
+
+ DTMFTone tone = DTMFTone.getDTMFTone(signal);
+
+ if(tone == null)
+ {
+ logger.warn("Unknown tone received: " + tone);
+ return false;
+ }
+
+ long duration = 0;
+ try
+ {
+ duration = Long.parseLong(durationStr);
+ }
+ catch(NumberFormatException ex)
+ {
+ logger.warn("Error parsing duration:" + durationStr, ex);
+ }
+
+ // fire event
+ fireToneEvent(tone, duration);
+ }
+ catch(IOException ioe)
+ {}
+
+ Response responseOK;
+
+ try
+ {
+ responseOK = pps.getMessageFactory().createResponse(
+ Response.OK, requestEvent.getRequest());
+ }
+ catch (ParseException ex)
+ {
+ //What else could we do apart from logging?
+ logger.warn("Failed to create OK for incoming INFO request", ex);
+ return false;
+ }
+
+ try
+ {
+ SipStackSharing.getOrCreateServerTransaction(requestEvent).
+ sendResponse(responseOK);
+ }
+ catch(TransactionUnavailableException ex)
+ {
+ if (logger.isInfoEnabled())
+ logger.info("Failed to respond to an incoming "
+ +"transactionless INFO request");
+ if (logger.isTraceEnabled())
+ logger.trace("Exception was:", ex);
+ return false;
+ }
+ catch (InvalidArgumentException ex)
+ {
+ //What else could we do apart from logging?
+ logger.warn("Failed to send OK for incoming INFO request", ex);
+ return false;
+ }
+ catch (SipException ex)
+ {
+ //What else could we do apart from logging?
+ logger.warn("Failed to send OK for incoming INFO request", ex);
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Fire event to interested listeners.
+ * @param tone to go into event.
+ * @param duration of the tone.
+ */
+ private void fireToneEvent(DTMFTone tone, long duration)
+ {
+ Collection<DTMFListener> listeners;
+ synchronized (this.dtmfListeners)
+ {
+ listeners = new ArrayList<DTMFListener>(this.dtmfListeners);
+ }
+
+ DTMFReceivedEvent evt = new DTMFReceivedEvent(pps, tone, duration);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Dispatching DTMFTone Listeners=" + listeners.size()
+ + " evt=" + evt);
+
+ try
+ {
+ for (DTMFListener listener : listeners)
+ {
+ listener.toneReceived(evt);
+ }
+ }
+ catch (Throwable e)
+ {
+ logger.error("Error delivering dtmf tone", e);
+ }
+ }
+
+ /**
+ * Registers the specified DTMFListener with this provider so that it could
+ * be notified when incoming DTMF tone is received.
+ * @param listener the listener to register with this provider.
+ *
+ */
+ public void addDTMFListener(DTMFListener listener)
+ {
+ synchronized (dtmfListeners)
+ {
+ if (!dtmfListeners.contains(listener))
+ {
+ dtmfListeners.add(listener);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified listener from the list of DTMF listeners.
+ * @param listener the listener to unregister.
+ */
+ public void removeDTMFListener(DTMFListener listener)
+ {
+ synchronized (dtmfListeners)
+ {
+ dtmfListeners.remove(listener);
+ }
+ }
}