home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / openh323.tar.gz / openh323.tar / openh323 / src / peclient.cxx < prev    next >
C/C++ Source or Header  |  2003-05-13  |  60KB  |  1,742 lines

  1. /*
  2.  * peclient.cxx
  3.  *
  4.  * H.323 Annex G Peer Element client protocol handler
  5.  *
  6.  * Open H323 Library
  7.  *
  8.  * Copyright (c) 2003 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Open H323 Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Contributor(s): ______________________________________.
  25.  *
  26.  * $Log: peclient.cxx,v $
  27.  * Revision 1.39  2003/05/14 03:06:22  rjongbloed
  28.  * Added another method for removing service relationships.
  29.  * Added virtual for handling SR requests.
  30.  *
  31.  * Revision 1.38  2003/05/05 08:28:25  craigs
  32.  * Fixed lastUpdate time in descriptors
  33.  *
  34.  * Revision 1.37  2003/04/30 07:32:55  craigs
  35.  * Improve handling of wildcard matches
  36.  *
  37.  * Revision 1.36  2003/04/30 04:55:41  craigs
  38.  * Improved handling for nonexistent routes
  39.  *
  40.  * Revision 1.35  2003/04/18 15:16:43  craigs
  41.  * Fixed problem with creation of alias keys
  42.  *
  43.  * Revision 1.34  2003/04/10 14:34:05  craigs
  44.  * Fixed wild card handling
  45.  *
  46.  * Revision 1.33  2003/04/10 09:41:02  robertj
  47.  * Added some more functions for converting to alias addresses.
  48.  *
  49.  * Revision 1.32  2003/04/10 07:05:35  craigs
  50.  * Allowed access to endpoint type in descriptors
  51.  *
  52.  * Revision 1.31  2003/04/10 03:41:58  craigs
  53.  * Allow AccessRequest to return multiple transport addresses
  54.  *
  55.  * Revision 1.30  2003/04/10 00:59:35  craigs
  56.  * Added support for multiple contact addresses per template
  57.  *
  58.  * Revision 1.29  2003/04/09 10:47:06  craigs
  59.  * Fixed problems
  60.  *
  61.  * Revision 1.28  2003/04/09 03:08:10  robertj
  62.  * Fixed race condition in shutting down transactor (pure virtual call)
  63.  *
  64.  * Revision 1.27  2003/04/08 12:23:37  craigs
  65.  * Fixed problem with descriptors not being removed when service relationships go away
  66.  *
  67.  * Revision 1.26  2003/04/07 05:10:50  craigs
  68.  * Added changes to get access to descriptor creates/updates/deletes
  69.  *
  70.  * Revision 1.25  2003/04/02 06:06:01  robertj
  71.  * Added versions of AddDescriptor that contain the GUID.
  72.  * Changed default localIdentifier to be the local username of the endpoint.
  73.  *
  74.  * Revision 1.24  2003/04/01 05:59:33  robertj
  75.  * Fixed H.501 transaction code setting members for m_common PDU part.
  76.  *
  77.  * Revision 1.23  2003/04/01 04:47:55  robertj
  78.  * Abstracted H.225 RAS transaction processing (RIP and secondary thread) in
  79.  *   server environment for use by H.501 peer elements.
  80.  *
  81.  * Revision 1.22  2003/04/01 01:18:16  robertj
  82.  * Minor changes to AccessEquest and AddDescriptor API to allow for
  83.  *   string arrays of aliases.
  84.  *
  85.  * Revision 1.21  2003/03/28 04:43:05  craigs
  86.  * Added noCallSpecific flag for compatibility
  87.  *
  88.  * Revision 1.20  2003/03/28 00:30:13  craigs
  89.  * Fixed problems with service relationship ordinals and better descriptor update access
  90.  *
  91.  * Revision 1.19  2003/03/27 09:23:41  craigs
  92.  * Rewritten support for descriptors and multiple templates
  93.  *
  94.  * Revision 1.18  2003/03/26 00:46:29  robertj
  95.  * Had another go at making H323Transactor being able to be created
  96.  *   without having a listener running.
  97.  *
  98.  * Revision 1.17  2003/03/25 12:53:00  robertj
  99.  * Added SetPromiscuous back in
  100.  *
  101.  * Revision 1.16  2003/03/25 12:01:30  craigs
  102.  * Fixed SEGV when no interface specified for peer element
  103.  *
  104.  * Revision 1.15  2003/03/25 07:50:23  craigs
  105.  * Added support for mutiple transports per descriptor
  106.  *
  107.  * Revision 1.14  2003/03/25 05:13:00  craigs
  108.  * More speed enhancements
  109.  *
  110.  * Revision 1.13  2003/03/25 02:57:04  craigs
  111.  * Fixed for update problems
  112.  *
  113.  * Revision 1.12  2003/03/25 01:59:13  robertj
  114.  * Fixed incorrect position of delete. Would do nothing there!
  115.  *
  116.  * Revision 1.11  2003/03/25 01:41:02  craigs
  117.  * Still more signficant H.501 updates
  118.  *
  119.  * Revision 1.10  2003/03/20 01:51:12  robertj
  120.  * More abstraction of H.225 RAS and H.501 protocols transaction handling.
  121.  *
  122.  * Revision 1.9  2003/03/19 01:18:38  robertj
  123.  * Fixed GNU warnings
  124.  *
  125.  * Revision 1.8  2003/03/19 01:11:37  robertj
  126.  * GNU compatibility
  127.  *
  128.  * Revision 1.7  2003/03/18 13:57:53  craigs
  129.  * More H.501 implementation
  130.  *
  131.  * Revision 1.6  2003/03/17 13:19:31  craigs
  132.  * More H501 implementation
  133.  *
  134.  * Revision 1.5  2003/03/14 06:01:16  craigs
  135.  * More updates
  136.  *
  137.  * Revision 1.4  2003/03/01 00:22:26  craigs
  138.  * New PeerElement implementation
  139.  *
  140.  * Revision 1.3  2003/02/25 06:48:19  robertj
  141.  * More work on PDU transaction abstraction.
  142.  *
  143.  * Revision 1.2  2003/02/21 07:23:18  robertj
  144.  * Fixed up some comments
  145.  *
  146.  * Revision 1.1  2003/02/21 05:27:06  craigs
  147.  * Initial version
  148.  *
  149.  */
  150.  
  151. #include <ptlib.h>
  152.  
  153. #ifdef __GNUC__
  154. #pragma implementation "peclient.h"
  155. #endif
  156.  
  157. #include "peclient.h"
  158.  
  159. #include "h323ep.h"
  160. #include "h323annexg.h"
  161. #include "h323pdu.h"
  162.  
  163. #define new PNEW
  164.  
  165. const unsigned ServiceRequestRetryTime       = 60;
  166. const unsigned ServiceRequestGracePeriod     = 10;
  167. const unsigned ServiceRelationshipTimeToLive = 60;
  168.  
  169. ////////////////////////////////////////////////////////////////
  170.  
  171. H501Transaction::H501Transaction(H323PeerElement & pe, const H501PDU & pdu, BOOL hasReject)
  172. : H323Transaction(pe, pdu, new H501PDU, hasReject ? new H501PDU : NULL),
  173.     requestCommon(((H501PDU &)request->GetPDU()).m_common),
  174.     confirmCommon(((H501PDU &)confirm->GetPDU()).m_common),
  175.     peerElement(pe)
  176. {
  177. }
  178.  
  179.  
  180. H323TransactionPDU * H501Transaction::CreateRIP(unsigned sequenceNumber,
  181.                                                 unsigned delay) const
  182. {
  183.   H501PDU * rip = new H501PDU;
  184.   rip->BuildRequestInProgress(sequenceNumber, delay);
  185.   return rip;
  186. }
  187.  
  188.  
  189. H235Authenticator::ValidationResult H501Transaction::ValidatePDU() const
  190. {
  191.   return request->Validate(requestCommon.m_tokens, H501_MessageCommonInfo::e_tokens,
  192.                            requestCommon.m_cryptoTokens, H501_MessageCommonInfo::e_cryptoTokens);
  193. }
  194.  
  195.  
  196. ////////////////////////////////////////////////////////////////
  197.  
  198. H501ServiceRequest::H501ServiceRequest(H323PeerElement & pe,
  199.                                        const H501PDU & pdu)
  200.   : H501Transaction(pe, pdu, TRUE),
  201.     srq((H501_ServiceRequest &)request->GetChoice().GetObject()),
  202.     scf(((H501PDU &)confirm->GetPDU()).BuildServiceConfirmation(pdu.m_common.m_sequenceNumber)),
  203.     srj(((H501PDU &)reject->GetPDU()).BuildServiceRejection(pdu.m_common.m_sequenceNumber,
  204.                                                             H501_ServiceRejectionReason::e_undefined))
  205. {
  206. }
  207.  
  208.  
  209. #if PTRACING
  210. const char * H501ServiceRequest::GetName() const
  211. {
  212.   return "ServiceRequest";
  213. }
  214. #endif
  215.  
  216.  
  217. void H501ServiceRequest::SetRejectReason(unsigned reasonCode)
  218. {
  219.   srj.m_reason.SetTag(reasonCode);
  220. }
  221.  
  222.  
  223. H323Transaction::Response H501ServiceRequest::OnHandlePDU()
  224. {
  225.   return peerElement.OnServiceRequest(*this);
  226. }
  227.  
  228.  
  229. ////////////////////////////////////////////////////////////////
  230.  
  231. H501DescriptorUpdate::H501DescriptorUpdate(H323PeerElement & pe,
  232.                                            const H501PDU & pdu)
  233.   : H501Transaction(pe, pdu, FALSE),
  234.     du((H501_DescriptorUpdate &)request->GetChoice().GetObject()),
  235.     ack(((H501PDU &)confirm->GetPDU()).BuildDescriptorUpdateAck(pdu.m_common.m_sequenceNumber))
  236. {
  237. }
  238.  
  239.  
  240. #if PTRACING
  241. const char * H501DescriptorUpdate::GetName() const
  242. {
  243.   return "DescriptorUpdate";
  244. }
  245. #endif
  246.  
  247.  
  248. void H501DescriptorUpdate::SetRejectReason(unsigned /*reasonCode*/)
  249. {
  250.   // Not possible!
  251. }
  252.  
  253.  
  254. H323Transaction::Response H501DescriptorUpdate::OnHandlePDU()
  255. {
  256.   return peerElement.OnDescriptorUpdate(*this);
  257. }
  258.  
  259.  
  260. ////////////////////////////////////////////////////////////////
  261.  
  262. H501AccessRequest::H501AccessRequest(H323PeerElement & pe,
  263.                                      const H501PDU & pdu)
  264.   : H501Transaction(pe, pdu, TRUE),
  265.     arq((H501_AccessRequest &)request->GetChoice().GetObject()),
  266.     acf(((H501PDU &)confirm->GetPDU()).BuildAccessConfirmation(pdu.m_common.m_sequenceNumber)),
  267.     arj(((H501PDU &)reject->GetPDU()).BuildAccessRejection(pdu.m_common.m_sequenceNumber,
  268.                                                            H501_AccessRejectionReason::e_undefined))
  269. {
  270. }
  271.  
  272.  
  273. #if PTRACING
  274. const char * H501AccessRequest::GetName() const
  275. {
  276.   return "AccessRequest";
  277. }
  278. #endif
  279.  
  280.  
  281. void H501AccessRequest::SetRejectReason(unsigned reasonCode)
  282. {
  283.   arj.m_reason.SetTag(reasonCode);
  284. }
  285.  
  286.  
  287. H323Transaction::Response H501AccessRequest::OnHandlePDU()
  288. {
  289.   return peerElement.OnAccessRequest(*this);
  290. }
  291.  
  292.  
  293. ////////////////////////////////////////////////////////////////
  294.  
  295. H323PeerElement::H323PeerElement(H323EndPoint & ep, H323Transport * trans)
  296.   : H323_AnnexG(ep, trans),
  297.     requestMutex(1, 1)
  298. {
  299.   Construct();
  300. }
  301.  
  302. H323PeerElement::H323PeerElement(H323EndPoint & ep, const H323TransportAddress & addr)
  303.   : H323_AnnexG(ep, addr),
  304.     requestMutex(1, 1)
  305. {
  306.   Construct();
  307. }
  308.  
  309. void H323PeerElement::Construct()
  310. {
  311.   if (transport != NULL)
  312.     transport->SetPromiscuous(H323Transport::AcceptFromAny);
  313.  
  314.   monitorStop       = FALSE;
  315.   localIdentifier   = endpoint.GetLocalUserName();
  316.   basePeerOrdinal   = RemoteServiceRelationshipOrdinal;
  317.  
  318.   StartChannel();
  319.  
  320.   monitor = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
  321.                             PThread::NoAutoDeleteThread,
  322.                             PThread::NormalPriority,
  323.                             "PeerElementMonitor:%x");
  324. }
  325.  
  326. H323PeerElement::~H323PeerElement()
  327. {
  328.   if (monitor != NULL) {
  329.     monitorStop = TRUE;
  330.     monitorTickle.Signal();
  331.     monitor->WaitForTermination();
  332.     delete monitor;
  333.   }
  334.  
  335.   StopChannel();
  336. }
  337.  
  338.  
  339. void H323PeerElement::SetLocalName(const PString & name)
  340. {
  341.   PWaitAndSignal m(localNameMutex);
  342.   localIdentifier = name;
  343. }
  344.  
  345. PString H323PeerElement::GetLocalName() const
  346. {
  347.   PWaitAndSignal m(localNameMutex);
  348.   return localIdentifier;
  349. }
  350.  
  351. void H323PeerElement::SetDomainName(const PString & name)
  352. {
  353.   PWaitAndSignal m(localNameMutex);
  354.   domainName = name;
  355. }
  356.  
  357. PString H323PeerElement::GetDomainName() const
  358. {
  359.   PWaitAndSignal m(localNameMutex);
  360.   return domainName;
  361. }
  362.  
  363.  
  364. void H323PeerElement::PrintOn(ostream & strm) const
  365. {
  366.   if (!localIdentifier)
  367.     strm << localIdentifier << '@';
  368.   H323Transactor::PrintOn(strm);
  369. }
  370.  
  371. void H323PeerElement::MonitorMain(PThread &, INT)
  372. {
  373.   PTRACE(3, "PeerElement\tBackground thread started");
  374.  
  375.   for (;;) {
  376.  
  377.     // refresh and retry remote service relationships by sending new ServiceRequests
  378.     PTime now;
  379.     PTime nextExpireTime = now + ServiceRequestRetryTime*1000;
  380.     {
  381.       for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
  382.  
  383.         if (now >= sr->expireTime) {
  384.           PTRACE(3, "PeerElement\tRenewing service relationship " << sr->serviceID << "before expiry");
  385.           ServiceRequestByID(sr->serviceID);
  386.         }
  387.  
  388.         // get minimum sleep time for next refresh or retry
  389.         if (sr->expireTime < nextExpireTime)
  390.           nextExpireTime = sr->expireTime;
  391.       }
  392.     }
  393.  
  394.     // expire local service relationships we have not received ServiceRequests for
  395.     {
  396.       for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstLocalServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
  397.  
  398.         // check to see if expired or needs refresh scheduled
  399.         PTime expireTime = sr->expireTime + 1000 * ServiceRequestGracePeriod;
  400.         if (now >= expireTime) {
  401.           PTRACE(3, "PeerElement\tService relationship " << sr->serviceID << "expired");
  402.           localServiceRelationships.Remove(sr);
  403.           {
  404.             PWaitAndSignal m(localPeerListMutex);
  405.             localServiceOrdinals -= sr->ordinal;
  406.           }
  407.         }
  408.         else if (expireTime < nextExpireTime)
  409.           nextExpireTime = sr->expireTime;
  410.       }
  411.     }
  412.  
  413.     // if any descriptor needs updating, then spawn a thread to do it
  414.     {
  415.       for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadOnly); descriptor != NULL; descriptor++) {
  416.         PWaitAndSignal m(localPeerListMutex);
  417.         if (
  418.             (descriptor->state != H323PeerElementDescriptor::Clean) || 
  419.             (
  420.              (descriptor->creator >= RemoteServiceRelationshipOrdinal) && 
  421.               !localServiceOrdinals.Contains(descriptor->creator)
  422.              )
  423.             ) {
  424.           PThread::Create(PCREATE_NOTIFIER(UpdateAllDescriptors), 0, PThread::AutoDeleteThread, PThread::NormalPriority);
  425.           break;
  426.         }
  427.       }
  428.     }
  429.  
  430.     // wait until just before the next expire time;
  431.     PTimeInterval timeToWait = nextExpireTime - PTime();
  432.     if (timeToWait > 60*1000)
  433.       timeToWait = 60*1000;
  434.     monitorTickle.Wait(timeToWait);
  435.  
  436.     if (monitorStop)
  437.       break;
  438.   }
  439.  
  440.   PTRACE(3, "PeerElement\tBackground thread ended");
  441. }
  442.  
  443. void H323PeerElement::UpdateAllDescriptors(PThread &, INT)
  444. {
  445.   PTRACE(2, "PeerElement\tDescriptor update thread started");
  446.  
  447.   for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadWrite); descriptor != NULL; descriptor++) {
  448.     PWaitAndSignal m(localPeerListMutex);
  449.  
  450.     // delete any descriptors which belong to service relationships that are now gone
  451.     if (
  452.         (descriptor->state != H323PeerElementDescriptor::Deleted) &&
  453.         (descriptor->creator >= RemoteServiceRelationshipOrdinal) && 
  454.         !localServiceOrdinals.Contains(descriptor->creator)
  455.        )
  456.       descriptor->state = H323PeerElementDescriptor::Deleted;
  457.  
  458.     UpdateDescriptor(descriptor);
  459.   }
  460.  
  461.   monitorTickle.Signal();
  462.  
  463.   PTRACE(2, "PeerElement\tDescriptor update thread ended");
  464. }
  465.  
  466. void H323PeerElement::TickleMonitor(PTimer &, INT)
  467. {
  468.   monitorTickle.Signal();
  469. }
  470.  
  471. ///////////////////////////////////////////////////////////
  472. //
  473. // service relationship functions
  474. //
  475.  
  476. H323PeerElementServiceRelationship * H323PeerElement::CreateServiceRelationship()
  477. {
  478.   return new H323PeerElementServiceRelationship();
  479. }
  480.  
  481. BOOL H323PeerElement::SetOnlyServiceRelationship(const PString & peer, BOOL keepTrying)
  482. {
  483.   if (peer.IsEmpty()) {
  484.     RemoveAllServiceRelationships();
  485.     return TRUE;
  486.   }
  487.  
  488.   for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++)
  489.     if (sr->peer != peer)
  490.       RemoveServiceRelationship(sr->peer);
  491.  
  492.   return AddServiceRelationship(peer, keepTrying);
  493. }
  494.  
  495. BOOL H323PeerElement::AddServiceRelationship(const H323TransportAddress & addr, BOOL keepTrying)
  496. {
  497.   OpalGloballyUniqueID serviceID;
  498.   return AddServiceRelationship(addr, serviceID, keepTrying);
  499. }
  500.  
  501. BOOL H323PeerElement::AddServiceRelationship(const H323TransportAddress & addr, OpalGloballyUniqueID & serviceID, BOOL keepTrying)
  502.  
  503. {
  504.   switch (ServiceRequestByAddr(addr, serviceID)) {
  505.     case Confirmed:
  506.     case ServiceRelationshipReestablished:
  507.       return TRUE;
  508.  
  509.     case NoResponse:
  510.       if (!keepTrying)
  511.         return FALSE;
  512.       break;    
  513.     
  514.     case Rejected:
  515.     case NoServiceRelationship:
  516.     default:
  517.       return FALSE;
  518.   }
  519.  
  520.   PTRACE(2, "PeerElement\tRetrying ServiceRequest to " << addr << " in " << ServiceRequestRetryTime);
  521.  
  522.   // this will cause the polling routines to keep trying to establish a new service relationship
  523.   H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
  524.   sr->peer = addr;
  525.   sr->expireTime = PTime() + (ServiceRequestRetryTime * 1000);
  526.   {
  527.     PWaitAndSignal m(basePeerOrdinalMutex);
  528.     sr->ordinal = basePeerOrdinal++;
  529.   }
  530.   {
  531.     PWaitAndSignal m(remotePeerListMutex);
  532.     remotePeerAddrToServiceID.SetAt(addr, sr->serviceID.AsString());
  533.     remotePeerAddrToOrdinalKey.SetAt(addr, new POrdinalKey(sr->ordinal));
  534.   }
  535.   remoteServiceRelationships.Append(sr);
  536.  
  537.   monitorTickle.Signal();
  538.  
  539.   return TRUE;
  540. }
  541.  
  542. BOOL H323PeerElement::RemoveServiceRelationship(const OpalGloballyUniqueID & serviceID, int reason)
  543. {
  544.   {
  545.     PWaitAndSignal m(remotePeerListMutex);
  546.  
  547.     // if no service relationship exists for this peer, then nothing to do
  548.     PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
  549.     if (sr == NULL) {
  550.       return FALSE;
  551.     }
  552.   }
  553.  
  554.   return ServiceRelease(serviceID, reason);
  555. }
  556.  
  557.  
  558. BOOL H323PeerElement::RemoveServiceRelationship(const H323TransportAddress & peer, int reason)
  559. {
  560.   OpalGloballyUniqueID serviceID;
  561.  
  562.   // if no service relationship exists for this peer, then nothing to do
  563.   {
  564.     PWaitAndSignal m(remotePeerListMutex);
  565.     if (!remotePeerAddrToServiceID.Contains(peer)) {
  566.       remotePeerListMutex.Signal();
  567.       return FALSE;
  568.     }
  569.     serviceID = remotePeerAddrToServiceID[peer];
  570.   }
  571.  
  572.   return ServiceRelease(serviceID, reason);
  573. }
  574.  
  575. BOOL H323PeerElement::RemoveAllServiceRelationships()
  576. {
  577.   // if a service relationship exists for this peer, then reconfirm it
  578.   for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++)
  579.     RemoveServiceRelationship(sr->peer);
  580.  
  581.   return TRUE;
  582. }
  583.  
  584. H323PeerElement::Error H323PeerElement::ServiceRequestByAddr(const H323TransportAddress & peer, OpalGloballyUniqueID & serviceID)
  585. {
  586.   if (PAssertNULL(transport) == NULL)
  587.     return NoResponse;
  588.  
  589.   // if a service relationship exists for this peer, then reconfirm it
  590.   remotePeerListMutex.Wait();
  591.   if (remotePeerAddrToServiceID.Contains(peer)) {
  592.     serviceID = remotePeerAddrToServiceID[peer];
  593.     remotePeerListMutex.Signal();
  594.     return ServiceRequestByID(serviceID);
  595.   }
  596.   remotePeerListMutex.Signal();
  597.  
  598.   // create a new service relationship
  599.   H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
  600.  
  601.   // build the service request
  602.   H501PDU pdu;
  603.   H323TransportAddressArray interfaces = GetInterfaceAddresses();
  604.   H501_ServiceRequest & body = pdu.BuildServiceRequest(GetNextSequenceNumber(), interfaces);
  605.  
  606.   // include the element indentifier
  607.   body.IncludeOptionalField(H501_ServiceRequest::e_elementIdentifier);
  608.   body.m_elementIdentifier = localIdentifier;
  609.  
  610.   // send the request
  611.   Request request(pdu.GetSequenceNumber(), pdu, peer);
  612.   H501PDU reply;
  613.   request.responseInfo = &reply;
  614.   if (!MakeRequest(request))  {
  615.     delete sr;
  616.     switch (request.responseResult) {
  617.       case Request::NoResponseReceived :
  618.         PTRACE(2, "PeerElement\tServiceRequest to " << peer << " failed due to no response");
  619.         return NoResponse;
  620.  
  621.       case Request::RejectReceived:
  622.         PTRACE(2, "PeerElement\tServiceRequest to " << peer << " rejected for reason " << request.rejectReason);
  623.         break;
  624.  
  625.       default:
  626.         PTRACE(2, "PeerElement\tServiceRequest to " << peer << " refused with unknown response " << (int)request.responseResult);
  627.         break;
  628.     }
  629.     return Rejected;
  630.   }
  631.  
  632.   // reply must contain a service ID
  633.   if (!reply.m_common.HasOptionalField(H501_MessageCommonInfo::e_serviceID)) {
  634.     PTRACE(1, "PeerElement\tServiceConfirmation contains no serviceID");
  635.     delete sr;
  636.     return Rejected;
  637.   }
  638.  
  639.   // create the service relationship
  640.   H501_ServiceConfirmation & replyBody = reply.m_body;
  641.   sr->peer = peer;
  642.   sr->serviceID = reply.m_common.m_serviceID;
  643.   sr->expireTime = PTime() + 1000 * ((replyBody.m_timeToLive < ServiceRequestRetryTime) ? (int)replyBody.m_timeToLive : ServiceRequestRetryTime);
  644.   sr->lastUpdateTime = PTime();
  645.   serviceID = sr->serviceID;
  646.  
  647.   {
  648.     if (sr->ordinal == LocalServiceRelationshipOrdinal) {
  649.       {
  650.         PWaitAndSignal m(basePeerOrdinalMutex);
  651.         sr->ordinal = basePeerOrdinal++;
  652.       }
  653.       {
  654.         PWaitAndSignal m(remotePeerListMutex);
  655.         remotePeerAddrToServiceID.SetAt(peer, sr->serviceID.AsString());
  656.         remotePeerAddrToOrdinalKey.SetAt(peer, new POrdinalKey(sr->ordinal));
  657.       }
  658.     }
  659.   }
  660.  
  661.   remoteServiceRelationships.Append(sr);
  662.  
  663.   PTRACE(2, "PeerElement\tNew service relationship established with " << peer << " - next update in " << replyBody.m_timeToLive);
  664.   OnAddServiceRelationship(peer);
  665.  
  666.   // mark all descriptors as needing an update
  667.   for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadWrite); descriptor != NULL; descriptor++) {
  668.     if (descriptor->state == H323PeerElementDescriptor::Clean)
  669.       descriptor->state = H323PeerElementDescriptor::Dirty;
  670.   }
  671.  
  672.   monitorTickle.Signal();
  673.   return Confirmed;
  674. }
  675.  
  676.  
  677. H323PeerElement::Error H323PeerElement::ServiceRequestByID(OpalGloballyUniqueID & serviceID)
  678. {
  679.   if (PAssertNULL(transport) == NULL)
  680.     return NoResponse;
  681.  
  682.   // build the service request
  683.   H501PDU pdu;
  684.   H501_ServiceRequest & body = pdu.BuildServiceRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
  685.  
  686.   // include the element indentifier
  687.   body.IncludeOptionalField(H501_ServiceRequest::e_elementIdentifier);
  688.   body.m_elementIdentifier = localIdentifier;
  689.  
  690.   // check to see if we have a service relationship with the peer already
  691.   PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
  692.   if (sr == NULL)
  693.     return NoServiceRelationship;
  694.  
  695.   // setup to update the old service relationship
  696.   pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
  697.   pdu.m_common.m_serviceID = sr->serviceID;
  698.   Request request(pdu.GetSequenceNumber(), pdu, sr->peer);
  699.   H501PDU reply;
  700.   request.responseInfo = &reply;
  701.  
  702.   if (MakeRequest(request)) {
  703.     H501_ServiceConfirmation & replyBody = reply.m_body;
  704.     sr->expireTime = PTime() + 1000 * ((replyBody.m_timeToLive < ServiceRequestRetryTime) ? (int)replyBody.m_timeToLive : ServiceRequestRetryTime);
  705.     sr->lastUpdateTime = PTime();
  706.     PTRACE(2, "PeerElement\tConfirmed service relationship with " << sr->peer << " - next update in " << replyBody.m_timeToLive);
  707.     return Confirmed;
  708.   }
  709.  
  710.   // if cannot update, then try again after 60 seconds
  711.   switch (request.responseResult) {
  712.     case Request::NoResponseReceived :
  713.       PTRACE(2, "PeerElement\tNo response to ServiceRequest - trying again in " << ServiceRequestRetryTime);
  714.       sr->expireTime = PTime() + (ServiceRequestRetryTime * 1000);
  715.       monitorTickle.Signal();
  716.       return NoResponse;
  717.  
  718.     case Request::RejectReceived:
  719.       switch (request.rejectReason) {
  720.         case H501_ServiceRejectionReason::e_unknownServiceID:
  721.           if (OnRemoteServiceRelationshipDisappeared(serviceID, sr->peer))
  722.             return Confirmed;
  723.           break;
  724.  
  725.         default:
  726.           PTRACE(2, "PeerElement\tServiceRequest to " << sr->peer << " rejected with unknown reason " << request.rejectReason);
  727.           break;
  728.       }
  729.       break;
  730.  
  731.     default:
  732.       PTRACE(2, "PeerElement\tServiceRequest to " << sr->peer << " failed with unknown response " << (int)request.responseResult);
  733.       break;
  734.   }
  735.  
  736.   return Rejected;
  737. }
  738.  
  739. H323Transaction::Response H323PeerElement::OnServiceRequest(H501ServiceRequest & info)
  740. {
  741.   info.SetRejectReason(H501_ServiceRejectionReason::e_serviceUnavailable);
  742.   return H323Transaction::Reject;
  743. }
  744.  
  745. H323Transaction::Response H323PeerElement::HandleServiceRequest(H501ServiceRequest & info)
  746. {
  747.   // if a serviceID is specified, this is should be an existing service relationship
  748.   if (info.requestCommon.HasOptionalField(H501_MessageCommonInfo::e_serviceID)) {
  749.  
  750.     // check to see if we have a service relationship with the peer already
  751.     OpalGloballyUniqueID serviceID(info.requestCommon.m_serviceID);
  752.     PSafePtr<H323PeerElementServiceRelationship> sr = localServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
  753.     if (sr == NULL) {
  754.       PTRACE(2, "PeerElement\nRejecting unknown service ID " << serviceID << " received from peer " << info.GetReplyAddress());
  755.       info.SetRejectReason(H501_ServiceRejectionReason::e_unknownServiceID);
  756.       return H323Transaction::Reject;
  757.     }
  758.  
  759.     // include service ID, local and domain identifiers
  760.     info.confirmCommon.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
  761.     info.confirmCommon.m_serviceID = sr->serviceID;
  762.     info.scf.m_elementIdentifier = GetLocalName();
  763.     H323SetAliasAddress(GetDomainName(), info.scf.m_domainIdentifier);
  764.  
  765.     // include time to live
  766.     info.scf.IncludeOptionalField(H501_ServiceConfirmation::e_timeToLive);
  767.     info.scf.m_timeToLive = ServiceRelationshipTimeToLive;
  768.     sr->lastUpdateTime = PTime();
  769.     sr->expireTime = PTime() + (info.scf.m_timeToLive * 1000);
  770.  
  771.     PTRACE(2, "PeerElement\nService relationship with " << sr->name << " at " << info.GetReplyAddress() << " updated - next update in " << info.scf.m_timeToLive);
  772.     return H323Transaction::Confirm;
  773.   }
  774.  
  775.   H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
  776.  
  777.   // get the name of the remote element
  778.   if (info.srq.HasOptionalField(H501_ServiceRequest::e_elementIdentifier))
  779.     sr->name = info.srq.m_elementIdentifier;
  780.  
  781.   // include service ID, local and domain identifiers
  782.   info.confirmCommon.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
  783.   info.confirmCommon.m_serviceID = sr->serviceID;
  784.   info.scf.m_elementIdentifier = GetLocalName();
  785.   H323SetAliasAddress(GetDomainName(), info.scf.m_domainIdentifier);
  786.  
  787.   // include time to live
  788.   info.scf.IncludeOptionalField(H501_ServiceConfirmation::e_timeToLive);
  789.   info.scf.m_timeToLive = ServiceRelationshipTimeToLive;
  790.   if (info.requestCommon.HasOptionalField(H501_MessageCommonInfo::e_replyAddress) && info.requestCommon.m_replyAddress.GetSize() > 0)
  791.     sr->peer = info.requestCommon.m_replyAddress[0];
  792.   else
  793.     sr->peer = transport->GetLastReceivedAddress();
  794.   sr->lastUpdateTime = PTime();
  795.   sr->expireTime = PTime() + (info.scf.m_timeToLive * 1000);
  796.   {
  797.     H323TransportAddress addr = transport->GetLastReceivedAddress();
  798.     {
  799.       PWaitAndSignal m(basePeerOrdinalMutex);
  800.       sr->ordinal = basePeerOrdinal++;
  801.     }
  802.     {
  803.       PWaitAndSignal m(localPeerListMutex);
  804.       localServiceOrdinals += sr->ordinal;
  805.     }
  806.   }
  807.  
  808.   // add to the list of known relationships
  809.   localServiceRelationships.Append(sr);
  810.   monitorTickle.Signal();
  811.  
  812.   // send the response
  813.   PTRACE(2, "PeerElement\nNew service relationship with " << sr->name << " at " << info.GetReplyAddress() << " created - next update in " << info.scf.m_timeToLive);
  814.   return H323Transaction::Confirm;
  815. }
  816.  
  817. BOOL H323PeerElement::OnReceiveServiceRequest(const H501PDU & pdu, const H501_ServiceRequest & /*pduBody*/)
  818. {
  819.   H501ServiceRequest * info = new H501ServiceRequest(*this, pdu);
  820.   if (!info->HandlePDU())
  821.     delete info;
  822.  
  823.   return FALSE;
  824. }
  825.  
  826. BOOL H323PeerElement::OnReceiveServiceConfirmation(const H501PDU & pdu, const H501_ServiceConfirmation & pduBody)
  827. {
  828.   if (!H323_AnnexG::OnReceiveServiceConfirmation(pdu, pduBody))
  829.     return FALSE;
  830.  
  831.   if (lastRequest->responseInfo != NULL)
  832.     *(H501PDU *)lastRequest->responseInfo = pdu;
  833.  
  834.   return TRUE;
  835. }
  836.  
  837. BOOL H323PeerElement::ServiceRelease(const OpalGloballyUniqueID & serviceID, unsigned reason)
  838. {
  839.   // remove any previous check to see if we have a service relationship with the peer already
  840.   PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
  841.   if (sr == NULL)
  842.     return FALSE;
  843.  
  844.   // send the request - no response
  845.   H501PDU pdu;
  846.   H501_ServiceRelease & body = pdu.BuildServiceRelease(GetNextSequenceNumber());
  847.   pdu.m_common.m_serviceID = sr->serviceID;
  848.   body.m_reason = reason;
  849.   WriteTo(pdu, sr->peer);
  850.  
  851.   OnRemoveServiceRelationship(sr->peer);
  852.   InternalRemoveServiceRelationship(sr->peer);
  853.   remoteServiceRelationships.Remove(sr);
  854.  
  855.   return TRUE;
  856. }
  857.  
  858. BOOL H323PeerElement::OnRemoteServiceRelationshipDisappeared(OpalGloballyUniqueID & serviceID, const H323TransportAddress & peer)
  859. {
  860.   OpalGloballyUniqueID oldServiceID = serviceID;
  861.  
  862.   // the service ID specified is now gone
  863.   PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
  864.   if (sr != NULL)
  865.     remoteServiceRelationships.Remove(sr);
  866.   InternalRemoveServiceRelationship(peer);
  867.  
  868.   // attempt to create a new service relationship
  869.   if (ServiceRequestByAddr(peer, serviceID) != Confirmed) { 
  870.     PTRACE(2, "PeerElement\tService relationship with " << peer << " disappeared and refused new relationship");
  871.     OnRemoveServiceRelationship(peer);
  872.     return FALSE;
  873.   }
  874.  
  875.   // we have a new service ID
  876.   PTRACE(2, "PeerElement\tService relationship with " << peer << " disappeared and new relationship established");
  877.   serviceID = remotePeerAddrToServiceID(peer);
  878.  
  879.   return TRUE;
  880. }
  881.  
  882. void H323PeerElement::InternalRemoveServiceRelationship(const H323TransportAddress & peer)
  883. {
  884.   {
  885.     PWaitAndSignal m(remotePeerListMutex);
  886.     remotePeerAddrToServiceID.RemoveAt(peer);
  887.     remotePeerAddrToOrdinalKey.RemoveAt(peer);
  888.   }
  889.   monitorTickle.Signal();
  890. }
  891.  
  892.  
  893.  
  894. ///////////////////////////////////////////////////////////
  895. //
  896. // descriptor table functions
  897. //
  898.  
  899. H323PeerElementDescriptor * H323PeerElement::CreateDescriptor(const OpalGloballyUniqueID & descriptorID)
  900. {
  901.   return new H323PeerElementDescriptor(descriptorID);
  902. }
  903.  
  904. BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
  905.                                             const PStringArray & aliasStrings, 
  906.                                const H323TransportAddressArray & transportAddresses, 
  907.                                                         unsigned options, 
  908.                                                             BOOL now)
  909. {
  910.   // convert transport addresses to aliases
  911.   H225_ArrayOf_AliasAddress aliases;
  912.   H323SetAliasAddresses(aliasStrings, aliases);
  913.   return AddDescriptor(descriptorID,
  914.                        aliases, transportAddresses, options, now);
  915. }
  916.  
  917.  
  918. BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
  919.                                const H225_ArrayOf_AliasAddress & aliases, 
  920.                                const H323TransportAddressArray & transportAddresses, 
  921.                                                         unsigned options, 
  922.                                                             BOOL now)
  923. {
  924.   H225_ArrayOf_AliasAddress addresses;
  925.   H323SetAliasAddresses(transportAddresses, addresses);
  926.   return AddDescriptor(descriptorID,
  927.                        LocalServiceRelationshipOrdinal,
  928.                        aliases, addresses, options, now);
  929. }
  930.  
  931.  
  932. BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
  933.                                const H225_ArrayOf_AliasAddress & aliases, 
  934.                                const H225_ArrayOf_AliasAddress & transportAddress, 
  935.                                                         unsigned options, 
  936.                                                             BOOL now)
  937. {
  938.   // create a new descriptor
  939.   return AddDescriptor(descriptorID,
  940.                        LocalServiceRelationshipOrdinal,
  941.                        aliases, transportAddress, options, now);
  942. }
  943.  
  944. BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
  945.                                              const POrdinalKey & creator,
  946.                                const H225_ArrayOf_AliasAddress & aliases, 
  947.                                const H225_ArrayOf_AliasAddress & transportAddresses, 
  948.                                                         unsigned options, 
  949.                                                             BOOL now)
  950. {
  951.   // create an const H501_ArrayOf_AddressTemplate with the template information
  952.   H501_ArrayOf_AddressTemplate addressTemplates;
  953.  
  954.   // copy data into the descriptor
  955.   addressTemplates.SetSize(1);
  956.   H225_EndpointType epType;
  957.   endpoint.SetEndpointTypeInfo(epType);
  958.   H323PeerElementDescriptor::CopyToAddressTemplate(addressTemplates[0], epType, aliases, transportAddresses, options);
  959.  
  960.   return AddDescriptor(descriptorID, creator, addressTemplates, now);
  961. }
  962.  
  963. BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
  964.                                              const POrdinalKey & creator,
  965.                             const H501_ArrayOf_AddressTemplate & addressTemplates,
  966.                                                    const PTime & updateTime,
  967.                                                             BOOL now)
  968. {
  969.   // see if there is actually a descriptor with this ID
  970.   PSafePtr<H323PeerElementDescriptor> descriptor = descriptors.FindWithLock(H323PeerElementDescriptor(descriptorID), PSafeReadWrite);
  971.   H501_UpdateInformation_updateType::Choices updateType = H501_UpdateInformation_updateType::e_changed;
  972.   BOOL add = FALSE;
  973.   {
  974.     PWaitAndSignal m(aliasMutex);
  975.     if (descriptor != NULL) {
  976.       RemoveDescriptorInformation(descriptor->addressTemplates);
  977.  
  978.       // only update if the update time is later than what we already have
  979.       if (updateTime < descriptor->lastChanged)
  980.         return TRUE;
  981.  
  982.     } else {
  983.       add = TRUE;
  984.       descriptor                   = CreateDescriptor(descriptorID);
  985.       descriptor->creator          = creator;
  986.       descriptor->addressTemplates = addressTemplates;
  987.       updateType                   = H501_UpdateInformation_updateType::e_added;
  988.     }
  989.     descriptor->lastChanged = PTime();
  990.  
  991.     // add all patterns and transport addresses to secondary lookup tables
  992.     PINDEX i, j, k;
  993.     for (i = 0; i < descriptor->addressTemplates.GetSize(); i++) {
  994.       H501_AddressTemplate & addressTemplate = addressTemplates[i];
  995.  
  996.       // add patterns for this descriptor
  997.       for (j = 0; j < addressTemplate.m_pattern.GetSize(); j++) {
  998.         H501_Pattern & pattern = addressTemplate.m_pattern[j];
  999.         switch (pattern.GetTag()) {
  1000.           case H501_Pattern::e_specific:
  1001.             specificAliasToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)pattern, descriptorID, i, FALSE));
  1002.             break;
  1003.           case H501_Pattern::e_wildcard:
  1004.             wildcardAliasToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)pattern, descriptorID, i, TRUE));
  1005.             break;
  1006.           case H501_Pattern::e_range:
  1007.             break;
  1008.         }
  1009.       }
  1010.  
  1011.       // add transport addresses for this descriptor
  1012.       H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
  1013.       for (j = 0; j < routeInfos.GetSize(); j++) {
  1014.         H501_ArrayOf_ContactInformation & contacts = routeInfos[j].m_contacts;
  1015.         for (k = 0; k < contacts.GetSize(); k++) {
  1016.           H501_ContactInformation & contact = contacts[k];
  1017.           H225_AliasAddress & transportAddress = contact.m_transportAddress;
  1018.           transportAddressToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)transportAddress, descriptorID, i));
  1019.         }
  1020.       }
  1021.     }
  1022.   }
  1023.  
  1024.   if (!add)
  1025.     OnUpdateDescriptor(*descriptor);
  1026.   else {
  1027.     descriptors.Append(descriptor);
  1028.     OnNewDescriptor(*descriptor);
  1029.   }
  1030.  
  1031.   // do the update now, or later
  1032.   if (now) {
  1033.     PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " added/updated");
  1034.     UpdateDescriptor(descriptor, updateType);
  1035.   } else if (descriptor->state != H323PeerElementDescriptor::Deleted) {
  1036.     PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " queued to be added");
  1037.     descriptor->state = H323PeerElementDescriptor::Dirty;
  1038.     monitorTickle.Signal();
  1039.   }
  1040.  
  1041.   return TRUE;
  1042. }
  1043.   
  1044. H323PeerElement::AliasKey * H323PeerElement::CreateAliasKey(const H225_AliasAddress & alias, const OpalGloballyUniqueID & id, PINDEX pos, BOOL wild)
  1045. {
  1046.   return new AliasKey(alias, id, pos, wild);
  1047. }
  1048.  
  1049. void H323PeerElement::RemoveDescriptorInformation(const H501_ArrayOf_AddressTemplate & addressTemplates)
  1050. {
  1051.   PWaitAndSignal m(aliasMutex);
  1052.   PINDEX i, j, k, idx;
  1053.  
  1054.   // remove all patterns and transport addresses for this descriptor
  1055.   for (i = 0; i < addressTemplates.GetSize(); i++) {
  1056.     H501_AddressTemplate & addressTemplate = addressTemplates[i];
  1057.  
  1058.     // remove patterns for this descriptor
  1059.     for (j = 0; j < addressTemplate.m_pattern.GetSize(); j++) {
  1060.       H501_Pattern & pattern = addressTemplate.m_pattern[j];
  1061.       switch (pattern.GetTag()) {
  1062.         case H501_Pattern::e_specific:
  1063.           idx = specificAliasToDescriptorID.GetValuesIndex((H225_AliasAddress &)pattern);
  1064.           if (idx != P_MAX_INDEX)
  1065.             specificAliasToDescriptorID.RemoveAt(idx);
  1066.           break;
  1067.         case H501_Pattern::e_wildcard:
  1068.           idx = wildcardAliasToDescriptorID.GetValuesIndex((H225_AliasAddress &)pattern);
  1069.           if (idx != P_MAX_INDEX)
  1070.             wildcardAliasToDescriptorID.RemoveAt(idx);
  1071.           break;
  1072.         case H501_Pattern::e_range:
  1073.           break;
  1074.       }
  1075.     }
  1076.  
  1077.     // remove transport addresses for this descriptor
  1078.     H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
  1079.     for (j = 0; j < routeInfos.GetSize(); j++) {
  1080.       H501_ArrayOf_ContactInformation & contacts = routeInfos[i].m_contacts;
  1081.       for (k = 0; k < contacts.GetSize(); k++) {
  1082.         H501_ContactInformation & contact = contacts[k];
  1083.         H225_AliasAddress & transportAddress = contact.m_transportAddress;
  1084.         idx = transportAddressToDescriptorID.GetValuesIndex(transportAddress);
  1085.         if (idx != P_MAX_INDEX)
  1086.           transportAddressToDescriptorID.RemoveAt(idx);
  1087.       }
  1088.     }
  1089.   }
  1090. }
  1091.  
  1092. BOOL H323PeerElement::DeleteDescriptor(const PString & str, BOOL now)
  1093. {
  1094.   H225_AliasAddress alias;
  1095.   H323SetAliasAddress(str, alias);
  1096.   return DeleteDescriptor(alias, now);
  1097. }
  1098.  
  1099. BOOL H323PeerElement::DeleteDescriptor(const H225_AliasAddress & alias, BOOL now)
  1100. {
  1101.   OpalGloballyUniqueID descriptorID("");
  1102.  
  1103.   // find the descriptor ID for the descriptor
  1104.   {
  1105.     PWaitAndSignal m(aliasMutex);
  1106.     PINDEX idx = specificAliasToDescriptorID.GetValuesIndex(alias);
  1107.     if (idx == P_MAX_INDEX)
  1108.       return FALSE;
  1109.     descriptorID = ((AliasKey &)specificAliasToDescriptorID[idx]).id;
  1110.   }
  1111.  
  1112.   return DeleteDescriptor(descriptorID, now);
  1113. }
  1114.  
  1115. BOOL H323PeerElement::DeleteDescriptor(const OpalGloballyUniqueID & descriptorID, BOOL now)
  1116. {
  1117.   // see if there is a descriptor with this ID
  1118.   PSafePtr<H323PeerElementDescriptor> descriptor = descriptors.FindWithLock(H323PeerElementDescriptor(descriptorID), PSafeReadWrite);
  1119.   if (descriptor == NULL)
  1120.     return FALSE;
  1121.  
  1122.   OnRemoveDescriptor(*descriptor);
  1123.  
  1124.   RemoveDescriptorInformation(descriptor->addressTemplates);
  1125.  
  1126.   // delete the descriptor, or mark it as to be deleted
  1127.   if (now) {
  1128.     PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " deleted");
  1129.     UpdateDescriptor(descriptor, H501_UpdateInformation_updateType::e_deleted);
  1130.   } else {
  1131.     PTRACE(2, "PeerElement\tDescriptor for " << descriptorID << " queued to be deleted");
  1132.     descriptor->state = H323PeerElementDescriptor::Deleted;
  1133.     monitorTickle.Signal();
  1134.   }
  1135.  
  1136.   return TRUE;
  1137. }
  1138.  
  1139. BOOL H323PeerElement::UpdateDescriptor(H323PeerElementDescriptor * descriptor)
  1140. {
  1141.   H501_UpdateInformation_updateType::Choices updateType = H501_UpdateInformation_updateType::e_changed;
  1142.   switch (descriptor->state) {
  1143.     case H323PeerElementDescriptor::Clean:
  1144.       return TRUE;
  1145.     
  1146.     case H323PeerElementDescriptor::Dirty:
  1147.       break;
  1148.  
  1149.     case H323PeerElementDescriptor::Deleted:
  1150.       updateType = H501_UpdateInformation_updateType::e_deleted;
  1151.       break;
  1152.   }
  1153.  
  1154.   return UpdateDescriptor(descriptor, updateType);
  1155. }
  1156.  
  1157. BOOL H323PeerElement::UpdateDescriptor(H323PeerElementDescriptor * descriptor, H501_UpdateInformation_updateType::Choices updateType)
  1158. {
  1159.   if (updateType == H501_UpdateInformation_updateType::e_deleted)
  1160.     descriptor->state = H323PeerElementDescriptor::Deleted;
  1161.   else if (descriptor->state == H323PeerElementDescriptor::Deleted)
  1162.     updateType = H501_UpdateInformation_updateType::e_deleted;
  1163.   else if (descriptor->state == H323PeerElementDescriptor::Clean)
  1164.     return TRUE;
  1165.   else
  1166.     descriptor->state = H323PeerElementDescriptor::Clean;
  1167.  
  1168.   for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
  1169.     SendUpdateDescriptorByID(sr->serviceID, descriptor, updateType);
  1170.   }
  1171.  
  1172.   if (descriptor->state == H323PeerElementDescriptor::Deleted)
  1173.     descriptors.Remove(descriptor);
  1174.  
  1175.   return TRUE;
  1176. }
  1177.  
  1178. ///////////////////////////////////////////////////////////
  1179. //
  1180. // descriptor peer element functions
  1181. //
  1182.  
  1183. H323PeerElement::Error H323PeerElement::SendUpdateDescriptorByID(const OpalGloballyUniqueID & serviceID, 
  1184.                                                               H323PeerElementDescriptor * descriptor, 
  1185.                                                H501_UpdateInformation_updateType::Choices updateType)
  1186. {
  1187.   if (PAssertNULL(transport) == NULL)
  1188.     return NoResponse;
  1189.  
  1190.   H501PDU pdu;
  1191.   pdu.BuildDescriptorUpdate(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
  1192.   H323TransportAddress peer;
  1193.  
  1194.   // put correct service descriptor into the common data
  1195.   {
  1196.     // check to see if we have a service relationship with the peer already
  1197.     PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
  1198.  
  1199.     // if there is no service relationship, then nothing to do
  1200.     if (sr == NULL)
  1201.       return NoServiceRelationship;
  1202.  
  1203.     pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
  1204.     pdu.m_common.m_serviceID = sr->serviceID;
  1205.     peer = sr->peer;
  1206.   }
  1207.  
  1208.   return SendUpdateDescriptor(pdu, peer, descriptor, updateType);
  1209. }
  1210.  
  1211. H323PeerElement::Error H323PeerElement::SendUpdateDescriptorByAddr(const H323TransportAddress & peer, 
  1212.                                                               H323PeerElementDescriptor * descriptor, 
  1213.                                                H501_UpdateInformation_updateType::Choices updateType)
  1214. {
  1215.   if (PAssertNULL(transport) == NULL)
  1216.     return NoResponse;
  1217.  
  1218.   H501PDU pdu;
  1219.   pdu.BuildDescriptorUpdate(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
  1220.   return SendUpdateDescriptor(pdu, peer, descriptor, updateType);
  1221. }
  1222.  
  1223. H323PeerElement::Error H323PeerElement::SendUpdateDescriptor(H501PDU & pdu, 
  1224.                                           const H323TransportAddress & peer, 
  1225.                                            H323PeerElementDescriptor * descriptor,
  1226.                             H501_UpdateInformation_updateType::Choices updateType)
  1227. {
  1228.   if (PAssertNULL(transport) == NULL)
  1229.     return NoResponse;
  1230.  
  1231.   H501_DescriptorUpdate & body = pdu.m_body;
  1232.  
  1233.   // put in sender address
  1234.   H323TransportAddressArray addrs = GetInterfaceAddresses();
  1235.   PAssert(addrs.GetSize() > 0, "No interface addresses");
  1236.   H323SetAliasAddress(addrs[0], body.m_sender, H225_AliasAddress::e_transportID);
  1237.  
  1238.   // add information
  1239.   body.m_updateInfo.SetSize(1);
  1240.   H501_UpdateInformation & info = body.m_updateInfo[0];
  1241.   info.m_descriptorInfo.SetTag(H501_UpdateInformation_descriptorInfo::e_descriptor);
  1242.   info.m_updateType.SetTag(updateType);
  1243.   descriptor->CopyTo(info.m_descriptorInfo);
  1244.  
  1245.   // make the request
  1246.   Request request(pdu.GetSequenceNumber(), pdu, peer);
  1247.   if (MakeRequest(request))
  1248.     return Confirmed;
  1249.  
  1250.   // if error was no service relationship, then establish relationship and try again
  1251.   switch (request.responseResult) {
  1252.     case Request::NoResponseReceived :
  1253.       PTRACE(2, "PeerElement\tUpdateDescriptor to " << peer << " failed due to no response");
  1254.       break;
  1255.  
  1256.     default:
  1257.       PTRACE(2, "PeerElement\tUpdateDescriptor to " << peer << " refused with unknown response " << (int)request.responseResult);
  1258.       return Rejected;
  1259.   }
  1260.  
  1261.   return Rejected;
  1262. }
  1263.  
  1264. H323Transaction::Response H323PeerElement::OnDescriptorUpdate(H501DescriptorUpdate & /*info*/)
  1265. {
  1266.   return H323Transaction::Ignore;
  1267. }
  1268.  
  1269. BOOL H323PeerElement::OnReceiveDescriptorUpdate(const H501PDU & pdu, const H501_DescriptorUpdate & /*pduBody*/)
  1270. {
  1271.   H501DescriptorUpdate * info = new H501DescriptorUpdate(*this, pdu);
  1272.   if (!info->HandlePDU())
  1273.     delete info;
  1274.  
  1275.   return FALSE;
  1276. }
  1277.  
  1278. BOOL H323PeerElement::OnReceiveDescriptorUpdateACK(const H501PDU & pdu, const H501_DescriptorUpdateAck & pduBody)
  1279. {
  1280.   if (!H323_AnnexG::OnReceiveDescriptorUpdateACK(pdu, pduBody))
  1281.     return FALSE;
  1282.  
  1283.   if (lastRequest->responseInfo != NULL)
  1284.     *(H501_MessageCommonInfo *)lastRequest->responseInfo = pdu.m_common;
  1285.  
  1286.   return TRUE;
  1287. }
  1288.  
  1289. ///////////////////////////////////////////////////////////
  1290. //
  1291. // access request functions
  1292. //
  1293.  
  1294. BOOL H323PeerElement::AccessRequest(const PString & searchAlias,
  1295.                                      PStringArray & destAliases,
  1296.                             H323TransportAddress & transportAddress,
  1297.                                           unsigned options)
  1298. {
  1299.   H225_AliasAddress h225searchAlias;
  1300.   H323SetAliasAddress(searchAlias, h225searchAlias);
  1301.  
  1302.   H225_ArrayOf_AliasAddress h225destAliases;
  1303.   if (!AccessRequest(h225searchAlias, h225destAliases, transportAddress, options))
  1304.     return FALSE;
  1305.  
  1306.   destAliases = H323GetAliasAddressStrings(h225destAliases);
  1307.   return TRUE;
  1308. }
  1309.  
  1310.  
  1311. BOOL H323PeerElement::AccessRequest(const PString & searchAlias, 
  1312.                         H225_ArrayOf_AliasAddress & destAliases,
  1313.                              H323TransportAddress & transportAddress, 
  1314.                                            unsigned options)
  1315. {
  1316.   H225_AliasAddress h225searchAlias;
  1317.   H323SetAliasAddress(searchAlias, h225searchAlias);
  1318.   return AccessRequest(h225searchAlias, destAliases, transportAddress, options);
  1319. }
  1320.  
  1321. BOOL H323PeerElement::AccessRequest(const H225_AliasAddress & searchAlias, 
  1322.                                   H225_ArrayOf_AliasAddress & destAliases,
  1323.                                        H323TransportAddress & transportAddress, 
  1324.                                                      unsigned options)
  1325. {
  1326.   H225_AliasAddress h225Address;
  1327.   if (!AccessRequest(searchAlias, destAliases, h225Address, options))
  1328.     return FALSE;
  1329.  
  1330.   transportAddress = H323GetAliasAddressString(h225Address);
  1331.   return TRUE;
  1332. }
  1333.  
  1334. BOOL H323PeerElement::AccessRequest(const H225_AliasAddress & searchAlias, 
  1335.                                   H225_ArrayOf_AliasAddress & destAliases,
  1336.                                           H225_AliasAddress & transportAddress, 
  1337.                                                      unsigned options)
  1338. {
  1339.   // try each service relationship in turn
  1340.   POrdinalSet peersTried;
  1341.  
  1342.   for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
  1343.  
  1344.     // create the request
  1345.     H501PDU request;
  1346.     H501_AccessRequest & requestBody = request.BuildAccessRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
  1347.  
  1348.     // set dest information
  1349.     H501_PartyInformation & destInfo = requestBody.m_destinationInfo;
  1350.     destInfo.m_logicalAddresses.SetSize(1);
  1351.     destInfo.m_logicalAddresses[0] = searchAlias;
  1352.  
  1353.     // set protocols
  1354.     requestBody.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols);
  1355.     H323PeerElementDescriptor::SetProtocolList(requestBody.m_desiredProtocols, options);
  1356.  
  1357.     // make the request
  1358.     H501PDU reply;
  1359.     H323PeerElement::Error error = SendAccessRequestByID(sr->serviceID, request, reply);
  1360.     H323TransportAddress peerAddr = sr->peer;
  1361.  
  1362.     while (error == Confirmed) {
  1363.  
  1364.       // make sure we got at least one template
  1365.       H501_AccessConfirmation & confirm = reply.m_body;
  1366.       H501_ArrayOf_AddressTemplate & addressTemplates = confirm.m_templates;
  1367.       if (addressTemplates.GetSize() == 0) {
  1368.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no templates");
  1369.         break;
  1370.       }
  1371.       H501_AddressTemplate & addressTemplate = addressTemplates[0];
  1372.  
  1373.       // make sure patterns are returned
  1374.       H501_ArrayOf_Pattern & patterns = addressTemplate.m_pattern;
  1375.       if (patterns.GetSize() == 0) {
  1376.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no patterns");
  1377.         break;
  1378.       }
  1379.  
  1380.       // make sure routes are returned
  1381.       H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
  1382.       if (routeInfos.GetSize() == 0) {
  1383.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no routes");
  1384.         break;
  1385.       }
  1386.       H501_RouteInformation & routeInfo = addressTemplate.m_routeInfo[0];
  1387.  
  1388.       // make sure routes contain contacts
  1389.       H501_ArrayOf_ContactInformation & contacts = routeInfo.m_contacts;
  1390.       if (contacts.GetSize() == 0) {
  1391.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no contacts");
  1392.         break;
  1393.       }
  1394.       H501_ContactInformation & contact = routeInfo.m_contacts[0];
  1395.  
  1396.       // get the address
  1397.       H225_AliasAddress contactAddress = contact.m_transportAddress;
  1398.       int tag = routeInfo.m_messageType.GetTag();
  1399.       if (tag == H501_RouteInformation_messageType::e_sendAccessRequest) {
  1400.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " redirected from " << peerAddr << " to " << contactAddress);
  1401.         peerAddr = H323GetAliasAddressString(contactAddress);
  1402.       }
  1403.       else if (tag == H501_RouteInformation_messageType::e_sendSetup) {
  1404.  
  1405.         // get the dest aliases
  1406.         destAliases.SetSize(addressTemplate.m_pattern.GetSize());
  1407.         PINDEX count = 0;
  1408.         PINDEX i;
  1409.         for (i = 0; i < addressTemplate.m_pattern.GetSize(); i++) {  
  1410.           if (addressTemplate.m_pattern[i].GetTag() == H501_Pattern::e_specific) {  
  1411.              H225_AliasAddress & alias = addressTemplate.m_pattern[i];  
  1412.              destAliases[count++] = alias;  
  1413.           }  
  1414.         }  
  1415.         destAliases.SetSize(count);  
  1416.  
  1417.         transportAddress = contactAddress;
  1418.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " returned " << transportAddress << " from " << peerAddr);
  1419.         return TRUE;
  1420.       }
  1421.       else { // H501_RouteInformation_messageType::e_nonExistent
  1422.         PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " returned nonExistent");
  1423.         break;
  1424.       }
  1425.  
  1426.       // this is the address to send the new request to
  1427.       H323TransportAddress addr = peerAddr;
  1428.  
  1429.       // create the request
  1430.       H501_AccessRequest & requestBody = request.BuildAccessRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
  1431.  
  1432.       // set dest information
  1433.       H501_PartyInformation & destInfo = requestBody.m_destinationInfo;
  1434.       destInfo.m_logicalAddresses.SetSize(1);
  1435.       destInfo.m_logicalAddresses[0] = searchAlias;
  1436.  
  1437.       // set protocols
  1438.       requestBody.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols);
  1439.       H323PeerElementDescriptor::SetProtocolList(requestBody.m_desiredProtocols, options);
  1440.  
  1441.       // make the request
  1442.       error = SendAccessRequestByAddr(addr, request, reply);
  1443.     }
  1444.   }
  1445.  
  1446.   return FALSE;
  1447. }
  1448.  
  1449. ///////////////////////////////////////////////////////////
  1450. //
  1451. // access request functions
  1452. //
  1453.  
  1454. H323PeerElement::Error H323PeerElement::SendAccessRequestByID(const OpalGloballyUniqueID & origServiceID, 
  1455.                                                                                  H501PDU & pdu, 
  1456.                                                                                  H501PDU & confirmPDU)
  1457. {
  1458.   if (PAssertNULL(transport) == NULL)
  1459.     return NoResponse;
  1460.  
  1461.   OpalGloballyUniqueID serviceID = origServiceID;
  1462.  
  1463.   for (;;) {
  1464.  
  1465.     // get the peer address
  1466.     H323TransportAddress peer;
  1467.     { 
  1468.       PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
  1469.       if (sr == NULL)
  1470.         return NoServiceRelationship;
  1471.       peer = sr->peer;
  1472.     }
  1473.  
  1474.     // set the service ID
  1475.     pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
  1476.     pdu.m_common.m_serviceID = serviceID;
  1477.  
  1478.     // make the request
  1479.     Request request(pdu.GetSequenceNumber(), pdu, peer);
  1480.     request.responseInfo = &confirmPDU;
  1481.     if (MakeRequest(request))
  1482.       return Confirmed;
  1483.  
  1484.     // if error was no service relationship, then establish relationship and try again
  1485.     switch (request.responseResult) {
  1486.       case Request::NoResponseReceived :
  1487.         PTRACE(2, "PeerElement\tAccessRequest to " << peer << " failed due to no response");
  1488.         return Rejected;
  1489.  
  1490.       case Request::RejectReceived:
  1491.         switch (request.rejectReason) {
  1492.           case H501_ServiceRejectionReason::e_unknownServiceID:
  1493.             if (!OnRemoteServiceRelationshipDisappeared(serviceID, peer))
  1494.               return Rejected;
  1495.             break;
  1496.           default:
  1497.             return Rejected;
  1498.         }
  1499.         break;
  1500.  
  1501.       default:
  1502.         PTRACE(2, "PeerElement\tAccessRequest to " << peer << " refused with unknown response " << (int)request.responseResult);
  1503.         return Rejected;
  1504.     }
  1505.   }
  1506.  
  1507.   return Rejected;
  1508. }
  1509.  
  1510. H323PeerElement::Error H323PeerElement::SendAccessRequestByAddr(const H323TransportAddress & peerAddr, 
  1511.                                                                                    H501PDU & pdu, 
  1512.                                                                                    H501PDU & confirmPDU)
  1513. {
  1514.   if (PAssertNULL(transport) == NULL)
  1515.     return NoResponse;
  1516.  
  1517.   pdu.m_common.RemoveOptionalField(H501_MessageCommonInfo::e_serviceID);
  1518.  
  1519.   // make the request
  1520.   Request request(pdu.GetSequenceNumber(), pdu, peerAddr);
  1521.   request.responseInfo = &confirmPDU;
  1522.   if (MakeRequest(request))
  1523.     return Confirmed;
  1524.  
  1525.   // if error was no service relationship, then establish relationship and try again
  1526.   switch (request.responseResult) {
  1527.     case Request::NoResponseReceived :
  1528.       PTRACE(2, "PeerElement\tAccessRequest to " << peerAddr << " failed due to no response");
  1529.       break;
  1530.  
  1531.     case Request::RejectReceived:
  1532.       PTRACE(2, "PeerElement\tAccessRequest failed due to " << request.rejectReason);
  1533.       break;
  1534.  
  1535.     default:
  1536.       PTRACE(2, "PeerElement\tAccessRequest to " << peerAddr << " refused with unknown response " << (int)request.responseResult);
  1537.       break;
  1538.   }
  1539.  
  1540.   return Rejected;
  1541. }
  1542.  
  1543. H323Transaction::Response H323PeerElement::OnAccessRequest(H501AccessRequest & info)
  1544. {
  1545.   info.SetRejectReason(H501_AccessRejectionReason::e_noServiceRelationship);
  1546.   return H323Transaction::Reject;
  1547. }
  1548.  
  1549. BOOL H323PeerElement::OnReceiveAccessRequest(const H501PDU & pdu, const H501_AccessRequest & /*pduBody*/)
  1550. {
  1551.   H501AccessRequest * info = new H501AccessRequest(*this, pdu);
  1552.   if (!info->HandlePDU())
  1553.     delete info;
  1554.  
  1555.   return FALSE;
  1556. }
  1557.  
  1558. BOOL H323PeerElement::OnReceiveAccessConfirmation(const H501PDU & pdu, const H501_AccessConfirmation & pduBody)
  1559. {
  1560.   if (!H323_AnnexG::OnReceiveAccessConfirmation(pdu, pduBody))
  1561.     return FALSE;
  1562.  
  1563.   if (lastRequest->responseInfo != NULL)
  1564.     *(H501PDU *)lastRequest->responseInfo = pdu;
  1565.  
  1566.   return TRUE;
  1567. }
  1568.  
  1569. BOOL H323PeerElement::OnReceiveAccessRejection(const H501PDU & pdu, const H501_AccessRejection & pduBody)
  1570. {
  1571.   if (!H323_AnnexG::OnReceiveAccessRejection(pdu, pduBody))
  1572.     return FALSE;
  1573.  
  1574.   return TRUE;
  1575. }
  1576.  
  1577. BOOL H323PeerElement::MakeRequest(Request & request)
  1578. {
  1579.   requestMutex.Wait();
  1580.   BOOL stat = H323_AnnexG::MakeRequest(request);
  1581.   requestMutex.Signal();
  1582.   return stat;
  1583. }
  1584.  
  1585. //////////////////////////////////////////////////////////////////////////////
  1586.  
  1587. PObject::Comparison H323PeerElementDescriptor::Compare(const PObject & obj) const
  1588.   H323PeerElementDescriptor & other = (H323PeerElementDescriptor &)obj;
  1589.   return descriptorID.Compare(other.descriptorID); 
  1590. }
  1591.  
  1592. void H323PeerElementDescriptor::CopyTo(H501_Descriptor & descriptor)
  1593. {
  1594.   descriptor.m_descriptorInfo.m_descriptorID = descriptorID;
  1595.   descriptor.m_descriptorInfo.m_lastChanged  = lastChanged.AsString("yyyyMMddhhmmss", PTime::GMT);
  1596.   descriptor.m_templates                     = addressTemplates;
  1597.  
  1598.   if (!gatekeeperID.IsEmpty()) {
  1599.     descriptor.IncludeOptionalField(H501_Descriptor::e_gatekeeperID);
  1600.     descriptor.m_gatekeeperID = gatekeeperID;
  1601.   }
  1602. }
  1603.  
  1604.  
  1605. BOOL H323PeerElementDescriptor::ContainsNonexistent()
  1606. {
  1607.   BOOL blocked = FALSE;
  1608.  
  1609.   // look for any nonexistent routes, which means this descriptor does NOT match
  1610.   PINDEX k, j;
  1611.   for (k = 0; !blocked && (k < addressTemplates.GetSize()); k++) {
  1612.       H501_ArrayOf_RouteInformation & routeInfo = addressTemplates[k].m_routeInfo;
  1613.     for (j = 0; !blocked && (j < routeInfo.GetSize()); j++) {
  1614.       if (routeInfo[j].m_messageType.GetTag() == H501_RouteInformation_messageType::e_nonExistent)
  1615.         blocked = TRUE;
  1616.     }
  1617.   }
  1618.  
  1619.   return blocked;
  1620. }
  1621.  
  1622.  
  1623. BOOL H323PeerElementDescriptor::CopyToAddressTemplate(H501_AddressTemplate & addressTemplate,
  1624.                                                    const H225_EndpointType & epInfo,
  1625.                                            const H225_ArrayOf_AliasAddress & aliases, 
  1626.                                            const H225_ArrayOf_AliasAddress & transportAddresses, 
  1627.                                                                     unsigned options)
  1628. {
  1629.   // add patterns for this descriptor
  1630.   addressTemplate.m_pattern.SetSize(aliases.GetSize());
  1631.   PINDEX j;
  1632.   for (j = 0; j < aliases.GetSize(); j++) {
  1633.     H501_Pattern & pattern = addressTemplate.m_pattern[j];
  1634.     if ((options & Option_WildCard) != 0)
  1635.       pattern.SetTag(H501_Pattern::e_wildcard);
  1636.     else 
  1637.       pattern.SetTag(H501_Pattern::e_specific);
  1638.     (H225_AliasAddress &)pattern = aliases[j];
  1639.   }
  1640.  
  1641.   // add transport addresses for this descriptor
  1642.   H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
  1643.   routeInfos.SetSize(1);
  1644.   H501_RouteInformation & routeInfo = routeInfos[0];
  1645.  
  1646.   if ((options & Option_NotAvailable) != 0)
  1647.     routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_nonExistent);
  1648.  
  1649.   else if ((options & Option_SendAccessRequest) != 0)
  1650.     routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_sendAccessRequest);
  1651.  
  1652.   else {
  1653.     routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_sendSetup);
  1654.     routeInfo.m_callSpecific = FALSE;
  1655.     routeInfo.IncludeOptionalField(H501_RouteInformation::e_type);
  1656.     routeInfo.m_type = epInfo;
  1657.   }
  1658.  
  1659.   routeInfo.m_callSpecific = FALSE;
  1660.   H501_ArrayOf_ContactInformation & contacts = routeInfos[0].m_contacts;
  1661.   contacts.SetSize(transportAddresses.GetSize());
  1662.   PINDEX i;
  1663.   for (i = 0; i < transportAddresses.GetSize(); i++) {
  1664.     H501_ContactInformation & contact = contacts[i];
  1665.     contact.m_transportAddress = transportAddresses[i];
  1666.     contact.m_priority         = 0;
  1667.   }
  1668.  
  1669.   // add protocols
  1670.   addressTemplate.IncludeOptionalField(H501_AddressTemplate::e_supportedProtocols);
  1671.   SetProtocolList(addressTemplate.m_supportedProtocols, options);
  1672.  
  1673.   return TRUE;
  1674. }
  1675.  
  1676. /*
  1677. BOOL H323PeerElementDescriptor::CopyFrom(const H501_Descriptor & descriptor)
  1678. {
  1679.   descriptorID                           = descriptor.m_descriptorInfo.m_descriptorID;
  1680.   //lastChanged.AsString("yyyyMMddhhmmss") = descriptor.m_descriptorInfo.m_lastChanged;
  1681.   addressTemplates                       = descriptor.m_templates;
  1682.  
  1683.   if (descriptor.HasOptionalField(H501_Descriptor::e_gatekeeperID))
  1684.     gatekeeperID = descriptor.m_gatekeeperID;
  1685.   else
  1686.     gatekeeperID = PString::Empty();
  1687.  
  1688.   return TRUE;
  1689. }
  1690. */
  1691.  
  1692. void H323PeerElementDescriptor::SetProtocolList(H501_ArrayOf_SupportedProtocols & h501Protocols, unsigned options)
  1693. {
  1694.   h501Protocols.SetSize(0);
  1695.   int mask =1;
  1696.   do {
  1697.     if (options & mask) {
  1698.       int pos = h501Protocols.GetSize();
  1699.       switch (mask) {
  1700.         case H323PeerElementDescriptor::Protocol_H323:
  1701.           h501Protocols.SetSize(pos+1);
  1702.           h501Protocols[pos].SetTag(H225_SupportedProtocols::e_h323);
  1703.           break;
  1704.  
  1705.         case H323PeerElementDescriptor::Protocol_Voice:
  1706.           h501Protocols.SetSize(pos+1);
  1707.           h501Protocols[pos].SetTag(H225_SupportedProtocols::e_voice);
  1708.           break;
  1709.  
  1710.         default:
  1711.           break;
  1712.       }
  1713.     }
  1714.     mask *= 2;
  1715.   } while (mask != Protocol_Max);
  1716. }
  1717.  
  1718. unsigned H323PeerElementDescriptor::GetProtocolList(const H501_ArrayOf_SupportedProtocols & h501Protocols)
  1719. {
  1720.   unsigned options = 0;
  1721.   PINDEX i;
  1722.   for (i = 0; i < h501Protocols.GetSize(); i++) {
  1723.     switch (h501Protocols[i].GetTag()) {
  1724.       case H225_SupportedProtocols::e_h323:
  1725.         options += Protocol_H323;
  1726.         break;
  1727.  
  1728.       case H225_SupportedProtocols::e_voice:
  1729.         options += Protocol_Voice;
  1730.         break;
  1731.  
  1732.       default:
  1733.         break;
  1734.     }
  1735.   }
  1736.   return options;
  1737. }
  1738.  
  1739.  
  1740. // End of file ////////////////////////////////////////////////////////////////
  1741.