Moves incoming SIP BYE processing to CallSipImpl

cusax-fix
Emil Ivov 17 years ago
parent 57d133288c
commit 5ed19cd93b

@ -203,7 +203,7 @@ public void peerDisplayNameChanged(CallPeerChangeEvent evt)
* Verifies whether the call peer has entered a state.
*
* @param evt The <tt>CallPeerChangeEvent</tt> instance containing
* the source event as well as its previous and its new status.
* the source event as well as its previous and its new status.
*/
public void peerStateChanged(CallPeerChangeEvent evt)
{
@ -226,10 +226,10 @@ else if ((newState == CallPeerState.CONNECTED
* Returns <tt>true</tt> if <tt>dialog</tt> matches the jain sip dialog
* established with one of the peers in this call.
*
* @param dialog the dialog whose corresponding peer we're looking
* for.
* @param dialog the dialog whose corresponding peer we're looking for.
*
* @return true if this call contains a call peer whose jain sip
* dialog is the same as the specified and false otherwise.
* dialog is the same as the specified and false otherwise.
*/
public boolean contains(Dialog dialog)
{
@ -240,10 +240,10 @@ public boolean contains(Dialog dialog)
* Returns the call peer whose associated jain sip dialog matches
* <tt>dialog</tt>.
*
* @param dialog the jain sip dialog whose corresponding peer we're
* looking for.
* @return the call peer whose jain sip dialog is the same as the
* specified or null if no such call peer was found.
* @param dialog the jain sip dialog whose corresponding peer we're looking
* for.
* @return the call peer whose jain sip dialog is the same as the specified
* or null if no such call peer was found.
*/
public CallPeerSipImpl findCallPeer(Dialog dialog)
{
@ -280,7 +280,7 @@ public CallPeerSipImpl findCallPeer(Dialog dialog)
* call.
*
* @param callSession the <tt>CallSession</tt> that the media service has
* created for this call.
* created for this call.
*/
public void setMediaCallSession(CallSession callSession)
{
@ -393,11 +393,9 @@ private void attachSdpOffer(Request invite, CallPeerSipImpl callPeer)
{
try
{
CallSession callSession =
SipActivator.getMediaService().createCallSession(
callPeer.getCall());
((CallSipImpl) callPeer.getCall())
.setMediaCallSession(callSession);
CallSession callSession = SipActivator.getMediaService()
.createCallSession(callPeer.getCall());
callPeer.getCall().setMediaCallSession(callSession);
callSession.setSessionCreatorCallback(callPeer);
@ -405,6 +403,7 @@ private void attachSdpOffer(Request invite, CallPeerSipImpl callPeer)
// that the media service can choose the most proper local
// address to advertise.
URI calleeURI = callPeer.getJainSipAddress().getURI();
if (calleeURI.isSipURI())
{
// content type should be application/sdp (not applications)
@ -1252,4 +1251,142 @@ public void processSessionProgress(ClientTransaction tran,
// change status
peer.setState(CallPeerState.CONNECTING_WITH_EARLY_MEDIA);
}
/**
* Sets the state of the specifies call peer as DISCONNECTED.
*
* @param serverTransaction the transaction that the cancel was received in.
* @param cancelRequest the Request that we've just received.
* @param callPeer the peer that sent the CANCEL request.
*/
public void processCancel(ServerTransaction serverTransaction,
Request cancelRequest,
CallPeerSipImpl callPeer)
{
// Cancels should be OK-ed and the initial transaction - terminated
// (report and fix by Ranga)
try
{
Response ok = messageFactory.createResponse(Response.OK,
cancelRequest);
serverTransaction.sendResponse(ok);
logger.debug("sent an ok response to a CANCEL request:\n" + ok);
}
catch (ParseException ex)
{
CallSipImpl.logAndFailCallPeer(
"Failed to create an OK Response to an CANCEL request.", ex,
callPeer);
return;
}
catch (Exception ex)
{
CallSipImpl.logAndFailCallPeer(
"Failed to send an OK Response to an CANCEL request.", ex,
callPeer);
return;
}
try
{
// stop the invite transaction as well
Transaction tran = callPeer.getFirstTransaction();
// should be server transaction and misplaced cancels should be
// filtered by the stack but it doesn't hurt checking anyway
if (!(tran instanceof ServerTransaction))
{
logger.error("Received a misplaced CANCEL request!");
return;
}
ServerTransaction inviteTran = (ServerTransaction) tran;
Request invite = callPeer.getFirstTransaction().getRequest();
Response requestTerminated = messageFactory
.createResponse(Response.REQUEST_TERMINATED, invite);
inviteTran.sendResponse(requestTerminated);
if (logger.isDebugEnabled())
logger.debug("sent request terminated response:\n"
+ requestTerminated);
}
catch (ParseException ex)
{
logger.error("Failed to create a REQUEST_TERMINATED Response to "
+ "an INVITE request.", ex);
}
catch (Exception ex)
{
logger.error("Failed to send an REQUEST_TERMINATED Response to "
+ "an INVITE request.", ex);
}
// change status
callPeer.setState(CallPeerState.DISCONNECTED);
}
/**
* Sets the state of the corresponding call peer to DISCONNECTED and
* sends an OK response.
*
* @param tran the ServerTransaction the the BYE request
* arrived in.
* @param byeRequest the BYE request to process
* @param callPeer the peer that sent the BYE request
*/
public void processBye(ServerTransaction tran,
Request byeRequest,
CallPeerSipImpl callPeer)
{
// Send OK
Response ok = null;
try
{
ok = messageFactory.createResponse(Response.OK, byeRequest);
}
catch (ParseException ex)
{
logger.error("Error while trying to send a response to a bye", ex);
// no need to let the user know about the error since it doesn't
// affect them
return;
}
try
{
tran.sendResponse(ok);
logger.debug("sent response " + ok);
}
catch (Exception ex)
{
// This is not really a problem according to the RFC
// so just dump to stdout should someone be interested
logger.error("Failed to send an OK response to BYE request,"
+ "exception was:\n", ex);
}
// change status
boolean dialogIsAlive;
try
{
dialogIsAlive = DialogUtils.processByeThenIsDialogAlive(tran.getDialog());
}
catch (SipException ex)
{
dialogIsAlive = false;
logger
.error(
"Failed to determine whether the dialog should stay alive.",
ex);
}
if (dialogIsAlive)
{
((CallSipImpl) callPeer.getCall()).getMediaCallSession()
.stopStreaming();
}
else
{
callPeer.setState(CallPeerState.DISCONNECTED);
}
}
}

@ -12,44 +12,43 @@
/**
* 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>
* Associates a specific subscription with the a given <tt>Dialog</tt>
* 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 dialog the <tt>Dialog</tt> 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
* <tt>dialog</tt> 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
* the given dialog; <tt>false</tt> if no changes were applied
*
* @throws SipException if the dialog is already terminated.
*/
public static boolean addSubscription(Dialog dialog, Object subscription)
throws SipException
{
synchronized (dialog)
{
DialogApplicationData applicationData =
DialogApplicationData appData =
(DialogApplicationData) SipApplicationData.getApplicationData(
dialog, SipApplicationData.KEY_SUBSCRIPTIONS);
if (applicationData == null)
if (appData == null)
{
applicationData = new DialogApplicationData();
appData = new DialogApplicationData();
SipApplicationData.setApplicationData(
dialog,
SipApplicationData.KEY_SUBSCRIPTIONS,
applicationData);
dialog, SipApplicationData.KEY_SUBSCRIPTIONS, appData);
}
if (applicationData.addSubscription(subscription))
if (appData.addSubscription(subscription))
{
try
{
@ -58,12 +57,11 @@ public static boolean addSubscription(Dialog dialog, Object subscription)
}
catch (SipException ex)
{
/*
* Since the subscription didn't quite register, undo the
* part of the registration which did succeed.
*/
applicationData.removeSubscription(subscription);
appData.removeSubscription(subscription);
throw ex;
}
}
@ -73,13 +71,14 @@ public static boolean addSubscription(Dialog dialog, Object subscription)
/**
* Determines whether a BYE request has already been processed in a specific
* <code>Dialog</code> and thus allows determining whether the dialog in
* <tt>Dialog</tt> and thus allows determining whether the dialog in
* question should be terminated when the last associated subscription is
* terminated.
*
* @param dialog the <code>Dialog</code> to be examined
*
* @param dialog the <tt>Dialog</tt> to be examined
*
* @return <tt>true</tt> if a BYE request has already been processed in the
* specified <code>dialog</code>; <tt>false</tt>, otherwise
* specified <tt>dialog</tt>; <tt>false</tt>, otherwise
*/
public static boolean isByeProcessed(Dialog dialog)
{
@ -94,17 +93,19 @@ public static boolean isByeProcessed(Dialog dialog)
}
/**
* Processes a BYE request in a specific <code>Dialog</code> for the
* Processes a BYE request in a specific <tt>Dialog</tt> 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
*
* @param dialog the <tt>Dialog</tt> in which a BYE request has arrived
*
* @return <tt>true</tt> if <tt>dialog</tt> should still be considered
* alive after processing the mentioned BYE request; <tt>false</tt> if
* <tt>dialog</tt> is to be expected to die after processing the request in
* question
*
* @throws SipException if the dialog is already terminated.
*/
public static boolean processByeThenIsDialogAlive(Dialog dialog)
throws SipException
@ -129,22 +130,22 @@ public static boolean processByeThenIsDialogAlive(Dialog dialog)
}
/**
* Dissociates a specific subscription with a given <code>Dialog</code> in
* Dissociates a specific subscription with a given <tt>Dialog</tt> 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 dialog the <tt>Dialog</tt> 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
* <tt>dialog</tt> 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
* dissociation; <tt>false</tt> if the dialog was terminated because of the
* dissociation
*/
public static boolean removeSubscriptionThenIsDialogAlive(Dialog dialog,
Object subscription)
@ -167,7 +168,7 @@ public static boolean removeSubscriptionThenIsDialogAlive(Dialog dialog,
}
/**
* Prevents the creation of <code>DialogUtils</code> instances.
* Prevents the creation of <tt>DialogUtils</tt> instances.
*/
private DialogUtils()
{
@ -178,7 +179,7 @@ private DialogUtils()
* 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
* subscriptions in a specific <tt>Dialog</tt> in order to make it
* possible to determine whether a BYE request should terminate the
* respective dialog.
* </p>
@ -188,7 +189,7 @@ 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
* processed in the owning <tt>Dialog</tt> and thus allows
* determining whether the dialog in question should be terminated when
* the last associated subscription is terminated.
*/
@ -196,21 +197,21 @@ private static class DialogApplicationData
/**
* The set of subscriptions not yet terminated in the owning
* <code>Dialog</code> i.e. keeping it alive even after a BYE request.
* <tt>Dialog</tt> 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
* <tt>Dialog</tt> 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>
* interest to this implementation to be associated with the
* owning <tt>Dialog</tt>
* @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
* modification of the list of associated subscriptions; <tt>false</tt>
* if no change to the mentioned list was applied
*/
public boolean addSubscription(Object subscription)
{
@ -223,12 +224,12 @@ public boolean addSubscription(Object subscription)
/**
* Determines whether a BYE request has already been processed in the
* owning <code>Dialog</code> and thus allows determining whether the
* owning <tt>Dialog</tt> 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
* the owning <tt>Dialog</tt>; <tt>false</tt>, otherwise
*/
public boolean isByeProcessed()
{
@ -237,11 +238,10 @@ public boolean isByeProcessed()
/**
* Determines the number of subscriptions associated with the owning
* <code>Dialog</code> i.e. keeping it alive even after a BYE request.
*
* <tt>Dialog</tt> 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
* <tt>Dialog</tt> i.e. keeping it alive even after a BYE request
*/
public int getSubscriptionCount()
{
@ -250,15 +250,15 @@ public int getSubscriptionCount()
/**
* Dissociates a specific subscription with the owning
* <code>Dialog</code> in order to no longer allow it to keep the dialog
* <tt>Dialog</tt> 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>
* interest to this implementation to be dissociated with the owning
* <tt>Dialog</tt>
* @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
* modification of the list of associated subscriptions; <tt>false</tt>
* if no change to the mentioned list was applied
*/
public boolean removeSubscription(Object subscription)
{
@ -267,13 +267,12 @@ public boolean removeSubscription(Object subscription)
/**
* Sets the indicator which determines whether a BYE request has already
* been processed in the owning <code>Dialog</code> and thus allows
* been processed in the owning <tt>Dialog</tt> 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
* processed in the owning <tt>Dialog</tt>; <tt>false</tt>, otherwise
*/
public void setByeProcessed(boolean byeIsProcessed)
{

@ -571,16 +571,16 @@ private void processReferAccepted(ClientTransaction clientTransaction,
* Updates the call state of the corresponding call peer.
*
* @param clientTransaction the transaction in which the response was
* received.
* received.
* @param response the trying response.
*/
private void processTrying(ClientTransaction clientTransaction,
Response response)
Response response)
{
Dialog dialog = clientTransaction.getDialog();
// find the call peer
CallPeerSipImpl callPeer =
activeCallsRepository.findCallPeer(dialog);
CallPeerSipImpl callPeer = activeCallsRepository.findCallPeer(dialog);
if (callPeer == null)
{
@ -592,7 +592,9 @@ private void processTrying(ClientTransaction clientTransaction,
CallPeerState callPeerState = callPeer.getState();
if (!CallPeerState.CONNECTED.equals(callPeerState)
&& !CallPeerState.isOnHold(callPeerState))
{
callPeer.setState(CallPeerState.CONNECTING);
}
}
/**
@ -601,7 +603,7 @@ private void processTrying(ClientTransaction clientTransaction,
* presentation and that we didn't have when establishing the call.
*
* @param clientTransaction the transaction in which the response was
* received.
* received.
* @param response the Trying response.
*/
private void processRinging(ClientTransaction clientTransaction,
@ -949,16 +951,15 @@ private void processInvite(SipProvider sourceProvider,
* sends an OK response.
*
* @param serverTransaction the ServerTransaction the the BYE request
* arrived in.
* arrived in.
* @param byeRequest the BYE request to process
*/
private void processBye(ServerTransaction serverTransaction,
Request byeRequest)
Request byeRequest)
{
// find the call
Dialog dialog = serverTransaction.getDialog();
CallPeerSipImpl callPeer =
activeCallsRepository.findCallPeer(dialog);
CallPeerSipImpl callPeer = activeCallsRepository.findCallPeer(dialog);
if (callPeer == null)
{
@ -966,72 +967,21 @@ private void processBye(ServerTransaction serverTransaction,
return;
}
// Send OK
Response ok = null;
try
{
ok = messageFactory.createResponse(Response.OK, byeRequest);
}
catch (ParseException ex)
{
logger.error("Error while trying to send a response to a bye", ex);
// no need to let the user know about the error since it doesn't
// affect them
return;
}
try
{
serverTransaction.sendResponse(ok);
logger.debug("sent response " + ok);
}
catch (Exception ex)
{
// This is not really a problem according to the RFC
// so just dump to stdout should someone be interested
logger.error("Failed to send an OK response to BYE request,"
+ "exception was:\n", ex);
}
// change status
boolean dialogIsAlive;
try
{
dialogIsAlive = DialogUtils.processByeThenIsDialogAlive(dialog);
}
catch (SipException ex)
{
dialogIsAlive = false;
logger
.error(
"Failed to determine whether the dialog should stay alive.",
ex);
}
if (dialogIsAlive)
{
((CallSipImpl) callPeer.getCall()).getMediaCallSession()
.stopStreaming();
}
else
{
callPeer.setState(CallPeerState.DISCONNECTED);
}
callPeer.getCall().processBye(serverTransaction, byeRequest, callPeer);
}
/**
* Updates the session description and sends the state of the corresponding
* call peer to CONNECTED.
*
* @param serverTransaction the transaction that the Ack was received in.
* @param ackRequest Request
* @param serverTransaction the transaction that the ACK was received in.
* @param ackRequest the ACK <tt>Request</tt> we need to process
*/
private void processAck(ServerTransaction serverTransaction,
Request ackRequest)
{
// find the call
CallPeerSipImpl peer
= activeCallsRepository.findCallPeer(
CallPeerSipImpl peer = activeCallsRepository.findCallPeer(
serverTransaction.getDialog());
if (peer == null)
@ -1044,8 +994,7 @@ private void processAck(ServerTransaction serverTransaction,
ContentLengthHeader contentLength = ackRequest.getContentLength();
if ((contentLength != null) && (contentLength.getContentLength() > 0))
{
peer.setSdpDescription(
new String(ackRequest.getRawContent()));
peer.setSdpDescription( new String(ackRequest.getRawContent()));
}
// change status
@ -1093,65 +1042,8 @@ private void processCancel(ServerTransaction serverTransaction,
return;
}
// Cancels should be OK-ed and the initial transaction - terminated
// (report and fix by Ranga)
try
{
Response ok
= messageFactory.createResponse(Response.OK, cancelRequest);
serverTransaction.sendResponse(ok);
logger.debug("sent an ok response to a CANCEL request:\n" + ok);
}
catch (ParseException ex)
{
CallSipImpl.logAndFailCallPeer(
"Failed to create an OK Response to an CANCEL request.", ex,
callPeer);
return;
}
catch (Exception ex)
{
CallSipImpl.logAndFailCallPeer(
"Failed to send an OK Response to an CANCEL request.", ex,
callPeer);
return;
}
try
{
// stop the invite transaction as well
Transaction tran = callPeer.getFirstTransaction();
// should be server transaction and misplaced cancels should be
// filtered by the stack but it doesn't hurt checking anyway
if (!(tran instanceof ServerTransaction))
{
logger.error("Received a misplaced CANCEL request!");
return;
}
ServerTransaction inviteTran = (ServerTransaction) tran;
Request invite = callPeer.getFirstTransaction().getRequest();
Response requestTerminated = protocolProvider.getMessageFactory()
.createResponse(Response.REQUEST_TERMINATED, invite);
inviteTran.sendResponse(requestTerminated);
if (logger.isDebugEnabled())
logger.debug("sent request terminated response:\n"
+ requestTerminated);
}
catch (ParseException ex)
{
logger.error("Failed to create a REQUEST_TERMINATED Response to "
+ "an INVITE request.", ex);
}
catch (Exception ex)
{
logger.error("Failed to send an REQUEST_TERMINATED Response to "
+ "an INVITE request.", ex);
}
// change status
callPeer.setState(CallPeerState.DISCONNECTED);
callPeer.getCall().processCancel(serverTransaction,
cancelRequest, callPeer);
}
/**

@ -430,7 +430,7 @@ private Message attachContactHeader(Message message)
* synchronized: needed for access to 'rand', else risk to generate same tag
* twice
*/
private synchronized String generateLocalTag()
public static synchronized String generateLocalTag()
{
if(localTagGenerator == null)
localTagGenerator = new Random();

Loading…
Cancel
Save