#149 Suspicious PDU Read Errors (H.225 or H.245)

open
nobody
OpenH323 (35)
5
2007-11-04
2007-11-04
arimont
No

Suspicious PDU Read Errors occur when a PDU Write comes inbetween pdu.Read()(resp. controlChannel->ReadPDU(strm)) and signallingChannel->GetErrorCode() (resp. controlChannel->GetErrorCode())caused by thread change.

Fix:

void H323Connection::HandleSignallingChannel()
{
PAssert(signallingChannel != NULL, PLogicError);

PTRACE(2, "H225\tReading PDUs: callRef=" << callReference);

while (signallingChannel->IsOpen()) {
H323SignalPDU pdu;
if (pdu.Read(*signallingChannel)) {
if (!HandleSignalPDU(pdu)) {
ClearCall(EndedByTransportFail);
break;
}
switch (connectionState) {
case EstablishedConnection :
signallingChannel->SetReadTimeout(MonitorCallStatusTime);
break;
default:
break;
}
}
else if (signallingChannel->GetErrorCode(PChannel::LastReadError) != PChannel::Timeout) { // FIX
if (controlChannel == NULL || !controlChannel->IsOpen())
ClearCall(EndedByTransportFail);
signallingChannel->Close();
break;
}
else {
switch (connectionState) {
case AwaitingSignalConnect :
// Had time out waiting for remote to send a CONNECT
ClearCall(EndedByNoAnswer);
break;
case HasExecutedSignalConnect :
// Have had minimum MonitorCallStatusTime delay since CONNECT but
// still no media to move it to EstablishedConnection state. Must
// thus not have any common codecs to use!
ClearCall(EndedByCapabilityExchange);
break;
default :
break;
}
}

if (controlChannel == NULL)
MonitorCallStatus();
}

// If we are the only link to the far end then indicate that we have
// received endSession even if we hadn't, because we are now never going
// to get one so there is no point in having CleanUpOnCallEnd wait.
if (controlChannel == NULL)
endSessionReceived.Signal();

PTRACE(2, "H225\tSignal channel closed.");
}

void H323Connection::HandleControlChannel()
{
// If have started separate H.245 channel then don't tunnel any more
h245Tunneling = FALSE;

// Start the TCS and MSD operations on new H.245 channel.
if (!StartControlNegotiations())
return;

// Disable the signalling channels timeout for monitoring call status and
// start up one in this thread instead. Then the Q.931 channel can be closed
// without affecting the call.
signallingChannel->SetReadTimeout(PMaxTimeInterval);
controlChannel->SetReadTimeout(MonitorCallStatusTime);

BOOL ok = TRUE;
while (ok) {
MonitorCallStatus();

PPER_Stream strm;
if (controlChannel->ReadPDU(strm)) {
// Lock while checking for shutting down.
if (Lock()) {
// Process the received PDU
PTRACE(4, "H245\tReceived TPKT: " << strm);
ok = HandleControlData(strm);
Unlock(); // Unlock connection
}
else
ok = InternalEndSessionCheck(strm);
}
else if (controlChannel->GetErrorCode(PChannel::LastReadError) != PChannel::Timeout) { // FIX
PTRACE(1, "H245\tRead error: " << controlChannel->GetErrorText(PChannel::LastReadError)
<< " endSessionSent=" << endSessionSent);
// If the connection is already shutting down then don't overwrite the
// call end reason. This could happen if the remote end point misbehaves
// and simply closes the H.245 TCP connection rather than sending an
// endSession.
if(endSessionSent == FALSE)
ClearCall(EndedByTransportFail);
else
PTRACE(1, "H245\tendSession already sent assuming H245 connection closed by remote side");
ok = FALSE;
}
}

// If we are the only link to the far end or if we have already sent our
// endSession command then indicate that we have received endSession even
// if we hadn't, because we are now never going to get one so there is no
// point in having CleanUpOnCallEnd wait.
if (signallingChannel == NULL || endSessionSent == TRUE)
endSessionReceived.Signal();

PTRACE(2, "H245\tControl channel closed.");
}

Discussion


Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks