mirror of https://github.com/sipwise/jitsi.git
Transfers a Call upon receiving a REFER request. The new Call being referred to/created as part of the transfer is still not displayed in the UI.
parent
c1bf31bad2
commit
bbfcbea0ec
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* SIP Communicator, 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 java.util.*;
|
||||
import javax.sip.*;
|
||||
|
||||
/**
|
||||
* Implements utility methods to aid the manipulation of {@link Dialog}
|
||||
* instances and extend the mentioned type with additional functionality.
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public final class DialogUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* Associates a specific subscription with the a given <code>Dialog</code>
|
||||
* in order to allow it to keep the dialog in question alive even after a
|
||||
* BYE request.
|
||||
*
|
||||
* @param dialog the <code>Dialog</code> to associate the subscription with
|
||||
* and to be kept alive after a BYE request because of the
|
||||
* subscription
|
||||
* @param subscription the subscription to be associated with
|
||||
* <code>dialog</code> and keep it alive after a BYE request
|
||||
* @return <tt>true</tt> if the specified subscription was associated with
|
||||
* the given dialog; <tt>false</tt> if no changes were applied
|
||||
* @throws SipException
|
||||
*/
|
||||
public static boolean addSubscription(Dialog dialog, Object subscription)
|
||||
throws SipException
|
||||
{
|
||||
synchronized (dialog)
|
||||
{
|
||||
DialogApplicationData applicationData =
|
||||
(DialogApplicationData) dialog.getApplicationData();
|
||||
if (applicationData == null)
|
||||
{
|
||||
applicationData = new DialogApplicationData();
|
||||
dialog.setApplicationData(applicationData);
|
||||
}
|
||||
|
||||
if (applicationData.addSubscription(subscription))
|
||||
{
|
||||
try
|
||||
{
|
||||
dialog.terminateOnBye(false);
|
||||
return true;
|
||||
}
|
||||
catch (SipException ex)
|
||||
{
|
||||
|
||||
/*
|
||||
* Since the subscription didn't quite register, undo the
|
||||
* part of the registration which did succeed.
|
||||
*/
|
||||
applicationData.removeSubscription(subscription);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a BYE request in a specific <code>Dialog</code> for the
|
||||
* purposes of subscription associations and returns an indicator which
|
||||
* determines whether the specified dialog should still be considered alive
|
||||
* after the processing of the BYE request.
|
||||
*
|
||||
* @param dialog the <code>Dialog</code> in which a BYE request has arrived
|
||||
* @return <tt>true</tt> if <code>dialog</code> should still be considered
|
||||
* alive after processing the mentioned BYE request; <tt>false</tt>
|
||||
* if <code>dialog</code> is to be expected to die after processing
|
||||
* the request in question
|
||||
* @throws SipException
|
||||
*/
|
||||
public static boolean processByeThenIsDialogAlive(Dialog dialog)
|
||||
throws SipException
|
||||
{
|
||||
synchronized (dialog)
|
||||
{
|
||||
DialogApplicationData applicationData =
|
||||
(DialogApplicationData) dialog.getApplicationData();
|
||||
if (applicationData != null)
|
||||
{
|
||||
applicationData.setByeProcessed(true);
|
||||
|
||||
if (applicationData.getSubscriptionCount() > 0)
|
||||
{
|
||||
dialog.terminateOnBye(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociates a specific subscription with a given <code>Dialog</code> in
|
||||
* order to no longer allow it to keep the dialog in question alive even
|
||||
* after a BYE request, deletes the dialog if there are no other
|
||||
* subscriptions associated with it and a BYE request has already been
|
||||
* received and returns an indicator which determines whether the specified
|
||||
* dialog is still alive after the dissociation of the given subscription.
|
||||
*
|
||||
* @param dialog the <code>Dialog</code> to dissociate the subscription with
|
||||
* and to no longer be kept alive after a BYE request because of
|
||||
* the subscription
|
||||
* @param subscription the subscription to be dissociated with
|
||||
* <code>dialog</code> and to no longer be kept alive after a BYE
|
||||
* request because of the subscription
|
||||
* @return <tt>true</tt> if the dialog is still alive after the
|
||||
* dissociation; <tt>false</tt> if the dialog was terminated because
|
||||
* of the dissociation
|
||||
*/
|
||||
public static boolean removeSubscriptionThenIsDialogAlive(Dialog dialog,
|
||||
Object subscription)
|
||||
{
|
||||
synchronized (dialog)
|
||||
{
|
||||
DialogApplicationData applicationData =
|
||||
(DialogApplicationData) dialog.getApplicationData();
|
||||
if ((applicationData != null)
|
||||
&& applicationData.removeSubscription(subscription)
|
||||
&& (applicationData.getSubscriptionCount() <= 0)
|
||||
&& applicationData.isByeProcessed())
|
||||
{
|
||||
dialog.delete();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the creation of <code>DialogUtils</code> instances.
|
||||
*/
|
||||
private DialogUtils()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the application-specific data which the SIP protocol provider
|
||||
* associates with {@link #Dialog} instances.
|
||||
* <p>
|
||||
* The implementation at the time of this writing allows tracking
|
||||
* subscriptions in a specific <code>Dialog</code> in order to make it
|
||||
* possible to determine whether a BYE request should terminate the
|
||||
* respective dialog.
|
||||
* </p>
|
||||
*/
|
||||
private static class DialogApplicationData
|
||||
{
|
||||
|
||||
/**
|
||||
* The indicator which determines whether a BYE request has already been
|
||||
* processed in the owning <code>Dialog</code> and thus allows
|
||||
* determining whether the dialog in question should be terminated when
|
||||
* the last associated subscription is terminated.
|
||||
*/
|
||||
private boolean byeIsProcessed;
|
||||
|
||||
/**
|
||||
* The set of subscriptions not yet terminated in the owning
|
||||
* <code>Dialog</code> i.e. keeping it alive even after a BYE request.
|
||||
*/
|
||||
private final List<Object> subscriptions = new ArrayList<Object>();
|
||||
|
||||
/**
|
||||
* Associates a specific subscription with the owning
|
||||
* <code>Dialog</code> in order to allow it to keep the dialog in
|
||||
* question alive even after a BYE request.
|
||||
*
|
||||
* @param subscription the subscription with no specific type of
|
||||
* interest to this implementation to be associated with the
|
||||
* owning <code>Dialog</code>
|
||||
* @return <tt>true</tt> if the specified subscription caused a
|
||||
* modification of the list of associated subscriptions;
|
||||
* <tt>false</tt> if no change to the mentioned list was applied
|
||||
*/
|
||||
public boolean addSubscription(Object subscription)
|
||||
{
|
||||
if (!subscriptions.contains(subscription))
|
||||
{
|
||||
return subscriptions.add(subscription);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a BYE request has already been processed in the
|
||||
* owning <code>Dialog</code> and thus allows determining whether the
|
||||
* dialog in question should be terminated when the last associated
|
||||
* subscription is terminated.
|
||||
*
|
||||
* @return <tt>true</tt> if a BYE request has already been processed in
|
||||
* the owning <code>Dialog</code>; <tt>false</tt>, otherwise
|
||||
*/
|
||||
public boolean isByeProcessed()
|
||||
{
|
||||
return byeIsProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of subscriptions associated with the owning
|
||||
* <code>Dialog</code> i.e. keeping it alive even after a BYE request.
|
||||
*
|
||||
* @return the number of subscriptions associated with the owning
|
||||
* <code>Dialog</code> i.e. keeping it alive even after a BYE
|
||||
* request
|
||||
*/
|
||||
public int getSubscriptionCount()
|
||||
{
|
||||
return subscriptions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociates a specific subscription with the owning
|
||||
* <code>Dialog</code> in order to no longer allow it to keep the dialog
|
||||
* in question alive even after a BYE request.
|
||||
*
|
||||
* @param subscription the subscription with no specific type of
|
||||
* interest to this implementation to be dissociated with the
|
||||
* owning <code>Dialog</code>
|
||||
* @return <tt>true</tt> if the specified subscription caused a
|
||||
* modification of the list of associated subscriptions;
|
||||
* <tt>false</tt> if no change to the mentioned list was applied
|
||||
*/
|
||||
public boolean removeSubscription(Object subscription)
|
||||
{
|
||||
return subscriptions.remove(subscription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indicator which determines whether a BYE request has already
|
||||
* been processed in the owning <code>Dialog</code> and thus allows
|
||||
* determining whether the dialog in question should be terminated when
|
||||
* the last associated subscription is terminated.
|
||||
*
|
||||
* @param byeIsProcessed <tt>true</tt> if a BYE request has already been
|
||||
* processed in the owning <code>Dialog</code>;
|
||||
* <tt>false</tt>, otherwise
|
||||
*/
|
||||
public void setByeProcessed(boolean byeIsProcessed)
|
||||
{
|
||||
this.byeIsProcessed = byeIsProcessed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.service.protocol.event;
|
||||
|
||||
/**
|
||||
* An abstract adapter class for receiving call-state (change) events. This
|
||||
* class exists only as a convenience for creating listener objects.
|
||||
* <p>
|
||||
* Extend this class to create a <code>CallChangeEvent</code> listener and
|
||||
* override the methods for the events of interest. (If you implement the
|
||||
* <code>CallChangeListener</code> interface, you have to define all of the
|
||||
* methods in it. This abstract class defines null methods for them all, so you
|
||||
* only have to define methods for events you care about.)
|
||||
* </p>
|
||||
*
|
||||
* @see CallChangeEvent
|
||||
* @see CallChangeListener
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public abstract class CallChangeAdapter
|
||||
implements CallChangeListener
|
||||
{
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seenet.java.sip.communicator.service.protocol.event.CallChangeListener#
|
||||
* callParticipantAdded
|
||||
* (net.java.sip.communicator.service.protocol.event.CallParticipantEvent)
|
||||
*/
|
||||
public void callParticipantAdded(CallParticipantEvent evt)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seenet.java.sip.communicator.service.protocol.event.CallChangeListener#
|
||||
* callParticipantRemoved
|
||||
* (net.java.sip.communicator.service.protocol.event.CallParticipantEvent)
|
||||
*/
|
||||
public void callParticipantRemoved(CallParticipantEvent evt)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seenet.java.sip.communicator.service.protocol.event.CallChangeListener#
|
||||
* callStateChanged
|
||||
* (net.java.sip.communicator.service.protocol.event.CallChangeEvent)
|
||||
*/
|
||||
public void callStateChanged(CallChangeEvent evt)
|
||||
{
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue