1 /*
2 * h323trans.cxx
3 *
4 * H.323 Transactor 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 * $Revision: 22170 $
27 * $Author: rjongbloed $
28 * $Date: 2009-03-08 21:48:51 -0500 (Sun, 08 Mar 2009) $
29 */
30
31 #include <ptlib.h>
32
33 #include <opal/buildopts.h>
34 #if OPAL_H323
35
36 #ifdef __GNUC__
37 #pragma implementation "h323trans.h"
38 #endif
39
40 #include <h323/h323trans.h>
41
42 #include <h323/h323ep.h>
43 #include <h323/h323pdu.h>
44
45 #include <ptclib/random.h>
46
47
48 static PTimeInterval ResponseRetirementAge(0, 30); // Seconds
49
50
51 #define new PNEW
52
53
54 static struct AuthenticatorString {
55 int code;
56 const char * desc;
57 } authenticatorStrings[] = {
58 { H235Authenticator::e_OK, "Security parameters and Msg are ok, no security attacks" },
59 { H235Authenticator::e_Absent, "Security parameters are expected but absent" },
60 { H235Authenticator::e_Error, "Security parameters are present but incorrect" },
61 { H235Authenticator::e_InvalidTime, "Security parameters indicate peer has bad real time clock" },
62 { H235Authenticator::e_BadPassword, "Security parameters indicate bad password in token" },
63 { H235Authenticator::e_ReplyAttack, "Security parameters indicate an attack was made" },
64 { H235Authenticator::e_Disabled, "Security is disabled by local system" },
65 { -1, NULL }
66 };
67
68 /////////////////////////////////////////////////////////////////////////////////
69
H323TransactionPDU()70 H323TransactionPDU::H323TransactionPDU()
71 {
72 }
73
74
H323TransactionPDU(const H235Authenticators & auth)75 H323TransactionPDU::H323TransactionPDU(const H235Authenticators & auth)
76 : authenticators(auth)
77 {
78 }
79
80
operator <<(ostream & strm,const H323TransactionPDU & pdu)81 ostream & operator<<(ostream & strm, const H323TransactionPDU & pdu)
82 {
83 pdu.GetPDU().PrintOn(strm);
84 return strm;
85 }
86
87
Read(H323Transport & transport)88 PBoolean H323TransactionPDU::Read(H323Transport & transport)
89 {
90 if (!transport.ReadPDU(rawPDU)) {
91 PTRACE(1, GetProtocolName() << "\tRead error ("
92 << transport.GetErrorNumber(PChannel::LastReadError)
93 << "): " << transport.GetErrorText(PChannel::LastReadError));
94 return PFalse;
95 }
96
97 rawPDU.ResetDecoder();
98 PBoolean ok = GetPDU().Decode(rawPDU);
99 if (!ok) {
100 PTRACE(1, GetProtocolName() << "\tRead error: PER decode failure:\n "
101 << setprecision(2) << rawPDU << "\n " << setprecision(2) << *this);
102 GetChoice().SetTag(UINT_MAX);
103 return PTrue;
104 }
105
106 H323TraceDumpPDU(GetProtocolName(), PFalse, rawPDU, GetPDU(), GetChoice(), GetSequenceNumber());
107
108 return PTrue;
109 }
110
111
Write(H323Transport & transport)112 PBoolean H323TransactionPDU::Write(H323Transport & transport)
113 {
114 PPER_Stream strm;
115 GetPDU().Encode(strm);
116 strm.CompleteEncoding();
117
118 // Finalise the security if present
119 for (H235Authenticators::iterator iterAuth = authenticators.begin(); iterAuth != authenticators.end(); ++iterAuth)
120 iterAuth->Finalise(strm);
121
122 H323TraceDumpPDU("Trans", PTrue, strm, GetPDU(), GetChoice(), GetSequenceNumber());
123
124 if (transport.WritePDU(strm))
125 return PTrue;
126
127 PTRACE(1, GetProtocolName() << "\tWrite PDU failed ("
128 << transport.GetErrorNumber(PChannel::LastWriteError)
129 << "): " << transport.GetErrorText(PChannel::LastWriteError));
130 return PFalse;
131 }
132
133
134 /////////////////////////////////////////////////////////////////////////////////
135
H323Transactor(H323EndPoint & ep,H323Transport * trans,WORD local_port,WORD remote_port)136 H323Transactor::H323Transactor(H323EndPoint & ep,
137 H323Transport * trans,
138 WORD local_port,
139 WORD remote_port)
140 : endpoint(ep),
141 defaultLocalPort(local_port),
142 defaultRemotePort(remote_port)
143 {
144 if (trans != NULL)
145 transport = trans;
146 else
147 transport = new H323TransportUDP(ep, PIPSocket::GetDefaultIpAny(), local_port);
148
149 Construct();
150 }
151
152
H323Transactor(H323EndPoint & ep,const H323TransportAddress & iface,WORD local_port,WORD remote_port)153 H323Transactor::H323Transactor(H323EndPoint & ep,
154 const H323TransportAddress & iface,
155 WORD local_port,
156 WORD remote_port)
157 : endpoint(ep),
158 defaultLocalPort(local_port),
159 defaultRemotePort(remote_port)
160 {
161 if (iface.IsEmpty())
162 transport = NULL;
163 else {
164 PIPSocket::Address addr;
165 PAssert(iface.GetIpAndPort(addr, local_port), "Cannot parse address");
166 transport = new H323TransportUDP(ep, addr, local_port);
167 }
168
169 Construct();
170 }
171
172
Construct()173 void H323Transactor::Construct()
174 {
175 nextSequenceNumber = PRandom::Number()%65536;
176 checkResponseCryptoTokens = PTrue;
177 lastRequest = NULL;
178
179 requests.DisallowDeleteObjects();
180 }
181
182
~H323Transactor()183 H323Transactor::~H323Transactor()
184 {
185 StopChannel();
186 }
187
188
PrintOn(ostream & strm) const189 void H323Transactor::PrintOn(ostream & strm) const
190 {
191 if (transport == NULL)
192 strm << "<<no-transport>>";
193 else {
194 H323TransportAddress addr = transport->GetRemoteAddress();
195
196 PIPSocket::Address ip;
197 WORD port;
198 if (addr.GetIpAndPort(ip, port)) {
199 strm << PIPSocket::GetHostName(ip);
200 if (port != defaultRemotePort)
201 strm << ':' << port;
202 }
203 else
204 strm << addr;
205 }
206 }
207
208
SetTransport(const H323TransportAddress & iface)209 PBoolean H323Transactor::SetTransport(const H323TransportAddress & iface)
210 {
211 PWaitAndSignal mutex(pduWriteMutex);
212
213 if (transport != NULL && transport->GetLocalAddress().IsEquivalent(iface)) {
214 PTRACE(2, "Trans\tAlready have listener for " << iface);
215 return PTrue;
216 }
217
218 PIPSocket::Address addr;
219 WORD port = defaultLocalPort;
220 if (!iface.GetIpAndPort(addr, port)) {
221 PTRACE(1, "Trans\tCannot create listener for " << iface);
222 return PFalse;
223 }
224
225 if (transport != NULL) {
226 transport->CleanUpOnTermination();
227 delete transport;
228 }
229
230 transport = new H323TransportUDP(endpoint, addr, port);
231 transport->SetPromiscuous(H323Transport::AcceptFromAny);
232 return StartChannel();;
233 }
234
235
GetInterfaceAddresses(bool excludeLocalHost)236 H323TransportAddressArray H323Transactor::GetInterfaceAddresses(bool excludeLocalHost)
237 {
238 if (transport == NULL)
239 return H323TransportAddressArray();
240 else
241 return endpoint.GetInterfaceAddresses(excludeLocalHost, transport);
242 }
243
244
StartChannel()245 PBoolean H323Transactor::StartChannel()
246 {
247 if (transport == NULL)
248 return PFalse;
249
250 transport->AttachThread(PThread::Create(PCREATE_NOTIFIER(HandleTransactions), "Transactor"));
251 return PTrue;
252 }
253
254
StopChannel()255 void H323Transactor::StopChannel()
256 {
257 if (transport != NULL) {
258 transport->CleanUpOnTermination();
259 delete transport;
260 transport = NULL;
261 }
262 }
263
264
HandleTransactions(PThread &,INT)265 void H323Transactor::HandleTransactions(PThread &, INT)
266 {
267 if (PAssertNULL(transport) == NULL)
268 return;
269
270 PTRACE(3, "Trans\tStarting listener thread on " << *transport);
271
272 transport->SetReadTimeout(PMaxTimeInterval);
273
274 PINDEX consecutiveErrors = 0;
275
276 PBoolean ok = PTrue;
277 while (ok) {
278 PTRACE(5, "Trans\tReading PDU");
279 H323TransactionPDU * response = CreateTransactionPDU();
280 if (response->Read(*transport)) {
281 consecutiveErrors = 0;
282 lastRequest = NULL;
283 if (HandleTransaction(response->GetPDU()))
284 lastRequest->responseHandled.Signal();
285 if (lastRequest != NULL)
286 lastRequest->responseMutex.Signal();
287 }
288 else {
289 switch (transport->GetErrorCode(PChannel::LastReadError)) {
290 case PChannel::Interrupted :
291 if (transport->IsOpen())
292 break;
293 // Do NotOpen case
294
295 case PChannel::NotOpen :
296 ok = PFalse;
297 break;
298
299 default :
300 switch (transport->GetErrorNumber(PChannel::LastReadError)) {
301 case ECONNRESET:
302 case ECONNREFUSED:
303 PTRACE(2, "Trans\tCannot access remote " << transport->GetRemoteAddress());
304 break;
305
306 default:
307 PTRACE(1, "Trans\tRead error: " << transport->GetErrorText(PChannel::LastReadError));
308 if (++consecutiveErrors > 10)
309 ok = PFalse;
310 }
311 }
312 }
313
314 delete response;
315 AgeResponses();
316 }
317
318 PTRACE(3, "Trans\tEnded listener thread on " << *transport);
319 }
320
321
SetUpCallSignalAddresses(H225_ArrayOf_TransportAddress & addresses)322 PBoolean H323Transactor::SetUpCallSignalAddresses(H225_ArrayOf_TransportAddress & addresses)
323 {
324 if (PAssertNULL(transport) == NULL)
325 return PFalse;
326
327 H323SetTransportAddresses(*transport,
328 endpoint.GetInterfaceAddresses(PFalse, transport),
329 addresses);
330
331 return addresses.GetSize() > 0;
332 }
333
334
GetNextSequenceNumber()335 unsigned H323Transactor::GetNextSequenceNumber()
336 {
337 PWaitAndSignal mutex(nextSequenceNumberMutex);
338 nextSequenceNumber++;
339 if (nextSequenceNumber >= 65536)
340 nextSequenceNumber = 1;
341 return nextSequenceNumber;
342 }
343
344
AgeResponses()345 void H323Transactor::AgeResponses()
346 {
347 PTime now;
348
349 PWaitAndSignal mutex(pduWriteMutex);
350
351 for (PINDEX i = 0; i < responses.GetSize(); i++) {
352 const Response & response = responses[i];
353 if ((now - response.lastUsedTime) > response.retirementAge) {
354 PTRACE(4, "Trans\tRemoving cached response: " << response);
355 responses.RemoveAt(i--);
356 }
357 }
358 }
359
360
SendCachedResponse(const H323TransactionPDU & pdu)361 PBoolean H323Transactor::SendCachedResponse(const H323TransactionPDU & pdu)
362 {
363 if (PAssertNULL(transport) == NULL)
364 return PFalse;
365
366 Response key(transport->GetLastReceivedAddress(), pdu.GetSequenceNumber());
367
368 PWaitAndSignal mutex(pduWriteMutex);
369
370 PINDEX idx = responses.GetValuesIndex(key);
371 if (idx != P_MAX_INDEX)
372 return responses[idx].SendCachedResponse(*transport);
373
374 responses.Append(new Response(key));
375 return PFalse;
376 }
377
378
WritePDU(H323TransactionPDU & pdu)379 PBoolean H323Transactor::WritePDU(H323TransactionPDU & pdu)
380 {
381 if (PAssertNULL(transport) == NULL)
382 return PFalse;
383
384 OnSendingPDU(pdu.GetPDU());
385
386 PWaitAndSignal mutex(pduWriteMutex);
387
388 Response key(transport->GetLastReceivedAddress(), pdu.GetSequenceNumber());
389 PINDEX idx = responses.GetValuesIndex(key);
390 if (idx != P_MAX_INDEX)
391 responses[idx].SetPDU(pdu);
392
393 return pdu.Write(*transport);
394 }
395
396
WriteTo(H323TransactionPDU & pdu,const H323TransportAddressArray & addresses,PBoolean callback)397 PBoolean H323Transactor::WriteTo(H323TransactionPDU & pdu,
398 const H323TransportAddressArray & addresses,
399 PBoolean callback)
400 {
401 if (PAssertNULL(transport) == NULL)
402 return PFalse;
403
404 if (addresses.IsEmpty()) {
405 if (callback)
406 return WritePDU(pdu);
407
408 return pdu.Write(*transport);
409 }
410
411 pduWriteMutex.Wait();
412
413 H323TransportAddress oldAddress = transport->GetRemoteAddress();
414
415 PBoolean ok = PFalse;
416 for (PINDEX i = 0; i < addresses.GetSize(); i++) {
417 if (transport->SetRemoteAddress(addresses[i])) {
418 PTRACE(3, "Trans\tWrite address set to " << addresses[i]);
419 if (callback)
420 ok = WritePDU(pdu);
421 else
422 ok = pdu.Write(*transport);
423 }
424 }
425
426 transport->SetRemoteAddress(oldAddress);
427
428 pduWriteMutex.Signal();
429
430 return ok;
431 }
432
433
MakeRequest(Request & request)434 PBoolean H323Transactor::MakeRequest(Request & request)
435 {
436 PTRACE(3, "Trans\tMaking request: " << request.requestPDU.GetChoice().GetTagName());
437
438 OnSendingPDU(request.requestPDU.GetPDU());
439
440 requestsMutex.Wait();
441 requests.SetAt(request.sequenceNumber, &request);
442 requestsMutex.Signal();
443
444 PBoolean ok = request.Poll(*this);
445
446 requestsMutex.Wait();
447 requests.SetAt(request.sequenceNumber, NULL);
448 requestsMutex.Signal();
449
450 return ok;
451 }
452
453
CheckForResponse(unsigned reqTag,unsigned seqNum,const PASN_Choice * reason)454 PBoolean H323Transactor::CheckForResponse(unsigned reqTag, unsigned seqNum, const PASN_Choice * reason)
455 {
456 requestsMutex.Wait();
457 lastRequest = requests.GetAt(seqNum);
458 requestsMutex.Signal();
459
460 if (lastRequest == NULL) {
461 PTRACE(2, "Trans\tTimed out or received sequence number (" << seqNum << ") for PDU we never requested");
462 return PFalse;
463 }
464
465 lastRequest->responseMutex.Wait();
466 lastRequest->CheckResponse(reqTag, reason);
467 return PTrue;
468 }
469
470
HandleRequestInProgress(const H323TransactionPDU & pdu,unsigned delay)471 PBoolean H323Transactor::HandleRequestInProgress(const H323TransactionPDU & pdu,
472 unsigned delay)
473 {
474 unsigned seqNum = pdu.GetSequenceNumber();
475
476 requestsMutex.Wait();
477 lastRequest = requests.GetAt(seqNum);
478 requestsMutex.Signal();
479
480 if (lastRequest == NULL) {
481 PTRACE(2, "Trans\tTimed out or received sequence number (" << seqNum << ") for PDU we never requested");
482 return PFalse;
483 }
484
485 lastRequest->responseMutex.Wait();
486
487 PTRACE(3, "Trans\tReceived RIP on sequence number " << seqNum);
488 lastRequest->OnReceiveRIP(delay);
489 return PTrue;
490 }
491
492
CheckCryptoTokens(const H323TransactionPDU & pdu,const PASN_Array & clearTokens,unsigned clearOptionalField,const PASN_Array & cryptoTokens,unsigned cryptoOptionalField)493 PBoolean H323Transactor::CheckCryptoTokens(const H323TransactionPDU & pdu,
494 const PASN_Array & clearTokens,
495 unsigned clearOptionalField,
496 const PASN_Array & cryptoTokens,
497 unsigned cryptoOptionalField)
498 {
499 // If cypto token checking disabled, just return PTrue.
500 if (!GetCheckResponseCryptoTokens())
501 return PTrue;
502
503 if (lastRequest != NULL && pdu.GetAuthenticators().IsEmpty()) {
504 ((H323TransactionPDU &)pdu).SetAuthenticators(lastRequest->requestPDU.GetAuthenticators());
505 PTRACE(4, "Trans\tUsing credentials from request: "
506 << setfill(',') << pdu.GetAuthenticators() << setfill(' '));
507 }
508
509 if (pdu.Validate(clearTokens, clearOptionalField,
510 cryptoTokens, cryptoOptionalField) == H235Authenticator::e_OK)
511 return PTrue;
512
513 /* Note that a crypto tokens error is flagged to the requestor in the
514 responseResult field but the other thread is NOT signalled. This is so
515 it can wait for the full timeout for any other packets that might have
516 the correct tokens, preventing a possible DOS attack.
517 */
518 if (lastRequest != NULL) {
519 lastRequest->responseResult = Request::BadCryptoTokens;
520 lastRequest->responseHandled.Signal();
521 lastRequest->responseMutex.Signal();
522 lastRequest = NULL;
523 }
524
525 return PFalse;
526 }
527
528
529 /////////////////////////////////////////////////////////////////////////////
530
Request(unsigned seqNum,H323TransactionPDU & pdu)531 H323Transactor::Request::Request(unsigned seqNum, H323TransactionPDU & pdu)
532 : requestPDU(pdu)
533 {
534 sequenceNumber = seqNum;
535 responseInfo = NULL;
536 }
537
538
Request(unsigned seqNum,H323TransactionPDU & pdu,const H323TransportAddressArray & addresses)539 H323Transactor::Request::Request(unsigned seqNum,
540 H323TransactionPDU & pdu,
541 const H323TransportAddressArray & addresses)
542 : requestAddresses(addresses),
543 requestPDU(pdu)
544 {
545 sequenceNumber = seqNum;
546 responseInfo = NULL;
547 }
548
549
Poll(H323Transactor & rasChannel,unsigned numRetries,PTimeInterval timeout)550 PBoolean H323Transactor::Request::Poll(H323Transactor & rasChannel, unsigned numRetries, PTimeInterval timeout)
551 {
552 H323EndPoint & endpoint = rasChannel.GetEndPoint();
553
554 responseResult = AwaitingResponse;
555
556 if (numRetries == 0)
557 numRetries = endpoint.GetRasRequestRetries();
558
559 if (timeout == 0)
560 timeout = endpoint.GetRasRequestTimeout();
561
562 for (unsigned retry = 1; retry <= numRetries; retry++) {
563 // To avoid race condition with RIP must set timeout before sending the packet
564 whenResponseExpected = PTimer::Tick() + timeout;
565
566 if (!rasChannel.WriteTo(requestPDU, requestAddresses, PFalse))
567 break;
568
569 PTRACE(3, "Trans\tWaiting on response to seqnum=" << requestPDU.GetSequenceNumber()
570 << " for " << setprecision(1) << timeout << " seconds");
571
572 do {
573 // Wait for a response
574 responseHandled.Wait(whenResponseExpected - PTimer::Tick());
575
576 PWaitAndSignal mutex(responseMutex); // Wait till lastRequest goes out of scope
577
578 switch (responseResult) {
579 case AwaitingResponse : // Was a timeout
580 responseResult = NoResponseReceived;
581 break;
582
583 case ConfirmReceived :
584 return PTrue;
585
586 case RejectReceived :
587 case TryAlternate :
588 return PFalse;
589
590 case BadCryptoTokens :
591 PTRACE(1, "Trans\tResponse to seqnum=" << requestPDU.GetSequenceNumber()
592 << " had invalid crypto tokens.");
593 return PFalse;
594
595 default : // RequestInProgress
596 responseResult = AwaitingResponse; // Keep waiting
597 }
598
599 PTRACE_IF(3, responseResult == AwaitingResponse,
600 "Trans\tWaiting again on response to seqnum=" << requestPDU.GetSequenceNumber() <<
601 " for " << setprecision(1) << (whenResponseExpected - PTimer::Tick()) << " seconds");
602 } while (responseResult == AwaitingResponse);
603
604 PTRACE(1, "Trans\tTimeout on request seqnum=" << requestPDU.GetSequenceNumber()
605 << ", try #" << retry << " of " << numRetries);
606 }
607
608 return PFalse;
609 }
610
611
CheckResponse(unsigned reqTag,const PASN_Choice * reason)612 void H323Transactor::Request::CheckResponse(unsigned reqTag, const PASN_Choice * reason)
613 {
614 if (requestPDU.GetChoice().GetTag() != reqTag) {
615 PTRACE(2, "Trans\tReceived reply for incorrect PDU tag.");
616 responseResult = RejectReceived;
617 rejectReason = UINT_MAX;
618 return;
619 }
620
621 if (reason == NULL) {
622 responseResult = ConfirmReceived;
623 return;
624 }
625
626 PTRACE(2, "Trans\t" << requestPDU.GetChoice().GetTagName()
627 << " rejected: " << reason->GetTagName());
628 responseResult = RejectReceived;
629 rejectReason = reason->GetTag();
630
631 switch(reqTag) {
632 case H225_RasMessage::e_admissionRequest:
633 if (rejectReason == H225_AdmissionRejectReason::e_callerNotRegistered)
634 responseResult = TryAlternate;
635 break;
636
637 case H225_RasMessage::e_gatekeeperRequest:
638 if (rejectReason == H225_GatekeeperRejectReason::e_resourceUnavailable)
639 responseResult = TryAlternate;
640 break;
641
642 case H225_RasMessage::e_disengageRequest:
643 if (rejectReason == H225_DisengageRejectReason::e_notRegistered)
644 responseResult = TryAlternate;
645 break;
646
647 case H225_RasMessage::e_registrationRequest:
648 if (rejectReason == H225_RegistrationRejectReason::e_resourceUnavailable)
649 responseResult = TryAlternate;
650 break;
651
652 case H225_RasMessage::e_infoRequestResponse:
653 if (rejectReason == H225_InfoRequestNakReason::e_notRegistered)
654 responseResult = TryAlternate;
655 break;
656 }
657 }
658
659
OnReceiveRIP(unsigned milliseconds)660 void H323Transactor::Request::OnReceiveRIP(unsigned milliseconds)
661 {
662 responseResult = RequestInProgress;
663 whenResponseExpected = PTimer::Tick() + PTimeInterval(milliseconds);
664 }
665
666
667 /////////////////////////////////////////////////////////////////////////////
668
Response(const H323TransportAddress & addr,unsigned seqNum)669 H323Transactor::Response::Response(const H323TransportAddress & addr, unsigned seqNum)
670 : PString(addr),
671 retirementAge(ResponseRetirementAge)
672 {
673 sprintf("#%u", seqNum);
674 replyPDU = NULL;
675 }
676
677
~Response()678 H323Transactor::Response::~Response()
679 {
680 if (replyPDU != NULL)
681 replyPDU->DeletePDU();
682 }
683
684
SetPDU(const H323TransactionPDU & pdu)685 void H323Transactor::Response::SetPDU(const H323TransactionPDU & pdu)
686 {
687 PTRACE(4, "Trans\tAdding cached response: " << *this);
688
689 if (replyPDU != NULL)
690 replyPDU->DeletePDU();
691 replyPDU = pdu.ClonePDU();
692 lastUsedTime = PTime();
693
694 unsigned delay = pdu.GetRequestInProgressDelay();
695 if (delay > 0)
696 retirementAge = ResponseRetirementAge + delay;
697 }
698
699
SendCachedResponse(H323Transport & transport)700 PBoolean H323Transactor::Response::SendCachedResponse(H323Transport & transport)
701 {
702 PTRACE(3, "Trans\tSending cached response: " << *this);
703
704 if (replyPDU != NULL) {
705 H323TransportAddress oldAddress = transport.GetRemoteAddress();
706 transport.ConnectTo(Left(FindLast('#')));
707 replyPDU->Write(transport);
708 transport.ConnectTo(oldAddress);
709 }
710 else {
711 PTRACE(2, "Trans\tRetry made by remote before sending response: " << *this);
712 }
713
714 lastUsedTime = PTime();
715 return PTrue;
716 }
717
718
719 /////////////////////////////////////////////////////////////////////////////////
720
H323Transaction(H323Transactor & trans,const H323TransactionPDU & requestToCopy,H323TransactionPDU * conf,H323TransactionPDU * rej)721 H323Transaction::H323Transaction(H323Transactor & trans,
722 const H323TransactionPDU & requestToCopy,
723 H323TransactionPDU * conf,
724 H323TransactionPDU * rej)
725 : transactor(trans),
726 replyAddresses(trans.GetTransport().GetLastReceivedAddress()),
727 request(requestToCopy.ClonePDU())
728 {
729 confirm = conf;
730 reject = rej;
731 authenticatorResult = H235Authenticator::e_Disabled;
732 fastResponseRequired = PTrue;
733 isBehindNAT = PFalse;
734 canSendRIP = PFalse;
735 }
736
737
~H323Transaction()738 H323Transaction::~H323Transaction()
739 {
740 delete request;
741 delete confirm;
742 delete reject;
743 }
744
745
HandlePDU()746 PBoolean H323Transaction::HandlePDU()
747 {
748 int response = OnHandlePDU();
749 switch (response) {
750 case Ignore :
751 return PFalse;
752
753 case Confirm :
754 if (confirm != NULL)
755 WritePDU(*confirm);
756 return PFalse;
757
758 case Reject :
759 if (reject != NULL)
760 WritePDU(*reject);
761 return PFalse;
762 }
763
764 H323TransactionPDU * rip = CreateRIP(request->GetSequenceNumber(), response);
765 PBoolean ok = WritePDU(*rip);
766 delete rip;
767
768 if (!ok)
769 return PFalse;
770
771 if (fastResponseRequired) {
772 fastResponseRequired = PFalse;
773 PThread::Create(PCREATE_NOTIFIER(SlowHandler), 0,
774 PThread::AutoDeleteThread,
775 PThread::NormalPriority,
776 "Transaction");
777 }
778
779 return PTrue;
780 }
781
782
SlowHandler(PThread &,INT)783 void H323Transaction::SlowHandler(PThread &, INT)
784 {
785 PTRACE(4, "Trans\tStarted slow PDU handler thread.");
786
787 while (HandlePDU())
788 ;
789
790 delete this;
791
792 PTRACE(4, "Trans\tEnded slow PDU handler thread.");
793 }
794
795
WritePDU(H323TransactionPDU & pdu)796 PBoolean H323Transaction::WritePDU(H323TransactionPDU & pdu)
797 {
798 pdu.SetAuthenticators(authenticators);
799 return transactor.WriteTo(pdu, replyAddresses, PTrue);
800 }
801
802
CheckCryptoTokens(const H235Authenticators & auth)803 PBoolean H323Transaction::CheckCryptoTokens(const H235Authenticators & auth)
804 {
805 authenticators = auth;
806
807 request->SetAuthenticators(authenticators);
808
809 authenticatorResult = ValidatePDU();
810
811 if (authenticatorResult == H235Authenticator::e_OK)
812 return PTrue;
813
814 PINDEX i;
815 for (i = 0; (authenticatorStrings[i].code >= 0) && (authenticatorStrings[i].code != authenticatorResult); ++i)
816 ;
817
818 const char * desc = "Unknown error";
819 if (authenticatorStrings[i].code >= 0)
820 desc = authenticatorStrings[i].desc;
821
822 PTRACE(2, "Trans\t" << GetName() << " rejected - " << desc);
823 return PFalse;
824 }
825
826
827 /////////////////////////////////////////////////////////////////////////////////
828
H323TransactionServer(H323EndPoint & ep)829 H323TransactionServer::H323TransactionServer(H323EndPoint & ep)
830 : ownerEndPoint(ep)
831 {
832 }
833
834
~H323TransactionServer()835 H323TransactionServer::~H323TransactionServer()
836 {
837 }
838
839
AddListeners(const H323TransportAddressArray & ifaces)840 PBoolean H323TransactionServer::AddListeners(const H323TransportAddressArray & ifaces)
841 {
842 if (ifaces.IsEmpty())
843 return AddListener("udp$*");
844
845 PINDEX i;
846
847 mutex.Wait();
848 ListenerList::iterator iterListener = listeners.begin();
849 while (iterListener != listeners.end()) {
850 PBoolean remove = PTrue;
851 for (PINDEX j = 0; j < ifaces.GetSize(); j++) {
852 if (iterListener->GetTransport().GetLocalAddress().IsEquivalent(ifaces[j], true)) {
853 remove = PFalse;
854 break;
855 }
856 }
857 if (remove) {
858 PTRACE(3, "Trans\tRemoving listener " << *iterListener);
859 listeners.erase(iterListener++);
860 }
861 else
862 ++iterListener;
863 }
864 mutex.Signal();
865
866 for (i = 0; i < ifaces.GetSize(); i++) {
867 if (!ifaces[i])
868 AddListener(ifaces[i]);
869 }
870
871 return listeners.GetSize() > 0;
872 }
873
874
AddListener(const H323TransportAddress & interfaceName)875 PBoolean H323TransactionServer::AddListener(const H323TransportAddress & interfaceName)
876 {
877 PWaitAndSignal wait(mutex);
878
879 PINDEX i;
880 for (ListenerList::iterator iterListener = listeners.begin(); iterListener != listeners.end(); ++iterListener) {
881 if (iterListener->GetTransport().GetLocalAddress().IsEquivalent(interfaceName, true)) {
882 PTRACE(2, "H323\tAlready have listener for " << interfaceName);
883 return PTrue;
884 }
885 }
886
887 PIPSocket::Address addr;
888 WORD port = GetDefaultUdpPort();
889 if (!interfaceName.GetIpAndPort(addr, port))
890 return AddListener(interfaceName.CreateTransport(ownerEndPoint));
891
892 if (!addr.IsAny())
893 return AddListener(new H323TransportUDP(ownerEndPoint, addr, port));
894
895 PIPSocket::InterfaceTable interfaces;
896 if (!PIPSocket::GetInterfaceTable(interfaces)) {
897 PTRACE(1, "Trans\tNo interfaces on system!");
898 if (!PIPSocket::GetHostAddress(addr))
899 return PFalse;
900 return AddListener(new H323TransportUDP(ownerEndPoint, addr, port));
901 }
902
903 PTRACE(4, "Trans\tAdding interfaces:\n" << setfill('\n') << interfaces << setfill(' '));
904
905 PBoolean atLeastOne = PFalse;
906
907 for (i = 0; i < interfaces.GetSize(); i++) {
908 addr = interfaces[i].GetAddress();
909 if (addr != 0) {
910 if (AddListener(new H323TransportUDP(ownerEndPoint, addr, port, false, true)))
911 atLeastOne = PTrue;
912 }
913 }
914
915 return atLeastOne;
916 }
917
918
AddListener(H323Transport * transport)919 PBoolean H323TransactionServer::AddListener(H323Transport * transport)
920 {
921 if (transport == NULL)
922 return PFalse;
923
924 if (!transport->IsOpen()) {
925 delete transport;
926 return PFalse;
927 }
928
929 return AddListener(CreateListener(transport));
930 }
931
932
AddListener(H323Transactor * listener)933 PBoolean H323TransactionServer::AddListener(H323Transactor * listener)
934 {
935 if (listener == NULL)
936 return PFalse;
937
938 PTRACE(3, "Trans\tStarted listener " << *listener);
939
940 mutex.Wait();
941 listeners.Append(listener);
942 mutex.Signal();
943
944 listener->StartChannel();
945
946 return PTrue;
947 }
948
949
RemoveListener(H323Transactor * listener)950 PBoolean H323TransactionServer::RemoveListener(H323Transactor * listener)
951 {
952 PBoolean ok = PTrue;
953
954 mutex.Wait();
955 if (listener != NULL) {
956 PTRACE(3, "Trans\tRemoving listener " << *listener);
957 ok = listeners.Remove(listener);
958 }
959 else {
960 PTRACE(3, "Trans\tRemoving all listeners");
961 listeners.RemoveAll();
962 }
963 mutex.Signal();
964
965 return ok;
966 }
967
968
969 #endif // OPAL_H323
970
971 /////////////////////////////////////////////////////////////////////////////////
972