8 * Copyright (C) 2004 Post Increment
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 Post Increment
24 * This code was written with assistance from TransNexus, Inc.
25 * http://www.transnexus.com
27 * Contributor(s): ______________________________________.
30 * Revision 1.24 2006/06/09 07:15:34 csoutheren
31 * Fixed warning when using old OSP toolkit
33 * Revision 1.23 2006/03/26 23:49:20 csoutheren
34 * Added extra logging for OSP release codes
36 * Revision 1.22 2006/03/09 23:43:23 csoutheren
37 * Change OSP call duration
39 * Revision 1.21 2006/02/27 07:04:18 csoutheren
40 * Ensure call ID allocated by the OSP toolkit is freed by the toolkit
42 * Revision 1.20 2006/02/24 04:53:01 csoutheren
43 * Fixed problem with incorrect flag in OSP population
45 * Revision 1.19 2006/02/21 23:50:21 csoutheren
46 * Remove requirement for destination call signaling address in SETUP for OSP validation
48 * Revision 1.18 2006/02/09 03:17:01 csoutheren
49 * Use OSP toolkit routines for allocating call IDs rather than automatic variables
51 * Revision 1.17 2006/01/30 06:11:04 csoutheren
52 * Added extra logging for OSP report usage call
54 * Revision 1.16 2005/12/20 02:08:02 csoutheren
55 * Look for called and calling number information in Q.931 header for OSP validation
57 * Revision 1.15 2005/12/08 06:31:13 csoutheren
58 * Look for called number information in Q.931 header
60 * Revision 1.14 2005/12/02 00:07:12 csoutheren
61 * Look for calling number information in Q.931 header
63 * Revision 1.13 2005/09/16 08:08:36 csoutheren
64 * Split ReportUsage from CallEnd function
66 * Revision 1.12 2005/08/30 08:30:14 csoutheren
67 * Added support for setting connection count on OSP server
69 * Revision 1.11 2005/08/30 01:12:38 csoutheren
70 * Added automatic detection of OSP toolkit version on Unix
72 * Revision 1.10 2005/08/27 02:11:58 csoutheren
73 * Added support for different pthread library required by new OSP toolkit on Windows
74 * Added support for new parameters to GetFirst and GetNext
75 * Fixed incorrect usage of destination address and destination device
77 * Revision 1.9 2005/08/15 01:58:13 csoutheren
78 * Adde support for version 3.3.2 of the OSP Toolkit
80 * Revision 1.8 2005/07/25 01:23:28 csoutheren
81 * Added ability to select token algorithm when validating OSP tokens
83 * Revision 1.7 2005/01/03 14:03:42 csoutheren
84 * Added new configure options and ability to disable/enable modules
86 * Revision 1.6 2004/12/20 02:32:36 csoutheren
87 * Cleeaned up OSP functions
89 * Revision 1.5 2004/12/16 00:34:36 csoutheren
90 * Fixed reporting of call end time and code
91 * Added GetNextDestination
93 * Revision 1.4 2004/12/14 06:22:22 csoutheren
94 * More OSP implementation
96 * Revision 1.3 2004/12/09 23:38:41 csoutheren
97 * More OSP implementation
99 * Revision 1.2 2004/12/08 05:16:14 csoutheren
100 * Fixed OSP compilation on Linux
102 * Revision 1.1 2004/12/08 01:59:23 csoutheren
103 * initial support for Transnexus OSP toolkit
108 #pragma implementation "opalosp.h"
112 #include <ptlib/sockets.h>
113 #include <ptclib/url.h>
121 #ifdef H323_TRANSNEXUS_OSP
124 // Windows has no way to determine which version of the OSP API is being used,
125 // while Unix systems will use a configure test.
126 // On Windows, set the default to the most recent version. This will need manual
127 // configuration if older versions of the toolkit are used
130 #define H323_NEW_OSP_API 1
132 #pragma comment(lib, H323_TRANSNEXUS_OSP_DIR_LIBRARY1)
134 #ifdef H323_NEW_OSP_API
135 #pragma comment(lib, H323_TRANSNEXUS_OSP_DIR_LIBRARY2b)
137 #pragma comment(lib, H323_TRANSNEXUS_OSP_DIR_LIBRARY2a)
141 #define DEFAULT_SSL_LIFETIME 3600 // SSL lifetime
142 #define DEFAULT_MAX_SIMULT_CONN 32 // maximum simultaneous connections
143 #define DEFAULT_HTTP_PERSIST 60 // HTTP persistence of 1 minute
144 #define DEFAULT_HTTP_RETRY_DELAY 600 // HTTP retry delay of 10 minutes
145 #define DEFAULT_HTTP_RETRY 3 // HTTP retry count of 3
146 #define DEFAULT_HTTP_TIMEOUT 10000 // HTTP timeout of 10 secs
147 #define DEFAULT_DELETE_TIMEOUT 4 // delete timeout
149 #define CALLID_SIZE 20 // size of call ID
150 #define CALLED_NUMBER_SIZE 100 // size of storage for called number
151 #define CALLING_NUMBER_SIZE 100 // size of storage for calling number
152 #define DESTINATION_SIZE 100 // size of storage for destination
153 #define DEVICE_SIZE 100 // size of storage for device
154 #define TOKEN_SIZE 16384 // size of OSP token
156 ////////////////////////////////////////////////////////////////////////////////////////////////////////
158 class OSPShutDown
: public PProcessStartup
160 PCLASSINFO(OSPShutDown
, PProcessStartup
);
163 { OpalOSP::Initialise(FALSE
); }
166 PFactory
<PProcessStartup
>::Worker
<OSPShutDown
> ospPluginLoaderStartupFactory("OSPShutDown", true);
168 void OpalOSP::Initialise(BOOL shutdown
)
170 static BOOL initialised
= FALSE
;
172 if (!initialised
&& !shutdown
) {
176 else if (initialised
&& shutdown
) {
181 PString
OpalOSP::TransportAddressToOSPString(const H323TransportAddress
& taddr
)
183 PIPSocket::Address addr
;
185 taddr
.GetIpAndPort(addr
, port
);
186 return IpAddressPortToOSPString(addr
, port
);
189 PString
OpalOSP::AddressToOSPString(const PString
& str
)
191 int b1
, b2
, b3
, b4
, port
;
192 if (sscanf((const char *)str
, "%d.%d.%d.%d:%d", &b1
, &b2
, &b3
, &b4
, &port
) == 5)
193 return psprintf("[%d.%d.%d.%d]:%d", b1
, b2
, b3
, b4
, port
);
194 else if (sscanf((const char *)str
, "%d.%d.%d.%d", &b1
, &b2
, &b3
, &b4
) == 4)
195 return psprintf("[%d.%d.%d.%d]", b1
, b2
, b3
, b4
);
200 H323TransportAddress
OpalOSP::OSPStringToAddress(const PString
& str
, WORD defaultPort
)
202 int b1
, b2
, b3
, b4
, port
;
203 if (sscanf((const char *)str
, "[%d.%d.%d.%d]:%d", &b1
, &b2
, &b3
, &b4
, &port
) == 5)
204 return H323TransportAddress(PIPSocket::Address((BYTE
)b1
, (BYTE
)b2
, (BYTE
)b3
, (BYTE
)b4
), (WORD
)port
);
205 else if (sscanf((const char *)str
, "[%d.%d.%d.%d]", &b1
, &b2
, &b3
, &b4
) == 4)
206 return H323TransportAddress(PIPSocket::Address((BYTE
)b1
, (BYTE
)b2
, (BYTE
)b3
, (BYTE
)b4
), defaultPort
);
208 return H323TransportAddress(str
);;
211 BOOL
OpalOSP::ConvertAliasToOSPString(const H225_AliasAddress
& alias
, int & format
, PString
& str
)
213 str
= H323GetAliasAddressString(alias
);
214 switch (alias
.GetTag()) {
215 case H225_AliasAddress::e_dialedDigits
:
216 format
= ::OSPC_E164
;
220 case H225_AliasAddress::e_url_ID
:
225 case H225_AliasAddress::e_email_ID
:
226 case H225_AliasAddress::e_h323_ID
:
227 case H225_AliasAddress::e_transportID
:
228 case H225_AliasAddress::e_partyNumber
:
229 case H225_AliasAddress::e_mobileUIM
:
235 ////////////////////////////////////////////////////////////////////////////////////////////////////////
237 // provider functions
240 OpalOSP::Provider::Provider()
244 handle
= IllegalHandle
;
246 sslLifeTime
= DEFAULT_SSL_LIFETIME
;
247 maxSimultConn
= DEFAULT_MAX_SIMULT_CONN
;
248 httpPersist
= DEFAULT_HTTP_PERSIST
;
249 httpRetryDelay
= DEFAULT_HTTP_RETRY_DELAY
;
250 httpRetry
= DEFAULT_HTTP_RETRY
;
251 httpTimeout
= DEFAULT_HTTP_TIMEOUT
;
252 deleteTimeout
= DEFAULT_DELETE_TIMEOUT
;
256 OpalOSP::Provider::~Provider()
261 int OpalOSP::Provider::Open(const PString
& servicePoint
, const PDirectory
& certDir
)
263 PURL
url(servicePoint
, "http");
264 PString hostName
= url
.GetHostName();
265 if (!PIPSocket::GetHostAddress(hostName
, hostAddress
)) {
266 PTRACE(2, "OSP\tCannot resolve address of OSP server " << hostName
);
270 PFilePath privateKeyFilename
= certDir
+ (hostName
+ "_priv.pem");
271 PFilePath publicKeyFilename
= certDir
+ (hostName
+ "_cert.pem");
272 PFilePath serverCAFilename
= certDir
+ (hostName
+ "_cacert.pem");
274 return Open(servicePoint
, privateKeyFilename
, publicKeyFilename
, serverCAFilename
);
277 int OpalOSP::Provider::Open(const PString
& servicePoint
,
278 const PFilePath
& localPrivateKeyName
,
279 const PFilePath
& localPublicCertName
,
280 const PFilePath
& localAuthCertName
)
282 PSSLPrivateKey privateKey
;
283 if (!privateKey
.Load(localPrivateKeyName
)) {
284 PTRACE(2, "OSP\tCannot load public cert " << localPrivateKeyName
);
288 PSSLCertificate publicCert
;
289 if (!publicCert
.Load(localPublicCertName
)) {
290 PTRACE(2, "OSP\tCannot load public cert " << localPublicCertName
);
294 PSSLCertificate authCert
;
295 if (!authCert
.Load(localAuthCertName
)) {
296 PTRACE(2, "OSP\tCannot load auth cert " << localAuthCertName
);
300 return Open(servicePoint
, privateKey
, publicCert
, authCert
);
303 int OpalOSP::Provider::Open(const PString
& servicePoint
,
304 PSSLPrivateKey
& localPrivateKey
,
305 PSSLCertificate
& localPublicCert
,
306 PSSLCertificate
& localAuthCert
)
308 const char * ospvServicePoint
= (const char *)servicePoint
;
310 OSPTPRIVATEKEY localKey
;
311 PBYTEArray localKeyData
= localPrivateKey
.GetData();
312 localKey
.PrivateKeyData
= localKeyData
.GetPointer();
313 localKey
.PrivateKeyLength
= localKeyData
.GetSize();
316 PBYTEArray localCertData
= localPublicCert
.GetData();
317 localCert
.CertData
= localCertData
.GetPointer();
318 localCert
.CertDataLength
= localCertData
.GetSize();
321 PBYTEArray authCertData
= localAuthCert
.GetData();
322 authCert
.CertData
= authCertData
.GetPointer();
323 authCert
.CertDataLength
= authCertData
.GetSize();
324 const OSPTCERT
* authCerts
= &authCert
;
326 unsigned long * ospvMessageCount
= NULL
;
327 if (messageCount
> 0) {
328 ospvMessageCount
= new unsigned long[1];
329 *ospvMessageCount
= messageCount
;
332 // create the provider handle
333 int stat
= ::OSPPProviderNew(
334 1, // number of service points
335 &ospvServicePoint
, // service point data
336 ospvMessageCount
, // max mesages per service point
338 &localKey
, // private key
339 &localCert
, // public cert
340 1, // number of public certs
341 &authCerts
, // public cert
342 0, // use local validation
343 sslLifeTime
, // SSL lifetime of one hour
344 maxSimultConn
, // maximum simultaneous connections
345 httpPersist
, // HTTP persistence of 1 minute
346 httpRetryDelay
, // HTTP retry delay of 10 minutes
347 httpRetry
, // HTTP retry count of 3
348 httpTimeout
, // HTTP timeout of 3.5 secs
349 (const char *)customerID
, // customer ID
350 (const char *)deviceID
, // device ID
353 delete[](ospvMessageCount
);
355 PTRACE_IF(1, stat
!= 0, "OSP\tOSPPProviderNew returned status " << stat
);
358 handle
= IllegalHandle
;
360 PTRACE(2, "OSP\tOSPPProviderNew succeeded ");
365 int OpalOSP::Provider::Close()
370 stat
= ::OSPPProviderDelete(handle
, deleteTimeout
);
371 PTRACE(2, "OSP\tOSPPProviderDelete returned status " << stat
);
372 handle
= IllegalHandle
;
379 ////////////////////////////////////////////////////////////////////////////////////////////////////////
381 // transaction functions
384 OpalOSP::Transaction::Transaction()
387 handle
= IllegalHandle
;
388 // endReason = H323Connection::NumCallEndReasons;
391 OpalOSP::Transaction::~Transaction()
396 BOOL
OpalOSP::Transaction::CheckOpenedAndNotEnded(const char * str
)
399 PTRACE(1, "OSP\tAttempt to " << str
<< " unopened transaction");
403 PTRACE(1, "OSP\tAttempt to " << str
<< " ended transaction");
410 int OpalOSP::Transaction::Open(Provider
& _provider
, const PString
& _user
)
412 // make sure the transaction is not already open
414 PTRACE(1, "OSP\tAttempt to open transaction that is already open");
418 // make sure the provider is open
419 if (!_provider
.IsOpen())
421 provider
= &_provider
;
423 // reset the call information
426 lostSentPackets
= lostReceivedPackets
= 0;
427 lostFractionSent
= lostFractionReceived
= -1;
429 // create the transaction
430 int stat
= ::OSPPTransactionNew(*provider
, &handle
);
433 handle
= IllegalHandle
;
439 void OpalOSP::Transaction::CallStatistics(unsigned _lostSentPackets
,
440 signed _lostFractionSent
,
441 unsigned _lostReceivedPackets
,
442 signed _lostFractionReceived
,
443 const PTime
& _firstRTPTime
)
445 if (CheckOpenedAndNotEnded("set call statistics")) {
446 lostSentPackets
= _lostSentPackets
;
447 lostFractionSent
= _lostFractionSent
;
448 lostReceivedPackets
= _lostReceivedPackets
;
449 lostFractionReceived
= _lostFractionReceived
;
450 firstRTPTime
= _firstRTPTime
;
454 static OSPTTIME
ValidateOSPTime(const PTime
& time
)
457 return (OSPTTIME
)time
.GetTimeInSeconds();
462 void OpalOSP::Transaction::CallEnd(H323Connection
& conn
)
464 if (!CheckOpenedAndNotEnded("end"))
469 // convert end reason to the correct code
470 // note that OSP codes are Q.931 codes, except for the UnknownCauseIE and normal call clearing
471 H323Connection::CallEndReason endReason
= conn
.GetCallEndReason();
472 if (endReason
!= H323Connection::NumCallEndReasons
) {
473 H225_ReleaseCompleteReason h225Reason
;
474 int ospReason
= (int)H323TranslateFromCallEndReason((H323Connection::CallEndReason
)endReason
, h225Reason
);
475 if (ospReason
== Q931::NormalCallClearing
)
476 ospReason
= OSPC_FAIL_NORMAL_CALL_CLEARING
;
477 else if (ospReason
== Q931::UnknownCauseIE
)
478 ospReason
= OSPC_FAIL_GENERAL
;
479 if (ospReason
!= OSPC_FAIL_NORMAL_CALL_CLEARING
) {
480 PTRACE(4, "OSP\tH323 call end reason " << endReason
<< " converted to OSP/Q.931 release code " << ospReason
);
481 result
= ::OSPPTransactionRecordFailure(*this, (OSPEFAILREASON
)ospReason
);
482 PTRACE_IF(1, result
!= 0, "OSP\tSetting result code failed");
489 void OpalOSP::Transaction::ReportUsage(H323Connection
& conn
)
491 if (!CheckOpenedAndNotEnded("end")) {
492 PTRACE(4, "OSP\tReportUsage skipped as transaction not opened or already reported");
496 // calculate duration of the call, in seconds
497 unsigned ospvCallDuration
= 0;
498 if (conn
.GetConnectionStartTime().IsValid())
499 ospvCallDuration
= ((unsigned)(PTime() - conn
.GetConnectionStartTime()).GetMilliSeconds() + 500) / 1000 ;
501 #ifdef H323_NEW_OSP_API
503 // get start time of call, in 1970 epoch
504 OSPTTIME ospvStartTime
= ValidateOSPTime(conn
.GetSetupUpTime());
506 // get end time of call, in 1970 epoch
507 OSPTTIME ospvEndTime
= ValidateOSPTime(conn
.GetConnectionEndTime());
509 // get alerting time of call, in 1970 epoch
510 OSPTTIME ospvAlertTime
= ValidateOSPTime(conn
.GetAlertingTime());
512 // get flag indicating whether local endpoint released the call
513 BOOL localRelease
= conn
.GetReleaseSequence() == H323Connection::ReleaseSequence_Local
;
515 // get flag for whether originator released the call
516 int ospvReleaseSource
= (conn
.HadAnsweredCall() ? !localRelease
: localRelease
) ? 0 : 1;
520 // get connection time of call, in 1970 epoch
521 OSPTTIME ospvConnectionTime
= ValidateOSPTime(conn
.GetConnectionStartTime());
523 // get post dial delay time (time from SETUP to media)
524 #ifdef H323_NEW_OSP_API
525 unsigned ospvPostDialDelay
= conn
.GetReverseMediaOpenTime().IsValid() ? (((unsigned)(conn
.GetReverseMediaOpenTime() - conn
.GetSetupUpTime()).GetMilliSeconds() + 500) / 1000) : 0;
530 int result
= ::OSPPTransactionReportUsage(
531 *this, /* In - Transaction handle */
532 ospvCallDuration
, /* In - Length of call */
533 #ifdef H323_NEW_OSP_API
534 ospvStartTime
, /* In - Call start time */
535 ospvEndTime
, /* In - Call end time */
536 ospvAlertTime
, /* In - Call alert time */
538 ospvConnectionTime
, /* In - Call connect time */
539 #ifdef H323_NEW_OSP_API
540 ospvPostDialDelay
> 0, /* In - Is PDD Info present */
541 ospvPostDialDelay
, /* In - Post Dial Delay */
542 ospvReleaseSource
, /* In - EP that released the call */
543 (unsigned char *)"", /* In - conference Id. Max 100 char long */
545 lostSentPackets
, /* In - Packets not received by peer */
546 lostFractionSent
, /* In - Fraction of packets not received by peer */
547 lostReceivedPackets
, /* In - Packets not received that were expected */
548 lostFractionReceived
, /* In - Fraction of packets expected but not received */
549 0, /* In/Out - Max size of detail log \ Actual size of detail log */
550 NULL
/* Out - Pointer to detail log storage */
553 PTRACE_IF(2, result
!= 0, "OSP\tOSPPTransactionReportUsage returned status " << result
);
554 PTRACE_IF(4, result
== 0, "OSP\tOSPPTransactionReportUsage call with duration " << ospvCallDuration
);
557 int OpalOSP::Transaction::Close()
562 // make sure the transaction is ended
566 // close the transaction
567 stat
= ::OSPPTransactionDelete(handle
);
568 PTRACE_IF(2, stat
!= 0, "OSP\tOSPPTransactionDelete returned status " << stat
);
569 handle
= IllegalHandle
;
575 ////////////////////////////////////////////////////////////////////////////////////
577 // transaction authorisation functions
579 int OpalOSP::Transaction::Authorise(AuthorisationInfo
& info
, unsigned & numberOfDestinations
)
583 info
.ospvSourceDevice
,
592 int OpalOSP::Transaction::Authorise(const PString
& ospvSource
,
593 const PString
& ospvSourceDevice
,
594 const H225_AliasAddress
& callingNumber
,
595 const H225_AliasAddress
& calledNumber
,
596 const PBYTEArray
& callID
,
597 unsigned & numberOfDestinations
)
599 int ospvCallingNumberFormat
;
600 PString ospvCallingNumber
;
601 if (!ConvertAliasToOSPString(callingNumber
, ospvCallingNumberFormat
, ospvCallingNumber
)) {
602 PTRACE(1, "OSP\tUnknown alias address type for calling number " << callingNumber
);
606 PString ospvCalledNumber
;
607 int ospvCalledNumberFormat
;
608 if (!ConvertAliasToOSPString(calledNumber
, ospvCalledNumberFormat
, ospvCalledNumber
)) {
609 PTRACE(1, "OSP\tUnknown alias address type for called number " << callingNumber
);
613 return Authorise(ospvSource
,
616 ospvCallingNumberFormat
,
618 ospvCalledNumberFormat
,
620 numberOfDestinations
);
623 int OpalOSP::Transaction::Authorise(const PString
& ospvSource
,
624 const PString
& _ospvSourceDevice
,
625 const PString
& ospvCallingNumber
,
626 int ospvCallingNumberFormat
,
627 const PString
& ospvCalledNumber
,
628 int ospvCalledNumberFormat
,
629 const PBYTEArray
& callID
,
630 unsigned & numberOfDestinations
)
632 // make sure the provider is open
633 if (!provider
->IsOpen())
636 // make sure the transaction is open
641 PString ospvSourceDevice
= _ospvSourceDevice
;
642 if (ospvSourceDevice
.IsEmpty())
643 ospvSourceDevice
= ospvSource
;
645 ::OSPTCALLID
* ospvCallID
= OSPPCallIdNew(callID
.GetSize(), (const BYTE
*)callID
);
647 unsigned logSize
= 0;
649 PTRACE(4, "OSP\tMaking OSP Authorise request: src=" << ospvSource
<< ",srcDev=" << ospvSourceDevice
<< ",callingDn=" << ospvCallingNumber
<< ",calledDn=" << ospvCalledNumber
);
651 // perform the authorisation
652 int stat
= ::OSPPTransactionRequestAuthorisation(
654 (const char *)ospvSource
, // source
655 (const char *)ospvSourceDevice
, // source device
656 (const char *)ospvCallingNumber
, // calling number
657 (OSPE_NUMBERING_FORMAT
)ospvCallingNumberFormat
, // calling number format
658 (const char *)ospvCalledNumber
, // called number
659 (OSPE_NUMBERING_FORMAT
)ospvCalledNumberFormat
, // called number format
660 user
.IsEmpty() ? "" : (const char *)user
, // user identifier
661 1, // number of call IDs
662 &ospvCallID
, // call ID
663 NULL
, // preferred destinations,
664 &numberOfDestinations
, // number of destinations,
665 &logSize
, // detail log size,
669 ::OSPPCallIdDelete(&ospvCallID
);
671 PTRACE_IF(1, stat
!= 0, "OSP\tOSPPTransactionRequestAuthorisation returned " << stat
);
676 static BOOL
ValidateAddress(const H225_ArrayOf_AliasAddress
& addresses
, H225_AliasAddress
& alias
)
679 for (i
= 0; i
< addresses
.GetSize(); ++i
) {
682 if (OpalOSP::ConvertAliasToOSPString(addresses
[i
], fmt
, str
)) {
683 alias
= addresses
[i
];
691 BOOL
OpalOSP::Transaction::AuthorisationInfo::Extract(const H323SignalPDU
& setupPDU
)
693 if (setupPDU
.m_h323_uu_pdu
.m_h323_message_body
.GetTag() != H225_H323_UU_PDU_h323_message_body::e_setup
)
696 const H225_Setup_UUIE
& setup
= setupPDU
.m_h323_uu_pdu
.m_h323_message_body
;
698 // must have a source call signalling address
699 if (!setup
.HasOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress
))
701 ospvSourceDevice
= ospvSource
= TransportAddressToOSPString(setup
.m_sourceCallSignalAddress
);
703 // must have one or more source addresses
704 // Use the Q.931 calling party number otherwise find a H.323 alias
705 // that is a valid OSP target
707 if (setupPDU
.GetQ931().GetCallingPartyNumber(str
))
708 H323SetAliasAddress(str
, callingNumber
, H225_AliasAddress::e_dialedDigits
);
709 else if (!setup
.HasOptionalField(H225_Setup_UUIE::e_sourceAddress
) ||
710 !ValidateAddress(setup
.m_sourceAddress
, callingNumber
))
713 // must have one or more destination addresses
714 // Use the Q.931 called party number otherwise find a H.323 destination alias
715 // that is a valid OSP target
716 if (setupPDU
.GetQ931().GetCalledPartyNumber(str
))
717 H323SetAliasAddress(str
, calledNumber
, H225_AliasAddress::e_dialedDigits
);
718 else if (!setup
.HasOptionalField(H225_Setup_UUIE::e_destinationAddress
) ||
719 !ValidateAddress(setup
.m_destinationAddress
, calledNumber
))
722 // get the call identifier (make sure it has non-zero length)
723 if (setup
.m_callIdentifier
.m_guid
.GetSize() == 0)
725 callID
= setup
.m_callIdentifier
.m_guid
;
730 BOOL
OpalOSP::Transaction::AuthorisationInfo::Extract(const H225_AdmissionRequest
& arq
)
732 // must have a source call signalling address
733 if (!arq
.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress
))
735 ospvSourceDevice
= ospvSource
= TransportAddressToOSPString(arq
.m_srcCallSignalAddress
);
737 // must have one or more source addresses
738 // pick the first one that is a valid OSP target
739 if (!ValidateAddress(arq
.m_srcInfo
, callingNumber
))
742 // must have one or more destination addresses
743 // pick the first one that is a valid OSP target
744 if (!arq
.HasOptionalField(H225_AdmissionRequest::e_destinationInfo
) ||
745 !ValidateAddress(arq
.m_destinationInfo
, calledNumber
))
748 // get the call identifier (make sure it has non-zero length)
749 if (arq
.m_callIdentifier
.m_guid
.GetSize() == 0)
751 callID
= arq
.m_callIdentifier
.m_guid
;
757 ////////////////////////////////////////////////////////////////////////////////////
759 // transaction validation functions
762 int OpalOSP::Transaction::Validate(const ValidationInfo
& info
, BOOL
& authorised
, unsigned & timeLimit
)
767 info
.ospvSourceDevice
,
779 int OpalOSP::Transaction::Validate(
780 const PString
& ospvSource
,
781 const PString
& ospvDest
,
782 const PString
& ospvSourceDevice
,
783 const PString
& ospvDestDevice
,
784 const H225_AliasAddress
& callingNumber
,
785 const H225_AliasAddress
& calledNumber
,
786 const PBYTEArray
& callID
,
787 const PBYTEArray
& token
,
788 unsigned int tokenAlgo
,
795 ConvertAliasToOSPString(callingNumber
, callingFormat
, calling
);
799 ConvertAliasToOSPString(calledNumber
, calledFormat
, called
);
801 return Validate(ospvSource
, ospvDest
, ospvSourceDevice
, ospvDestDevice
,
802 callingFormat
, calling
,
803 calledFormat
, called
,
804 callID
, token
, tokenAlgo
, authorised
, timeLimit
);
807 int OpalOSP::Transaction::Validate(
808 const PString
& ospvSource
,
809 const PString
& ospvDest
,
810 const PString
& ospvSourceDevice
,
811 const PString
& ospvDestDevice
,
812 int ospvCallingNumberFormat
,
813 const PString
& ospvCallingNumber
,
814 int ospvCalledNumberFormat
,
815 const PString
& ospvCalledNumber
,
816 const PBYTEArray
& callID
,
817 const PBYTEArray
& token
,
818 unsigned int tokenAlgo
,
823 // make sure the provider is open
824 if (!provider
->IsOpen())
827 // make sure the transaction is open
833 unsigned int authorised
= 0;
834 unsigned int logSize
= 0;
836 stat
= ::OSPPTransactionValidateAuthorisation(
838 (const char *)ospvSource
,
839 (const char *)ospvDest
,
840 (const char *)ospvSourceDevice
,
841 (const char *)ospvDestDevice
,
842 (const char *)ospvCallingNumber
,
843 (OSPE_NUMBERING_FORMAT
)ospvCallingNumberFormat
,
844 (const char *)ospvCalledNumber
,
845 (OSPE_NUMBERING_FORMAT
)ospvCalledNumberFormat
,
846 callID
.GetSize(), (const BYTE
*)callID
,
847 token
.GetSize(), (const BYTE
*)token
,
854 isAuthorised
= authorised
!= 0;
858 BOOL
OpalOSP::Transaction::ValidationInfo::ExtractToken(const H225_ArrayOf_ClearToken
& clearTokens
)
860 PINDEX tokenCount
= clearTokens
.GetSize();
862 for (i
= 0; i
< tokenCount
; ++i
) {
863 H235_ClearToken
& clearToken
= clearTokens
[i
];
864 if (clearToken
.m_tokenOID
== ETSIXMLTokenOID
&&
865 clearToken
.HasOptionalField(H235_ClearToken::e_nonStandard
) &&
866 clearToken
.m_nonStandard
.m_nonStandardIdentifier
== ETSIXMLTokenOID
)
868 token
= clearToken
.m_nonStandard
.m_data
;
875 BOOL
OpalOSP::Transaction::ValidationInfo::Extract(const H323SignalPDU
& setupPDU
)
877 if (setupPDU
.m_h323_uu_pdu
.m_h323_message_body
.GetTag() != H225_H323_UU_PDU_h323_message_body::e_setup
)
880 const H225_Setup_UUIE
& setup
= setupPDU
.m_h323_uu_pdu
.m_h323_message_body
;
882 // must have a source call signalling address
883 if (!setup
.HasOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress
))
885 ospvSourceDevice
= ospvSource
= TransportAddressToOSPString(setup
.m_sourceCallSignalAddress
);
887 // must have one or more source addresses
888 // Use the Q.931 calling party number otherwise find a H.323 alias
889 // that is a valid OSP target
891 if (setupPDU
.GetQ931().GetCallingPartyNumber(str
))
892 H323SetAliasAddress(str
, callingNumber
, H225_AliasAddress::e_dialedDigits
);
893 else if (!setup
.HasOptionalField(H225_Setup_UUIE::e_sourceAddress
) ||
894 !ValidateAddress(setup
.m_sourceAddress
, callingNumber
))
897 // use destination call signalling address if present
898 if (setup
.HasOptionalField(H225_Setup_UUIE::e_destCallSignalAddress
))
899 ospvDestDevice
= ospvDest
= TransportAddressToOSPString(setup
.m_destCallSignalAddress
);
901 // must have one or more destination addresses
902 // Use the Q.931 called party number otherwise find a H.323 destination alias
903 // that is a valid OSP target
904 if (setupPDU
.GetQ931().GetCalledPartyNumber(str
))
905 H323SetAliasAddress(str
, calledNumber
, H225_AliasAddress::e_dialedDigits
);
906 else if (!setup
.HasOptionalField(H225_Setup_UUIE::e_destinationAddress
) ||
907 !ValidateAddress(setup
.m_destinationAddress
, calledNumber
))
910 // get the call identifier (make sure it has non-zero length)
911 if (setup
.m_callIdentifier
.m_guid
.GetSize() == 0)
913 callID
= setup
.m_callIdentifier
.m_guid
;
916 return setup
.HasOptionalField(H225_Setup_UUIE::e_tokens
) && ExtractToken(setup
.m_tokens
);
919 BOOL
OpalOSP::Transaction::ValidationInfo::Extract(const H225_AdmissionRequest
& arq
)
921 // must have a source call signalling address
922 if (!arq
.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress
))
924 PIPSocket::Address addr
;
926 H323TransportAddress
taddr(arq
.m_srcCallSignalAddress
);
927 if (!taddr
.GetIpAndPort(addr
, port
))
929 ospvSourceDevice
= ospvSource
= IpAddressPortToOSPString(addr
, port
);
931 // must have one or more source addresses
932 // pick the first one that is a valid OSP target
933 if (!ValidateAddress(arq
.m_srcInfo
, callingNumber
))
936 // must have one or more destination addresses
937 // pick the first one that is a valid OSP target
938 if (!arq
.HasOptionalField(H225_AdmissionRequest::e_destinationInfo
) ||
939 !ValidateAddress(arq
.m_destinationInfo
, calledNumber
))
942 // get the call identifier (make sure it has non-zero length)
943 if (arq
.m_callIdentifier
.m_guid
.GetSize() == 0)
945 callID
= arq
.m_callIdentifier
.m_guid
;
951 ////////////////////////////////////////////////////////////////////////////////////
953 // transaction destination functions
956 int OpalOSP::Transaction::GetFirstDestination(DestinationInfo
& info
)
959 PString calledNumber
;
960 PString callingNumber
;
962 int result
= GetFirstDestination(
975 info
.destinationAddress
= OSPStringToAddress(destAddress
, H323EndPoint::DefaultTcpPort
);
976 H323SetAliasAddress(calledNumber
, info
.calledNumber
, H225_AliasAddress::e_dialedDigits
);
978 info
.hasCallingNumber
= !callingNumber
.IsEmpty();
979 if (info
.hasCallingNumber
)
980 H323SetAliasAddress(callingNumber
, info
.callingNumber
, H225_AliasAddress::e_dialedDigits
);
985 int OpalOSP::Transaction::GetFirstDestination(unsigned & timeLimit
,
987 PString
& calledNumber
,
988 PString
& callingNumber
,
989 PString
& destAddress
,
990 PString
& destDevice
,
993 if (!CheckOpenedAndNotEnded("get first destination"))
996 callID
.SetSize(CALLID_SIZE
);
997 unsigned callIDSize
= callID
.GetSize();
999 calledNumber
.SetSize(CALLED_NUMBER_SIZE
+1);
1000 callingNumber
.SetSize(CALLING_NUMBER_SIZE
+1);
1001 destAddress
.SetSize(DESTINATION_SIZE
+1);
1002 destDevice
.SetSize(DEVICE_SIZE
+1);
1004 token
.SetSize(TOKEN_SIZE
);
1005 unsigned tokenSize
= token
.GetSize();
1007 int stat
= ::OSPPTransactionGetFirstDestination(
1008 *this, /* In - Transaction handle */
1009 0, /* In - Max size for timestamp string */
1010 NULL
, /* Out - Valid After time in string format */
1011 NULL
, /* Out - Valid Until time in string format */
1012 &timeLimit
, /* Out - Number of seconds call is authorised for */
1013 &callIDSize
, /* In/Out - Max size for CallId string Actual size of CallId string */
1014 callID
.GetPointer(), /* Out - Call Id string */
1015 calledNumber
.GetSize(), /* In - Max size of called number */
1016 calledNumber
.GetPointer(), /* Out - Called number string */
1017 #ifdef H323_NEW_OSP_API
1018 callingNumber
.GetSize(), /* In - Max size of calling number */
1019 callingNumber
.GetPointer(), /* Out - Calling number string */
1021 destAddress
.GetSize(), /* In - Max size of destination string */
1022 destAddress
.GetPointer(), /* Out - Destination string */
1023 destDevice
.GetSize(), /* In - Max size of dest device string */
1024 destDevice
.GetPointer(), /* Out - Dest device string */
1025 &tokenSize
, /* In/Out - Max size of token string Actual size of token string */
1026 token
.GetPointer() /* Out - Token string */
1029 callID
.SetSize(callIDSize
);
1030 calledNumber
.MakeMinimumSize();
1031 callingNumber
.MakeMinimumSize();
1032 destAddress
.MakeMinimumSize();
1033 destDevice
.MakeMinimumSize();
1034 token
.SetSize(tokenSize
);
1039 int OpalOSP::Transaction::GetNextDestination(int reason
, DestinationInfo
& info
)
1041 PString destAddress
;
1042 PString calledNumber
;
1043 PString callingNumber
;
1045 int result
= GetNextDestination(
1059 info
.destinationAddress
= OSPStringToAddress(destAddress
, H323EndPoint::DefaultTcpPort
);
1060 H323SetAliasAddress(calledNumber
, info
.calledNumber
, H225_AliasAddress::e_dialedDigits
);
1062 info
.hasCallingNumber
= !callingNumber
.IsEmpty();
1063 if (info
.hasCallingNumber
)
1064 H323SetAliasAddress(callingNumber
, info
.callingNumber
, H225_AliasAddress::e_dialedDigits
);
1069 int OpalOSP::Transaction::GetNextDestination(int reason
,
1070 unsigned & timeLimit
,
1071 PBYTEArray
& callID
,
1072 PString
& calledNumber
,
1073 PString
& callingNumber
,
1074 PString
& destAddress
,
1075 PString
& destDevice
,
1078 if (!CheckOpenedAndNotEnded("get first destination"))
1081 callID
.SetSize(CALLID_SIZE
);
1082 unsigned callIDSize
= callID
.GetSize();
1084 calledNumber
.SetSize(CALLED_NUMBER_SIZE
+1);
1085 callingNumber
.SetSize(CALLING_NUMBER_SIZE
+1);
1086 destAddress
.SetSize(DESTINATION_SIZE
+1);
1087 destDevice
.SetSize(DEVICE_SIZE
+1);
1089 token
.SetSize(TOKEN_SIZE
);
1090 unsigned tokenSize
= token
.GetSize();
1092 int stat
= ::OSPPTransactionGetNextDestination(
1093 *this, /* In - Transaction handle */
1094 (OSPEFAILREASON
)reason
, /* In - Failure code */
1095 0, /* In - Max size of timestamp string */
1096 NULL
, /* Out - Valid after time string */
1097 NULL
, /* Out - Valid until time string */
1098 &timeLimit
, /* Out - Number of seconds call is authorised for */
1099 &callIDSize
, /* In - Max size of call id string */
1100 callID
.GetPointer(), /* Out - Call Id string */
1101 calledNumber
.GetSize(), /* In - Max size of called number */
1102 calledNumber
.GetPointer(), /* Out - Called number string */
1103 #ifdef H323_NEW_OSP_API
1104 callingNumber
.GetSize(), /* In - Max size of calling number */
1105 callingNumber
.GetPointer(), /* Out - Calling number string */
1107 destAddress
.GetSize(), /* In - Max size of destination string */
1108 destAddress
.GetPointer(), /* Out - Destination string */
1109 destDevice
.GetSize(), /* In - Max size of dest device string */
1110 destDevice
.GetPointer(), /* Out - Dest device string */
1111 &tokenSize
, /* In/Out - Max size of token string Actual size of token string */
1112 token
.GetPointer() /* Out - Token string */
1115 callID
.SetSize(callIDSize
);
1116 calledNumber
.MakeMinimumSize();
1117 callingNumber
.MakeMinimumSize();
1118 destAddress
.MakeMinimumSize();
1119 destDevice
.MakeMinimumSize();
1120 token
.SetSize(tokenSize
);
1125 void OpalOSP::Transaction::DestinationInfo::InsertToken(H225_ArrayOf_ClearToken
& clearTokens
, BOOL useCiscoBug
)
1127 PINDEX tokenCount
= clearTokens
.GetSize();
1128 clearTokens
.SetSize(tokenCount
+1);
1129 H235_ClearToken
& clearToken
= clearTokens
[tokenCount
];
1130 clearToken
.m_tokenOID
= ETSIXMLTokenOID
;
1131 clearToken
.IncludeOptionalField(H235_ClearToken::e_nonStandard
);
1132 clearToken
.m_nonStandard
.m_nonStandardIdentifier
= ETSIXMLTokenOID
;
1135 clearToken
.m_nonStandard
.m_data
= token
;
1137 PASN_OctetString
& destToken
= clearToken
.m_nonStandard
.m_data
;
1138 PINDEX tokenSize
= token
.GetSize();
1139 destToken
.SetSize(token
.GetSize()+3);
1141 destToken
[1] = (BYTE
)(0x80+(tokenSize
>>8));
1142 destToken
[2] = (BYTE
)tokenSize
;
1143 memcpy(&destToken
[3], &token
[0], tokenSize
);
1147 BOOL
OpalOSP::Transaction::DestinationInfo::Insert(H323SignalPDU
& setupPDU
, BOOL useCiscoBug
)
1149 if (setupPDU
.m_h323_uu_pdu
.m_h323_message_body
.GetTag() != H225_H323_UU_PDU_h323_message_body::e_setup
)
1152 H225_Setup_UUIE
& setup
= setupPDU
.m_h323_uu_pdu
.m_h323_message_body
;
1154 return Insert(setup
, useCiscoBug
);
1157 BOOL
OpalOSP::Transaction::DestinationInfo::Insert(H225_Setup_UUIE
& setup
, BOOL useCiscoBug
)
1159 // insert the OSP token into the PDU
1160 setup
.IncludeOptionalField(H225_Setup_UUIE::e_tokens
);
1161 InsertToken(setup
.m_tokens
, useCiscoBug
);
1163 // set the destination address array to the called number
1164 setup
.IncludeOptionalField(H225_Setup_UUIE::e_destinationAddress
);
1165 setup
.m_destinationAddress
.SetSize(1);
1166 setup
.m_destinationAddress
[0] = calledNumber
;
1171 BOOL
OpalOSP::Transaction::DestinationInfo::Insert(H225_AdmissionConfirm
& acf
, BOOL useCiscoBug
)
1173 // insert the OSP token into the PDU
1174 acf
.IncludeOptionalField(H225_AdmissionConfirm::e_tokens
);
1175 InsertToken(acf
.m_tokens
, useCiscoBug
);
1177 // set the destinationInfo field to the called number
1178 destinationAddress
.SetPDU(acf
.m_destCallSignalAddress
);
1180 // set the destCallSignalAddress field to the destination address
1181 acf
.IncludeOptionalField(H225_AdmissionConfirm::e_destinationInfo
);
1182 acf
.m_destinationInfo
.SetSize(1);
1183 acf
.m_destinationInfo
[0] = calledNumber
;
1188 ////////////////////////////////////////////////////////////////////////////////////////////////////////
1190 #endif // H323_TRANSNEXUS_OSP