|
|
#ifndef __iptel_q931msg_h
#define __iptel_q931msg_h
// To use the Q931_MESSAGE class:
//
// To decode Q.931 PDUs:
//
// Create an instance of the Q931_MESSAGE class.
// Call the AssignDecodePdu method, supplying the buffer and length of the PDU data.
// If the AssignDecodePdu succeeds, then the buffer is now "bound" to the
// Q931_MESSAGE instance. You may then examine the elements of Q931_MESSAGE:
//
// MessageType - The type of Q.931 PDU received (Setup, etc.)
// CallReferenceValue
// InfoElementArray - An ordered array of IEs that were in the PDU
// UserInformation - If an ASN.1 UUIE was present, this field will be non-NULL
//
// You may also use the FindInfoElement method to locate a specific IE (cause code, etc.)
//
// When you are done using the contents of the Q931_MESSAGE instance, you must call the
// FreeAll method. This destroys the association between the buffer and the Q931_MESSAGE class.
// This step MUST be performed before destroying the instance of the Q931_MESSAGE class.
//
//
// To encode Q.931 PDUs:
//
// Create an instance of the Q931_MESSAGE class.
// Set the MessageType and CallReferenceValue fields.
// For each IE that should be encoded, call AppendInfoElement.
// (This includes the UUIE.)
// Call EncodePdu. The buffer on return contains the fully encoded PDU.
//
// If the buffer supplied to EncodePdu is not long enough, then the ReturnLength
// parameter will contain the required length, and the method will return
// HRESULT_FROM_WIN32 (ERROR_MORE_DATA).
//
// When calling InsertInfoElement, you must insure that the buffer supplied in the
// Q931_IE structure is still valid when the EncodePdu call is made. All IE buffers
// should remain valid until the Q931_MESSAGE::FreeAll method is called.
#include "q931defs.h"
#include "dynarray.h"
struct H323_UserInformation;
struct Q931_ENCODE_CONTEXT;
struct Q931_BEARER_CAPABILITY { };
// Q931_IE_DATA contains the decoded contents of those information elements whose
// interpretation is known and implemented in this module.
// Not all IEs are supported.
union Q931_IE_DATA { // Q931_IE_USER_TO_USER
struct { Q931_UUIE_TYPE Type; H323_UserInformation * PduStructure; BOOL IsOwner; // if true, delete PduStructure on deletion
} UserToUser;
// Q931_IE_CAUSE
DWORD CauseCode;
// Q931_BEARER_CAPABILITY
Q931_BEARER_CAPABILITY BearerCapability;
// Q931_DISPLAY
struct { LPSTR String; } Display;
// IEs that are not implemented here, and are of variable length
struct { LPBYTE Data; DWORD Length; } UnknownVariable;
// IEs that are not implemented here, and are of fixed length
struct { BYTE Value; } UnknownFixed; };
struct Q931_IE { Q931_IE_IDENTIFIER Identifier; Q931_IE_DATA Data; };
// it is the responsibility of the user of this object to synchronize access
// and object lifetime.
//
// The Decode method builds the InfoElementArray. Elements in this array
// may refer to the original buffer passed to Encode. Therefore, users of
// Q931_MESSAGE::Decode must insure that the original buffer remains accessible
// and does not change, until the user no longer requires the use of this Q931_MESSAGE
// object, or calls Q931_MESSAGE::FreeAll.
struct Q931_MESSAGE { public:
Q931_MESSAGE_TYPE MessageType; WORD CallReferenceValue; DYNAMIC_ARRAY <Q931_IE> InfoElementArray;
LPBYTE Buffer; DWORD BufferLength; BOOL BufferIsOwner;
private:
HRESULT DecodeInfoElement ( IN OUT LPBYTE * Pos, IN LPBYTE End, OUT Q931_IE * ReturnInfoElement);
void FreeInfoElementArray (void);
// ParseInfoElement examines the contents of an IE that has already been decoded
// (type and length determined), and for known IE types, decodes their contents
// and assigns to data structures
HRESULT ParseIE ( IN Q931_IE * InfoElement);
HRESULT ParseIE_UUIE ( IN Q931_IE * InfoElement);
HRESULT EncodeIE_UUIE ( IN Q931_ENCODE_CONTEXT * Context, IN Q931_IE * InfoElement);
// for those IEs that have attached allocated data, free it
void FreeInfoElement ( IN Q931_IE * InfoElement);
HRESULT EncodeHeader ( IN Q931_ENCODE_CONTEXT * Context);
HRESULT EncodeInfoElement ( IN Q931_ENCODE_CONTEXT * Context, IN Q931_IE * InfoElement);
static INT __cdecl CompareInfoElement (const Q931_IE *, const Q931_IE *);
static INT InfoElementSearchFunc ( IN const Q931_IE_IDENTIFIER * SearchKey, IN const Q931_IE * Comparand);
public:
// initializes array and UserInformation
Q931_MESSAGE (void);
// will free the UserInformation field if present
~Q931_MESSAGE (void);
HRESULT EncodePdu ( IN OUT LPBYTE Data, IN OUT LPDWORD Length);
HRESULT AttachDecodePdu ( IN LPBYTE Data, IN DWORD Length, IN BOOL IsDataOwner); // if TRUE, Q931_MESSAGE will free on dtor
void FreeAll (void);
// if Q931_MESSAGE currently has a Buffer, and it owns the Buffer,
// then it will free it here, using GkHeapFree
void Detach (void);
// if Q931_MESSAGE currently has a Buffer, regardless of whether it owns the buffer,
// then it will be returned here
// returns S_OK if a buffer was returned
// returns S_FALSE if no buffer was returned, and ReturnBuffer set to null
HRESULT Detach ( OUT LPBYTE * ReturnBuffer, OUT DWORD * ReturnBufferLength);
void SetUserInformation ( IN H323_UserInformation *, IN BOOL FreeOnDelete);
// information element manipulation
HRESULT AppendInfoElement ( IN Q931_IE * InfoElement);
HRESULT DeleteInfoElement ( IN Q931_IE_IDENTIFIER Identifier);
HRESULT FindInfoElement ( IN Q931_IE_IDENTIFIER Identifier, OUT Q931_IE ** ReturnInfoElement);
void SortInfoElementArray (void);
};
DECLARE_SEARCH_FUNC_CAST(Q931_IE_IDENTIFIER, Q931_IE);
#if DBG
// in debug builds, this function will take a Q.931 PDU buffer,
// decode it, re-encode it, verify that the contents match,
// and attempt to decode the re-encoded PDU.
// this is good for verifying the integrity of the Q931_MESSAGE class.
void Q931TestDecoder ( IN LPBYTE PduData, IN DWORD PduLength);
#else
#define Q931TestDecoder(x,y) 0
#endif
#endif // __iptel_q931msg_h
|