📄 h323ep.cxx
字号:
controlThreadStackSize = 30000; logicalThreadStackSize = 30000; listenerThreadStackSize = 30000; rasThreadStackSize = 30000; gatekeeper = NULL; connectionsActive.DisallowDeleteObjects(); connectionsToBeCleaned.DisallowDeleteObjects(); connectionsCleaner = new H323ConnectionsCleaner(*this); srand((unsigned)time(NULL)+clock()); PTRACE(3, "H323\tCreated endpoint.");}H323EndPoint::~H323EndPoint(){ // And shut down the gatekeeper (if there was one) RemoveGatekeeper(); // Shut down the listeners as soon as possible to avoid race conditions listeners.RemoveAll(); // Clear any pending calls on this endpoint ClearAllCalls(); // Shut down the cleaner thread delete connectionsCleaner; // Clean up any connections that the cleaner thread missed CleanUpConnections(); PTRACE(3, "H323\tDeleted endpoint.");}void H323EndPoint::SetEndpointTypeInfo(H225_EndpointType & info) const{ info.IncludeOptionalField(H225_EndpointType::e_vendor); SetVendorIdentifierInfo(info.m_vendor); switch (terminalType) { case e_TerminalOnly : case e_TerminalAndMC : info.IncludeOptionalField(H225_EndpointType::e_terminal); break; case e_GatewayOnly : case e_GatewayAndMC : case e_GatewayAndMCWithDataMP : case e_GatewayAndMCWithAudioMP : case e_GatewayAndMCWithAVMP : info.IncludeOptionalField(H225_EndpointType::e_gateway); break; case e_GatekeeperOnly : case e_GatekeeperWithDataMP : case e_GatekeeperWithAudioMP : case e_GatekeeperWithAVMP : info.IncludeOptionalField(H225_EndpointType::e_gatekeeper); break; case e_MCUOnly : case e_MCUWithDataMP : case e_MCUWithAudioMP : case e_MCUWithAVMP : info.IncludeOptionalField(H225_EndpointType::e_mcu); info.m_mc = TRUE; }}void H323EndPoint::SetVendorIdentifierInfo(H225_VendorIdentifier & info) const{ SetH221NonStandardInfo(info.m_vendor); info.IncludeOptionalField(H225_VendorIdentifier::e_productId); info.m_productId = PProcess::Current().GetManufacturer() & PProcess::Current().GetName(); info.m_productId.SetSize(info.m_productId.GetSize()+2); info.IncludeOptionalField(H225_VendorIdentifier::e_versionId); info.m_versionId = PProcess::Current().GetVersion(TRUE); info.m_versionId.SetSize(info.m_versionId.GetSize()+2);}void H323EndPoint::SetH221NonStandardInfo(H225_H221NonStandard & info) const{ info.m_t35CountryCode = t35CountryCode; info.m_t35Extension = t35Extension; info.m_manufacturerCode = manufacturerCode;}H323Capability * H323EndPoint::FindCapability(const H245_Capability & cap) const{ return capabilities.FindCapability(cap);}H323Capability * H323EndPoint::FindCapability(const H245_DataType & dataType) const{ return capabilities.FindCapability(dataType);}H323Capability * H323EndPoint::FindCapability(H323Capability::MainTypes mainType, unsigned subType) const{ return capabilities.FindCapability(mainType, subType);}void H323EndPoint::AddCapability(H323Capability * capability){ capabilities.Add(capability);}PINDEX H323EndPoint::SetCapability(PINDEX descriptorNum, PINDEX simultaneousNum, H323Capability * capability){ return capabilities.SetCapability(descriptorNum, simultaneousNum, capability);}BOOL H323EndPoint::SetGatekeeper(const PString & address, H323Transport * transport){ RemoveGatekeeper(H225_UnregRequestReason::e_reregistrationRequired); if (transport == NULL) transport = new H323TransportUDP(*this); H323Gatekeeper * gk = CreateGatekeeper(transport); if (gk->Discover(address) && gk->RegistrationRequest()) { gatekeeper = gk; return TRUE; } delete gk; return FALSE;}BOOL H323EndPoint::DiscoverGatekeeper(H323Transport * transport){ if (!RemoveGatekeeper(H225_UnregRequestReason::e_reregistrationRequired)) return FALSE; if (transport == NULL) transport = new H323TransportUDP(*this); H323Gatekeeper * gk = CreateGatekeeper(transport); if (gk->Discover("") && gk->RegistrationRequest()) { gatekeeper = gk; return TRUE; } delete gk; return FALSE;}H323Gatekeeper * H323EndPoint::CreateGatekeeper(H323Transport * transport){ return new H323Gatekeeper(*this, transport);}BOOL H323EndPoint::RemoveGatekeeper(int reason){ if (gatekeeper == NULL) return TRUE; ClearAllCalls(); if (!gatekeeper->UnregistrationRequest(reason)) return FALSE; delete gatekeeper; gatekeeper = NULL; return TRUE;}BOOL H323EndPoint::StartListener(H323Listener * listener){ if (!listener->Open()) return FALSE; listeners.Append(listener); listener->Resume(); return TRUE;}H323Connection * H323EndPoint::MakeCall(const PString & remoteParty, PString & token){ return MakeCall(remoteParty, NULL, token);}H323Connection * H323EndPoint::MakeCall(const PString & remoteParty, H323Transport * transport, PString & token){ PTRACE(2, "H323\tMaking call to: " << remoteParty); PString alias; H323TransportAddress address; ParsePartyName(remoteParty, alias, address); 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); else transport = address.CreateTransport(*this); if (transport == NULL) { PTRACE(1, "H323\tInvalid transport in \"" << remoteParty << '"'); return NULL; } } static unsigned lastReference = PRandom::Number()&0x3fff; connectionsMutex.Wait(); do { lastReference = (lastReference+1)&0x3fff; token = BuildConnectionToken(*transport, lastReference, FALSE); } while (connectionsActive.Contains(token)); H323Connection * connection = CreateConnection(lastReference); connectionsActive.SetAt(token, connection); connectionsMutex.Signal(); PAssertNULL(connection); connection->AttachSignalChannel(transport); PTRACE(3, "H323\tCreated new connection: " << token); new H225CallThread(*this, *connection, *transport, alias, address); return connection;}void H323EndPoint::ParsePartyName(const PString & remoteParty, PString & alias, H323TransportAddress & address) const{ /*Determine the alias part and the address part of the remote party name string. This depends on if there is an '@' to separate the alias from the transport address or a '$' for if it is explicitly a transport address. */ PINDEX at = remoteParty.Find('@'); if (at != P_MAX_INDEX) { alias = remoteParty.Left(at++); address = remoteParty.Mid(at); } else if (gatekeeper != NULL) { alias = remoteParty; address = gatekeeper->GetTransport().GetRemoteAddress(); PIPSocket::Address ip; WORD port; if (address.GetIpAndPort(ip, port)) address = ip.AsString(); } else { alias = ""; address = remoteParty; }}BOOL H323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason){ /*The hugely multi-threaded nature of the H323Connection objects means that to avoid many forms of race condition, a call is cleared by moving it from the "active" call dictionary to a list of calls to be cleared that will be processed by a background thread specifically for the purpose of cleaning up cleared connections. So that is all that this function actually does. The real work is done in the H323ConnectionsCleaner thread. */ PWaitAndSignal wait(connectionsMutex); // Find the connection by token, callid or conferenceid H323Connection * connection = FindConnectionWithoutLocks(token); if (connection == NULL) return FALSE; PTRACE(3, "H323\tClearing connection " << connection->GetCallToken() << " reason=" << reason); // Remove from active dictionary and put into clean up list connectionsActive.SetAt(connection->GetCallToken(), NULL); connectionsToBeCleaned.Append(connection); // Now set reason for the connection close connection->SetCallEndReason(reason); // Signal the background threads that there is some stuff to process. connectionsCleaner->Signal(); return TRUE;}void H323EndPoint::ClearAllCalls(H323Connection::CallEndReason reason, BOOL wait){ /*The hugely multi-threaded nature of the H323Connection objects means that to avoid many forms of race condition, a call is cleared by moving it from the "active" call dictionary to a list of calls to be cleared that will be processed by a background thread specifically for the purpose of cleaning up cleared connections. So that is all that this function actually does. The real work is done in the H323ConnectionsCleaner thread. */ connectionsMutex.Wait(); // Remove all connections from the active list first PINDEX i; for (i = 0; i < connectionsActive.GetSize(); i++) connectionsToBeCleaned.Append(&connectionsActive.GetDataAt(i)); connectionsActive.RemoveAll(); // Now set reason for the connection close for (i = 0; i < connectionsToBeCleaned.GetSize(); i++) connectionsToBeCleaned[i].SetCallEndReason(reason); // Signal the background threads that there is some stuff to process. connectionsCleaner->Signal(); // Make sure any previous signals are removed before waiting later while (connectionsAreCleaned.Wait(0)) ; connectionsMutex.Signal(); if (wait) connectionsAreCleaned.Wait();}void H323EndPoint::CleanUpConnections(){ H323ConnectionList connections; connectionsMutex.Wait(); // Now get all the connections that have been closed while (connectionsToBeCleaned.GetSize() > 0) connections.Append(connectionsToBeCleaned.RemoveAt(0));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -