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