📄 q931.cxx
字号:
/* * q931.cxx * * Q.931 protocol handler * * Open H323 Library * * Copyright (c) 1998-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions of this code were written with the assisance of funding from * Vovida Networks, Inc. http://www.vovida.com. * * Contributor(s): ______________________________________. * * $Log: q931.cxx,v $ * Revision 1.27 2000/07/11 11:17:01 robertj * Improved trace log display of Q.931 PDU's (correct order and extra IE fields). * * Revision 1.26 2000/07/09 14:54:11 robertj * Added facility IE to facility message. * Changed reference to the word "field" to be more correct IE or "Information Element" * * Revision 1.25 2000/06/21 08:07:47 robertj * Added cause/reason to release complete PDU, where relevent. * * Revision 1.24 2000/05/09 12:19:31 robertj * Added ability to get and set "distinctive ring" Q.931 functionality. * * Revision 1.23 2000/05/08 14:07:35 robertj * Improved the provision and detection of calling and caller numbers, aliases and hostnames. * * Revision 1.22 2000/05/06 02:18:26 robertj * Changed the new CallingPartyNumber code so defaults for octet3a are application dependent. * * Revision 1.21 2000/05/05 00:44:05 robertj * Added presentation and screening fields to Calling Party Number field, thanks Dean Anderson. * * Revision 1.20 2000/05/02 04:32:27 robertj * Fixed copyright notice comment. * * Revision 1.19 2000/03/21 01:08:11 robertj * Fixed incorrect call reference code being used in originated call. * * Revision 1.18 2000/02/17 12:07:43 robertj * Used ne wPWLib random number generator after finding major problem in MSVC rand(). * * Revision 1.17 1999/12/23 22:44:06 robertj * Added calling party number field. * * Revision 1.16 1999/09/22 04:18:29 robertj * Fixed missing "known" message types in debugging output. * * Revision 1.15 1999/09/10 03:36:48 robertj * Added simple Q.931 Status response to Q.931 Status Enquiry * * Revision 1.14 1999/08/31 13:54:35 robertj * Fixed problem with memory overrun building PDU's * * Revision 1.13 1999/08/31 12:34:19 robertj * Added gatekeeper support. * * Revision 1.12 1999/08/13 06:34:38 robertj * Fixed problem in CallPartyNumber Q.931 encoding. * Added field name display to Q.931 protocol. * * Revision 1.11 1999/08/10 13:14:15 robertj * Added Q.931 Called Number field if have "phone number" style destination addres. * * Revision 1.10 1999/07/16 02:15:30 robertj * Fixed more tunneling problems. * * Revision 1.9 1999/07/09 14:59:59 robertj * Fixed GNU C++ compatibility. * * Revision 1.8 1999/07/09 06:09:50 robertj * Major implementation. An ENORMOUS amount of stuff added everywhere. * * Revision 1.7 1999/06/14 15:19:48 robertj * GNU C compatibility * * Revision 1.6 1999/06/13 12:41:14 robertj * Implement logical channel transmitter. * Fixed H245 connect on receiving call. * * Revision 1.5 1999/06/09 05:26:20 robertj * Major restructuring of classes. * * Revision 1.4 1999/02/23 11:04:29 robertj * Added capability to make outgoing call. * * Revision 1.3 1999/01/16 01:31:38 robertj * Major implementation. * * Revision 1.2 1999/01/02 04:00:52 robertj * Added higher level protocol negotiations. * * Revision 1.1 1998/12/14 09:13:37 robertj * Initial revision * */#include <ptlib.h>#include <ptclib/random.h>#include "q931.h"#define new PNEWQ931::Q931(){ protocolDiscriminator = 8; // Q931 always has 00001000 messageType = NationalEscapeMsg; fromDestination = FALSE; callReference = 0;}Q931 & Q931::operator=(const Q931 & other){ protocolDiscriminator = other.protocolDiscriminator; callReference = other.callReference; fromDestination = other.fromDestination; messageType = other.messageType; informationElements.RemoveAll(); for (PINDEX i = 0; i < other.informationElements.GetSize(); i++) informationElements.SetAt(other.informationElements.GetKeyAt(i), new PBYTEArray(other.informationElements.GetDataAt(i))); return *this;}void Q931::BuildFacility(int callRef, BOOL fromDest){ messageType = FacilityMsg; callReference = callRef; fromDestination = fromDest; informationElements.RemoveAll(); PBYTEArray data; SetIE(FacilityIE, data);}void Q931::BuildCallProceeding(int callRef){ messageType = CallProceedingMsg; callReference = callRef; fromDestination = TRUE; informationElements.RemoveAll();}void Q931::BuildAlerting(int callRef){ messageType = AlertingMsg; callReference = callRef; fromDestination = TRUE; informationElements.RemoveAll();}static const BYTE BearerCapabilityData[3] = { 0x88, 0xc0, 0xa5 };void Q931::BuildSetup(int callRef){ messageType = SetupMsg; if (callRef < 0) GenerateCallReference(); else callReference = callRef; fromDestination = FALSE; informationElements.RemoveAll(); SetIE(BearerCapabilityIE, PBYTEArray(BearerCapabilityData, sizeof(BearerCapabilityData)));}void Q931::BuildConnect(int callRef){ messageType = ConnectMsg; callReference = callRef; fromDestination = TRUE; informationElements.RemoveAll(); SetIE(BearerCapabilityIE, PBYTEArray(BearerCapabilityData, sizeof(BearerCapabilityData)));}void Q931::BuildStatus(int callRef, BOOL fromDest){ messageType = StatusMsg; callReference = callRef; fromDestination = fromDest; informationElements.RemoveAll(); PBYTEArray data(1); // Call State as per Q.931 section 4.5.7 data[0] = 0; // Use CCITT Null SetIE(CallStateIE, data); // Cause field as per Q.850 SetCause(StatusEnquiryResponse);}void Q931::BuildReleaseComplete(int callRef, BOOL fromDest){ messageType = ReleaseCompleteMsg; callReference = callRef; fromDestination = fromDest; informationElements.RemoveAll();}BOOL Q931::Decode(const PBYTEArray & data){ // Clear all existing data before reading new informationElements.RemoveAll(); if (data.GetSize() < 5) // Packet too short return FALSE; protocolDiscriminator = data[0]; if (data[1] != 2) // Call reference must be 2 bytes long return FALSE; callReference = ((data[2]&0x7f) << 8) | data[3]; fromDestination = (data[2]&0x80) != 0; messageType = (MsgTypes)data[4]; // Have preamble, start getting the informationElements into buffers PINDEX offset = 5; while (offset < data.GetSize()) { // Get field discriminator int discriminator = data[offset++]; PBYTEArray * item = new PBYTEArray; // For discriminator with high bit set there is no data if ((discriminator&0x80) == 0) { int len = data[offset++]; if (discriminator == UserUserIE) { // Special case of User-user field, there is some confusion here as // the Q931 documentation claims the length is a single byte, // unfortunately all H.323 based apps have a 16 bit length here, so // we allow for said longer length. There is presumably an addendum // to Q931 which describes this, and provides a means to discriminate // between the old 1 byte and the new 2 byte systems. However, at // present we assume it is always 2 bytes until we find something that // breaks it. len <<= 8; len |= data[offset++]; // we also have a protocol discriminator, which we ignore offset++; len--; } if (offset + len > data.GetSize()) return FALSE; memcpy(item->GetPointer(len), (const BYTE *)data+offset, len); offset += len; } informationElements.SetAt(discriminator, item); } return TRUE;}BOOL Q931::Encode(PBYTEArray & data) const{ PINDEX totalBytes = 5; unsigned discriminator; for (discriminator = 0; discriminator < 256; discriminator++) { if (informationElements.Contains(discriminator)) { if (discriminator < 128) totalBytes += informationElements[discriminator].GetSize() + (discriminator != UserUserIE ? 2 : 4); else totalBytes++; } } if (!data.SetMinSize(totalBytes)) return FALSE; // Put in Q931 header PAssert(protocolDiscriminator < 256, PInvalidParameter); data[0] = (BYTE)protocolDiscriminator; data[1] = 2; // Length of call reference data[2] = (BYTE)(callReference >> 8); if (fromDestination) data[2] |= 0x80; data[3] = (BYTE)callReference; PAssert(messageType < 256, PInvalidParameter); data[4] = (BYTE)messageType; // The following assures disciminators are in ascending value order // as required by Q931 specification PINDEX offset = 5; for (discriminator = 0; discriminator < 256; discriminator++) { if (informationElements.Contains(discriminator)) { if (discriminator < 128) { int len = informationElements[discriminator].GetSize(); if (discriminator != UserUserIE) { data[offset++] = (BYTE)discriminator; data[offset++] = (BYTE)len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -