Utilise new MergeSym feature to no longer overwrite the source .DEF file when buildin...
[openh323.git] / src / peclient.cxx
blobaa31a269dc51d93baddb10423002e4362a2b397f
1 /*
2 * peclient.cxx
4 * H.323 Annex G Peer Element client protocol handler
6 * Open H323 Library
8 * Copyright (c) 2003 Equivalence Pty. Ltd.
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/
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.
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.45 2004/05/05 14:11:17 csoutheren
28 * Fixed problems with AccessRequest returning wildcards
30 * Revision 1.44 2004/04/20 01:37:10 csoutheren
31 * Removed uneeded mutex signal
33 * Revision 1.43 2004/04/14 00:32:13 csoutheren
34 * Quick changes to ensure that non-specific H.501 routes are returned
35 * This will need to be changed later to allow retreiving multiple routes
36 * from an AccessRequest
38 * Revision 1.42 2004/03/29 08:13:15 csoutheren
39 * Fixed problem with priorities
41 * Revision 1.41 2004/03/29 06:58:15 csoutheren
42 * Added extra trace messages
44 * Revision 1.40 2004/03/29 05:35:21 csoutheren
45 * Changed to use default address for descriptor if blank
47 * Revision 1.39 2003/05/14 03:06:22 rjongbloed
48 * Added another method for removing service relationships.
49 * Added virtual for handling SR requests.
51 * Revision 1.38 2003/05/05 08:28:25 craigs
52 * Fixed lastUpdate time in descriptors
54 * Revision 1.37 2003/04/30 07:32:55 craigs
55 * Improve handling of wildcard matches
57 * Revision 1.36 2003/04/30 04:55:41 craigs
58 * Improved handling for nonexistent routes
60 * Revision 1.35 2003/04/18 15:16:43 craigs
61 * Fixed problem with creation of alias keys
63 * Revision 1.34 2003/04/10 14:34:05 craigs
64 * Fixed wild card handling
66 * Revision 1.33 2003/04/10 09:41:02 robertj
67 * Added some more functions for converting to alias addresses.
69 * Revision 1.32 2003/04/10 07:05:35 craigs
70 * Allowed access to endpoint type in descriptors
72 * Revision 1.31 2003/04/10 03:41:58 craigs
73 * Allow AccessRequest to return multiple transport addresses
75 * Revision 1.30 2003/04/10 00:59:35 craigs
76 * Added support for multiple contact addresses per template
78 * Revision 1.29 2003/04/09 10:47:06 craigs
79 * Fixed problems
81 * Revision 1.28 2003/04/09 03:08:10 robertj
82 * Fixed race condition in shutting down transactor (pure virtual call)
84 * Revision 1.27 2003/04/08 12:23:37 craigs
85 * Fixed problem with descriptors not being removed when service relationships go away
87 * Revision 1.26 2003/04/07 05:10:50 craigs
88 * Added changes to get access to descriptor creates/updates/deletes
90 * Revision 1.25 2003/04/02 06:06:01 robertj
91 * Added versions of AddDescriptor that contain the GUID.
92 * Changed default localIdentifier to be the local username of the endpoint.
94 * Revision 1.24 2003/04/01 05:59:33 robertj
95 * Fixed H.501 transaction code setting members for m_common PDU part.
97 * Revision 1.23 2003/04/01 04:47:55 robertj
98 * Abstracted H.225 RAS transaction processing (RIP and secondary thread) in
99 * server environment for use by H.501 peer elements.
101 * Revision 1.22 2003/04/01 01:18:16 robertj
102 * Minor changes to AccessEquest and AddDescriptor API to allow for
103 * string arrays of aliases.
105 * Revision 1.21 2003/03/28 04:43:05 craigs
106 * Added noCallSpecific flag for compatibility
108 * Revision 1.20 2003/03/28 00:30:13 craigs
109 * Fixed problems with service relationship ordinals and better descriptor update access
111 * Revision 1.19 2003/03/27 09:23:41 craigs
112 * Rewritten support for descriptors and multiple templates
114 * Revision 1.18 2003/03/26 00:46:29 robertj
115 * Had another go at making H323Transactor being able to be created
116 * without having a listener running.
118 * Revision 1.17 2003/03/25 12:53:00 robertj
119 * Added SetPromiscuous back in
121 * Revision 1.16 2003/03/25 12:01:30 craigs
122 * Fixed SEGV when no interface specified for peer element
124 * Revision 1.15 2003/03/25 07:50:23 craigs
125 * Added support for mutiple transports per descriptor
127 * Revision 1.14 2003/03/25 05:13:00 craigs
128 * More speed enhancements
130 * Revision 1.13 2003/03/25 02:57:04 craigs
131 * Fixed for update problems
133 * Revision 1.12 2003/03/25 01:59:13 robertj
134 * Fixed incorrect position of delete. Would do nothing there!
136 * Revision 1.11 2003/03/25 01:41:02 craigs
137 * Still more signficant H.501 updates
139 * Revision 1.10 2003/03/20 01:51:12 robertj
140 * More abstraction of H.225 RAS and H.501 protocols transaction handling.
142 * Revision 1.9 2003/03/19 01:18:38 robertj
143 * Fixed GNU warnings
145 * Revision 1.8 2003/03/19 01:11:37 robertj
146 * GNU compatibility
148 * Revision 1.7 2003/03/18 13:57:53 craigs
149 * More H.501 implementation
151 * Revision 1.6 2003/03/17 13:19:31 craigs
152 * More H501 implementation
154 * Revision 1.5 2003/03/14 06:01:16 craigs
155 * More updates
157 * Revision 1.4 2003/03/01 00:22:26 craigs
158 * New PeerElement implementation
160 * Revision 1.3 2003/02/25 06:48:19 robertj
161 * More work on PDU transaction abstraction.
163 * Revision 1.2 2003/02/21 07:23:18 robertj
164 * Fixed up some comments
166 * Revision 1.1 2003/02/21 05:27:06 craigs
167 * Initial version
171 #include <ptlib.h>
173 #ifdef __GNUC__
174 #pragma implementation "peclient.h"
175 #endif
177 #include "peclient.h"
179 #include "h323ep.h"
180 #include "h323annexg.h"
181 #include "h323pdu.h"
183 #define new PNEW
185 const unsigned ServiceRequestRetryTime = 60;
186 const unsigned ServiceRequestGracePeriod = 10;
187 const unsigned ServiceRelationshipTimeToLive = 60;
189 ////////////////////////////////////////////////////////////////
191 H501Transaction::H501Transaction(H323PeerElement & pe, const H501PDU & pdu, BOOL hasReject)
192 : H323Transaction(pe, pdu, new H501PDU, hasReject ? new H501PDU : NULL),
193 requestCommon(((H501PDU &)request->GetPDU()).m_common),
194 confirmCommon(((H501PDU &)confirm->GetPDU()).m_common),
195 peerElement(pe)
200 H323TransactionPDU * H501Transaction::CreateRIP(unsigned sequenceNumber,
201 unsigned delay) const
203 H501PDU * rip = new H501PDU;
204 rip->BuildRequestInProgress(sequenceNumber, delay);
205 return rip;
209 H235Authenticator::ValidationResult H501Transaction::ValidatePDU() const
211 return request->Validate(requestCommon.m_tokens, H501_MessageCommonInfo::e_tokens,
212 requestCommon.m_cryptoTokens, H501_MessageCommonInfo::e_cryptoTokens);
216 ////////////////////////////////////////////////////////////////
218 H501ServiceRequest::H501ServiceRequest(H323PeerElement & pe,
219 const H501PDU & pdu)
220 : H501Transaction(pe, pdu, TRUE),
221 srq((H501_ServiceRequest &)request->GetChoice().GetObject()),
222 scf(((H501PDU &)confirm->GetPDU()).BuildServiceConfirmation(pdu.m_common.m_sequenceNumber)),
223 srj(((H501PDU &)reject->GetPDU()).BuildServiceRejection(pdu.m_common.m_sequenceNumber,
224 H501_ServiceRejectionReason::e_undefined))
229 #if PTRACING
230 const char * H501ServiceRequest::GetName() const
232 return "ServiceRequest";
234 #endif
237 void H501ServiceRequest::SetRejectReason(unsigned reasonCode)
239 srj.m_reason.SetTag(reasonCode);
243 H323Transaction::Response H501ServiceRequest::OnHandlePDU()
245 return peerElement.OnServiceRequest(*this);
249 ////////////////////////////////////////////////////////////////
251 H501DescriptorUpdate::H501DescriptorUpdate(H323PeerElement & pe,
252 const H501PDU & pdu)
253 : H501Transaction(pe, pdu, FALSE),
254 du((H501_DescriptorUpdate &)request->GetChoice().GetObject()),
255 ack(((H501PDU &)confirm->GetPDU()).BuildDescriptorUpdateAck(pdu.m_common.m_sequenceNumber))
260 #if PTRACING
261 const char * H501DescriptorUpdate::GetName() const
263 return "DescriptorUpdate";
265 #endif
268 void H501DescriptorUpdate::SetRejectReason(unsigned /*reasonCode*/)
270 // Not possible!
274 H323Transaction::Response H501DescriptorUpdate::OnHandlePDU()
276 return peerElement.OnDescriptorUpdate(*this);
280 ////////////////////////////////////////////////////////////////
282 H501AccessRequest::H501AccessRequest(H323PeerElement & pe,
283 const H501PDU & pdu)
284 : H501Transaction(pe, pdu, TRUE),
285 arq((H501_AccessRequest &)request->GetChoice().GetObject()),
286 acf(((H501PDU &)confirm->GetPDU()).BuildAccessConfirmation(pdu.m_common.m_sequenceNumber)),
287 arj(((H501PDU &)reject->GetPDU()).BuildAccessRejection(pdu.m_common.m_sequenceNumber,
288 H501_AccessRejectionReason::e_undefined))
293 #if PTRACING
294 const char * H501AccessRequest::GetName() const
296 return "AccessRequest";
298 #endif
301 void H501AccessRequest::SetRejectReason(unsigned reasonCode)
303 arj.m_reason.SetTag(reasonCode);
307 H323Transaction::Response H501AccessRequest::OnHandlePDU()
309 return peerElement.OnAccessRequest(*this);
313 ////////////////////////////////////////////////////////////////
315 H323PeerElement::H323PeerElement(H323EndPoint & ep, H323Transport * trans)
316 : H323_AnnexG(ep, trans),
317 requestMutex(1, 1)
319 Construct();
322 H323PeerElement::H323PeerElement(H323EndPoint & ep, const H323TransportAddress & addr)
323 : H323_AnnexG(ep, addr),
324 requestMutex(1, 1)
326 Construct();
329 void H323PeerElement::Construct()
331 if (transport != NULL)
332 transport->SetPromiscuous(H323Transport::AcceptFromAny);
334 monitorStop = FALSE;
335 localIdentifier = endpoint.GetLocalUserName();
336 basePeerOrdinal = RemoteServiceRelationshipOrdinal;
338 StartChannel();
340 monitor = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
341 PThread::NoAutoDeleteThread,
342 PThread::NormalPriority,
343 "PeerElementMonitor:%x");
346 H323PeerElement::~H323PeerElement()
348 if (monitor != NULL) {
349 monitorStop = TRUE;
350 monitorTickle.Signal();
351 monitor->WaitForTermination();
352 delete monitor;
355 StopChannel();
359 void H323PeerElement::SetLocalName(const PString & name)
361 PWaitAndSignal m(localNameMutex);
362 localIdentifier = name;
365 PString H323PeerElement::GetLocalName() const
367 PWaitAndSignal m(localNameMutex);
368 return localIdentifier;
371 void H323PeerElement::SetDomainName(const PString & name)
373 PWaitAndSignal m(localNameMutex);
374 domainName = name;
377 PString H323PeerElement::GetDomainName() const
379 PWaitAndSignal m(localNameMutex);
380 return domainName;
384 void H323PeerElement::PrintOn(ostream & strm) const
386 if (!localIdentifier)
387 strm << localIdentifier << '@';
388 H323Transactor::PrintOn(strm);
391 void H323PeerElement::MonitorMain(PThread &, INT)
393 PTRACE(3, "PeerElement\tBackground thread started");
395 for (;;) {
397 // refresh and retry remote service relationships by sending new ServiceRequests
398 PTime now;
399 PTime nextExpireTime = now + ServiceRequestRetryTime*1000;
401 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
403 if (now >= sr->expireTime) {
404 PTRACE(3, "PeerElement\tRenewing service relationship " << sr->serviceID << "before expiry");
405 ServiceRequestByID(sr->serviceID);
408 // get minimum sleep time for next refresh or retry
409 if (sr->expireTime < nextExpireTime)
410 nextExpireTime = sr->expireTime;
414 // expire local service relationships we have not received ServiceRequests for
416 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstLocalServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
418 // check to see if expired or needs refresh scheduled
419 PTime expireTime = sr->expireTime + 1000 * ServiceRequestGracePeriod;
420 if (now >= expireTime) {
421 PTRACE(3, "PeerElement\tService relationship " << sr->serviceID << "expired");
422 localServiceRelationships.Remove(sr);
424 PWaitAndSignal m(localPeerListMutex);
425 localServiceOrdinals -= sr->ordinal;
428 else if (expireTime < nextExpireTime)
429 nextExpireTime = sr->expireTime;
433 // if any descriptor needs updating, then spawn a thread to do it
435 for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadOnly); descriptor != NULL; descriptor++) {
436 PWaitAndSignal m(localPeerListMutex);
437 if (
438 (descriptor->state != H323PeerElementDescriptor::Clean) ||
440 (descriptor->creator >= RemoteServiceRelationshipOrdinal) &&
441 !localServiceOrdinals.Contains(descriptor->creator)
444 PThread::Create(PCREATE_NOTIFIER(UpdateAllDescriptors), 0, PThread::AutoDeleteThread, PThread::NormalPriority);
445 break;
450 // wait until just before the next expire time;
451 PTimeInterval timeToWait = nextExpireTime - PTime();
452 if (timeToWait > 60*1000)
453 timeToWait = 60*1000;
454 monitorTickle.Wait(timeToWait);
456 if (monitorStop)
457 break;
460 PTRACE(3, "PeerElement\tBackground thread ended");
463 void H323PeerElement::UpdateAllDescriptors(PThread &, INT)
465 PTRACE(2, "PeerElement\tDescriptor update thread started");
467 for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadWrite); descriptor != NULL; descriptor++) {
468 PWaitAndSignal m(localPeerListMutex);
470 // delete any descriptors which belong to service relationships that are now gone
471 if (
472 (descriptor->state != H323PeerElementDescriptor::Deleted) &&
473 (descriptor->creator >= RemoteServiceRelationshipOrdinal) &&
474 !localServiceOrdinals.Contains(descriptor->creator)
476 descriptor->state = H323PeerElementDescriptor::Deleted;
478 PTRACE(4, "PeerElement\tUpdating descriptor " << descriptor->descriptorID << " in state " << descriptor->state);
480 UpdateDescriptor(descriptor);
483 monitorTickle.Signal();
485 PTRACE(2, "PeerElement\tDescriptor update thread ended");
488 void H323PeerElement::TickleMonitor(PTimer &, INT)
490 monitorTickle.Signal();
493 ///////////////////////////////////////////////////////////
495 // service relationship functions
498 H323PeerElementServiceRelationship * H323PeerElement::CreateServiceRelationship()
500 return new H323PeerElementServiceRelationship();
503 BOOL H323PeerElement::SetOnlyServiceRelationship(const PString & peer, BOOL keepTrying)
505 if (peer.IsEmpty()) {
506 RemoveAllServiceRelationships();
507 return TRUE;
510 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++)
511 if (sr->peer != peer)
512 RemoveServiceRelationship(sr->peer);
514 return AddServiceRelationship(peer, keepTrying);
517 BOOL H323PeerElement::AddServiceRelationship(const H323TransportAddress & addr, BOOL keepTrying)
519 OpalGloballyUniqueID serviceID;
520 return AddServiceRelationship(addr, serviceID, keepTrying);
523 BOOL H323PeerElement::AddServiceRelationship(const H323TransportAddress & addr, OpalGloballyUniqueID & serviceID, BOOL keepTrying)
526 switch (ServiceRequestByAddr(addr, serviceID)) {
527 case Confirmed:
528 case ServiceRelationshipReestablished:
529 return TRUE;
531 case NoResponse:
532 if (!keepTrying)
533 return FALSE;
534 break;
536 case Rejected:
537 case NoServiceRelationship:
538 default:
539 return FALSE;
542 PTRACE(2, "PeerElement\tRetrying ServiceRequest to " << addr << " in " << ServiceRequestRetryTime);
544 // this will cause the polling routines to keep trying to establish a new service relationship
545 H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
546 sr->peer = addr;
547 sr->expireTime = PTime() + (ServiceRequestRetryTime * 1000);
549 PWaitAndSignal m(basePeerOrdinalMutex);
550 sr->ordinal = basePeerOrdinal++;
553 PWaitAndSignal m(remotePeerListMutex);
554 remotePeerAddrToServiceID.SetAt(addr, sr->serviceID.AsString());
555 remotePeerAddrToOrdinalKey.SetAt(addr, new POrdinalKey(sr->ordinal));
557 remoteServiceRelationships.Append(sr);
559 monitorTickle.Signal();
561 return TRUE;
564 BOOL H323PeerElement::RemoveServiceRelationship(const OpalGloballyUniqueID & serviceID, int reason)
567 PWaitAndSignal m(remotePeerListMutex);
569 // if no service relationship exists for this peer, then nothing to do
570 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
571 if (sr == NULL) {
572 return FALSE;
576 return ServiceRelease(serviceID, reason);
580 BOOL H323PeerElement::RemoveServiceRelationship(const H323TransportAddress & peer, int reason)
582 OpalGloballyUniqueID serviceID;
584 // if no service relationship exists for this peer, then nothing to do
586 PWaitAndSignal m(remotePeerListMutex);
587 if (!remotePeerAddrToServiceID.Contains(peer))
588 return FALSE;
589 serviceID = remotePeerAddrToServiceID[peer];
592 return ServiceRelease(serviceID, reason);
595 BOOL H323PeerElement::RemoveAllServiceRelationships()
597 // if a service relationship exists for this peer, then reconfirm it
598 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++)
599 RemoveServiceRelationship(sr->peer);
601 return TRUE;
604 H323PeerElement::Error H323PeerElement::ServiceRequestByAddr(const H323TransportAddress & peer, OpalGloballyUniqueID & serviceID)
606 if (PAssertNULL(transport) == NULL)
607 return NoResponse;
609 // if a service relationship exists for this peer, then reconfirm it
610 remotePeerListMutex.Wait();
611 if (remotePeerAddrToServiceID.Contains(peer)) {
612 serviceID = remotePeerAddrToServiceID[peer];
613 remotePeerListMutex.Signal();
614 return ServiceRequestByID(serviceID);
616 remotePeerListMutex.Signal();
618 // create a new service relationship
619 H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
621 // build the service request
622 H501PDU pdu;
623 H323TransportAddressArray interfaces = GetInterfaceAddresses();
624 H501_ServiceRequest & body = pdu.BuildServiceRequest(GetNextSequenceNumber(), interfaces);
626 // include the element indentifier
627 body.IncludeOptionalField(H501_ServiceRequest::e_elementIdentifier);
628 body.m_elementIdentifier = localIdentifier;
630 // send the request
631 Request request(pdu.GetSequenceNumber(), pdu, peer);
632 H501PDU reply;
633 request.responseInfo = &reply;
634 if (!MakeRequest(request)) {
635 delete sr;
636 switch (request.responseResult) {
637 case Request::NoResponseReceived :
638 PTRACE(2, "PeerElement\tServiceRequest to " << peer << " failed due to no response");
639 return NoResponse;
641 case Request::RejectReceived:
642 PTRACE(2, "PeerElement\tServiceRequest to " << peer << " rejected for reason " << request.rejectReason);
643 break;
645 default:
646 PTRACE(2, "PeerElement\tServiceRequest to " << peer << " refused with unknown response " << (int)request.responseResult);
647 break;
649 return Rejected;
652 // reply must contain a service ID
653 if (!reply.m_common.HasOptionalField(H501_MessageCommonInfo::e_serviceID)) {
654 PTRACE(1, "PeerElement\tServiceConfirmation contains no serviceID");
655 delete sr;
656 return Rejected;
659 // create the service relationship
660 H501_ServiceConfirmation & replyBody = reply.m_body;
661 sr->peer = peer;
662 sr->serviceID = reply.m_common.m_serviceID;
663 sr->expireTime = PTime() + 1000 * ((replyBody.m_timeToLive < ServiceRequestRetryTime) ? (int)replyBody.m_timeToLive : ServiceRequestRetryTime);
664 sr->lastUpdateTime = PTime();
665 serviceID = sr->serviceID;
668 if (sr->ordinal == LocalServiceRelationshipOrdinal) {
670 PWaitAndSignal m(basePeerOrdinalMutex);
671 sr->ordinal = basePeerOrdinal++;
674 PWaitAndSignal m(remotePeerListMutex);
675 remotePeerAddrToServiceID.SetAt(peer, sr->serviceID.AsString());
676 remotePeerAddrToOrdinalKey.SetAt(peer, new POrdinalKey(sr->ordinal));
681 remoteServiceRelationships.Append(sr);
683 PTRACE(2, "PeerElement\tNew service relationship established with " << peer << " - next update in " << replyBody.m_timeToLive);
684 OnAddServiceRelationship(peer);
686 // mark all descriptors as needing an update
687 for (PSafePtr<H323PeerElementDescriptor> descriptor = GetFirstDescriptor(PSafeReadWrite); descriptor != NULL; descriptor++) {
688 if (descriptor->state == H323PeerElementDescriptor::Clean)
689 descriptor->state = H323PeerElementDescriptor::Dirty;
692 monitorTickle.Signal();
693 return Confirmed;
697 H323PeerElement::Error H323PeerElement::ServiceRequestByID(OpalGloballyUniqueID & serviceID)
699 if (PAssertNULL(transport) == NULL)
700 return NoResponse;
702 // build the service request
703 H501PDU pdu;
704 H501_ServiceRequest & body = pdu.BuildServiceRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
706 // include the element indentifier
707 body.IncludeOptionalField(H501_ServiceRequest::e_elementIdentifier);
708 body.m_elementIdentifier = localIdentifier;
710 // check to see if we have a service relationship with the peer already
711 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
712 if (sr == NULL)
713 return NoServiceRelationship;
715 // setup to update the old service relationship
716 pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
717 pdu.m_common.m_serviceID = sr->serviceID;
718 Request request(pdu.GetSequenceNumber(), pdu, sr->peer);
719 H501PDU reply;
720 request.responseInfo = &reply;
722 if (MakeRequest(request)) {
723 H501_ServiceConfirmation & replyBody = reply.m_body;
724 sr->expireTime = PTime() + 1000 * ((replyBody.m_timeToLive < ServiceRequestRetryTime) ? (int)replyBody.m_timeToLive : ServiceRequestRetryTime);
725 sr->lastUpdateTime = PTime();
726 PTRACE(2, "PeerElement\tConfirmed service relationship with " << sr->peer << " - next update in " << replyBody.m_timeToLive);
727 return Confirmed;
730 // if cannot update, then try again after 60 seconds
731 switch (request.responseResult) {
732 case Request::NoResponseReceived :
733 PTRACE(2, "PeerElement\tNo response to ServiceRequest - trying again in " << ServiceRequestRetryTime);
734 sr->expireTime = PTime() + (ServiceRequestRetryTime * 1000);
735 monitorTickle.Signal();
736 return NoResponse;
738 case Request::RejectReceived:
739 switch (request.rejectReason) {
740 case H501_ServiceRejectionReason::e_unknownServiceID:
741 if (OnRemoteServiceRelationshipDisappeared(serviceID, sr->peer))
742 return Confirmed;
743 break;
745 default:
746 PTRACE(2, "PeerElement\tServiceRequest to " << sr->peer << " rejected with unknown reason " << request.rejectReason);
747 break;
749 break;
751 default:
752 PTRACE(2, "PeerElement\tServiceRequest to " << sr->peer << " failed with unknown response " << (int)request.responseResult);
753 break;
756 return Rejected;
759 H323Transaction::Response H323PeerElement::OnServiceRequest(H501ServiceRequest & info)
761 info.SetRejectReason(H501_ServiceRejectionReason::e_serviceUnavailable);
762 return H323Transaction::Reject;
765 H323Transaction::Response H323PeerElement::HandleServiceRequest(H501ServiceRequest & info)
767 // if a serviceID is specified, this is should be an existing service relationship
768 if (info.requestCommon.HasOptionalField(H501_MessageCommonInfo::e_serviceID)) {
770 // check to see if we have a service relationship with the peer already
771 OpalGloballyUniqueID serviceID(info.requestCommon.m_serviceID);
772 PSafePtr<H323PeerElementServiceRelationship> sr = localServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
773 if (sr == NULL) {
774 PTRACE(2, "PeerElement\nRejecting unknown service ID " << serviceID << " received from peer " << info.GetReplyAddress());
775 info.SetRejectReason(H501_ServiceRejectionReason::e_unknownServiceID);
776 return H323Transaction::Reject;
779 // include service ID, local and domain identifiers
780 info.confirmCommon.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
781 info.confirmCommon.m_serviceID = sr->serviceID;
782 info.scf.m_elementIdentifier = GetLocalName();
783 H323SetAliasAddress(GetDomainName(), info.scf.m_domainIdentifier);
785 // include time to live
786 info.scf.IncludeOptionalField(H501_ServiceConfirmation::e_timeToLive);
787 info.scf.m_timeToLive = ServiceRelationshipTimeToLive;
788 sr->lastUpdateTime = PTime();
789 sr->expireTime = PTime() + (info.scf.m_timeToLive * 1000);
791 PTRACE(2, "PeerElement\nService relationship with " << sr->name << " at " << info.GetReplyAddress() << " updated - next update in " << info.scf.m_timeToLive);
792 return H323Transaction::Confirm;
795 H323PeerElementServiceRelationship * sr = CreateServiceRelationship();
797 // get the name of the remote element
798 if (info.srq.HasOptionalField(H501_ServiceRequest::e_elementIdentifier))
799 sr->name = info.srq.m_elementIdentifier;
801 // include service ID, local and domain identifiers
802 info.confirmCommon.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
803 info.confirmCommon.m_serviceID = sr->serviceID;
804 info.scf.m_elementIdentifier = GetLocalName();
805 H323SetAliasAddress(GetDomainName(), info.scf.m_domainIdentifier);
807 // include time to live
808 info.scf.IncludeOptionalField(H501_ServiceConfirmation::e_timeToLive);
809 info.scf.m_timeToLive = ServiceRelationshipTimeToLive;
810 if (info.requestCommon.HasOptionalField(H501_MessageCommonInfo::e_replyAddress) && info.requestCommon.m_replyAddress.GetSize() > 0)
811 sr->peer = info.requestCommon.m_replyAddress[0];
812 else
813 sr->peer = transport->GetLastReceivedAddress();
814 sr->lastUpdateTime = PTime();
815 sr->expireTime = PTime() + (info.scf.m_timeToLive * 1000);
817 H323TransportAddress addr = transport->GetLastReceivedAddress();
819 PWaitAndSignal m(basePeerOrdinalMutex);
820 sr->ordinal = basePeerOrdinal++;
823 PWaitAndSignal m(localPeerListMutex);
824 localServiceOrdinals += sr->ordinal;
828 // add to the list of known relationships
829 localServiceRelationships.Append(sr);
830 monitorTickle.Signal();
832 // send the response
833 PTRACE(2, "PeerElement\nNew service relationship with " << sr->name << " at " << info.GetReplyAddress() << " created - next update in " << info.scf.m_timeToLive);
834 return H323Transaction::Confirm;
837 BOOL H323PeerElement::OnReceiveServiceRequest(const H501PDU & pdu, const H501_ServiceRequest & /*pduBody*/)
839 H501ServiceRequest * info = new H501ServiceRequest(*this, pdu);
840 if (!info->HandlePDU())
841 delete info;
843 return FALSE;
846 BOOL H323PeerElement::OnReceiveServiceConfirmation(const H501PDU & pdu, const H501_ServiceConfirmation & pduBody)
848 if (!H323_AnnexG::OnReceiveServiceConfirmation(pdu, pduBody))
849 return FALSE;
851 if (lastRequest->responseInfo != NULL)
852 *(H501PDU *)lastRequest->responseInfo = pdu;
854 return TRUE;
857 BOOL H323PeerElement::ServiceRelease(const OpalGloballyUniqueID & serviceID, unsigned reason)
859 // remove any previous check to see if we have a service relationship with the peer already
860 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadWrite);
861 if (sr == NULL)
862 return FALSE;
864 // send the request - no response
865 H501PDU pdu;
866 H501_ServiceRelease & body = pdu.BuildServiceRelease(GetNextSequenceNumber());
867 pdu.m_common.m_serviceID = sr->serviceID;
868 body.m_reason = reason;
869 WriteTo(pdu, sr->peer);
871 OnRemoveServiceRelationship(sr->peer);
872 InternalRemoveServiceRelationship(sr->peer);
873 remoteServiceRelationships.Remove(sr);
875 return TRUE;
878 BOOL H323PeerElement::OnRemoteServiceRelationshipDisappeared(OpalGloballyUniqueID & serviceID, const H323TransportAddress & peer)
880 OpalGloballyUniqueID oldServiceID = serviceID;
882 // the service ID specified is now gone
883 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
884 if (sr != NULL)
885 remoteServiceRelationships.Remove(sr);
886 InternalRemoveServiceRelationship(peer);
888 // attempt to create a new service relationship
889 if (ServiceRequestByAddr(peer, serviceID) != Confirmed) {
890 PTRACE(2, "PeerElement\tService relationship with " << peer << " disappeared and refused new relationship");
891 OnRemoveServiceRelationship(peer);
892 return FALSE;
895 // we have a new service ID
896 PTRACE(2, "PeerElement\tService relationship with " << peer << " disappeared and new relationship established");
897 serviceID = remotePeerAddrToServiceID(peer);
899 return TRUE;
902 void H323PeerElement::InternalRemoveServiceRelationship(const H323TransportAddress & peer)
905 PWaitAndSignal m(remotePeerListMutex);
906 remotePeerAddrToServiceID.RemoveAt(peer);
907 remotePeerAddrToOrdinalKey.RemoveAt(peer);
909 monitorTickle.Signal();
914 ///////////////////////////////////////////////////////////
916 // descriptor table functions
919 H323PeerElementDescriptor * H323PeerElement::CreateDescriptor(const OpalGloballyUniqueID & descriptorID)
921 return new H323PeerElementDescriptor(descriptorID);
924 BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
925 const PStringArray & aliasStrings,
926 const H323TransportAddressArray & transportAddresses,
927 unsigned options,
928 BOOL now)
930 // convert transport addresses to aliases
931 H225_ArrayOf_AliasAddress aliases;
932 H323SetAliasAddresses(aliasStrings, aliases);
933 return AddDescriptor(descriptorID,
934 aliases, transportAddresses, options, now);
938 BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
939 const H225_ArrayOf_AliasAddress & aliases,
940 const H323TransportAddressArray & transportAddresses,
941 unsigned options,
942 BOOL now)
944 H225_ArrayOf_AliasAddress addresses;
945 H323SetAliasAddresses(transportAddresses, addresses);
946 return AddDescriptor(descriptorID,
947 LocalServiceRelationshipOrdinal,
948 aliases, addresses, options, now);
952 BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
953 const H225_ArrayOf_AliasAddress & aliases,
954 const H225_ArrayOf_AliasAddress & transportAddress,
955 unsigned options,
956 BOOL now)
958 // create a new descriptor
959 return AddDescriptor(descriptorID,
960 LocalServiceRelationshipOrdinal,
961 aliases, transportAddress, options, now);
964 BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
965 const POrdinalKey & creator,
966 const H225_ArrayOf_AliasAddress & aliases,
967 const H225_ArrayOf_AliasAddress & transportAddresses,
968 unsigned options,
969 BOOL now)
971 // create an const H501_ArrayOf_AddressTemplate with the template information
972 H501_ArrayOf_AddressTemplate addressTemplates;
974 // copy data into the descriptor
975 addressTemplates.SetSize(1);
976 H225_EndpointType epType;
977 endpoint.SetEndpointTypeInfo(epType);
978 H323PeerElementDescriptor::CopyToAddressTemplate(addressTemplates[0], epType, aliases, transportAddresses, options);
980 return AddDescriptor(descriptorID, creator, addressTemplates, now);
983 BOOL H323PeerElement::AddDescriptor(const OpalGloballyUniqueID & descriptorID,
984 const POrdinalKey & creator,
985 const H501_ArrayOf_AddressTemplate & addressTemplates,
986 const PTime & updateTime,
987 BOOL now)
989 // see if there is actually a descriptor with this ID
990 PSafePtr<H323PeerElementDescriptor> descriptor = descriptors.FindWithLock(H323PeerElementDescriptor(descriptorID), PSafeReadWrite);
991 H501_UpdateInformation_updateType::Choices updateType = H501_UpdateInformation_updateType::e_changed;
992 BOOL add = FALSE;
994 PWaitAndSignal m(aliasMutex);
995 if (descriptor != NULL) {
996 RemoveDescriptorInformation(descriptor->addressTemplates);
998 // only update if the update time is later than what we already have
999 if (updateTime < descriptor->lastChanged) {
1000 PTRACE(4, "PeerElement\tNot updating descriptor " << descriptorID << " as " << updateTime << " < " << descriptor->lastChanged);
1001 return TRUE;
1004 } else {
1005 add = TRUE;
1006 descriptor = CreateDescriptor(descriptorID);
1007 descriptor->creator = creator;
1008 descriptor->addressTemplates = addressTemplates;
1009 updateType = H501_UpdateInformation_updateType::e_added;
1011 descriptor->lastChanged = PTime();
1013 // add all patterns and transport addresses to secondary lookup tables
1014 PINDEX i, j, k;
1015 for (i = 0; i < descriptor->addressTemplates.GetSize(); i++) {
1016 H501_AddressTemplate & addressTemplate = addressTemplates[i];
1018 // add patterns for this descriptor
1019 for (j = 0; j < addressTemplate.m_pattern.GetSize(); j++) {
1020 H501_Pattern & pattern = addressTemplate.m_pattern[j];
1021 switch (pattern.GetTag()) {
1022 case H501_Pattern::e_specific:
1023 specificAliasToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)pattern, descriptorID, i, FALSE));
1024 break;
1025 case H501_Pattern::e_wildcard:
1026 wildcardAliasToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)pattern, descriptorID, i, TRUE));
1027 break;
1028 case H501_Pattern::e_range:
1029 break;
1033 // add transport addresses for this descriptor
1034 H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
1035 for (j = 0; j < routeInfos.GetSize(); j++) {
1036 H501_ArrayOf_ContactInformation & contacts = routeInfos[j].m_contacts;
1037 for (k = 0; k < contacts.GetSize(); k++) {
1038 H501_ContactInformation & contact = contacts[k];
1039 H225_AliasAddress & transportAddress = contact.m_transportAddress;
1040 transportAddressToDescriptorID.Append(CreateAliasKey((H225_AliasAddress &)transportAddress, descriptorID, i));
1046 if (!add)
1047 OnUpdateDescriptor(*descriptor);
1048 else {
1049 descriptors.Append(descriptor);
1050 OnNewDescriptor(*descriptor);
1053 // do the update now, or later
1054 if (now) {
1055 PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " added/updated");
1056 UpdateDescriptor(descriptor, updateType);
1057 } else if (descriptor->state != H323PeerElementDescriptor::Deleted) {
1058 PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " queued to be added");
1059 descriptor->state = H323PeerElementDescriptor::Dirty;
1060 monitorTickle.Signal();
1063 return TRUE;
1066 H323PeerElement::AliasKey * H323PeerElement::CreateAliasKey(const H225_AliasAddress & alias, const OpalGloballyUniqueID & id, PINDEX pos, BOOL wild)
1068 return new AliasKey(alias, id, pos, wild);
1071 void H323PeerElement::RemoveDescriptorInformation(const H501_ArrayOf_AddressTemplate & addressTemplates)
1073 PWaitAndSignal m(aliasMutex);
1074 PINDEX i, j, k, idx;
1076 // remove all patterns and transport addresses for this descriptor
1077 for (i = 0; i < addressTemplates.GetSize(); i++) {
1078 H501_AddressTemplate & addressTemplate = addressTemplates[i];
1080 // remove patterns for this descriptor
1081 for (j = 0; j < addressTemplate.m_pattern.GetSize(); j++) {
1082 H501_Pattern & pattern = addressTemplate.m_pattern[j];
1083 switch (pattern.GetTag()) {
1084 case H501_Pattern::e_specific:
1085 idx = specificAliasToDescriptorID.GetValuesIndex((H225_AliasAddress &)pattern);
1086 if (idx != P_MAX_INDEX)
1087 specificAliasToDescriptorID.RemoveAt(idx);
1088 break;
1089 case H501_Pattern::e_wildcard:
1090 idx = wildcardAliasToDescriptorID.GetValuesIndex((H225_AliasAddress &)pattern);
1091 if (idx != P_MAX_INDEX)
1092 wildcardAliasToDescriptorID.RemoveAt(idx);
1093 break;
1094 case H501_Pattern::e_range:
1095 break;
1099 // remove transport addresses for this descriptor
1100 H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
1101 for (j = 0; j < routeInfos.GetSize(); j++) {
1102 H501_ArrayOf_ContactInformation & contacts = routeInfos[i].m_contacts;
1103 for (k = 0; k < contacts.GetSize(); k++) {
1104 H501_ContactInformation & contact = contacts[k];
1105 H225_AliasAddress & transportAddress = contact.m_transportAddress;
1106 idx = transportAddressToDescriptorID.GetValuesIndex(transportAddress);
1107 if (idx != P_MAX_INDEX)
1108 transportAddressToDescriptorID.RemoveAt(idx);
1114 BOOL H323PeerElement::DeleteDescriptor(const PString & str, BOOL now)
1116 H225_AliasAddress alias;
1117 H323SetAliasAddress(str, alias);
1118 return DeleteDescriptor(alias, now);
1121 BOOL H323PeerElement::DeleteDescriptor(const H225_AliasAddress & alias, BOOL now)
1123 OpalGloballyUniqueID descriptorID("");
1125 // find the descriptor ID for the descriptor
1127 PWaitAndSignal m(aliasMutex);
1128 PINDEX idx = specificAliasToDescriptorID.GetValuesIndex(alias);
1129 if (idx == P_MAX_INDEX)
1130 return FALSE;
1131 descriptorID = ((AliasKey &)specificAliasToDescriptorID[idx]).id;
1134 return DeleteDescriptor(descriptorID, now);
1137 BOOL H323PeerElement::DeleteDescriptor(const OpalGloballyUniqueID & descriptorID, BOOL now)
1139 // see if there is a descriptor with this ID
1140 PSafePtr<H323PeerElementDescriptor> descriptor = descriptors.FindWithLock(H323PeerElementDescriptor(descriptorID), PSafeReadWrite);
1141 if (descriptor == NULL)
1142 return FALSE;
1144 OnRemoveDescriptor(*descriptor);
1146 RemoveDescriptorInformation(descriptor->addressTemplates);
1148 // delete the descriptor, or mark it as to be deleted
1149 if (now) {
1150 PTRACE(2, "PeerElement\tDescriptor " << descriptorID << " deleted");
1151 UpdateDescriptor(descriptor, H501_UpdateInformation_updateType::e_deleted);
1152 } else {
1153 PTRACE(2, "PeerElement\tDescriptor for " << descriptorID << " queued to be deleted");
1154 descriptor->state = H323PeerElementDescriptor::Deleted;
1155 monitorTickle.Signal();
1158 return TRUE;
1161 BOOL H323PeerElement::UpdateDescriptor(H323PeerElementDescriptor * descriptor)
1163 H501_UpdateInformation_updateType::Choices updateType = H501_UpdateInformation_updateType::e_changed;
1164 switch (descriptor->state) {
1165 case H323PeerElementDescriptor::Clean:
1166 return TRUE;
1168 case H323PeerElementDescriptor::Dirty:
1169 break;
1171 case H323PeerElementDescriptor::Deleted:
1172 updateType = H501_UpdateInformation_updateType::e_deleted;
1173 break;
1176 return UpdateDescriptor(descriptor, updateType);
1179 BOOL H323PeerElement::UpdateDescriptor(H323PeerElementDescriptor * descriptor, H501_UpdateInformation_updateType::Choices updateType)
1181 if (updateType == H501_UpdateInformation_updateType::e_deleted)
1182 descriptor->state = H323PeerElementDescriptor::Deleted;
1183 else if (descriptor->state == H323PeerElementDescriptor::Deleted)
1184 updateType = H501_UpdateInformation_updateType::e_deleted;
1185 else if (descriptor->state == H323PeerElementDescriptor::Clean)
1186 return TRUE;
1187 else
1188 descriptor->state = H323PeerElementDescriptor::Clean;
1190 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
1191 PTRACE(4, "PeerElement\tUpdating descriptor " << descriptor->descriptorID << " for service ID " << sr->serviceID);
1192 SendUpdateDescriptorByID(sr->serviceID, descriptor, updateType);
1195 if (descriptor->state == H323PeerElementDescriptor::Deleted)
1196 descriptors.Remove(descriptor);
1198 return TRUE;
1201 ///////////////////////////////////////////////////////////
1203 // descriptor peer element functions
1206 H323PeerElement::Error H323PeerElement::SendUpdateDescriptorByID(const OpalGloballyUniqueID & serviceID,
1207 H323PeerElementDescriptor * descriptor,
1208 H501_UpdateInformation_updateType::Choices updateType)
1210 if (PAssertNULL(transport) == NULL)
1211 return NoResponse;
1213 H501PDU pdu;
1214 pdu.BuildDescriptorUpdate(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
1215 H323TransportAddress peer;
1217 // put correct service descriptor into the common data
1219 // check to see if we have a service relationship with the peer already
1220 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
1222 // if there is no service relationship, then nothing to do
1223 if (sr == NULL)
1224 return NoServiceRelationship;
1226 pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
1227 pdu.m_common.m_serviceID = sr->serviceID;
1228 peer = sr->peer;
1231 return SendUpdateDescriptor(pdu, peer, descriptor, updateType);
1234 H323PeerElement::Error H323PeerElement::SendUpdateDescriptorByAddr(const H323TransportAddress & peer,
1235 H323PeerElementDescriptor * descriptor,
1236 H501_UpdateInformation_updateType::Choices updateType)
1238 if (PAssertNULL(transport) == NULL)
1239 return NoResponse;
1241 H501PDU pdu;
1242 pdu.BuildDescriptorUpdate(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
1243 return SendUpdateDescriptor(pdu, peer, descriptor, updateType);
1246 H323PeerElement::Error H323PeerElement::SendUpdateDescriptor(H501PDU & pdu,
1247 const H323TransportAddress & peer,
1248 H323PeerElementDescriptor * descriptor,
1249 H501_UpdateInformation_updateType::Choices updateType)
1251 if (PAssertNULL(transport) == NULL)
1252 return NoResponse;
1254 H501_DescriptorUpdate & body = pdu.m_body;
1256 // put in sender address
1257 H323TransportAddressArray addrs = GetInterfaceAddresses();
1258 PAssert(addrs.GetSize() > 0, "No interface addresses");
1259 H323SetAliasAddress(addrs[0], body.m_sender, H225_AliasAddress::e_transportID);
1261 // add information
1262 body.m_updateInfo.SetSize(1);
1263 H501_UpdateInformation & info = body.m_updateInfo[0];
1264 info.m_descriptorInfo.SetTag(H501_UpdateInformation_descriptorInfo::e_descriptor);
1265 info.m_updateType.SetTag(updateType);
1266 descriptor->CopyTo(info.m_descriptorInfo);
1268 // make the request
1269 Request request(pdu.GetSequenceNumber(), pdu, peer);
1270 if (MakeRequest(request))
1271 return Confirmed;
1273 // if error was no service relationship, then establish relationship and try again
1274 switch (request.responseResult) {
1275 case Request::NoResponseReceived :
1276 PTRACE(2, "PeerElement\tUpdateDescriptor to " << peer << " failed due to no response");
1277 break;
1279 default:
1280 PTRACE(2, "PeerElement\tUpdateDescriptor to " << peer << " refused with unknown response " << (int)request.responseResult);
1281 return Rejected;
1284 return Rejected;
1287 H323Transaction::Response H323PeerElement::OnDescriptorUpdate(H501DescriptorUpdate & /*info*/)
1289 return H323Transaction::Ignore;
1292 BOOL H323PeerElement::OnReceiveDescriptorUpdate(const H501PDU & pdu, const H501_DescriptorUpdate & /*pduBody*/)
1294 H501DescriptorUpdate * info = new H501DescriptorUpdate(*this, pdu);
1295 if (!info->HandlePDU())
1296 delete info;
1298 return FALSE;
1301 BOOL H323PeerElement::OnReceiveDescriptorUpdateACK(const H501PDU & pdu, const H501_DescriptorUpdateAck & pduBody)
1303 if (!H323_AnnexG::OnReceiveDescriptorUpdateACK(pdu, pduBody))
1304 return FALSE;
1306 if (lastRequest->responseInfo != NULL)
1307 *(H501_MessageCommonInfo *)lastRequest->responseInfo = pdu.m_common;
1309 return TRUE;
1312 ///////////////////////////////////////////////////////////
1314 // access request functions
1317 BOOL H323PeerElement::AccessRequest(const PString & searchAlias,
1318 PStringArray & destAliases,
1319 H323TransportAddress & transportAddress,
1320 unsigned options)
1322 H225_AliasAddress h225searchAlias;
1323 H323SetAliasAddress(searchAlias, h225searchAlias);
1325 H225_ArrayOf_AliasAddress h225destAliases;
1326 if (!AccessRequest(h225searchAlias, h225destAliases, transportAddress, options))
1327 return FALSE;
1329 destAliases = H323GetAliasAddressStrings(h225destAliases);
1330 return TRUE;
1334 BOOL H323PeerElement::AccessRequest(const PString & searchAlias,
1335 H225_ArrayOf_AliasAddress & destAliases,
1336 H323TransportAddress & transportAddress,
1337 unsigned options)
1339 H225_AliasAddress h225searchAlias;
1340 H323SetAliasAddress(searchAlias, h225searchAlias);
1341 return AccessRequest(h225searchAlias, destAliases, transportAddress, options);
1344 BOOL H323PeerElement::AccessRequest(const H225_AliasAddress & searchAlias,
1345 H225_ArrayOf_AliasAddress & destAliases,
1346 H323TransportAddress & transportAddress,
1347 unsigned options)
1349 H225_AliasAddress h225Address;
1350 if (!AccessRequest(searchAlias, destAliases, h225Address, options))
1351 return FALSE;
1353 transportAddress = H323GetAliasAddressString(h225Address);
1354 return TRUE;
1357 BOOL H323PeerElement::AccessRequest(const H225_AliasAddress & searchAlias,
1358 H225_ArrayOf_AliasAddress & destAliases,
1359 H225_AliasAddress & transportAddress,
1360 unsigned options)
1362 // try each service relationship in turn
1363 POrdinalSet peersTried;
1365 for (PSafePtr<H323PeerElementServiceRelationship> sr = GetFirstRemoteServiceRelationship(PSafeReadOnly); sr != NULL; sr++) {
1367 // create the request
1368 H501PDU request;
1369 H501_AccessRequest & requestBody = request.BuildAccessRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
1371 // set dest information
1372 H501_PartyInformation & destInfo = requestBody.m_destinationInfo;
1373 destInfo.m_logicalAddresses.SetSize(1);
1374 destInfo.m_logicalAddresses[0] = searchAlias;
1376 // set protocols
1377 requestBody.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols);
1378 H323PeerElementDescriptor::SetProtocolList(requestBody.m_desiredProtocols, options);
1380 // make the request
1381 H501PDU reply;
1382 H323PeerElement::Error error = SendAccessRequestByID(sr->serviceID, request, reply);
1383 H323TransportAddress peerAddr = sr->peer;
1385 while (error == Confirmed) {
1387 // make sure we got at least one template
1388 H501_AccessConfirmation & confirm = reply.m_body;
1389 H501_ArrayOf_AddressTemplate & addressTemplates = confirm.m_templates;
1390 if (addressTemplates.GetSize() == 0) {
1391 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no templates");
1392 break;
1394 H501_AddressTemplate & addressTemplate = addressTemplates[0];
1396 // make sure patterns are returned
1397 H501_ArrayOf_Pattern & patterns = addressTemplate.m_pattern;
1398 if (patterns.GetSize() == 0) {
1399 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no patterns");
1400 break;
1403 // make sure routes are returned
1404 H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
1405 if (routeInfos.GetSize() == 0) {
1406 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no routes");
1407 break;
1409 H501_RouteInformation & routeInfo = addressTemplate.m_routeInfo[0];
1411 // make sure routes contain contacts
1412 H501_ArrayOf_ContactInformation & contacts = routeInfo.m_contacts;
1413 if (contacts.GetSize() == 0) {
1414 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " contains no contacts");
1415 break;
1417 H501_ContactInformation & contact = routeInfo.m_contacts[0];
1419 // get the address
1420 H225_AliasAddress contactAddress = contact.m_transportAddress;
1421 int tag = routeInfo.m_messageType.GetTag();
1422 if (tag == H501_RouteInformation_messageType::e_sendAccessRequest) {
1423 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " redirected from " << peerAddr << " to " << contactAddress);
1424 peerAddr = H323GetAliasAddressString(contactAddress);
1426 else if (tag == H501_RouteInformation_messageType::e_sendSetup) {
1428 // get the dest aliases
1429 destAliases.SetSize(addressTemplate.m_pattern.GetSize());
1430 PINDEX count = 0;
1431 PINDEX i;
1432 for (i = 0; i < addressTemplate.m_pattern.GetSize(); i++) {
1433 if (addressTemplate.m_pattern[i].GetTag() == H501_Pattern::e_specific) {
1434 H225_AliasAddress & alias = addressTemplate.m_pattern[i];
1435 destAliases[count++] = alias;
1438 destAliases.SetSize(count);
1440 transportAddress = contactAddress;
1441 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " returned " << transportAddress << " from " << peerAddr);
1442 return TRUE;
1444 else { // H501_RouteInformation_messageType::e_nonExistent
1445 PTRACE(2, "Main\tAccessRequest for " << searchAlias << " from " << peerAddr << " returned nonExistent");
1446 break;
1449 // this is the address to send the new request to
1450 H323TransportAddress addr = peerAddr;
1452 // create the request
1453 H501_AccessRequest & requestBody = request.BuildAccessRequest(GetNextSequenceNumber(), transport->GetLastReceivedAddress());
1455 // set dest information
1456 H501_PartyInformation & destInfo = requestBody.m_destinationInfo;
1457 destInfo.m_logicalAddresses.SetSize(1);
1458 destInfo.m_logicalAddresses[0] = searchAlias;
1460 // set protocols
1461 requestBody.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols);
1462 H323PeerElementDescriptor::SetProtocolList(requestBody.m_desiredProtocols, options);
1464 // make the request
1465 error = SendAccessRequestByAddr(addr, request, reply);
1469 return FALSE;
1472 ///////////////////////////////////////////////////////////
1474 // access request functions
1477 H323PeerElement::Error H323PeerElement::SendAccessRequestByID(const OpalGloballyUniqueID & origServiceID,
1478 H501PDU & pdu,
1479 H501PDU & confirmPDU)
1481 if (PAssertNULL(transport) == NULL)
1482 return NoResponse;
1484 OpalGloballyUniqueID serviceID = origServiceID;
1486 for (;;) {
1488 // get the peer address
1489 H323TransportAddress peer;
1491 PSafePtr<H323PeerElementServiceRelationship> sr = remoteServiceRelationships.FindWithLock(H323PeerElementServiceRelationship(serviceID), PSafeReadOnly);
1492 if (sr == NULL)
1493 return NoServiceRelationship;
1494 peer = sr->peer;
1497 // set the service ID
1498 pdu.m_common.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID);
1499 pdu.m_common.m_serviceID = serviceID;
1501 // make the request
1502 Request request(pdu.GetSequenceNumber(), pdu, peer);
1503 request.responseInfo = &confirmPDU;
1504 if (MakeRequest(request))
1505 return Confirmed;
1507 // if error was no service relationship, then establish relationship and try again
1508 switch (request.responseResult) {
1509 case Request::NoResponseReceived :
1510 PTRACE(2, "PeerElement\tAccessRequest to " << peer << " failed due to no response");
1511 return Rejected;
1513 case Request::RejectReceived:
1514 switch (request.rejectReason) {
1515 case H501_ServiceRejectionReason::e_unknownServiceID:
1516 if (!OnRemoteServiceRelationshipDisappeared(serviceID, peer))
1517 return Rejected;
1518 break;
1519 default:
1520 return Rejected;
1522 break;
1524 default:
1525 PTRACE(2, "PeerElement\tAccessRequest to " << peer << " refused with unknown response " << (int)request.responseResult);
1526 return Rejected;
1530 return Rejected;
1533 H323PeerElement::Error H323PeerElement::SendAccessRequestByAddr(const H323TransportAddress & peerAddr,
1534 H501PDU & pdu,
1535 H501PDU & confirmPDU)
1537 if (PAssertNULL(transport) == NULL)
1538 return NoResponse;
1540 pdu.m_common.RemoveOptionalField(H501_MessageCommonInfo::e_serviceID);
1542 // make the request
1543 Request request(pdu.GetSequenceNumber(), pdu, peerAddr);
1544 request.responseInfo = &confirmPDU;
1545 if (MakeRequest(request))
1546 return Confirmed;
1548 // if error was no service relationship, then establish relationship and try again
1549 switch (request.responseResult) {
1550 case Request::NoResponseReceived :
1551 PTRACE(2, "PeerElement\tAccessRequest to " << peerAddr << " failed due to no response");
1552 break;
1554 case Request::RejectReceived:
1555 PTRACE(2, "PeerElement\tAccessRequest failed due to " << request.rejectReason);
1556 break;
1558 default:
1559 PTRACE(2, "PeerElement\tAccessRequest to " << peerAddr << " refused with unknown response " << (int)request.responseResult);
1560 break;
1563 return Rejected;
1566 H323Transaction::Response H323PeerElement::OnAccessRequest(H501AccessRequest & info)
1568 info.SetRejectReason(H501_AccessRejectionReason::e_noServiceRelationship);
1569 return H323Transaction::Reject;
1572 BOOL H323PeerElement::OnReceiveAccessRequest(const H501PDU & pdu, const H501_AccessRequest & /*pduBody*/)
1574 H501AccessRequest * info = new H501AccessRequest(*this, pdu);
1575 if (!info->HandlePDU())
1576 delete info;
1578 return FALSE;
1581 BOOL H323PeerElement::OnReceiveAccessConfirmation(const H501PDU & pdu, const H501_AccessConfirmation & pduBody)
1583 if (!H323_AnnexG::OnReceiveAccessConfirmation(pdu, pduBody))
1584 return FALSE;
1586 if (lastRequest->responseInfo != NULL)
1587 *(H501PDU *)lastRequest->responseInfo = pdu;
1589 return TRUE;
1592 BOOL H323PeerElement::OnReceiveAccessRejection(const H501PDU & pdu, const H501_AccessRejection & pduBody)
1594 if (!H323_AnnexG::OnReceiveAccessRejection(pdu, pduBody))
1595 return FALSE;
1597 return TRUE;
1600 BOOL H323PeerElement::MakeRequest(Request & request)
1602 requestMutex.Wait();
1603 BOOL stat = H323_AnnexG::MakeRequest(request);
1604 requestMutex.Signal();
1605 return stat;
1608 //////////////////////////////////////////////////////////////////////////////
1610 PObject::Comparison H323PeerElementDescriptor::Compare(const PObject & obj) const
1612 H323PeerElementDescriptor & other = (H323PeerElementDescriptor &)obj;
1613 return descriptorID.Compare(other.descriptorID);
1616 void H323PeerElementDescriptor::CopyTo(H501_Descriptor & descriptor)
1618 descriptor.m_descriptorInfo.m_descriptorID = descriptorID;
1619 descriptor.m_descriptorInfo.m_lastChanged = lastChanged.AsString("yyyyMMddhhmmss", PTime::GMT);
1620 descriptor.m_templates = addressTemplates;
1622 if (!gatekeeperID.IsEmpty()) {
1623 descriptor.IncludeOptionalField(H501_Descriptor::e_gatekeeperID);
1624 descriptor.m_gatekeeperID = gatekeeperID;
1629 BOOL H323PeerElementDescriptor::ContainsNonexistent()
1631 BOOL blocked = FALSE;
1633 // look for any nonexistent routes, which means this descriptor does NOT match
1634 PINDEX k, j;
1635 for (k = 0; !blocked && (k < addressTemplates.GetSize()); k++) {
1636 H501_ArrayOf_RouteInformation & routeInfo = addressTemplates[k].m_routeInfo;
1637 for (j = 0; !blocked && (j < routeInfo.GetSize()); j++) {
1638 if (routeInfo[j].m_messageType.GetTag() == H501_RouteInformation_messageType::e_nonExistent)
1639 blocked = TRUE;
1643 return blocked;
1647 BOOL H323PeerElementDescriptor::CopyToAddressTemplate(H501_AddressTemplate & addressTemplate,
1648 const H225_EndpointType & epInfo,
1649 const H225_ArrayOf_AliasAddress & aliases,
1650 const H225_ArrayOf_AliasAddress & transportAddresses,
1651 unsigned options)
1653 // add patterns for this descriptor
1654 addressTemplate.m_pattern.SetSize(aliases.GetSize());
1655 PINDEX j;
1656 for (j = 0; j < aliases.GetSize(); j++) {
1657 H501_Pattern & pattern = addressTemplate.m_pattern[j];
1658 if ((options & Option_WildCard) != 0)
1659 pattern.SetTag(H501_Pattern::e_wildcard);
1660 else
1661 pattern.SetTag(H501_Pattern::e_specific);
1662 (H225_AliasAddress &)pattern = aliases[j];
1665 // add transport addresses for this descriptor
1666 H501_ArrayOf_RouteInformation & routeInfos = addressTemplate.m_routeInfo;
1667 routeInfos.SetSize(1);
1668 H501_RouteInformation & routeInfo = routeInfos[0];
1670 if ((options & Option_NotAvailable) != 0)
1671 routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_nonExistent);
1673 else if ((options & Option_SendAccessRequest) != 0)
1674 routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_sendAccessRequest);
1676 else {
1677 routeInfo.m_messageType.SetTag(H501_RouteInformation_messageType::e_sendSetup);
1678 routeInfo.m_callSpecific = FALSE;
1679 routeInfo.IncludeOptionalField(H501_RouteInformation::e_type);
1680 routeInfo.m_type = epInfo;
1683 routeInfo.m_callSpecific = FALSE;
1684 H501_ArrayOf_ContactInformation & contacts = routeInfos[0].m_contacts;
1685 contacts.SetSize(transportAddresses.GetSize());
1686 PINDEX i;
1687 for (i = 0; i < transportAddresses.GetSize(); i++) {
1688 H501_ContactInformation & contact = contacts[i];
1689 contact.m_transportAddress = transportAddresses[i];
1690 contact.m_priority = H323PeerElementDescriptor::GetPriorityOption(options);
1693 // add protocols
1694 addressTemplate.IncludeOptionalField(H501_AddressTemplate::e_supportedProtocols);
1695 SetProtocolList(addressTemplate.m_supportedProtocols, options);
1697 return TRUE;
1701 BOOL H323PeerElementDescriptor::CopyFrom(const H501_Descriptor & descriptor)
1703 descriptorID = descriptor.m_descriptorInfo.m_descriptorID;
1704 //lastChanged.AsString("yyyyMMddhhmmss") = descriptor.m_descriptorInfo.m_lastChanged;
1705 addressTemplates = descriptor.m_templates;
1707 if (descriptor.HasOptionalField(H501_Descriptor::e_gatekeeperID))
1708 gatekeeperID = descriptor.m_gatekeeperID;
1709 else
1710 gatekeeperID = PString::Empty();
1712 return TRUE;
1716 void H323PeerElementDescriptor::SetProtocolList(H501_ArrayOf_SupportedProtocols & h501Protocols, unsigned options)
1718 h501Protocols.SetSize(0);
1719 int mask =1;
1720 do {
1721 if (options & mask) {
1722 int pos = h501Protocols.GetSize();
1723 switch (mask) {
1724 case H323PeerElementDescriptor::Protocol_H323:
1725 h501Protocols.SetSize(pos+1);
1726 h501Protocols[pos].SetTag(H225_SupportedProtocols::e_h323);
1727 break;
1729 case H323PeerElementDescriptor::Protocol_Voice:
1730 h501Protocols.SetSize(pos+1);
1731 h501Protocols[pos].SetTag(H225_SupportedProtocols::e_voice);
1732 break;
1734 default:
1735 break;
1738 mask *= 2;
1739 } while (mask != Protocol_Max);
1742 unsigned H323PeerElementDescriptor::GetProtocolList(const H501_ArrayOf_SupportedProtocols & h501Protocols)
1744 unsigned options = 0;
1745 PINDEX i;
1746 for (i = 0; i < h501Protocols.GetSize(); i++) {
1747 switch (h501Protocols[i].GetTag()) {
1748 case H225_SupportedProtocols::e_h323:
1749 options += Protocol_H323;
1750 break;
1752 case H225_SupportedProtocols::e_voice:
1753 options += Protocol_Voice;
1754 break;
1756 default:
1757 break;
1760 return options;
1764 // End of file ////////////////////////////////////////////////////////////////