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