4 * H.323 Annex G Peer Element client protocol handler
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
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
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
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
145 * Revision 1.8 2003/03/19 01:11:37 robertj
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
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
174 #pragma implementation "peclient.h"
177 #include "peclient.h"
180 #include "h323annexg.h"
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
),
200 H323TransactionPDU
* H501Transaction::CreateRIP(unsigned sequenceNumber
,
201 unsigned delay
) const
203 H501PDU
* rip
= new H501PDU
;
204 rip
->BuildRequestInProgress(sequenceNumber
, delay
);
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
,
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
))
230 const char * H501ServiceRequest::GetName() const
232 return "ServiceRequest";
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
,
253 : H501Transaction(pe
, pdu
, FALSE
),
254 du((H501_DescriptorUpdate
&)request
->GetChoice().GetObject()),
255 ack(((H501PDU
&)confirm
->GetPDU()).BuildDescriptorUpdateAck(pdu
.m_common
.m_sequenceNumber
))
261 const char * H501DescriptorUpdate::GetName() const
263 return "DescriptorUpdate";
268 void H501DescriptorUpdate::SetRejectReason(unsigned /*reasonCode*/)
274 H323Transaction::Response
H501DescriptorUpdate::OnHandlePDU()
276 return peerElement
.OnDescriptorUpdate(*this);
280 ////////////////////////////////////////////////////////////////
282 H501AccessRequest::H501AccessRequest(H323PeerElement
& pe
,
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
))
294 const char * H501AccessRequest::GetName() const
296 return "AccessRequest";
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
),
322 H323PeerElement::H323PeerElement(H323EndPoint
& ep
, const H323TransportAddress
& addr
)
323 : H323_AnnexG(ep
, addr
),
329 void H323PeerElement::Construct()
331 if (transport
!= NULL
)
332 transport
->SetPromiscuous(H323Transport::AcceptFromAny
);
335 localIdentifier
= endpoint
.GetLocalUserName();
336 basePeerOrdinal
= RemoteServiceRelationshipOrdinal
;
340 monitor
= PThread::Create(PCREATE_NOTIFIER(MonitorMain
), 0,
341 PThread::NoAutoDeleteThread
,
342 PThread::NormalPriority
,
343 "PeerElementMonitor:%x");
346 H323PeerElement::~H323PeerElement()
348 if (monitor
!= NULL
) {
350 monitorTickle
.Signal();
351 monitor
->WaitForTermination();
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
);
377 PString
H323PeerElement::GetDomainName() const
379 PWaitAndSignal
m(localNameMutex
);
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");
397 // refresh and retry remote service relationships by sending new ServiceRequests
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
);
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
);
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
);
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
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();
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
)) {
528 case ServiceRelationshipReestablished
:
537 case NoServiceRelationship
:
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();
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();
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
);
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
))
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
);
604 H323PeerElement::Error
H323PeerElement::ServiceRequestByAddr(const H323TransportAddress
& peer
, OpalGloballyUniqueID
& serviceID
)
606 if (PAssertNULL(transport
) == NULL
)
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
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
;
631 Request
request(pdu
.GetSequenceNumber(), pdu
, peer
);
633 request
.responseInfo
= &reply
;
634 if (!MakeRequest(request
)) {
636 switch (request
.responseResult
) {
637 case Request::NoResponseReceived
:
638 PTRACE(2, "PeerElement\tServiceRequest to " << peer
<< " failed due to no response");
641 case Request::RejectReceived
:
642 PTRACE(2, "PeerElement\tServiceRequest to " << peer
<< " rejected for reason " << request
.rejectReason
);
646 PTRACE(2, "PeerElement\tServiceRequest to " << peer
<< " refused with unknown response " << (int)request
.responseResult
);
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");
659 // create the service relationship
660 H501_ServiceConfirmation
& replyBody
= reply
.m_body
;
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();
697 H323PeerElement::Error
H323PeerElement::ServiceRequestByID(OpalGloballyUniqueID
& serviceID
)
699 if (PAssertNULL(transport
) == NULL
)
702 // build the service request
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
);
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
);
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
);
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();
738 case Request::RejectReceived
:
739 switch (request
.rejectReason
) {
740 case H501_ServiceRejectionReason::e_unknownServiceID
:
741 if (OnRemoteServiceRelationshipDisappeared(serviceID
, sr
->peer
))
746 PTRACE(2, "PeerElement\tServiceRequest to " << sr
->peer
<< " rejected with unknown reason " << request
.rejectReason
);
752 PTRACE(2, "PeerElement\tServiceRequest to " << sr
->peer
<< " failed with unknown response " << (int)request
.responseResult
);
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
);
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];
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();
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())
846 BOOL
H323PeerElement::OnReceiveServiceConfirmation(const H501PDU
& pdu
, const H501_ServiceConfirmation
& pduBody
)
848 if (!H323_AnnexG::OnReceiveServiceConfirmation(pdu
, pduBody
))
851 if (lastRequest
->responseInfo
!= NULL
)
852 *(H501PDU
*)lastRequest
->responseInfo
= pdu
;
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
);
864 // send the request - no response
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
);
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
);
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
);
895 // we have a new service ID
896 PTRACE(2, "PeerElement\tService relationship with " << peer
<< " disappeared and new relationship established");
897 serviceID
= remotePeerAddrToServiceID(peer
);
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
,
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
,
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
,
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
,
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
,
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
;
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
);
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
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
));
1025 case H501_Pattern::e_wildcard
:
1026 wildcardAliasToDescriptorID
.Append(CreateAliasKey((H225_AliasAddress
&)pattern
, descriptorID
, i
, TRUE
));
1028 case H501_Pattern::e_range
:
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
));
1047 OnUpdateDescriptor(*descriptor
);
1049 descriptors
.Append(descriptor
);
1050 OnNewDescriptor(*descriptor
);
1053 // do the update now, or later
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();
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
);
1089 case H501_Pattern::e_wildcard
:
1090 idx
= wildcardAliasToDescriptorID
.GetValuesIndex((H225_AliasAddress
&)pattern
);
1091 if (idx
!= P_MAX_INDEX
)
1092 wildcardAliasToDescriptorID
.RemoveAt(idx
);
1094 case H501_Pattern::e_range
:
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
)
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
)
1144 OnRemoveDescriptor(*descriptor
);
1146 RemoveDescriptorInformation(descriptor
->addressTemplates
);
1148 // delete the descriptor, or mark it as to be deleted
1150 PTRACE(2, "PeerElement\tDescriptor " << descriptorID
<< " deleted");
1151 UpdateDescriptor(descriptor
, H501_UpdateInformation_updateType::e_deleted
);
1153 PTRACE(2, "PeerElement\tDescriptor for " << descriptorID
<< " queued to be deleted");
1154 descriptor
->state
= H323PeerElementDescriptor::Deleted
;
1155 monitorTickle
.Signal();
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
:
1168 case H323PeerElementDescriptor::Dirty
:
1171 case H323PeerElementDescriptor::Deleted
:
1172 updateType
= H501_UpdateInformation_updateType::e_deleted
;
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
)
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
);
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
)
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
1224 return NoServiceRelationship
;
1226 pdu
.m_common
.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID
);
1227 pdu
.m_common
.m_serviceID
= sr
->serviceID
;
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
)
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
)
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
);
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
);
1269 Request
request(pdu
.GetSequenceNumber(), pdu
, peer
);
1270 if (MakeRequest(request
))
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");
1280 PTRACE(2, "PeerElement\tUpdateDescriptor to " << peer
<< " refused with unknown response " << (int)request
.responseResult
);
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())
1301 BOOL
H323PeerElement::OnReceiveDescriptorUpdateACK(const H501PDU
& pdu
, const H501_DescriptorUpdateAck
& pduBody
)
1303 if (!H323_AnnexG::OnReceiveDescriptorUpdateACK(pdu
, pduBody
))
1306 if (lastRequest
->responseInfo
!= NULL
)
1307 *(H501_MessageCommonInfo
*)lastRequest
->responseInfo
= pdu
.m_common
;
1312 ///////////////////////////////////////////////////////////
1314 // access request functions
1317 BOOL
H323PeerElement::AccessRequest(const PString
& searchAlias
,
1318 PStringArray
& destAliases
,
1319 H323TransportAddress
& transportAddress
,
1322 H225_AliasAddress h225searchAlias
;
1323 H323SetAliasAddress(searchAlias
, h225searchAlias
);
1325 H225_ArrayOf_AliasAddress h225destAliases
;
1326 if (!AccessRequest(h225searchAlias
, h225destAliases
, transportAddress
, options
))
1329 destAliases
= H323GetAliasAddressStrings(h225destAliases
);
1334 BOOL
H323PeerElement::AccessRequest(const PString
& searchAlias
,
1335 H225_ArrayOf_AliasAddress
& destAliases
,
1336 H323TransportAddress
& transportAddress
,
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
,
1349 H225_AliasAddress h225Address
;
1350 if (!AccessRequest(searchAlias
, destAliases
, h225Address
, options
))
1353 transportAddress
= H323GetAliasAddressString(h225Address
);
1357 BOOL
H323PeerElement::AccessRequest(const H225_AliasAddress
& searchAlias
,
1358 H225_ArrayOf_AliasAddress
& destAliases
,
1359 H225_AliasAddress
& transportAddress
,
1362 // try each service relationship in turn
1363 POrdinalSet peersTried
;
1365 for (PSafePtr
<H323PeerElementServiceRelationship
> sr
= GetFirstRemoteServiceRelationship(PSafeReadOnly
); sr
!= NULL
; sr
++) {
1367 // create the 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
;
1377 requestBody
.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols
);
1378 H323PeerElementDescriptor::SetProtocolList(requestBody
.m_desiredProtocols
, options
);
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");
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");
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");
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");
1417 H501_ContactInformation
& contact
= routeInfo
.m_contacts
[0];
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());
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
);
1444 else { // H501_RouteInformation_messageType::e_nonExistent
1445 PTRACE(2, "Main\tAccessRequest for " << searchAlias
<< " from " << peerAddr
<< " returned nonExistent");
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
;
1461 requestBody
.IncludeOptionalField(H501_AccessRequest::e_desiredProtocols
);
1462 H323PeerElementDescriptor::SetProtocolList(requestBody
.m_desiredProtocols
, options
);
1465 error
= SendAccessRequestByAddr(addr
, request
, reply
);
1472 ///////////////////////////////////////////////////////////
1474 // access request functions
1477 H323PeerElement::Error
H323PeerElement::SendAccessRequestByID(const OpalGloballyUniqueID
& origServiceID
,
1479 H501PDU
& confirmPDU
)
1481 if (PAssertNULL(transport
) == NULL
)
1484 OpalGloballyUniqueID serviceID
= origServiceID
;
1488 // get the peer address
1489 H323TransportAddress peer
;
1491 PSafePtr
<H323PeerElementServiceRelationship
> sr
= remoteServiceRelationships
.FindWithLock(H323PeerElementServiceRelationship(serviceID
), PSafeReadOnly
);
1493 return NoServiceRelationship
;
1497 // set the service ID
1498 pdu
.m_common
.IncludeOptionalField(H501_MessageCommonInfo::e_serviceID
);
1499 pdu
.m_common
.m_serviceID
= serviceID
;
1502 Request
request(pdu
.GetSequenceNumber(), pdu
, peer
);
1503 request
.responseInfo
= &confirmPDU
;
1504 if (MakeRequest(request
))
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");
1513 case Request::RejectReceived
:
1514 switch (request
.rejectReason
) {
1515 case H501_ServiceRejectionReason::e_unknownServiceID
:
1516 if (!OnRemoteServiceRelationshipDisappeared(serviceID
, peer
))
1525 PTRACE(2, "PeerElement\tAccessRequest to " << peer
<< " refused with unknown response " << (int)request
.responseResult
);
1533 H323PeerElement::Error
H323PeerElement::SendAccessRequestByAddr(const H323TransportAddress
& peerAddr
,
1535 H501PDU
& confirmPDU
)
1537 if (PAssertNULL(transport
) == NULL
)
1540 pdu
.m_common
.RemoveOptionalField(H501_MessageCommonInfo::e_serviceID
);
1543 Request
request(pdu
.GetSequenceNumber(), pdu
, peerAddr
);
1544 request
.responseInfo
= &confirmPDU
;
1545 if (MakeRequest(request
))
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");
1554 case Request::RejectReceived
:
1555 PTRACE(2, "PeerElement\tAccessRequest failed due to " << request
.rejectReason
);
1559 PTRACE(2, "PeerElement\tAccessRequest to " << peerAddr
<< " refused with unknown response " << (int)request
.responseResult
);
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())
1581 BOOL
H323PeerElement::OnReceiveAccessConfirmation(const H501PDU
& pdu
, const H501_AccessConfirmation
& pduBody
)
1583 if (!H323_AnnexG::OnReceiveAccessConfirmation(pdu
, pduBody
))
1586 if (lastRequest
->responseInfo
!= NULL
)
1587 *(H501PDU
*)lastRequest
->responseInfo
= pdu
;
1592 BOOL
H323PeerElement::OnReceiveAccessRejection(const H501PDU
& pdu
, const H501_AccessRejection
& pduBody
)
1594 if (!H323_AnnexG::OnReceiveAccessRejection(pdu
, pduBody
))
1600 BOOL
H323PeerElement::MakeRequest(Request
& request
)
1602 requestMutex
.Wait();
1603 BOOL stat
= H323_AnnexG::MakeRequest(request
);
1604 requestMutex
.Signal();
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
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
)
1647 BOOL
H323PeerElementDescriptor::CopyToAddressTemplate(H501_AddressTemplate
& addressTemplate
,
1648 const H225_EndpointType
& epInfo
,
1649 const H225_ArrayOf_AliasAddress
& aliases
,
1650 const H225_ArrayOf_AliasAddress
& transportAddresses
,
1653 // add patterns for this descriptor
1654 addressTemplate
.m_pattern
.SetSize(aliases
.GetSize());
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
);
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
);
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());
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
);
1694 addressTemplate
.IncludeOptionalField(H501_AddressTemplate::e_supportedProtocols
);
1695 SetProtocolList(addressTemplate
.m_supportedProtocols
, options
);
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;
1710 gatekeeperID = PString::Empty();
1716 void H323PeerElementDescriptor::SetProtocolList(H501_ArrayOf_SupportedProtocols
& h501Protocols
, unsigned options
)
1718 h501Protocols
.SetSize(0);
1721 if (options
& mask
) {
1722 int pos
= h501Protocols
.GetSize();
1724 case H323PeerElementDescriptor::Protocol_H323
:
1725 h501Protocols
.SetSize(pos
+1);
1726 h501Protocols
[pos
].SetTag(H225_SupportedProtocols::e_h323
);
1729 case H323PeerElementDescriptor::Protocol_Voice
:
1730 h501Protocols
.SetSize(pos
+1);
1731 h501Protocols
[pos
].SetTag(H225_SupportedProtocols::e_voice
);
1739 } while (mask
!= Protocol_Max
);
1742 unsigned H323PeerElementDescriptor::GetProtocolList(const H501_ArrayOf_SupportedProtocols
& h501Protocols
)
1744 unsigned options
= 0;
1746 for (i
= 0; i
< h501Protocols
.GetSize(); i
++) {
1747 switch (h501Protocols
[i
].GetTag()) {
1748 case H225_SupportedProtocols::e_h323
:
1749 options
+= Protocol_H323
;
1752 case H225_SupportedProtocols::e_voice
:
1753 options
+= Protocol_Voice
;
1764 // End of file ////////////////////////////////////////////////////////////////