4 * Q.931 protocol handler
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
27 * Contributor(s): ______________________________________.
30 * Revision 1.66 2006/08/12 03:59:46 csoutheren
31 * Added additional Q.931 message types
34 * Revision 1.65 2004/12/09 23:37:14 csoutheren
35 * Added new Q.931 termination codes
37 * Revision 1.64 2004/11/19 00:14:18 csoutheren
38 * Prevent GetBearerCapabilities from reading invalid memory (array index out of bounds)
39 * Thanks to Michal Zygmuntowicz
41 * Revision 1.63 2004/11/07 12:45:09 rjongbloed
42 * Minor change to parsing of bearer capabilities, thanks Michal Zygmuntowicz
44 * Revision 1.62 2004/07/11 11:37:28 rjongbloed
45 * Added ConnectAck support and fixed bugs in ChannelIdentificationIE, thanks Eize Slange
47 * Revision 1.61 2004/06/06 08:44:26 rjongbloed
48 * Fixed incorrect test for Q.931 calls state information element, thanks Stelios Vaiopoulos
50 * Revision 1.60 2004/05/07 06:44:17 csoutheren
51 * Fixed problem with empty Q>931 DisplayName
53 * Revision 1.59 2003/08/24 23:10:30 rjongbloed
54 * Fixed incorrect mask in bearer caps decoding, thanks Greg Adams
56 * Revision 1.58 2003/03/18 05:54:18 robertj
57 * Added ChannelIdentifier IE support, thanks Eize Slange
59 * Revision 1.57 2003/02/12 02:23:01 robertj
60 * Fixed printing of cause codes that are impossible as opposed to merely
61 * unlikely or unallocated.
63 * Revision 1.56 2003/02/12 00:02:23 robertj
64 * Added more Q.931 cause codes.
65 * Added ability to trace text version of cause codes and IE codes.
67 * Revision 1.55 2002/11/19 06:19:25 robertj
68 * Added extra "congested" Q.931 codes.
70 * Revision 1.54 2002/08/06 02:27:39 robertj
71 * GNU C++ v3 compatibility.
73 * Revision 1.53 2002/08/05 10:03:48 robertj
74 * Cosmetic changes to normalise the usage of pragma interface/implementation.
76 * Revision 1.52 2002/07/25 10:55:44 robertj
77 * Changes to allow more granularity in PDU dumps, hex output increasing
78 * with increasing trace level.
80 * Revision 1.51 2002/07/05 03:13:38 robertj
81 * Added copy constructor for Q.931 so makes duplicate instead of reference to IE's.
83 * Revision 1.50 2002/07/03 10:26:05 robertj
84 * Fixed bearer capabilities for H,450.1 needing non ITU standard, thanks Florian Winterstein
86 * Revision 1.49 2002/05/22 23:12:03 robertj
87 * Enhanced the display of Release-Complete cause codes.
89 * Revision 1.48 2002/05/07 23:49:35 craigs
90 * Changed comment on length of userUserIE field thanks to Paul Long
92 * Revision 1.47 2002/05/03 05:38:19 robertj
93 * Added Q.931 Keypad IE mechanism for user indications (DTMF).
95 * Revision 1.46 2002/04/22 07:32:16 craigs
96 * Changed GetProgressIndicator to be const
98 * Revision 1.45 2002/04/19 04:49:14 robertj
99 * Fixed currect bit shift for CallState IE standard bits.
101 * Revision 1.44 2002/04/19 02:16:47 robertj
102 * Added CallState IE processing.
104 * Revision 1.43 2002/04/18 06:16:32 craigs
105 * Extra robustness in handling of strange UserUserIE lengths
107 * Revision 1.42 2002/01/07 04:25:21 robertj
108 * Added support for Connected-Number Information Element, thanks Hans Verbeek
110 * Revision 1.41 2002/01/06 05:28:41 robertj
111 * Fixed crash if given bad data in number field, thanks Chih-Wei Huang.
113 * Revision 1.40 2001/09/17 02:06:40 robertj
114 * Added Redirecting Number IE to Q.931, thanks Frank Derks
116 * Revision 1.39 2001/09/13 02:41:21 robertj
117 * Fixed call reference generation to use full range and common code, thanks Carlo Kielstra
119 * Revision 1.38 2001/08/27 03:45:59 robertj
120 * Added automatic setting of bearer capability transfer mode from H.323
121 * capabilities on connection at time of SETUP PDU.
123 * Revision 1.37 2001/08/20 06:48:28 robertj
124 * Added Q.931 function for setting bearer capabilities, allowing
125 * applications to set the data rate as they require.
127 * Revision 1.36 2001/08/07 02:57:09 robertj
128 * Fixed incorrect Q.931 bearer capability, thanks Carlo Kielstra.
130 * Revision 1.35 2001/07/24 23:40:15 craigs
131 * Added ability to remove Q931 IE
133 * Revision 1.34 2001/06/14 06:25:16 robertj
134 * Added further H.225 PDU build functions.
135 * Moved some functionality from connection to PDU class.
137 * Revision 1.33 2001/05/30 04:38:40 robertj
138 * Added BuildStatusEnquiry() Q.931 function, thanks Markus Storm
140 * Revision 1.32 2001/04/05 00:06:31 robertj
141 * Fixed some more encoding/decoding problems with little used bits of
142 * the Q.931 protocol, thanks Hans Verbeek.
144 * Revision 1.31 2001/04/03 23:06:15 robertj
145 * Fixed correct encoding and decoding of Q.850 cause field, thanks Hans Verbeek.
147 * Revision 1.30 2001/02/09 05:13:56 craigs
148 * Added pragma implementation to (hopefully) reduce the executable image size
151 * Revision 1.29 2001/01/19 06:57:26 robertj
152 * Added Information message type.
154 * Revision 1.28 2000/10/13 02:16:04 robertj
155 * Added support for Progress Indicator Q.931/H.225 message.
157 * Revision 1.27 2000/07/11 11:17:01 robertj
158 * Improved trace log display of Q.931 PDU's (correct order and extra IE fields).
160 * Revision 1.26 2000/07/09 14:54:11 robertj
161 * Added facility IE to facility message.
162 * Changed reference to the word "field" to be more correct IE or "Information Element"
164 * Revision 1.25 2000/06/21 08:07:47 robertj
165 * Added cause/reason to release complete PDU, where relevent.
167 * Revision 1.24 2000/05/09 12:19:31 robertj
168 * Added ability to get and set "distinctive ring" Q.931 functionality.
170 * Revision 1.23 2000/05/08 14:07:35 robertj
171 * Improved the provision and detection of calling and caller numbers, aliases and hostnames.
173 * Revision 1.22 2000/05/06 02:18:26 robertj
174 * Changed the new CallingPartyNumber code so defaults for octet3a are application dependent.
176 * Revision 1.21 2000/05/05 00:44:05 robertj
177 * Added presentation and screening fields to Calling Party Number field, thanks Dean Anderson.
179 * Revision 1.20 2000/05/02 04:32:27 robertj
180 * Fixed copyright notice comment.
182 * Revision 1.19 2000/03/21 01:08:11 robertj
183 * Fixed incorrect call reference code being used in originated call.
185 * Revision 1.18 2000/02/17 12:07:43 robertj
186 * Used ne wPWLib random number generator after finding major problem in MSVC rand().
188 * Revision 1.17 1999/12/23 22:44:06 robertj
189 * Added calling party number field.
191 * Revision 1.16 1999/09/22 04:18:29 robertj
192 * Fixed missing "known" message types in debugging output.
194 * Revision 1.15 1999/09/10 03:36:48 robertj
195 * Added simple Q.931 Status response to Q.931 Status Enquiry
197 * Revision 1.14 1999/08/31 13:54:35 robertj
198 * Fixed problem with memory overrun building PDU's
200 * Revision 1.13 1999/08/31 12:34:19 robertj
201 * Added gatekeeper support.
203 * Revision 1.12 1999/08/13 06:34:38 robertj
204 * Fixed problem in CallPartyNumber Q.931 encoding.
205 * Added field name display to Q.931 protocol.
207 * Revision 1.11 1999/08/10 13:14:15 robertj
208 * Added Q.931 Called Number field if have "phone number" style destination addres.
210 * Revision 1.10 1999/07/16 02:15:30 robertj
211 * Fixed more tunneling problems.
213 * Revision 1.9 1999/07/09 14:59:59 robertj
214 * Fixed GNU C++ compatibility.
216 * Revision 1.8 1999/07/09 06:09:50 robertj
217 * Major implementation. An ENORMOUS amount of stuff added everywhere.
219 * Revision 1.7 1999/06/14 15:19:48 robertj
220 * GNU C compatibility
222 * Revision 1.6 1999/06/13 12:41:14 robertj
223 * Implement logical channel transmitter.
224 * Fixed H245 connect on receiving call.
226 * Revision 1.5 1999/06/09 05:26:20 robertj
227 * Major restructuring of classes.
229 * Revision 1.4 1999/02/23 11:04:29 robertj
230 * Added capability to make outgoing call.
232 * Revision 1.3 1999/01/16 01:31:38 robertj
233 * Major implementation.
235 * Revision 1.2 1999/01/02 04:00:52 robertj
236 * Added higher level protocol negotiations.
238 * Revision 1.1 1998/12/14 09:13:37 robertj
246 #pragma implementation "q931.h"
251 #include <ptclib/random.h>
257 ostream
& operator<<(ostream
& strm
, Q931::InformationElementCodes ie
)
259 static POrdinalToString::Initialiser IENamesInit
[] = {
260 { Q931::BearerCapabilityIE
, "Bearer-Capability" },
261 { Q931::CauseIE
, "Cause" },
262 { Q931::FacilityIE
, "Facility" },
263 { Q931::ProgressIndicatorIE
, "Progress-Indicator" },
264 { Q931::CallStateIE
, "Call-State" },
265 { Q931::DisplayIE
, "Display" },
266 { Q931::SignalIE
, "Signal" },
267 { Q931::KeypadIE
, "Keypad" },
268 { Q931::ConnectedNumberIE
, "Connected-Number" },
269 { Q931::CallingPartyNumberIE
, "Calling-Party-Number" },
270 { Q931::CalledPartyNumberIE
, "Called-Party-Number" },
271 { Q931::RedirectingNumberIE
, "Redirecting-Number" },
272 { Q931::ChannelIdentificationIE
,"Channel-Identification"},
273 { Q931::UserUserIE
, "User-User" }
275 static const POrdinalToString
IENames(PARRAYSIZE(IENamesInit
), IENamesInit
);
277 if (IENames
.Contains((PINDEX
)ie
))
280 strm
<< "0x" << hex
<< (unsigned)ie
<< dec
<< " (" << (unsigned)ie
<< ')';
286 ostream
& operator<<(ostream
& strm
, Q931::CauseValues cause
)
288 static POrdinalToString::Initialiser CauseNamesInit
[] = {
289 { Q931::UnallocatedNumber
, "Unallocated number" },
290 { Q931::NoRouteToNetwork
, "No route to network" },
291 { Q931::NoRouteToDestination
, "No route to destination" },
292 { Q931::SendSpecialTone
, "Send special tone" },
293 { Q931::MisdialledTrunkPrefix
, "Misdialled trunk prefix" },
294 { Q931::ChannelUnacceptable
, "Channel unacceptable" },
295 { Q931::NormalCallClearing
, "Normal call clearing" },
296 { Q931::UserBusy
, "User busy" },
297 { Q931::NoResponse
, "No response" },
298 { Q931::NoAnswer
, "No answer" },
299 { Q931::SubscriberAbsent
, "Subscriber absent" },
300 { Q931::CallRejected
, "Call rejected" },
301 { Q931::NumberChanged
, "Number changed" },
302 { Q931::Redirection
, "Redirection" },
303 { Q931::ExchangeRoutingError
, "Exchange routing error" },
304 { Q931::NonSelectedUserClearing
, "Non selected user clearing" },
305 { Q931::DestinationOutOfOrder
, "Destination out of order" },
306 { Q931::InvalidNumberFormat
, "Invalid number format" },
307 { Q931::FacilityRejected
, "Facility rejected" },
308 { Q931::StatusEnquiryResponse
, "Status enquiry response" },
309 { Q931::NormalUnspecified
, "Normal unspecified" },
310 { Q931::NoCircuitChannelAvailable
, "No circuit/channel available" },
311 { Q931::NetworkOutOfOrder
, "Network out of order" },
312 { Q931::TemporaryFailure
, "Temporary failure" },
313 { Q931::Congestion
, "Congestion" },
314 { Q931::RequestedCircuitNotAvailable
,"RequestedCircuitNotAvailable" },
315 { Q931::ResourceUnavailable
, "Resource unavailable" },
316 { Q931::ServiceOptionNotAvailable
, "Service or option not available" },
317 { Q931::InvalidCallReference
, "Invalid call reference" },
318 { Q931::IncompatibleDestination
, "Incompatible destination" },
319 { Q931::IENonExistantOrNotImplemented
,"IE non-existent or not implemented" },
320 { Q931::TimerExpiry
, "Recovery from timer expiry" },
321 { Q931::ProtocolErrorUnspecified
, "Protocol error, unspecified" },
322 { Q931::InterworkingUnspecified
, "Interworking, unspecified" },
323 { Q931::CallAwarded
, "Call awarded, delivered via established channel" },
324 { Q931::Preemption
, "Call is being preempted" },
325 { Q931::PreemptionCircuitReserved
, "Preemption - circuit reserved for reuse" },
326 { Q931::CallQueued
, "Call queued" },
327 { Q931::FrameModeOOS
, "Frame mode out of service" },
328 { Q931::FrameModeOperational
, "Frame mode operational" },
329 { Q931::AccessInformationDiscarded
, "Access information discarded" },
330 { Q931::PrecedenceCallBlocked
, "Precedence Call Blocked" },
331 { Q931::QoSNotAvailable
, "QoS not available" },
332 { Q931::RequestedFacilityNotSubscribed
, "Requested facility not subscribed" },
333 { Q931::OutgoingCallsBarred
, "Outgoing calls barred" },
334 { Q931::OutgoingCallsBarredInCUG
, "Outgoing calls barred in CUG" },
335 { Q931::IncomingCallsBarred
, "Incoming calls barred" },
336 { Q931::IncomingCallsBarredInCUG
, "Incoming calls barred in CUG" },
337 { Q931::BearerCapNotAuthorised
, "Bearer cap not authorised" },
338 { Q931::BearerCapNotPresentlyAvailable
, "Bearer cap not presently available" },
339 { Q931::InconsistentOutgoingIE
, "Inconsistent outgoing information element" },
340 { Q931::BearerCapNotImplemented
, "Bearer cap not implemented" },
341 { Q931::ChannelTypeNotImplemented
, "Channel type not implemented" },
342 { Q931::RequestedFacilityNotImplemented
, "Requested facility not implemented" },
343 { Q931::OnlyRestrictedDigitalBearerCapAvailable
, "Only restricted digital bearer cap available" },
344 { Q931::ServiceOrOptionNotImplemented
, "Service or option not implemented" },
345 { Q931::IdentifiedChannelNonExistent
, "IdentifiedChannelNonExistent" },
346 { Q931::CallIdentifyNotSuspendedCall
, "CallIdentifyNotSuspendedCall" },
347 { Q931::CallIdentifyInUse
, "CallIdentifyInUse" },
348 { Q931::NoCallSuspended
, "NoCallSuspended" },
349 { Q931::ClearedRequestedCallIdentity
, "ClearedRequestedCallIdentity" },
350 { Q931::UserNotInCUG
, "UserNotInCUG" },
352 static const POrdinalToString
CauseNames(PARRAYSIZE(CauseNamesInit
), CauseNamesInit
);
354 if (CauseNames
.Contains((PINDEX
)cause
))
355 strm
<< CauseNames
[cause
];
356 else if (cause
< Q931::ErrorInCauseIE
)
357 strm
<< "0x" << hex
<< (unsigned)cause
<< dec
<< " (" << (unsigned)cause
<< ')';
365 ///////////////////////////////////////////////////////////////////////////////
369 protocolDiscriminator
= 8; // Q931 always has 00001000
370 messageType
= NationalEscapeMsg
;
371 fromDestination
= FALSE
;
376 Q931::Q931(const Q931
& other
)
382 Q931
& Q931::operator=(const Q931
& other
)
384 callReference
= other
.callReference
;
385 fromDestination
= other
.fromDestination
;
386 protocolDiscriminator
= other
.protocolDiscriminator
;
387 messageType
= other
.messageType
;
389 informationElements
.RemoveAll();
390 for (PINDEX i
= 0; i
< other
.informationElements
.GetSize(); i
++)
391 informationElements
.SetAt(other
.informationElements
.GetKeyAt(i
), new PBYTEArray(other
.informationElements
.GetDataAt(i
)));
397 void Q931::BuildFacility(int callRef
, BOOL fromDest
)
399 messageType
= FacilityMsg
;
400 callReference
= callRef
;
401 fromDestination
= fromDest
;
402 informationElements
.RemoveAll();
404 SetIE(FacilityIE
, data
);
408 void Q931::BuildInformation(int callRef
, BOOL fromDest
)
410 messageType
= InformationMsg
;
411 callReference
= callRef
;
412 fromDestination
= fromDest
;
413 informationElements
.RemoveAll();
417 void Q931::BuildProgress(int callRef
,
419 unsigned description
,
420 unsigned codingStandard
,
423 messageType
= ProgressMsg
;
424 callReference
= callRef
;
425 fromDestination
= fromDest
;
426 informationElements
.RemoveAll();
427 SetProgressIndicator(description
, codingStandard
, location
);
431 void Q931::BuildNotify(int callRef
, BOOL fromDest
)
433 messageType
= NotifyMsg
;
434 callReference
= callRef
;
435 fromDestination
= fromDest
;
436 informationElements
.RemoveAll();
440 void Q931::BuildSetupAcknowledge(int callRef
)
442 messageType
= SetupAckMsg
;
443 callReference
= callRef
;
444 fromDestination
= TRUE
;
445 informationElements
.RemoveAll();
449 void Q931::BuildCallProceeding(int callRef
)
451 messageType
= CallProceedingMsg
;
452 callReference
= callRef
;
453 fromDestination
= TRUE
;
454 informationElements
.RemoveAll();
458 void Q931::BuildAlerting(int callRef
)
460 messageType
= AlertingMsg
;
461 callReference
= callRef
;
462 fromDestination
= TRUE
;
463 informationElements
.RemoveAll();
467 void Q931::BuildSetup(int callRef
)
469 messageType
= SetupMsg
;
471 callReference
= GenerateCallReference();
473 callReference
= callRef
;
474 fromDestination
= FALSE
;
475 informationElements
.RemoveAll();
476 SetBearerCapabilities(TransferSpeech
, 1);
480 void Q931::BuildConnect(int callRef
)
482 messageType
= ConnectMsg
;
483 callReference
= callRef
;
484 fromDestination
= TRUE
;
485 informationElements
.RemoveAll();
486 SetBearerCapabilities(TransferSpeech
, 1);
489 void Q931::BuildConnectAck(int callRef
, BOOL fromDest
)
491 messageType
= ConnectAckMsg
;
492 callReference
= callRef
;
493 fromDestination
= fromDest
;
494 informationElements
.RemoveAll();
498 void Q931::BuildStatus(int callRef
, BOOL fromDest
)
500 messageType
= StatusMsg
;
501 callReference
= callRef
;
502 fromDestination
= fromDest
;
503 informationElements
.RemoveAll();
504 SetCallState(CallState_Active
);
505 // Cause field as per Q.850
506 SetCause(StatusEnquiryResponse
);
510 void Q931::BuildStatusEnquiry(int callRef
, BOOL fromDest
)
512 messageType
= StatusEnquiryMsg
;
513 callReference
= callRef
;
514 fromDestination
= fromDest
;
515 informationElements
.RemoveAll();
519 void Q931::BuildReleaseComplete(int callRef
, BOOL fromDest
)
521 messageType
= ReleaseCompleteMsg
;
522 callReference
= callRef
;
523 fromDestination
= fromDest
;
524 informationElements
.RemoveAll();
528 BOOL
Q931::Decode(const PBYTEArray
& data
)
530 // Clear all existing data before reading new
531 informationElements
.RemoveAll();
533 if (data
.GetSize() < 5) // Packet too short
536 protocolDiscriminator
= data
[0];
538 if (data
[1] != 2) // Call reference must be 2 bytes long
541 callReference
= ((data
[2]&0x7f) << 8) | data
[3];
542 fromDestination
= (data
[2]&0x80) != 0;
544 messageType
= (MsgTypes
)data
[4];
546 // Have preamble, start getting the informationElements into buffers
548 while (offset
< data
.GetSize()) {
549 // Get field discriminator
550 int discriminator
= data
[offset
++];
552 PBYTEArray
* item
= new PBYTEArray
;
554 // For discriminator with high bit set there is no data
555 if ((discriminator
&0x80) == 0) {
556 int len
= data
[offset
++];
558 if (discriminator
== UserUserIE
) {
559 // Special case of User-user field. See 7.2.2.31/H.225.0v4.
561 len
|= data
[offset
++];
563 // we also have a protocol discriminator, which we ignore
566 // before decrementing the length, make sure it is not zero
570 // adjust for protocol discriminator
574 if (offset
+ len
> data
.GetSize())
577 memcpy(item
->GetPointer(len
), (const BYTE
*)data
+offset
, len
);
581 informationElements
.SetAt(discriminator
, item
);
588 BOOL
Q931::Encode(PBYTEArray
& data
) const
590 PINDEX totalBytes
= 5;
591 unsigned discriminator
;
592 for (discriminator
= 0; discriminator
< 256; discriminator
++) {
593 if (informationElements
.Contains(discriminator
)) {
594 if (discriminator
< 128)
595 totalBytes
+= informationElements
[discriminator
].GetSize() +
596 (discriminator
!= UserUserIE
? 2 : 4);
602 if (!data
.SetMinSize(totalBytes
))
605 // Put in Q931 header
606 PAssert(protocolDiscriminator
< 256, PInvalidParameter
);
607 data
[0] = (BYTE
)protocolDiscriminator
;
608 data
[1] = 2; // Length of call reference
609 data
[2] = (BYTE
)(callReference
>> 8);
612 data
[3] = (BYTE
)callReference
;
613 PAssert(messageType
< 256, PInvalidParameter
);
614 data
[4] = (BYTE
)messageType
;
616 // The following assures disciminators are in ascending value order
617 // as required by Q931 specification
619 for (discriminator
= 0; discriminator
< 256; discriminator
++) {
620 if (informationElements
.Contains(discriminator
)) {
621 if (discriminator
< 128) {
622 int len
= informationElements
[discriminator
].GetSize();
624 if (discriminator
!= UserUserIE
) {
625 data
[offset
++] = (BYTE
)discriminator
;
626 data
[offset
++] = (BYTE
)len
;
629 len
++; // Allow for protocol discriminator
630 data
[offset
++] = (BYTE
)discriminator
;
631 data
[offset
++] = (BYTE
)(len
>> 8);
632 data
[offset
++] = (BYTE
)len
;
633 len
--; // Then put the length back again
634 // We shall assume that the user-user field is an ITU protocol block (5)
638 memcpy(&data
[offset
], (const BYTE
*)informationElements
[discriminator
], len
);
642 data
[offset
++] = (BYTE
)discriminator
;
646 return data
.SetSize(offset
);
650 void Q931::PrintOn(ostream
& strm
) const
652 int indent
= strm
.precision() + 2;
653 _Ios_Fmtflags flags
= strm
.flags();
656 << setw(indent
+24) << "protocolDiscriminator = " << protocolDiscriminator
<< '\n'
657 << setw(indent
+16) << "callReference = " << callReference
<< '\n'
658 << setw(indent
+7) << "from = " << (fromDestination
? "destination" : "originator") << '\n'
659 << setw(indent
+14) << "messageType = " << GetMessageTypeName() << '\n';
661 for (unsigned discriminator
= 0; discriminator
< 256; discriminator
++) {
662 if (informationElements
.Contains(discriminator
)) {
663 strm
<< setw(indent
+4) << "IE: " << (InformationElementCodes
)discriminator
;
664 if (discriminator
== CauseIE
) {
665 if (informationElements
[discriminator
].GetSize() > 1)
666 strm
<< " - " << (CauseValues
)(informationElements
[discriminator
][1]&0x7f);
669 << hex
<< setfill('0') << resetiosflags(ios::floatfield
)
670 << setprecision(indent
+2) << setw(16);
672 PBYTEArray value
= informationElements
[discriminator
];
673 if (value
.GetSize() <= 32 || (flags
&ios::floatfield
) != ios::fixed
)
676 PBYTEArray
truncatedArray(value
, 32);
677 strm
<< truncatedArray
<< '\n'
679 << setw(indent
+5) << "...";
682 strm
<< dec
<< setfill(' ')
684 << setw(indent
+2) << "}\n";
688 strm
<< setw(indent
-1) << "}";
694 PString
Q931::GetMessageTypeName() const
696 switch (messageType
) {
699 case CallProceedingMsg
:
700 return "CallProceeding";
713 case ReleaseCompleteMsg
:
714 return "ReleaseComplete";
715 case StatusEnquiryMsg
:
716 return "StatusEnquiry";
719 case InformationMsg
:
720 return "Information";
721 case NationalEscapeMsg
:
728 return "ResumeAckMsg";
729 case ResumeRejectMsg
:
730 return "ResumeRejectMsg";
734 return "SuspendAckMsg";
735 case SuspendRejectMsg
:
736 return "SuspendRejectMsg";
737 case UserInformationMsg
:
738 return "UserInformationMsg";
740 return "DisconnectMsg";
746 return "RestartAckMsg";
749 case CongestionCtrlMsg
:
750 return "CongestionCtrlMsg";
755 return psprintf("<%u>", messageType
);
759 unsigned Q931::GenerateCallReference()
761 static unsigned LastCallReference
;
763 PWaitAndSignal
wait(mutex
);
765 if (LastCallReference
== 0)
766 LastCallReference
= PRandom::Number();
770 LastCallReference
&= 0x7fff;
772 if (LastCallReference
== 0)
773 LastCallReference
= 1;
775 return LastCallReference
;
779 BOOL
Q931::HasIE(InformationElementCodes ie
) const
781 return informationElements
.Contains(POrdinalKey(ie
));
785 PBYTEArray
Q931::GetIE(InformationElementCodes ie
) const
787 if (informationElements
.Contains(POrdinalKey(ie
)))
788 return informationElements
[ie
];
794 void Q931::SetIE(InformationElementCodes ie
, const PBYTEArray
& userData
)
796 informationElements
.SetAt(ie
, new PBYTEArray(userData
));
799 void Q931::RemoveIE(InformationElementCodes ie
)
801 informationElements
.RemoveAt(ie
);
805 void Q931::SetBearerCapabilities(InformationTransferCapability capability
,
806 unsigned transferRate
,
807 unsigned codingStandard
,
808 unsigned userInfoLayer1
)
812 data
[0] = (BYTE
)(0x80 | ((codingStandard
&3) << 5) | (capability
&31));
814 switch (codingStandard
) {
815 case 0 : // ITU-T standardized coding
818 // Note this is always "Circuit Mode"
819 switch (transferRate
) {
836 PAssert(transferRate
> 0 && transferRate
< 128, PInvalidParameter
);
838 data
[2] = (BYTE
)(0x80 | transferRate
);
842 PAssert(userInfoLayer1
>= 2 && userInfoLayer1
<= 5, PInvalidParameter
);
843 data
[size
-1] = (BYTE
)(0x80 | (1<<5) | userInfoLayer1
);
846 case 1 : // Other international standard
848 data
[1] = 0x80; // Call independent signalling connection
855 SetIE(BearerCapabilityIE
, PBYTEArray(data
, size
));
859 BOOL
Q931::GetBearerCapabilities(InformationTransferCapability
& capability
,
860 unsigned & transferRate
,
861 unsigned * codingStandard
,
862 unsigned * userInfoLayer1
)
864 if (!HasIE(BearerCapabilityIE
))
867 PBYTEArray data
= GetIE(BearerCapabilityIE
);
868 if (data
.GetSize() < 2)
871 capability
= (InformationTransferCapability
)data
[0];
872 if (codingStandard
!= NULL
)
873 *codingStandard
= (data
[0] >> 5)&3;
893 if (data
.GetSize() < 3)
895 transferRate
= data
[2]&0x7f;
902 if (userInfoLayer1
!= NULL
)
903 *userInfoLayer1
= data
.GetSize() > nextByte
&& ((data
[nextByte
]>>5)&3) == 1 ? (data
[nextByte
]&0x1f) : 0;
909 void Q931::SetCause(CauseValues value
, unsigned standard
, unsigned location
)
912 data
[0] = (BYTE
)(0x80 | ((standard
&3) << 5) | (location
&15));
913 data
[1] = (BYTE
)(0x80 | value
);
914 SetIE(CauseIE
, data
);
918 Q931::CauseValues
Q931::GetCause(unsigned * standard
, unsigned * location
) const
921 return ErrorInCauseIE
;
923 PBYTEArray data
= GetIE(CauseIE
);
924 if (data
.GetSize() < 2)
925 return ErrorInCauseIE
;
927 if (standard
!= NULL
)
928 *standard
= (data
[0] >> 5)&3;
929 if (location
!= NULL
)
930 *location
= data
[0]&15;
932 if ((data
[0]&0x80) != 0)
933 return (CauseValues
)(data
[1]&0x7f);
935 // Allow for optional octet
936 if (data
.GetSize() < 3)
937 return ErrorInCauseIE
;
939 return (CauseValues
)(data
[2]&0x7f);
943 void Q931::SetCallState(CallStates value
, unsigned standard
)
945 if (value
>= CallState_ErrorInIE
)
948 // Call State as per Q.931 section 4.5.7
950 data
[0] = (BYTE
)(((standard
&3) << 6) | value
);
951 SetIE(CallStateIE
, data
);
955 Q931::CallStates
Q931::GetCallState(unsigned * standard
) const
957 if (!HasIE(CallStateIE
))
958 return CallState_ErrorInIE
;
960 PBYTEArray data
= GetIE(CallStateIE
);
962 return CallState_ErrorInIE
;
964 if (standard
!= NULL
)
965 *standard
= (data
[0] >> 6)&3;
967 return (CallStates
)(data
[0]&0x3f);
971 void Q931::SetSignalInfo(SignalInfo value
)
974 data
[0] = (BYTE
)value
;
975 SetIE(SignalIE
, data
);
979 Q931::SignalInfo
Q931::GetSignalInfo() const
981 if (!HasIE(SignalIE
))
982 return SignalErrorInIE
;
984 PBYTEArray data
= GetIE(SignalIE
);
986 return SignalErrorInIE
;
988 return (SignalInfo
)data
[0];
992 void Q931::SetKeypad(const PString
& digits
)
994 PBYTEArray
bytes((const BYTE
*)(const char *)digits
, digits
.GetLength()+1);
995 SetIE(KeypadIE
, bytes
);
999 PString
Q931::GetKeypad() const
1001 if (!HasIE(Q931::KeypadIE
))
1004 PBYTEArray digits
= GetIE(Q931::KeypadIE
);
1005 if (digits
.IsEmpty())
1008 return PString((const char *)(const BYTE
*)digits
, digits
.GetSize());
1012 void Q931::SetProgressIndicator(unsigned description
,
1013 unsigned codingStandard
,
1017 data
[0] = (BYTE
)(0x80+((codingStandard
&0x03)<<5)+(location
&0x0f));
1018 data
[1] = (BYTE
)(0x80+(description
&0x7f));
1019 SetIE(ProgressIndicatorIE
, data
);
1023 BOOL
Q931::GetProgressIndicator(unsigned & description
,
1024 unsigned * codingStandard
,
1025 unsigned * location
) const
1027 if (!HasIE(ProgressIndicatorIE
))
1030 PBYTEArray data
= GetIE(ProgressIndicatorIE
);
1031 if (data
.GetSize() < 2)
1034 if (codingStandard
!= NULL
)
1035 *codingStandard
= (data
[0]>>5)&0x03;
1036 if (location
!= NULL
)
1037 *location
= data
[0]&0x0f;
1038 description
= data
[1]&0x7f;
1044 void Q931::SetDisplayName(const PString
& name
)
1046 PBYTEArray
bytes((const BYTE
*)(const char *)name
, name
.GetLength()+1);
1047 if (name
.GetLength() == 0)
1048 RemoveIE(DisplayIE
);
1050 SetIE(DisplayIE
, bytes
);
1054 PString
Q931::GetDisplayName() const
1056 if (!HasIE(Q931::DisplayIE
))
1059 PBYTEArray display
= GetIE(Q931::DisplayIE
);
1060 if (display
.IsEmpty())
1063 return PString((const char *)(const BYTE
*)display
, display
.GetSize());
1067 static PBYTEArray
SetNumberIE(const PString
& number
,
1076 PINDEX len
= number
.GetLength();
1079 if (presentation
== -1 || screening
== -1) {
1080 bytes
.SetSize(len
+1);
1081 bytes
[0] = (BYTE
)(0x80|((type
&7)<<4)|(plan
&15));
1082 memcpy(bytes
.GetPointer()+1, (const char *)number
, len
);
1085 bytes
.SetSize(len
+2);
1086 bytes
[0] = (BYTE
)(((type
&7)<<4)|(plan
&15));
1087 bytes
[1] = (BYTE
)(0x80|((presentation
&3)<<5)|(screening
&3));
1088 memcpy(bytes
.GetPointer()+2, (const char *)number
, len
);
1092 // If octet 3b is present, then octet 3a must also be present!
1093 if (presentation
== -1 || screening
== -1) {
1094 // This situation should never occur!!!
1095 bytes
.SetSize(len
+1);
1096 bytes
[0] = (BYTE
)(0x80|((type
&7)<<4)|(plan
&15));
1097 memcpy(bytes
.GetPointer()+1, (const char *)number
, len
);
1100 bytes
.SetSize(len
+3);
1101 bytes
[0] = (BYTE
)(0x80|((type
&7)<<4)|(plan
&15));
1102 bytes
[1] = (BYTE
)(0x80|((presentation
&3)<<5)|(screening
&3));
1103 bytes
[2] = (BYTE
)(0x80|(reason
&15));
1104 memcpy(bytes
.GetPointer()+3, (const char *)number
, len
);
1112 static BOOL
GetNumberIE(const PBYTEArray
& bytes
,
1116 unsigned * presentation
,
1117 unsigned * screening
,
1119 unsigned defPresentation
,
1120 unsigned defScreening
,
1125 if (bytes
.IsEmpty())
1129 *plan
= bytes
[0]&15;
1132 *type
= (bytes
[0]>>4)&7;
1135 if ((bytes
[0] & 0x80) != 0) { // Octet 3a not provided, set defaults
1136 if (presentation
!= NULL
)
1137 *presentation
= defPresentation
;
1139 if (screening
!= NULL
)
1140 *screening
= defScreening
;
1145 if (bytes
.GetSize() < 2)
1148 if (presentation
!= NULL
)
1149 *presentation
= (bytes
[1]>>5)&3;
1151 if (screening
!= NULL
)
1152 *screening
= bytes
[1]&3;
1154 if ((bytes
[1] & 0x80) != 0) { // Octet 3b not provided, set defaults
1156 *reason
= defReason
;
1161 if (bytes
.GetSize() < 3)
1165 *reason
= bytes
[2]&15;
1171 if (bytes
.GetSize() < offset
)
1174 PINDEX len
= bytes
.GetSize()-offset
;
1177 memcpy(number
.GetPointer(len
+1), ((const BYTE
*)bytes
)+offset
, len
);
1183 void Q931::SetCallingPartyNumber(const PString
& number
,
1189 SetIE(CallingPartyNumberIE
,
1190 SetNumberIE(number
, plan
, type
, presentation
, screening
, -1));
1194 BOOL
Q931::GetCallingPartyNumber(PString
& number
,
1197 unsigned * presentation
,
1198 unsigned * screening
,
1199 unsigned defPresentation
,
1200 unsigned defScreening
) const
1202 return GetNumberIE(GetIE(CallingPartyNumberIE
), number
,
1203 plan
, type
, presentation
, screening
, NULL
,
1204 defPresentation
, defScreening
, 0);
1208 void Q931::SetCalledPartyNumber(const PString
& number
, unsigned plan
, unsigned type
)
1210 SetIE(CalledPartyNumberIE
,
1211 SetNumberIE(number
, plan
, type
, -1, -1, -1));
1215 BOOL
Q931::GetCalledPartyNumber(PString
& number
, unsigned * plan
, unsigned * type
) const
1217 return GetNumberIE(GetIE(CalledPartyNumberIE
),
1218 number
, plan
, type
, NULL
, NULL
, NULL
, 0, 0, 0);
1222 void Q931::SetRedirectingNumber(const PString
& number
,
1229 SetIE(RedirectingNumberIE
,
1230 SetNumberIE(number
, plan
, type
, presentation
, screening
, reason
));
1234 BOOL
Q931::GetRedirectingNumber(PString
& number
,
1237 unsigned * presentation
,
1238 unsigned * screening
,
1240 unsigned defPresentation
,
1241 unsigned defScreening
,
1242 unsigned defReason
) const
1244 return GetNumberIE(GetIE(RedirectingNumberIE
),
1245 number
, plan
, type
, presentation
, screening
, reason
,
1246 defPresentation
, defScreening
, defReason
);
1250 BOOL
Q931::GetConnectedNumber(PString
& number
,
1253 unsigned * presentation
,
1254 unsigned * screening
,
1256 unsigned defPresentation
,
1257 unsigned defScreening
,
1258 unsigned defReason
) const
1260 return GetNumberIE(GetIE(ConnectedNumberIE
), number
,
1261 plan
, type
, presentation
, screening
, reason
,
1262 defPresentation
, defScreening
, defReason
);
1266 void Q931::SetConnectedNumber(const PString
& number
,
1273 SetIE(ConnectedNumberIE
,
1274 SetNumberIE(number
, plan
, type
, presentation
, screening
, reason
));
1278 void Q931::SetChannelIdentification(unsigned interfaceType
,
1279 unsigned preferredOrExclusive
,
1282 // Known limitations:
1283 // - the interface identifier cannot be specified
1284 // - channel in PRI can only be indicated by number and cannot be indicated by map
1285 // - one and only one channel can be indicated
1286 // - the coding standard is always ITU Q.931
1291 PAssert(interfaceType
< 2, PInvalidParameter
);
1293 if (interfaceType
== 0) { // basic rate
1294 if (channelNumber
== -1) { // any channel
1295 bytes
[0] = 0x80 | 0x03;
1297 if (channelNumber
== 0) { // D channel
1298 bytes
[0] = 0x80 | 0x04;
1300 if (channelNumber
> 0) { // B channel
1301 bytes
[0] = (BYTE
)(0x80 | ((preferredOrExclusive
& 0x01) << 3) | (channelNumber
& 0x03));
1305 if (interfaceType
== 1) { // primary rate
1306 if (channelNumber
== -1) { // any channel
1307 bytes
[0] = 0x80 | 0x20 | 0x03;
1308 bytes
[1] = 0x80 | 0x03; // dummy octet 3.2
1309 bytes
[2] = (BYTE
)(0x80 | 1); // dummy octet 3.3
1311 if (channelNumber
== 0) { // D channel
1312 bytes
[0] = 0x80 | 0x04 | 0x20;
1314 if (channelNumber
> 0) { // B channel
1317 bytes
[0] = (BYTE
)(0x80 | 0x20 | ((preferredOrExclusive
& 0x01) << 3) | 0x01);
1318 bytes
[1] = 0x80 | 0x03;
1319 bytes
[2] = (BYTE
)(0x80 | channelNumber
);
1323 SetIE(ChannelIdentificationIE
, bytes
);
1327 BOOL
Q931::GetChannelIdentification(unsigned * interfaceType
,
1328 unsigned * preferredOrExclusive
,
1329 int * channelNumber
) const
1331 if (!HasIE(ChannelIdentificationIE
))
1334 PBYTEArray bytes
= GetIE(ChannelIdentificationIE
);
1335 if (bytes
.GetSize() < 1)
1338 *interfaceType
= (bytes
[0]>>5) & 0x01;
1339 *preferredOrExclusive
= (bytes
[0]>>3) & 0x01;
1341 if (*interfaceType
== 0) { // basic rate
1342 if ( (bytes
[0] & 0x04) == 0x04 ) { // D Channel
1346 if ( (bytes
[0] & 0x03) == 0x03 ) { // any channel
1347 *channelNumber
= -1;
1350 *channelNumber
= (bytes
[0] & 0x03);
1355 if (*interfaceType
== 1) { // primary rate
1356 if ( (bytes
[0] & 0x04) == 0x04 ) { // D Channel
1360 if ( (bytes
[0] & 0x03) == 0x03 ) { // any channel
1361 *channelNumber
= -1;
1364 if (bytes
.GetSize() < 3)
1367 if (bytes
[1] != 0x83)
1370 *channelNumber
= bytes
[2] & 0x7f;
1379 /////////////////////////////////////////////////////////////////////////////