Hi, I have found an issue with H323EndPoint::InternalMakeCall function for case when it running from H323EndPoint::ForwardConnection function (may be for some others cases too). Take a look: 1.We are trying to connect to some host which uses Gatekeeper. 2.From H323EndPoint::ForwardConnection call H323EndPoint::InternalMakeCall function with some internal token="ip$xxx.xxx.xxx.xxx/port" 3.In the body of H323EndPoint::InternalMakeCall we have the replacement current callToken-connection pair to new one with "ip$xxx.xxx.xxx.xxx/port-replaced-1" string, like connectionsActive.SetAt(adjustedToken, connectionsActive.RemoveAt(newToken)); connectionsToBeCleaned += adjustedToken; 4.But if for some reason our virtual CreateConnection function returns NULL... connection = CreateConnection(lastReference, userData, transport, NULL); if (connection == NULL) { PTRACE(1, "H323\tCreateConnection returned NULL"); connectionsMutex.Signal();
return NULL; } ... we cannot clear current Connection because it has not actual callToken "ip$xxx.xxx.xxx.xxx/port" but H323EndPoint::connectionsActive has "ip$xxx.xxx.xxx.xxx/port-replaced-1" and endpoint.ClearCall(callToken, reason) or something similar will be failed because not able to found the Connection by own callToken. 5.Also we have redundant call connectionsMutex.Signal(). if (connection == NULL) { PTRACE(1, "H323\tCreateConnection returned NULL"); connectionsMutex.Signal();
return NULL; }
My proposition - just rename back callToken for H323EndPoint::connectionsActive and remove adjustedToken from H323EndPoint::connectionsToBeCleaned if we have NULL connection. My H323EndPoint::InternalMakeCall function looks like this: H323Connection * H323EndPoint::InternalMakeCall(const PString & trasferFromToken, const PString & callIdentity, unsigned capabilityLevel, const PString & remoteParty, H323Transport * transport, PString & newToken, void * userData, PBoolean supplimentary ) { PTRACE(2, "H323\tMaking call to: " << remoteParty); PString alias; H323TransportAddress address; if (!ParsePartyName(remoteParty, alias, address)) { PTRACE(2, "H323\tCould not parse "" << remoteParty << '"'); return NULL; } #ifdef H323_H46017 // If H.460.17 use the existing H.460.17 Transport if (transport == NULL && RegisteredWithH46017()) transport = GetH46017Transport(); #endif if (transport == NULL) { // Restriction: the call must be made on the same transport as the one // that the gatekeeper is using. if (gatekeeper != NULL) transport = gatekeeper->GetTransport().GetRemoteAddress().CreateTransport(*this); // assume address is an IP address/hostname else transport = address.CreateTransport(*this); if (transport == NULL) { PTRACE(1, "H323\tInvalid transport in "" << remoteParty << '"'); return NULL; } } H323Connection * connection; connectionsMutex.Wait(); PString adjustedToken; unsigned lastReference; if (newToken.IsEmpty()) { do { lastReference = Q931::GenerateCallReference(); newToken = BuildConnectionToken(*transport, lastReference, FALSE); } while (connectionsActive.Contains(newToken)); } else { lastReference = newToken.Mid(newToken.Find('/')+1).AsUnsigned(); // Move old connection on token to new value and flag for removal unsigned tieBreaker = 0; do { adjustedToken = newToken + "-replaced"; adjustedToken.sprintf("-%u", ++tieBreaker); } while (connectionsActive.Contains(adjustedToken)); connectionsActive.SetAt(adjustedToken, connectionsActive.RemoveAt(newToken)); connectionsToBeCleaned += adjustedToken; PTRACE(3, "H323\tOverwriting call " << newToken << ", renamed to " << adjustedToken); } connectionsMutex.Signal(); connection = CreateConnection(lastReference, userData, transport, NULL); if (connection == NULL) { PTRACE(1, "H323\tCreateConnection returned NULL"); if (!adjustedToken.IsEmpty()) { connectionsMutex.Wait(); connectionsActive.SetAt(newToken, connectionsActive.RemoveAt(adjustedToken)); connectionsToBeCleaned -= adjustedToken; PTRACE(3, "H323\tOverwriting call " << adjustedToken << ", renamed to " << newToken); connectionsMutex.Signal(); } return NULL; } connection->SetRemotePartyName(remoteParty); if (supplimentary) connection->SetNonCallConnection(); connection->Lock(); connectionsMutex.Wait(); connectionsActive.SetAt(newToken, connection); connectionsMutex.Signal(); connection->AttachSignalChannel(newToken, transport, FALSE); #ifdef H323_H450 if (capabilityLevel == UINT_MAX) connection->HandleTransferCall(trasferFromToken, callIdentity); else { connection->HandleIntrudeCall(trasferFromToken, callIdentity); connection->IntrudeCall(capabilityLevel); } #endif PTRACE(3, "H323\tCreated new connection: " << newToken); #ifdef H323_H46017 if (RegisteredWithH46017()) { H323Connection::CallEndReason reason = connection->SendSignalSetup(alias, address); if (reason != H323Connection::NumCallEndReasons) connection->ClearCall(reason); } else #endif new H225CallThread(*this, *connection, *transport, alias, address); return connection; }
Thanks -- Iurii Gordiienko