aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2009-04-27 17:37:20 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2009-04-27 17:37:20 +0000
commit27194e062ffb11162ac7d7e99f61c79a5e98251f (patch)
tree60d14d0ac38720f93feb8929c91f32addb4409a2 /src/net/java/sip
parent39779d7707b2a721ea3dc134b231c616897a358a (diff)
downloadjitsi-27194e062ffb11162ac7d7e99f61c79a5e98251f.zip
jitsi-27194e062ffb11162ac7d7e99f61c79a5e98251f.tar.gz
jitsi-27194e062ffb11162ac7d7e99f61c79a5e98251f.tar.bz2
Fixes reINVITE-related functionality so that SC can join a 3-way auto-conference (SC doesn't really see that it's a conference) created by X-Lite.
Diffstat (limited to 'src/net/java/sip')
-rw-r--r--src/net/java/sip/communicator/impl/media/CallSessionImpl.java408
-rw-r--r--src/net/java/sip/communicator/impl/media/MediaControl.java4
-rwxr-xr-xsrc/net/java/sip/communicator/impl/media/transform/TransformConnector.java18
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java114
-rw-r--r--src/net/java/sip/communicator/service/media/CallSession.java10
5 files changed, 336 insertions, 218 deletions
diff --git a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
index a7d9bc2..c3a0570 100644
--- a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
+++ b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
@@ -73,14 +73,14 @@ import gnu.java.zrtp.*;
*/
public class CallSessionImpl
extends PropertyChangeNotifier
- implements CallSession
- , CallParticipantListener
- , CallChangeListener
- , ReceiveStreamListener
- , SendStreamListener
- , SessionListener
- , ControllerListener
-// , SecureEventListener
+ implements CallSession
+ , CallParticipantListener
+ , CallChangeListener
+ , ReceiveStreamListener
+ , SendStreamListener
+ , SessionListener
+ , ControllerListener
+// , SecureEventListener
{
private static final Logger logger
= Logger.getLogger(CallSessionImpl.class);
@@ -462,32 +462,71 @@ public class CallSessionImpl
applyOnHold();
}
+ /* Implements CallSession#startStreamingAndProcessingMedia(). */
+ public void startStreamingAndProcessingMedia()
+ throws MediaException
+ {
+ startStreaming();
+ mediaServCallback.getMediaControl(getCall()).startProcessingMedia(this);
+ }
+
/**
* Stops and closes all streams that have been initialized for local
- * RTP managers.
+ * RTP managers and disposes of the local RTP managers.
*/
public boolean stopStreaming()
{
+ return stopStreaming(true);
+ }
+
+ /**
+ * Stops and closes all streams that have been initialized for local
+ * RTP managers and, optionally, disposes of the local RTP managers.
+ *
+ * @param dispose <tt>true</tt> to dispose of the local RTP managers once
+ * their streams have been stopped and closed; <tt>false</tt> to
+ * only stop and close the initialized streams but not dispose of
+ * the local RTP managers
+ * @return <tt>true</tt> if at least one stream has been closed and stopped;
+ * otherwise, <tt>false</tt>
+ */
+ private boolean stopStreaming(boolean dispose)
+ {
boolean stoppedStreaming = false;
RTPManager audioRtpManager = getAudioRtpManager();
if (audioRtpManager != null)
{
- stoppedStreaming = stopStreaming(audioRtpManager);
- this.audioRtpManager = null;
+ stoppedStreaming = stopStreaming(audioRtpManager, dispose);
+ if (dispose)
+ {
+ transConnectors.remove(this.audioRtpManager); // clean up
+ this.audioRtpManager = null;
+ }
}
RTPManager videoRtpManager = getVideoRtpManager();
if (videoRtpManager != null)
{
stoppedStreaming =
- stopStreaming(videoRtpManager) || stoppedStreaming;
- this.videoRtpManager = null;
+ stopStreaming(videoRtpManager, dispose) || stoppedStreaming;
+ if (dispose)
+ {
+ transConnectors.remove(this.videoRtpManager); // clean up
+ this.videoRtpManager = null;
+ }
}
lastIntendedDestination = null;
return stoppedStreaming;
}
+ /**
+ * Stops and closes the <code>SendStream</code>s initialized for the local
+ * RTP managers.
+ *
+ * @return <tt>true</tt> if at least one stream has been closed and stopped;
+ * otherwise, <tt>false</tt>
+ */
private boolean stopSendStreaming()
{
boolean stoppedAtLeastOneStream = false;
@@ -505,9 +544,18 @@ public class CallSessionImpl
return stoppedAtLeastOneStream;
}
+ /**
+ * Stops and closes the <code>SendStream</code>s initialized for a specific
+ * <code>RTPManager</code>.
+ *
+ * @param rtpManager the <code>RTPManager</code> whose
+ * <code>SendStream</code>s are to be stopped and closed
+ * @return <tt>true</tt> if at least one stream has been closed and stopped;
+ * otherwise, <tt>false</tt>
+ */
private boolean stopSendStreaming(RTPManager rtpManager)
{
- List<SendStream> sendStreams = rtpManager.getSendStreams();
+ Iterable<SendStream> sendStreams = rtpManager.getSendStreams();
boolean stoppedAtLeastOneStream = false;
for (SendStream stream : sendStreams)
@@ -535,7 +583,7 @@ public class CallSessionImpl
* the streaming wasn't already stopped before this request;
* <tt>false</tt>, otherwise
*/
- private boolean stopStreaming(RTPManager rtpManager)
+ private boolean stopStreaming(RTPManager rtpManager, boolean dispose)
{
boolean stoppedAtLeastOneStream = stopSendStreaming(rtpManager);
@@ -556,7 +604,14 @@ public class CallSessionImpl
{
try
{
- stream.getDataSource().stop();
+ DataSource streamDataSource = stream.getDataSource();
+
+ /*
+ * For an unknown reason, the stream DataSource can be null at
+ * the end of the Call after re-INVITEs have been handled.
+ */
+ if (streamDataSource != null)
+ streamDataSource.stop();
}
catch (IOException ex)
{
@@ -575,7 +630,7 @@ public class CallSessionImpl
if (transConnector != null)
{
- if (usingZRTP)
+ if (dispose && usingZRTP)
{
ZRTPTransformEngine engine
= (ZRTPTransformEngine) transConnector.getEngine();
@@ -593,11 +648,14 @@ public class CallSessionImpl
printFlowStatistics(rtpManager);
- //stop listening
- rtpManager.removeReceiveStreamListener(this);
- rtpManager.removeSendStreamListener(this);
- rtpManager.removeSessionListener(this);
- rtpManager.dispose();
+ if (dispose)
+ {
+ //stop listening
+ rtpManager.removeReceiveStreamListener(this);
+ rtpManager.removeSendStreamListener(this);
+ rtpManager.removeSessionListener(this);
+ rtpManager.dispose();
+ }
return stoppedAtLeastOneStream;
}
@@ -728,13 +786,40 @@ public class CallSessionImpl
* callee to be put on hold or answer an offer from the remote
* callee to be put on hold; <tt>false</tt> to work in the
* context of a put-off-hold offer
- * @return an SDP description <tt>String</tt> which offers the remote
+ * @return a SDP description <tt>String</tt> which offers the remote
* callee to be put her on/off hold or answers an offer from the
* remote callee to be put on/off hold
* @throws MediaException
*/
public String createSdpDescriptionForHold(String participantSdpDescription,
- boolean on) throws MediaException
+ boolean on)
+ throws MediaException
+ {
+ return
+ createSessionDescriptionForHold(participantSdpDescription, on)
+ .toString();
+ }
+
+ /**
+ * The method is meant for use by protocol service implementations when
+ * willing to send an in-dialog invitation to a remote callee to put her
+ * on/off hold or to send an answer to an offer to be put on/off hold.
+ *
+ * @param participantSdpDescription the last SDP description of the remote
+ * callee
+ * @param on <tt>true</tt> if the SDP description should offer the remote
+ * callee to be put on hold or answer an offer from the remote
+ * callee to be put on hold; <tt>false</tt> to work in the
+ * context of a put-off-hold offer
+ * @return a <code>SessionDescription</code> which offers the remote
+ * callee to be put her on/off hold or answers an offer from the
+ * remote callee to be put on/off hold
+ * @throws MediaException
+ */
+ private SessionDescription createSessionDescriptionForHold(
+ String participantSdpDescription,
+ boolean on)
+ throws MediaException
{
SessionDescription participantDescription = null;
try
@@ -793,7 +878,7 @@ public class CallSessionImpl
MediaException.INTERNAL_ERROR, ex);
}
- return sdpOffer.toString();
+ return sdpOffer;
}
/**
@@ -1066,33 +1151,81 @@ public class CallSessionImpl
* String.
*/
public void processSdpAnswer(CallParticipant responder,
- String sdpAnswerStr)
+ String sdpAnswerStr)
+ throws MediaException, ParseException
+ {
+ processSdpStr(responder, sdpAnswerStr, true);
+ }
+
+ private String processSdpStr(CallParticipant participant,
+ String sdpStr,
+ boolean answer)
throws MediaException, ParseException
{
- logger.trace("Parsing sdp answer: " + sdpAnswerStr);
+ String answerStr = answer ? "answer" : "offer";
+
+ logger.trace("Parsing SDP " + answerStr + ": " + sdpStr);
+
//first parse the answer
- SessionDescription sdpAnswer = null;
+ SessionDescription sdp;
try
{
- sdpAnswer = mediaServCallback.getSdpFactory()
- .createSessionDescription(sdpAnswerStr);
+ sdp = mediaServCallback.getSdpFactory()
+ .createSessionDescription(sdpStr);
}
catch (SdpParseException ex)
{
- throw new ParseException("Failed to parse SDPOffer: "
- + ex.getMessage()
- , ex.getCharOffset());
+ throw new ParseException("Failed to parse SDP "
+ + answerStr
+ + ": "
+ + ex.getMessage(),
+ ex.getCharOffset());
+ }
+ //it appears that in some cases parsing could also fail with
+ //other exceptions such as a NullPointerException for example so make
+ //sure we get those too.
+ catch (Exception ex)
+ {
+ throw new ParseException("Failed to parse SDP "
+ + answerStr
+ + ": "
+ + ex.getMessage(),
+ 0);
+ }
+
+ SessionDescription sdpAnswer;
+
+ if (answer)
+ {
+ /*
+ * extract URI (rfc4566 says that if present it should be before the
+ * media description so let's start with it)
+ */
+ setCallURL(sdp.getURI());
+
+ sdpAnswer = sdp;
}
+ else
+ {
+ //create an sdp answer.
+ CallParticipantState participantState = participant.getState();
- //extract URI (rfc4566 says that if present it should be before the
- //media description so let's start with it)
- setCallURL(sdpAnswer.getURI());
+ if (CallParticipantState.CONNECTED.equals(participantState)
+ || CallParticipantState.isOnHold(participantState))
+ sdpAnswer =
+ createSessionDescriptionForHold(
+ sdpStr,
+ (getSdpOfferMediaFlags(sdpStr)
+ & CallSession.ON_HOLD_REMOTELY) != 0);
+ else
+ sdpAnswer = createSessionDescription(sdp, null);
+ }
//extract media descriptions
- Vector<MediaDescription> mediaDescriptions = null;
+ Vector<MediaDescription> mediaDescriptions;
try
{
- mediaDescriptions = sdpAnswer.getMediaDescriptions(true);
+ mediaDescriptions = sdp.getMediaDescriptions(true);
}
catch (SdpException exc)
{
@@ -1103,20 +1236,22 @@ public class CallSessionImpl
}
//add the RTP targets
- this.initStreamTargets(sdpAnswer.getConnection(), mediaDescriptions);
+ initStreamTargets(sdp.getConnection(), mediaDescriptions);
//create and init the streams (don't start streaming just yet but wait
//for the call to enter the connected state).
createSendStreams(mediaDescriptions);
- CallParticipantState responderState = responder.getState();
- if (CallParticipantState.CONNECTED.equals(responderState)
- || CallParticipantState.isOnHold(responderState))
+ if (answer)
{
- mediaServCallback.getMediaControl(getCall())
- .startProcessingMedia(this);
- startStreaming();
+ CallParticipantState participantState = participant.getState();
+
+ if (CallParticipantState.CONNECTED.equals(participantState)
+ || CallParticipantState.isOnHold(participantState))
+ startStreamingAndProcessingMedia();
}
+
+ return sdpAnswer.toString();
}
/**
@@ -1140,55 +1275,7 @@ public class CallSessionImpl
public String processSdpOffer(CallParticipant offerer, String sdpOfferStr)
throws MediaException, ParseException
{
- //first parse the offer
- SessionDescription sdpOffer = null;
- try
- {
- sdpOffer = mediaServCallback.getSdpFactory()
- .createSessionDescription(sdpOfferStr);
- }
- catch (SdpParseException ex)
- {
- throw new ParseException("Failed to parse SDPOffer: "
- + ex.getMessage()
- , ex.getCharOffset());
- }
- //it appears that in some cases parsing could also fail with
- //other exceptions such as a NullPointerException for example so make
- //sure we get those too.
- catch(Exception ex)
- {
- throw new ParseException("Failed to parse SDPOffer: "
- + ex.getMessage()
- , 0);
- }
-
- //create an sdp answer.
- SessionDescription sdpAnswer = createSessionDescription(sdpOffer, null);
-
- //extract the remote addresses.
- Vector<MediaDescription> mediaDescriptions = null;
- try
- {
- mediaDescriptions = sdpOffer.getMediaDescriptions(true);
- }
- catch (SdpException exc)
- {
- logger.error("failed to extract media descriptions", exc);
- throw new MediaException("failed to extract media descriptions"
- , MediaException.INTERNAL_ERROR
- , exc);
- }
-
-
- //add the RTP targets
- this.initStreamTargets(sdpOffer.getConnection(), mediaDescriptions);
-
- //create and init the streams (don't start streaming just yet but wait
- //for the call to enter the connected state).
- createSendStreams(mediaDescriptions);
-
- return sdpAnswer.toString();
+ return processSdpStr(offerer, sdpOfferStr, false);
}
/**
@@ -1448,8 +1535,6 @@ public class CallSessionImpl
//we don't yet implement ice so just try to choose a local address
//that corresponds to the address provided by the offer or as an
//intended destination.
- NetworkAddressManagerService netAddressManager
- = MediaActivator.getNetworkAddressManagerService();
if(offer != null)
{
@@ -1511,34 +1596,23 @@ public class CallSessionImpl
*/
boolean allocateMediaPorts = false;
- /*
- * TODO Should the reinitializing for the purposes of re-INVITE
- * start the streaming before ACK?
- */
- boolean startStreaming = false;
if ((audioSessionAddress == null) || (videoSessionAddress == null))
{
allocateMediaPorts = true;
}
- else
- {
- if ((intendedDestination != null)
+ else if ((intendedDestination != null)
&& !intendedDestination.equals(lastIntendedDestination))
- {
- startStreaming = stopStreaming();
- audioRtpManager = RTPManager.newInstance();
- videoRtpManager = RTPManager.newInstance();
+ {
+ stopStreaming(false);
+ //audioRtpManager = RTPManager.newInstance();
+ //videoRtpManager = RTPManager.newInstance();
- allocateMediaPorts = true;
- }
+ //allocateMediaPorts = true;
}
if (allocateMediaPorts)
{
allocateMediaPorts(intendedDestination);
lastIntendedDestination = intendedDestination;
-
- if (startStreaming)
- startStreaming();
}
InetAddress publicIpAddress = audioPublicAddress.getAddress();
@@ -1578,9 +1652,10 @@ public class CallSessionImpl
sessDescr.setTimeDescriptions(timeDescs);
//media descriptions.
- Vector<MediaDescription> offeredMediaDescriptions = null;
- if(offer != null)
- offeredMediaDescriptions = offer.getMediaDescriptions(false);
+ Vector<MediaDescription> offeredMediaDescriptions
+ = (offer == null)
+ ? null
+ : offer.getMediaDescriptions(false);
logger.debug("Will create media descs with: audio public address="
+ audioPublicAddress
@@ -1595,9 +1670,7 @@ public class CallSessionImpl
sessDescr.setMediaDescriptions(mediaDescs);
if (logger.isTraceEnabled())
- {
logger.trace("Generated SDP - " + sessDescr.toString());
- }
return sessDescr;
}
@@ -1605,7 +1678,7 @@ public class CallSessionImpl
{
throw new MediaException(
"An SDP exception occurred while generating local "
- + "sdp description"
+ + "SDP description"
, MediaException.INTERNAL_ERROR
, exc);
}
@@ -2086,58 +2159,60 @@ public class CallSessionImpl
private void allocateMediaPorts(InetAddress intendedDestination)
throws MediaException
{
- NetworkAddressManagerService netAddressManager = MediaActivator
- .getNetworkAddressManagerService();
-
// Get our local address for the intended destination.
// Use this address to bind our local RTP sockets
InetAddress inAddrLocal
- = netAddressManager.getLocalHost(intendedDestination);
+ = MediaActivator.getNetworkAddressManagerService()
+ .getLocalHost(intendedDestination);
//check the number of times that we'd have to retry binding to local
//ports before giving up.
- String bindRetriesStr
- = MediaActivator.getConfigurationService().getString(
- MediaService.BIND_RETRIES_PROPERTY_NAME);
+ int bindRetries
+ = MediaActivator.getConfigurationService()
+ .getInt(
+ MediaService.BIND_RETRIES_PROPERTY_NAME,
+ MediaService.BIND_RETRIES_DEFAULT_VALUE);
- int bindRetries = MediaService.BIND_RETRIES_DEFAULT_VALUE;
- try
- {
- if(bindRetriesStr != null && bindRetriesStr.length() > 0)
- bindRetries = Integer.parseInt(bindRetriesStr);
- }
- catch (NumberFormatException ex)
+ //initialize audio rtp manager.
+
+ /*
+ * XXX If the ports have to be relocated, keep in mind that when X-Lite
+ * sends a re-INVITE and our port change is reported as part of the OK
+ * response to the re-INVITE, X-Lite continues to stream to the old
+ * ports and not to the new ones.
+ */
+ if (audioSessionAddress == null)
{
- logger.warn(bindRetriesStr
- + " is not a valid value for number of bind retries."
- , ex);
- }
+ audioSessionAddress
+ = new SessionAddress(inAddrLocal, minPortNumber);
+ audioPublicAddress
+ = allocatePort(
+ intendedDestination, audioSessionAddress, bindRetries);
- //initialize audio rtp manager.
- audioSessionAddress = new SessionAddress(inAddrLocal, minPortNumber);
- audioPublicAddress = allocatePort(intendedDestination,
- audioSessionAddress,
- bindRetries);
+ //augment min port number so that no one else tries to bind here.
+ minPortNumber = audioSessionAddress.getDataPort() + 2;
+ }
if (logger.isDebugEnabled()) {
logger.debug("AudioSessionAddress=" + audioSessionAddress);
logger.debug("AudioPublicAddress=" + audioPublicAddress);
}
- //augment min port number so that no one else tries to bind here.
- minPortNumber = audioSessionAddress.getDataPort() + 2;
-
//initialize video rtp manager.
- videoSessionAddress = new SessionAddress(inAddrLocal, minPortNumber);
- videoPublicAddress = allocatePort(intendedDestination,
- videoSessionAddress,
- bindRetries);
+ if (videoSessionAddress == null)
+ {
+ videoSessionAddress
+ = new SessionAddress(inAddrLocal, minPortNumber);
+ videoPublicAddress
+ = allocatePort(
+ intendedDestination, videoSessionAddress, bindRetries);
- //augment min port number so that no one else tries to bind here.
- minPortNumber = videoSessionAddress.getDataPort() + 2;
+ //augment min port number so that no one else tries to bind here.
+ minPortNumber = videoSessionAddress.getDataPort() + 2;
+ }
//if we have reached the max port number - reinit.
- if(minPortNumber > maxPortNumber -2)
+ if (minPortNumber > maxPortNumber - 2)
initializePortNumbers();
//now init the rtp managers and make them bind
@@ -2446,9 +2521,7 @@ public class CallSessionImpl
try
{
logger.debug("call connected. starting streaming");
- startStreaming();
- mediaServCallback.getMediaControl(getCall())
- .startProcessingMedia(this);
+ startStreamingAndProcessingMedia();
}
catch (MediaException ex)
{
@@ -2591,27 +2664,26 @@ public class CallSessionImpl
*/
public synchronized void update(SessionEvent event)
{
- if (event instanceof NewParticipantEvent)
+ if (logger.isDebugEnabled())
{
- Participant participant
- = ( (NewParticipantEvent) event).getParticipant();
- if (logger.isDebugEnabled())
+ if (event instanceof NewParticipantEvent)
{
+ Participant participant
+ = ((NewParticipantEvent) event).getParticipant();
+
logger.debug("A new participant had just joined: "
- + participant.getCNAME());
+ + participant.getCNAME());
}
- }
- else
- {
- if (logger.isDebugEnabled())
+ else
{
- logger.debug(
- "Received the following JMF Session event - "
- + event.getClass().getName() + "=" + event);
+ logger.debug("Received the following JMF Session event - "
+ + event.getClass().getName()
+ + "="
+ + event);
}
}
-
}
+
/**
* Method called back in the RTPSessionListener to notify
* listener of all SendStream Events.
diff --git a/src/net/java/sip/communicator/impl/media/MediaControl.java b/src/net/java/sip/communicator/impl/media/MediaControl.java
index fc1fd17..a7bd547 100644
--- a/src/net/java/sip/communicator/impl/media/MediaControl.java
+++ b/src/net/java/sip/communicator/impl/media/MediaControl.java
@@ -655,8 +655,8 @@ public class MediaControl
logger.debug(
"sourceProcessor is in state "
+ sourceProcessor.getState()
- + "which is > Processor.Configured"
- + "and then TrackControl.setFormat(Format) may not work.");
+ + " which is > Processor.Configured"
+ + " and then TrackControl.setFormat(Format) may not work.");
boolean atLeastOneTrack = false;
// Program the tracks.
for (int i = 0; i < tracks.length; i++)
diff --git a/src/net/java/sip/communicator/impl/media/transform/TransformConnector.java b/src/net/java/sip/communicator/impl/media/transform/TransformConnector.java
index 6344ec2..8dcf15c 100755
--- a/src/net/java/sip/communicator/impl/media/transform/TransformConnector.java
+++ b/src/net/java/sip/communicator/impl/media/transform/TransformConnector.java
@@ -12,6 +12,8 @@ import java.net.*;
import javax.media.protocol.*;
import javax.media.rtp.*;
+import net.java.sip.communicator.util.*;
+
/**
* TransformConnector implements the RTPConnector interface. RTPConnector
* is originally designed for programmers to abstract the underlying transport
@@ -37,6 +39,9 @@ import javax.media.rtp.*;
public class TransformConnector
implements RTPConnector
{
+ private static final Logger logger
+ = Logger.getLogger(TransformConnector.class);
+
/**
* The customized TransformEngine object, which contains the concrete
* transform logic.
@@ -102,9 +107,18 @@ public class TransformConnector
this.localAddr.getControlPort(),
this.localAddr.getControlAddress());
}
- catch (SocketException e)
+ catch (SocketException se)
{
- throw new InvalidSessionAddressException();
+ /*
+ * TODO Could anyone please provide a meaningful message for the
+ * Logger here because I don't have an idea?
+ */
+ logger.error(null, se);
+
+ InvalidSessionAddressException isae
+ = new InvalidSessionAddressException();
+ isae.initCause(se);
+ throw isae;
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
index 7a0eca0..7e740f3 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
@@ -6,7 +6,7 @@
*/
package net.java.sip.communicator.impl.protocol.sip;
-import gov.nist.javax.sip.header.HeaderFactoryImpl;
+import gov.nist.javax.sip.header.HeaderFactoryImpl; // disambiguates Contact
import gov.nist.javax.sip.header.extensions.*;
import java.net.*;
@@ -696,10 +696,7 @@ public class OperationSetBasicTelephonySipImpl
processInviteOK(clientTransaction, response);
processed = true;
}
- else if (method.equals(Request.BYE))
- {
- // ignore
- }
+ // Ignore the case of method.equals(Request.BYE)
break;
// Ringing
@@ -1074,8 +1071,8 @@ public class OperationSetBasicTelephonySipImpl
// !!! set sdp content before setting call state as that is where
// listeners get alerted and they need the sdp
// ignore sdp if we have already received one in early media
- if(!CallParticipantState.CONNECTING_WITH_EARLY_MEDIA.
- equals(callParticipant.getState()))
+ if(!CallParticipantState.CONNECTING_WITH_EARLY_MEDIA
+ .equals(callParticipant.getState()))
callParticipant.setSdpDescription(new String(ok.getRawContent()));
// notify the media manager of the sdp content
@@ -1098,9 +1095,10 @@ public class OperationSetBasicTelephonySipImpl
callSession
.setSessionCreatorCallback(callParticipant);
- String sdp =
- callSession.processSdpOffer(callParticipant,
- callParticipant.getSdpDescription());
+ String sdp
+ = callSession.processSdpOffer(
+ callParticipant,
+ callParticipant.getSdpDescription());
ack.setContent(sdp, contentTypeHeader);
// set the call url in case there was one
@@ -1141,9 +1139,11 @@ public class OperationSetBasicTelephonySipImpl
if (!CallParticipantState.CONNECTING_WITH_EARLY_MEDIA
.equals(callParticipantState))
{
- callSession.processSdpAnswer(callParticipant, callParticipant
- .getSdpDescription());
+ callSession.processSdpAnswer(
+ callParticipant,
+ callParticipant.getSdpDescription());
}
+
// set the call url in case there was one
/**
* @todo this should be done in CallSession, once we move it here.
@@ -1155,20 +1155,23 @@ public class OperationSetBasicTelephonySipImpl
catch (Exception exc)//Media or parse exception.
{
logger.error("There was an error parsing the SDP description of "
- + callParticipant.getDisplayName() + "("
- + callParticipant.getAddress() + ")", exc);
- try{
+ + callParticipant.getDisplayName()
+ + "(" + callParticipant.getAddress() + ")",
+ exc);
+ try
+ {
//we are connected from a SIP point of view (cause we sent our
- //ack) sp make sure we set the state accordingly or the hangup
+ //ack) so make sure we set the state accordingly or the hangup
//method won't know how to end the call.
callParticipant.setState(CallParticipantState.CONNECTED);
hangupCallParticipant(callParticipant);
}
- catch (Exception e){
+ catch (Exception e)
+ {
//I don't see what more we could do.
logger.error(e);
callParticipant.setState(CallParticipantState.FAILED,
- e.getMessage());
+ e.getMessage());
}
return;
}
@@ -1788,18 +1791,15 @@ public class OperationSetBasicTelephonySipImpl
CallSession callSession =
((CallSipImpl) participant.getCall()).getMediaCallSession();
- CallParticipantSipImpl sipParticipant =
- (CallParticipantSipImpl) participant;
- String sdpOffer = sipParticipant.getSdpDescription();
String sdpAnswer = null;
try
{
- sdpAnswer =
- callSession.createSdpDescriptionForHold(
- sdpOffer,
- (callSession.getSdpOfferMediaFlags(sdpOffer)
- & CallSession.ON_HOLD_REMOTELY) != 0);
+ sdpAnswer
+ = callSession.processSdpOffer(
+ participant,
+ ((CallParticipantSipImpl) participant)
+ .getSdpDescription());
}
catch (MediaException ex)
{
@@ -1808,8 +1808,10 @@ public class OperationSetBasicTelephonySipImpl
OperationFailedException.INTERNAL_ERROR, ex);
}
- response.setContent(sdpAnswer, protocolProvider.getHeaderFactory()
- .createContentTypeHeader("application", "sdp"));
+ response.setContent(
+ sdpAnswer,
+ protocolProvider.getHeaderFactory()
+ .createContentTypeHeader("application", "sdp"));
}
/**
@@ -1974,26 +1976,47 @@ public class OperationSetBasicTelephonySipImpl
Request ackRequest)
{
// find the call
- CallParticipantSipImpl callParticipant =
- activeCallsRepository.findCallParticipant(serverTransaction
- .getDialog());
+ CallParticipantSipImpl participant
+ = activeCallsRepository.findCallParticipant(
+ serverTransaction.getDialog());
- if (callParticipant == null)
+ if (participant == null)
{
// this is most probably the ack for a killed call - don't signal it
logger.debug("didn't find an ack's call, returning");
return;
}
- ContentLengthHeader cl = ackRequest.getContentLength();
- if (cl != null && cl.getContentLength() > 0)
+ ContentLengthHeader contentLength = ackRequest.getContentLength();
+ if ((contentLength != null) && (contentLength.getContentLength() > 0))
{
- callParticipant.setSdpDescription(new String(ackRequest
- .getRawContent()));
+ participant.setSdpDescription(
+ new String(ackRequest.getRawContent()));
}
+
// change status
- if (!CallParticipantState.isOnHold(callParticipant.getState()))
- callParticipant.setState(CallParticipantState.CONNECTED);
+ CallParticipantState participantState = participant.getState();
+ if (!CallParticipantState.isOnHold(participantState))
+ {
+ if (CallParticipantState.CONNECTED.equals(participantState))
+ {
+ try
+ {
+ ((CallSipImpl) participant.getCall())
+ .getMediaCallSession()
+ .startStreamingAndProcessingMedia();
+ }
+ catch (MediaException ex)
+ {
+ logger.error(
+ "Failed to start the streaming"
+ + " and the processing of the media",
+ ex);
+ }
+ }
+ else
+ participant.setState(CallParticipantState.CONNECTED);
+ }
}
/**
@@ -2002,8 +2025,8 @@ public class OperationSetBasicTelephonySipImpl
* @param serverTransaction the transaction that the cancel was received in.
* @param cancelRequest the Request that we've just received.
*/
- void processCancel(ServerTransaction serverTransaction,
- Request cancelRequest)
+ private void processCancel(ServerTransaction serverTransaction,
+ Request cancelRequest)
{
// find the call
CallParticipantSipImpl callParticipant =
@@ -2966,11 +2989,11 @@ public class OperationSetBasicTelephonySipImpl
//exception as it would go to the stack and there's nothing it could
//do with it.
logger.error(
- "Failed to created an SDP description for an ok response "
- + "to an INVITE request!",
+ "Failed to create an SDP description for an OK response "
+ + "to an INVITE request!",
ex);
this.sayError((CallParticipantSipImpl) participant,
- Response.NOT_ACCEPTABLE_HERE);
+ Response.NOT_ACCEPTABLE_HERE);
}
catch (ParseException ex)
{
@@ -2981,7 +3004,7 @@ public class OperationSetBasicTelephonySipImpl
"Failed to parse sdp data while creating invite request!",
ex);
this.sayError((CallParticipantSipImpl) participant,
- Response.NOT_ACCEPTABLE_HERE);
+ Response.NOT_ACCEPTABLE_HERE);
}
ContactHeader contactHeader = protocolProvider.getContactHeader(
@@ -2998,7 +3021,8 @@ public class OperationSetBasicTelephonySipImpl
callParticipant.setState(CallParticipantState.DISCONNECTED);
throwOperationFailedException(
"Failed to send an OK response to an INVITE request",
- OperationFailedException.NETWORK_FAILURE, ex);
+ OperationFailedException.NETWORK_FAILURE,
+ ex);
}
} // answer call
diff --git a/src/net/java/sip/communicator/service/media/CallSession.java b/src/net/java/sip/communicator/service/media/CallSession.java
index 8e3d915..8911003 100644
--- a/src/net/java/sip/communicator/service/media/CallSession.java
+++ b/src/net/java/sip/communicator/service/media/CallSession.java
@@ -179,7 +179,7 @@ public interface CallSession
* by the caller in their <tt>sdpOffer</tt>.
*
* @throws MediaException code INTERNAL_ERROR if processing the offer and/or
- * generating the anser fail for some reason.
+ * generating the answer fail for some reason.
* @throws ParseException if <tt>sdpOfferStr</tt> does not contain a valid
* sdp string.
*/
@@ -252,6 +252,14 @@ public interface CallSession
throws MediaException;
/**
+ * Calls {@link #startStreaming() in order to start the streaming of the
+ * local media and then begins processing the received and sent media
+ * streams.
+ */
+ public void startStreamingAndProcessingMedia()
+ throws MediaException;
+
+ /**
* Stops and closes the audio and video streams flowing through this
* session.
*