Fixes un-graceful handling of invalid SDP offers and answers(was crashing when receiving an empty zrtp-hash attribute). This include sending an error response when the SDP offer was corrupt and a BYE request when the problem is inside the SDP answer.

Fixes impossibility to close the full screen window after a call has been ended remotely.
cusax-fix
Emil Ivov 17 years ago
parent 7018f589cb
commit ecf9648254

@ -26,7 +26,7 @@
* The <tt>CallParticipantPanel</tt> is the panel containing data for a call
* participant in a given call. It contains information like call participant
* name, photo, call duration, etc.
*
*
* @author Yana Stamcheva
* @author Lubomir Marinov
*/
@ -70,7 +70,7 @@ public class CallParticipantPanel
private ZrtpPanel zrtpPanel = null;
/**
* Creates a <tt>CallParticipantPanel</tt> for the given call participant.
*
*
* @param callManager the <tt>CallManager</tt> that manages the call
* @param callParticipant a call participant
*/
@ -164,7 +164,7 @@ private Component createButtonBar( boolean heavyweight,
* Creates the <code>Component</code> hierarchy of the central area of this
* <code>CallParticipantPanel</code> which displays the photo of the
* <code>CallParticipant</code> or the video if any.
*
*
* @return the root of the <code>Component</code> hierarchy of the central
* area of this <code>CallParticipantPanel</code> which displays the
* photo of the <code>CallParticipant</code> or the video if any
@ -215,7 +215,7 @@ public void hierarchyChanged(HierarchyEvent event)
* returned <code>Container</code> will track the <code>Components</code>s
* added to and removed from it in order to make sure that
* <code>noVideoContainer</code> is displayed as described.
*
*
* @param noVideoComponent the predefined default <code>Component</code> to
* be displayed in the returned <code>Container</code> when there
* is no other <code>Component</code> in it
@ -242,7 +242,7 @@ private Component createNameBar()
* Creates the <code>Component</code> hierarchy of the area of
* status-related information such as <code>CallParticipant</code> display
* name, call duration, security status.
*
*
* @return the root of the <code>Component</code> hierarchy of the area of
* status-related information such as <code>CallParticipant</code>
* display name, call duration, security status
@ -287,7 +287,7 @@ private Component createStatusBar()
* Creates a new <code>Component</code> representing a UI means to transfer
* the <code>Call</code> of the associated <code>callParticipant</code> or
* <tt>null</tt> if call-transfer is unsupported.
*
*
* @return a new <code>Component</code> representing the UI means to
* transfer the <code>Call</code> of <code>callParticipant</code> or
* <tt>null</tt> if call-transfer is unsupported
@ -312,7 +312,7 @@ private Component createTransferCallButton()
* Creates a new <code>Component</code> representing a UI means to secure
* the <code>Call</code> of the associated <code>callParticipant</code> or
* <tt>null</tt> if secure call is unsupported.
*
*
* @return a new <code>Component</code> representing the UI means to secure
* the <code>Call</code> of <code>callParticipant</code> or
* <tt>null</tt> if secure call is unsupported
@ -518,7 +518,7 @@ private void removeVideoListener()
/**
* When a video is added or removed for the <code>callParticipant</code>,
* makes sure to display or hide it respectively.
*
*
* @param event a <code>VideoEvent</code> describing the added visual
* <code>Component</code> representing video and the provider it
* was added into or <code>null</code> if such information is not
@ -608,7 +608,7 @@ public void run()
/**
* Sets the state of the contained call participant by specifying the
* state name and icon.
*
*
* @param state the state of the contained call participant
* @param icon the icon of the state
*/
@ -659,7 +659,7 @@ public void actionPerformed(ActionEvent e)
* example if we receive a call, the call start time is when the call is
* received and the conversation start time would be when we accept the
* call.
*
*
* @return the start time of the contained participant call
*/
public Date getCallStartTime()
@ -669,7 +669,7 @@ public Date getCallStartTime()
/**
* Returns the duration of the contained participant call.
*
*
* @return the duration of the contained participant call
*/
public Date getCallDuration()
@ -680,7 +680,7 @@ public Date getCallDuration()
/**
* Returns this call type - GuiCallParticipantRecord: INCOMING_CALL or
* OUTGOING_CALL
*
*
* @return Returns this call type : INCOMING_CALL or OUTGOING_CALL
*/
public String getCallType()
@ -695,7 +695,7 @@ public String getCallType()
* Sets the type of the call. Call type could be
* <tt>GuiCallParticipantRecord.INCOMING_CALL</tt> or
* <tt>GuiCallParticipantRecord.INCOMING_CALL</tt>.
*
*
* @param callType the type of call to set
*/
public void setCallType(String callType)
@ -705,7 +705,7 @@ public void setCallType(String callType)
/**
* Returns the name of the participant, contained in this panel.
*
*
* @return the name of the participant, contained in this panel
*/
public String getParticipantName()
@ -852,7 +852,11 @@ public void windowStateChanged(WindowEvent event)
private void exitFullScreen(Window fullScreenWindow)
{
getGraphicsConfiguration().getDevice().setFullScreenWindow(null);
GraphicsConfiguration gConfig = getGraphicsConfiguration();
if(gConfig != null)
gConfig.getDevice().setFullScreenWindow(null);
if (fullScreenWindow != null)
{
if (fullScreenWindow.isVisible())

@ -500,7 +500,19 @@ private boolean stopStreaming(RTPManager rtpManager)
stoppedAtLeastOneStream = true;
}
Vector<ReceiveStream> receiveStreams = rtpManager.getReceiveStreams();
Vector<ReceiveStream> receiveStreams;
try
{
receiveStreams = rtpManager.getReceiveStreams();
}
//it appears that in early call states, when there are no streams
//this method could throug a null pointer exception. Make sure we handle
//it gracefully
catch (Exception e)
{
logger.trace("Failed to retrieve receive streams", e);
receiveStreams = new Vector<ReceiveStream>();
}
Iterator<ReceiveStream> rsIter = receiveStreams.iterator();
while(rsIter.hasNext())
{
@ -1040,6 +1052,15 @@ public String processSdpOffer(CallParticipant offerer, String sdpOfferStr)
+ 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);

@ -933,6 +933,7 @@ private void processSessionProgress(ClientTransaction clientTransaction,
"There was an error parsing the SDP description of "
+ callParticipant.getDisplayName() + "("
+ callParticipant.getAddress() + ")", exc, callParticipant);
return;
}
catch (MediaException exc)
{
@ -941,6 +942,7 @@ private void processSessionProgress(ClientTransaction clientTransaction,
+ callParticipant.getDisplayName() + "("
+ callParticipant.getAddress() + ")" + ". Error was: "
+ exc.getMessage(), exc, callParticipant);
return;
}
// set the call url in case there was one
@ -1046,6 +1048,7 @@ private void processInviteOK(ClientTransaction clientTransaction,
logErrorAndFailCallParticipant(
"Failed to create a content type header for the ACK request",
ex, callParticipant);
return;
}
catch (InvalidArgumentException ex)
{
@ -1053,6 +1056,7 @@ private void processInviteOK(ClientTransaction clientTransaction,
logErrorAndFailCallParticipant(
"Failed ACK request, problem with the supplied cseq", ex,
callParticipant);
return;
}
catch (SipException ex)
{
@ -1132,20 +1136,27 @@ private void processInviteOK(ClientTransaction clientTransaction,
*/
callParticipant.setCallInfoURL(callSession.getCallInfoURL());
}
catch (ParseException exc)
{
logErrorAndFailCallParticipant(
"There was an error parsing the SDP description of "
+ callParticipant.getDisplayName() + "("
+ callParticipant.getAddress() + ")", exc, callParticipant);
}
catch (MediaException exc)
{
logErrorAndFailCallParticipant(
"We failed to process the SDP description of "
+ callParticipant.getDisplayName() + "("
+ callParticipant.getAddress() + ")" + ". Error was: "
+ exc.getMessage(), exc, callParticipant);
//at this point we have already sent our ack so in adition to logging
//an error we also need to hangup the call participant.
catch (Exception exc)//Media or parse exception.
{
logger.error("There was an error parsing the SDP description of "
+ 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
//method won't know how to end the call.
callParticipant.setState(CallParticipantState.CONNECTED);
hangupCallParticipant(callParticipant);
}
catch (Exception e){
//I don't see what more we could do.
logger.error(e);
callParticipant.setState(CallParticipantState.FAILED,
e.getMessage());
}
return;
}
// change status
@ -1242,6 +1253,7 @@ private void processAuthenticationChallenge(
logErrorAndFailCallParticipant(
"We failed to authenticate an INVITE request.", exc,
callParticipant);
return;
}
}
@ -1990,12 +2002,14 @@ void processCancel(ServerTransaction serverTransaction,
logErrorAndFailCallParticipant(
"Failed to create an OK Response to an CANCEL request.", ex,
callParticipant);
return;
}
catch (Exception ex)
{
logErrorAndFailCallParticipant(
"Failed to send an OK Response to an CANCEL request.", ex,
callParticipant);
return;
}
try
{
@ -2609,7 +2623,8 @@ public void sayInternalError(CallParticipantSipImpl callParticipant)
* @throws OperationFailedException if we failed constructing or sending a
* SIP Message.
*/
public void sayError(CallParticipantSipImpl callParticipant, int errorCode)
public void sayError(CallParticipantSipImpl callParticipant,
int errorCode)
throws OperationFailedException
{
Dialog dialog = callParticipant.getDialog();
@ -2634,13 +2649,13 @@ public void sayError(CallParticipantSipImpl callParticipant, int errorCode)
}
ServerTransaction serverTransaction = (ServerTransaction) transaction;
Response internalError = null;
Response errorResponse = null;
try
{
internalError =
errorResponse =
protocolProvider.getMessageFactory().createResponse(errorCode,
callParticipant.getFirstTransaction().getRequest());
protocolProvider.attachToTag(internalError, dialog);
protocolProvider.attachToTag(errorResponse, dialog);
}
catch (ParseException ex)
{
@ -2651,12 +2666,12 @@ public void sayError(CallParticipantSipImpl callParticipant, int errorCode)
ContactHeader contactHeader = protocolProvider
.getContactHeader(dialog.getRemoteTarget());
internalError.addHeader(contactHeader);
errorResponse.addHeader(contactHeader);
try
{
serverTransaction.sendResponse(internalError);
serverTransaction.sendResponse(errorResponse);
if (logger.isDebugEnabled())
logger.debug("sent response: " + internalError);
logger.debug("sent response: " + errorResponse);
}
catch (Exception ex)
{
@ -2913,19 +2928,26 @@ public synchronized void answerCallParticipant(CallParticipant participant)
}
catch (MediaException ex)
{
//log, the error and tell the remote party. do not throw an
//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!",
ex);
this.sayError((CallParticipantSipImpl) participant,
Response.NOT_ACCEPTABLE_HERE);
throwOperationFailedException(
"Failed to created an SDP description for an ok response "
+ "to an INVITE request!",
OperationFailedException.INTERNAL_ERROR, ex);
}
catch (ParseException ex)
{
callParticipant.setState(CallParticipantState.DISCONNECTED);
throwOperationFailedException(
//log, the error and tell the remote party. do not throw an
//exception as it would go to the stack and there's nothing it could
//do with it.
logger.error(
"Failed to parse sdp data while creating invite request!",
OperationFailedException.INTERNAL_ERROR, ex);
ex);
this.sayError((CallParticipantSipImpl) participant,
Response.NOT_ACCEPTABLE_HERE);
}
ContactHeader contactHeader = protocolProvider.getContactHeader(

Loading…
Cancel
Save