929 lines
27 KiB
C++
929 lines
27 KiB
C++
#include "precomp.h"
|
||
DEBUG_FILEZONE(ZONE_T120_T123PSTN);
|
||
|
||
/* Mplex.cpp
|
||
*
|
||
* Copyright (c) 1994-1995 by DataBeam Corporation, Lexington, KY
|
||
*
|
||
* Abstract:
|
||
* This is the implementation file for the Q922 multiplexer class. This
|
||
* class multiplexes higher layers to a single lower layer.
|
||
*
|
||
* Private Instance Variables:
|
||
* Q922_Layers - List of the higher layers we are multiplexing
|
||
* Owner_Object - Address of our owner object.
|
||
* m_pComPort - Address of our lower layer
|
||
* m_hCommLink- The identifier we pass to the lower layer. This
|
||
* is how the lower layer identifies us
|
||
* m_nMsgBase - Message base we use for owner callbacks. The
|
||
* owner identifies us by the message base
|
||
* Maximum_Packet_Size Maximum packet size we can send to lower layer
|
||
* Packet_Size - Maximum packet size the higher layer can send
|
||
* to us
|
||
* Data_Request_Buffer Buffer we use for data coming from higher layer
|
||
* Data_Request_Memory_Object Memory object used for data transmission
|
||
* Data_Request_Length Length of packet from higher layer
|
||
* Data_Request_Offset Current offset into packet. Maintains current
|
||
* position as we send to lower layer.
|
||
* Data_Indication_Buffer Buffer we use for data coming from lower layer
|
||
* Data_Indication_Length Length of packet
|
||
* Data_Indication_Ready Flag indicating that packet is ready to send up
|
||
*
|
||
* Framer - Address of packet framer object
|
||
* CRC - Address of crc generator and checker
|
||
*
|
||
* Decode_In_Progress Flag telling us if we are in the middle of a
|
||
* packet
|
||
* CRC_Size - Number of bytes in the CRC
|
||
* Disconnect - TRUE if a disconnect is pending
|
||
*
|
||
* Caveats:
|
||
* None.
|
||
*
|
||
* Authors:
|
||
* James W. Lawwill
|
||
*/
|
||
#include "mplex.h"
|
||
|
||
|
||
/*
|
||
* Multiplexer::Multiplexer (
|
||
* IObject * owner_object,
|
||
* IProtocolLayer * lower_layer,
|
||
* USHORT identifier,
|
||
* USHORT message_base,
|
||
* PPacketFrame framer,
|
||
* PCRC crc,
|
||
* BOOL * initialized)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function initializes the Q922 multiplexer.
|
||
*/
|
||
Multiplexer::Multiplexer
|
||
(
|
||
T123 *owner_object,
|
||
ComPort *comport, // lower layer
|
||
PhysicalHandle physical_handle,
|
||
USHORT message_base,
|
||
PPacketFrame framer,
|
||
PCRC crc,
|
||
BOOL *initialized
|
||
)
|
||
:
|
||
Q922_Layers(TRANSPORT_HASHING_BUCKETS)
|
||
{
|
||
TRACE_OUT(("Multiplexer::Multiplexer"));
|
||
|
||
USHORT overhead;
|
||
ProtocolLayerError error;
|
||
USHORT lower_layer_prepend;
|
||
USHORT lower_layer_append;
|
||
|
||
*initialized = TRUE;
|
||
|
||
m_pT123 = owner_object;
|
||
m_pComPort = comport;
|
||
m_hCommLink = physical_handle;
|
||
m_nMsgBase = message_base;
|
||
Framer = framer;
|
||
CRC = crc;
|
||
CRC_Size = 0;
|
||
|
||
m_pComPort->GetParameters(
|
||
&Maximum_Packet_Size,
|
||
&lower_layer_prepend,
|
||
&lower_layer_append);
|
||
|
||
if (Maximum_Packet_Size == 0xffff)
|
||
{
|
||
/*
|
||
** The lower layer is a stream device, base the higher maximum packet
|
||
** size on the Multiplexer max. packet size
|
||
*/
|
||
Packet_Size = MULTIPLEXER_MAXIMUM_PACKET_SIZE;
|
||
Maximum_Packet_Size = Packet_Size;
|
||
|
||
if (CRC != NULL)
|
||
{
|
||
CRC -> GetOverhead (0, &CRC_Size);
|
||
Maximum_Packet_Size += CRC_Size;
|
||
}
|
||
|
||
if (Framer != NULL)
|
||
Framer -> GetOverhead (Maximum_Packet_Size, &Maximum_Packet_Size);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
** The lower layer is a packet device, determine the max. packet
|
||
** size of the higher layer.
|
||
*/
|
||
overhead = 0;
|
||
if (Framer != NULL)
|
||
Framer -> GetOverhead (overhead, &overhead);
|
||
|
||
if (CRC != NULL)
|
||
{
|
||
CRC -> GetOverhead (0, &CRC_Size);
|
||
overhead += CRC_Size;
|
||
}
|
||
|
||
Packet_Size = Maximum_Packet_Size - overhead;
|
||
}
|
||
|
||
TRACE_OUT(("MPlex: max_packet = %d", Maximum_Packet_Size));
|
||
|
||
/*
|
||
** Now we have to allocate a buffer for data going to the lower layer
|
||
*/
|
||
if (Framer != NULL)
|
||
{
|
||
Data_Request_Buffer = (LPBYTE) LocalAlloc (LMEM_FIXED, Maximum_Packet_Size);
|
||
Data_Indication_Buffer = (LPBYTE) LocalAlloc (LMEM_FIXED, Maximum_Packet_Size);
|
||
if ((Data_Request_Buffer == NULL) ||
|
||
(Data_Indication_Buffer == NULL))
|
||
{
|
||
*initialized = FALSE;
|
||
}
|
||
}
|
||
|
||
Data_Request_Length = 0;
|
||
Data_Request_Offset = 0;
|
||
Data_Request_Memory_Object = NULL;
|
||
|
||
Data_Indication_Length = 0;
|
||
Data_Indication_Ready = FALSE;
|
||
|
||
|
||
Decode_In_Progress = FALSE;
|
||
Disconnect = FALSE;
|
||
|
||
/*
|
||
** Register with the lower layer
|
||
*/
|
||
error = m_pComPort->RegisterHigherLayer(
|
||
(ULONG_PTR) m_hCommLink,
|
||
NULL,
|
||
(IProtocolLayer *) this);
|
||
|
||
if (error != PROTOCOL_LAYER_NO_ERROR)
|
||
{
|
||
TRACE_OUT(("Multiplexer: constructor: Error registering with lower layer"));
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* Multiplexer::~Multiplexer (void);
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* Destructor
|
||
*/
|
||
Multiplexer::~Multiplexer (void)
|
||
{
|
||
TRACE_OUT(("Multiplexer::~Multiplexer"));
|
||
|
||
PMPlexStruct lpmpStruct;
|
||
/*
|
||
** Remove our reference from the lower layer
|
||
*/
|
||
m_pComPort->RemoveHigherLayer((ULONG_PTR) m_hCommLink);
|
||
|
||
if (Framer != NULL)
|
||
{
|
||
if (Data_Request_Buffer != NULL)
|
||
LocalFree ((HLOCAL) Data_Request_Buffer);
|
||
if (Data_Indication_Buffer != NULL)
|
||
LocalFree ((HLOCAL) Data_Indication_Buffer);
|
||
}
|
||
else
|
||
{
|
||
if (Data_Request_Memory_Object != NULL)
|
||
{
|
||
if (Q922_Layers.find ((DWORD_PTR) Data_Request_DLCI, (PDWORD_PTR) &lpmpStruct))
|
||
lpmpStruct->data_request_memory_manager->UnlockMemory (Data_Request_Memory_Object);
|
||
}
|
||
}
|
||
|
||
Q922_Layers.reset();
|
||
while (Q922_Layers.iterate((PDWORD_PTR) &lpmpStruct))
|
||
delete lpmpStruct;
|
||
|
||
/*
|
||
** Delete the Framer that was instantiated by the controller.
|
||
*/
|
||
if (Framer != NULL)
|
||
delete Framer;
|
||
if (CRC != NULL)
|
||
delete CRC;
|
||
}
|
||
|
||
|
||
/*
|
||
* MultiplexerError Multiplexer::ConnectRequest (void)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function simply notifies the higher layer that it is ready
|
||
* for operation
|
||
*/
|
||
MultiplexerError Multiplexer::ConnectRequest (void)
|
||
{
|
||
TRACE_OUT(("Multiplexer::ConnectRequest"));
|
||
|
||
m_pT123->OwnerCallback(m_nMsgBase + NEW_CONNECTION);
|
||
|
||
return (MULTIPLEXER_NO_ERROR);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* MultiplexerError Multiplexer::DisconnectRequest (void)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function removes itself from the lower layer and notifies the
|
||
* owner.
|
||
*/
|
||
MultiplexerError Multiplexer::DisconnectRequest (void)
|
||
{
|
||
TRACE_OUT(("Multiplexer::DisconnectRequest"));
|
||
|
||
if (Data_Request_Length == 0)
|
||
{
|
||
m_pT123->OwnerCallback(m_nMsgBase + BROKEN_CONNECTION);
|
||
}
|
||
Disconnect = TRUE;
|
||
|
||
return (MULTIPLEXER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::PollReceiver (
|
||
* ULONG)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* If this function has a packet ready to send to a higher layer, it
|
||
* attempts to send it.
|
||
*/
|
||
ProtocolLayerError Multiplexer::PollReceiver(void)
|
||
{
|
||
// TRACE_OUT(("Multiplexer::PollReceiver"));
|
||
|
||
if (Data_Indication_Ready)
|
||
{
|
||
SendDataToHigherLayer (
|
||
Data_Indication_Buffer,
|
||
Data_Indication_Length);
|
||
|
||
Data_Indication_Ready = FALSE;
|
||
}
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::PollTransmitter (
|
||
* ULONG)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* If we have data to send to the lower layer, we attempt to send it.
|
||
*/
|
||
ProtocolLayerError Multiplexer::PollTransmitter (
|
||
ULONG_PTR,
|
||
USHORT,
|
||
USHORT *,
|
||
USHORT *)
|
||
{
|
||
// TRACE_OUT(("Multiplexer::PollTransmitter"));
|
||
|
||
ULONG bytes_accepted;
|
||
HPUChar packet_address;
|
||
ProtocolLayerError return_value = PROTOCOL_LAYER_NO_ERROR;
|
||
|
||
if (Data_Request_Length != 0)
|
||
{
|
||
if (Framer != NULL)
|
||
{
|
||
m_pComPort->DataRequest(
|
||
(ULONG_PTR) m_hCommLink,
|
||
Data_Request_Buffer + Data_Request_Offset,
|
||
Data_Request_Length - Data_Request_Offset,
|
||
&bytes_accepted);
|
||
}
|
||
else
|
||
{
|
||
packet_address = (HPUChar) Data_Request_Memory_Object->GetPointer ();
|
||
m_pComPort->DataRequest(
|
||
(ULONG_PTR) m_hCommLink,
|
||
((LPBYTE) packet_address) + Data_Request_Offset,
|
||
Data_Request_Length - Data_Request_Offset,
|
||
&bytes_accepted);
|
||
}
|
||
|
||
/*
|
||
** If the lower layer has accepted all of the packet, reset
|
||
** our length and offset variables
|
||
*/
|
||
if (bytes_accepted <=
|
||
(ULONG) (Data_Request_Length - Data_Request_Offset))
|
||
{
|
||
Data_Request_Offset += (USHORT) bytes_accepted;
|
||
if (Data_Request_Offset == Data_Request_Length)
|
||
{
|
||
Data_Request_Offset = 0;
|
||
Data_Request_Length = 0;
|
||
if (Framer == NULL)
|
||
{
|
||
PMPlexStruct lpmpStruct;
|
||
|
||
/*
|
||
** Unlock the memory object so that it can be released
|
||
*/
|
||
|
||
if (Q922_Layers.find ((DWORD_PTR) Data_Request_DLCI, (PDWORD_PTR) &lpmpStruct))
|
||
lpmpStruct->data_request_memory_manager->UnlockMemory (Data_Request_Memory_Object);
|
||
|
||
Data_Request_Memory_Object = NULL;
|
||
}
|
||
|
||
/*
|
||
** If the Disconnect is pending, issue the callback
|
||
*/
|
||
if (Disconnect)
|
||
{
|
||
Disconnect = FALSE;
|
||
m_pT123->OwnerCallback(m_nMsgBase + BROKEN_CONNECTION);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return (return_value);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::RegisterHigherLayer (
|
||
* ULONG identifier,
|
||
* PMemoryManager memory_manager,
|
||
* IProtocolLayer * q922);
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function is called to register an identifier with a higher
|
||
* layer address.
|
||
*/
|
||
ProtocolLayerError Multiplexer::RegisterHigherLayer (
|
||
ULONG_PTR identifier,
|
||
PMemoryManager memory_manager,
|
||
IProtocolLayer * q922)
|
||
{
|
||
TRACE_OUT(("Multiplexer::RegisterHigherLayer"));
|
||
|
||
DLCI dlci;
|
||
PMPlexStruct lpmpStruct;
|
||
|
||
dlci = (DLCI) identifier;
|
||
|
||
if (Q922_Layers.find ((DWORD) dlci))
|
||
return (PROTOCOL_LAYER_REGISTRATION_ERROR);
|
||
|
||
lpmpStruct = new MPlexStruct;
|
||
if (lpmpStruct != NULL)
|
||
{
|
||
Q922_Layers.insert ((DWORD_PTR) dlci, (DWORD_PTR) lpmpStruct);
|
||
lpmpStruct -> q922 = q922;
|
||
lpmpStruct -> data_request_memory_manager = memory_manager;
|
||
}
|
||
else
|
||
{
|
||
return (PROTOCOL_LAYER_ERROR);
|
||
}
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::RemoveHigherLayer (
|
||
* ULONG identifier);
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function removes the higher layer from our list
|
||
*/
|
||
ProtocolLayerError Multiplexer::RemoveHigherLayer (
|
||
ULONG_PTR identifier)
|
||
{
|
||
TRACE_OUT(("Multiplexer::RemoveHigherLayer"));
|
||
|
||
DLCI dlci;
|
||
PMPlexStruct lpmpStruct;
|
||
|
||
dlci = (DLCI) identifier;
|
||
|
||
if (Q922_Layers.find ((DWORD_PTR) dlci, (PDWORD_PTR) &lpmpStruct) == FALSE)
|
||
return (PROTOCOL_LAYER_REGISTRATION_ERROR);
|
||
|
||
if (Data_Request_Memory_Object != NULL)
|
||
{
|
||
if (Data_Request_DLCI == dlci)
|
||
{
|
||
/*
|
||
** Unlock the memory object so that it can be released
|
||
*/
|
||
lpmpStruct->data_request_memory_manager->UnlockMemory (Data_Request_Memory_Object);
|
||
|
||
Data_Request_Offset = 0;
|
||
Data_Request_Length = 0;
|
||
Data_Request_Memory_Object = NULL;
|
||
}
|
||
}
|
||
|
||
delete lpmpStruct;
|
||
Q922_Layers.remove ((DWORD) dlci);
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::GetParameters (
|
||
* ULONG,
|
||
* USHORT * max_packet_size,
|
||
* USHORT * prepend_bytes,
|
||
* USHORT * append_bytes)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function returns the maximum packet size permitted by
|
||
* the higher layer.
|
||
*/
|
||
ProtocolLayerError Multiplexer::GetParameters (
|
||
USHORT * max_packet_size,
|
||
USHORT * prepend_bytes,
|
||
USHORT * append_bytes)
|
||
{
|
||
TRACE_OUT(("Multiplexer::GetParameters"));
|
||
|
||
*max_packet_size = Packet_Size;
|
||
*prepend_bytes = 0;
|
||
*append_bytes = CRC_Size;
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* MultiplexerError Multiplexer::DataRequest (
|
||
* ULONG identifier,
|
||
* PMemory memory,
|
||
* PULong bytes_accepted)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function takes the packet passed in, runs it thru the framer and
|
||
* CRC, and passes it to the lower layer.
|
||
*/
|
||
ProtocolLayerError Multiplexer::DataRequest (
|
||
ULONG_PTR identifier,
|
||
PMemory memory,
|
||
PULong bytes_accepted)
|
||
{
|
||
TRACE_OUT(("Multiplexer::DataRequest"));
|
||
|
||
USHORT crc;
|
||
USHORT pending_data;
|
||
HPUChar packet_address;
|
||
ULONG length;
|
||
USHORT holding_data;
|
||
USHORT i;
|
||
DLCI dlci;
|
||
PMPlexStruct lpmpStruct;
|
||
|
||
dlci = (DLCI) identifier;
|
||
|
||
/*
|
||
** Set bytes_accepted to 0
|
||
*/
|
||
*bytes_accepted = 0;
|
||
|
||
if (Data_Request_Length != 0)
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
|
||
/*
|
||
** Get the address of the memory block
|
||
*/
|
||
packet_address = (HPUChar) memory -> GetPointer ();
|
||
length = memory -> GetLength ();
|
||
|
||
/*
|
||
** Remove the CRC length from the total size of the packet.
|
||
*/
|
||
length -= CRC_Size;
|
||
|
||
if (length > Packet_Size)
|
||
{
|
||
TRACE_OUT(("MPLEX: DataRequest: Packet too big"));
|
||
return (PROTOCOL_LAYER_PACKET_TOO_BIG);
|
||
}
|
||
|
||
/*
|
||
** Lock the memory object so that it won't be released
|
||
*/
|
||
if (Q922_Layers.find ((DWORD_PTR) dlci, (PDWORD_PTR) &lpmpStruct))
|
||
lpmpStruct->data_request_memory_manager->LockMemory (memory);
|
||
|
||
if (CRC != NULL)
|
||
{
|
||
/*
|
||
** Generate the CRC and put it at the end of the packet.
|
||
*/
|
||
crc = (USHORT) CRC -> CRCGenerator (
|
||
(LPBYTE) packet_address, length);
|
||
for (i=0; i<CRC_Size; i++)
|
||
*(packet_address + length + i) = (crc >> (i * 8)) & 0xff;
|
||
}
|
||
|
||
/*
|
||
** Add the CRC size to the packet length.
|
||
*/
|
||
length += CRC_Size;
|
||
|
||
if (Framer != NULL)
|
||
{
|
||
/*
|
||
** Use the framer to encode the packet
|
||
*/
|
||
Framer -> PacketEncode (
|
||
(LPBYTE) packet_address,
|
||
(USHORT) length,
|
||
Data_Request_Buffer,
|
||
Maximum_Packet_Size,
|
||
TRUE,
|
||
TRUE,
|
||
&Data_Request_Length);
|
||
|
||
/*
|
||
** If we are using a framer, we can release the memory object
|
||
** right now.
|
||
*/
|
||
lpmpStruct->data_request_memory_manager->UnlockMemory (memory);
|
||
*bytes_accepted = length;
|
||
}
|
||
else
|
||
{
|
||
|
||
/*
|
||
** Save the memory object and the identifier
|
||
*/
|
||
Data_Request_DLCI = (DLCI) dlci;
|
||
Data_Request_Memory_Object = memory;
|
||
Data_Request_Length = (USHORT) length;
|
||
*bytes_accepted = length;
|
||
}
|
||
|
||
/*
|
||
** Attempt to send the packet to the lower layer
|
||
*/
|
||
PollTransmitter (
|
||
0,
|
||
PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA,
|
||
&pending_data,
|
||
&holding_data);
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* MultiplexerError Multiplexer::DataRequest (
|
||
* ULONG,
|
||
* LPBYTE
|
||
* ULONG
|
||
* PULong bytes_accepted)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function takes the packet passed in, runs it thru the framer and
|
||
* CRC, and passes it to the lower layer.
|
||
*/
|
||
ProtocolLayerError Multiplexer::DataRequest (
|
||
ULONG_PTR,
|
||
LPBYTE,
|
||
ULONG,
|
||
PULong bytes_accepted)
|
||
{
|
||
*bytes_accepted = 0;
|
||
return (PROTOCOL_LAYER_ERROR);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError Multiplexer::DataIndication (
|
||
* LPBYTE buffer_address,
|
||
* ULONG length,
|
||
* PULong bytes_accepted)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function is called by the lower layer when it has data
|
||
* ready for us.
|
||
*/
|
||
ProtocolLayerError Multiplexer::DataIndication (
|
||
LPBYTE buffer_address,
|
||
ULONG length,
|
||
PULong bytes_accepted)
|
||
{
|
||
// TRACE_OUT(("Multiplexer::DataIndication"));
|
||
|
||
BOOL process_packet = TRUE;
|
||
USHORT packet_size;
|
||
|
||
LPBYTE source_address;
|
||
USHORT source_length;
|
||
|
||
LPBYTE dest_address;
|
||
USHORT dest_length;
|
||
PacketFrameError return_value;
|
||
BOOL crc_valid;
|
||
USHORT bytes_processed;
|
||
|
||
|
||
*bytes_accepted = 0;
|
||
|
||
if (Framer == NULL)
|
||
{
|
||
*bytes_accepted = length;
|
||
|
||
/*
|
||
** If the framer does NOT exist, the data is coming to us in packet
|
||
** format
|
||
*/
|
||
if (CRC != NULL)
|
||
{
|
||
crc_valid = CRC -> CheckCRC (buffer_address, length);
|
||
|
||
if (crc_valid == FALSE)
|
||
{
|
||
TRACE_OUT(("MPLEX: Invalid CRC"));
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
length -= CRC_Size;
|
||
}
|
||
|
||
SendDataToHigherLayer (buffer_address, (USHORT) length);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
** A framer exists; the lower layer is giving us the data
|
||
** in a stream fashion
|
||
*/
|
||
Data_Indication_Ready = FALSE;
|
||
|
||
source_address = buffer_address;
|
||
source_length = (USHORT) length;
|
||
|
||
while (process_packet)
|
||
{
|
||
if (Decode_In_Progress)
|
||
{
|
||
dest_length = 0;
|
||
dest_address = NULL;
|
||
}
|
||
else
|
||
{
|
||
dest_address = Data_Indication_Buffer;
|
||
dest_length = Maximum_Packet_Size;
|
||
}
|
||
|
||
/*
|
||
** Pass the data to the framer to decode it.
|
||
*/
|
||
return_value = Framer -> PacketDecode (
|
||
source_address,
|
||
source_length,
|
||
dest_address,
|
||
dest_length,
|
||
&bytes_processed,
|
||
&packet_size,
|
||
Decode_In_Progress);
|
||
|
||
source_address = NULL;
|
||
|
||
switch (return_value)
|
||
{
|
||
case PACKET_FRAME_NO_ERROR:
|
||
/*
|
||
** A complete packet was not found by the decoder
|
||
*/
|
||
Decode_In_Progress = TRUE;
|
||
Data_Indication_Ready = FALSE;
|
||
process_packet = FALSE;
|
||
*bytes_accepted += bytes_processed;
|
||
break;
|
||
|
||
case PACKET_FRAME_PACKET_DECODED:
|
||
/*
|
||
** Complete packet found, check the CRC, and pass it to
|
||
** the higher layer.
|
||
*/
|
||
Decode_In_Progress = FALSE;
|
||
*bytes_accepted += bytes_processed;
|
||
|
||
if (CRC != NULL)
|
||
{
|
||
if (packet_size <= CRC_Size)
|
||
break;
|
||
|
||
crc_valid = CRC -> CheckCRC (
|
||
Data_Indication_Buffer,
|
||
packet_size);
|
||
if (crc_valid == FALSE)
|
||
{
|
||
TRACE_OUT(("MPLEX: Invalid CRC: packet_size = %d", packet_size));
|
||
break;
|
||
}
|
||
packet_size -= CRC_Size;
|
||
}
|
||
|
||
Data_Indication_Ready = TRUE;
|
||
Data_Indication_Length = packet_size;
|
||
|
||
/*
|
||
** Send packet on up
|
||
*/
|
||
PollReceiver();
|
||
break;
|
||
|
||
case PACKET_FRAME_DEST_BUFFER_TOO_SMALL:
|
||
/*
|
||
** The packet received is too big for our buffer.
|
||
** This sometimes occurs if a trailing flag is lost
|
||
** during transmission
|
||
*/
|
||
TRACE_OUT(("PACKET_FRAME_DEST_BUFFER_TOO_SMALL"));
|
||
Decode_In_Progress = FALSE;
|
||
*bytes_accepted += bytes_processed;
|
||
break;
|
||
|
||
case PACKET_FRAME_ILLEGAL_FLAG_FOUND:
|
||
/*
|
||
** The packet received contained an illegal flag.
|
||
*/
|
||
Decode_In_Progress = FALSE;
|
||
*bytes_accepted += bytes_processed;
|
||
break;
|
||
|
||
case PACKET_FRAME_FATAL_ERROR:
|
||
/*
|
||
** Incoming packets do not meet framer requirements.
|
||
** Tell the owner object to break the link
|
||
*/
|
||
m_pT123->OwnerCallback(m_nMsgBase + BROKEN_CONNECTION);
|
||
process_packet = FALSE;
|
||
break;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* void Multiplexer::SendDataToHigherLayer (
|
||
* LPBYTE buffer_address,
|
||
* USHORT length)
|
||
*
|
||
* Functional Description
|
||
* This function is called to send a packet to the higher layer
|
||
*
|
||
* Formal Parameters
|
||
* buffer_address (i) - Buffer address
|
||
* length (i) - Number of bytes in packet
|
||
*
|
||
* Return Value
|
||
* TRUE - The packet was sent to the higher layer
|
||
* FALSE - The packet was NOT sent to the higher layer
|
||
*
|
||
* Side Effects
|
||
* None
|
||
*
|
||
* Caveats
|
||
* None
|
||
*/
|
||
void Multiplexer::SendDataToHigherLayer (
|
||
LPBYTE buffer_address,
|
||
USHORT buffer_length)
|
||
{
|
||
TRACE_OUT(("Multiplexer::SendDataToHigherLayer"));
|
||
|
||
DLCI dlci;
|
||
ProtocolLayerError error;
|
||
IProtocolLayer * q922;
|
||
ULONG bytes_accepted;
|
||
PMPlexStruct lpmpStruct;
|
||
|
||
|
||
/*
|
||
** Find out who the packet is intended for
|
||
*/
|
||
dlci = GetDLCI (buffer_address, buffer_length);
|
||
|
||
if (Q922_Layers.find((DWORD_PTR) dlci, (PDWORD_PTR) &lpmpStruct))
|
||
{
|
||
q922 = lpmpStruct->q922;
|
||
error = q922 -> DataIndication (
|
||
buffer_address,
|
||
buffer_length,
|
||
&bytes_accepted);
|
||
|
||
if (error != PROTOCOL_LAYER_NO_ERROR)
|
||
{
|
||
ERROR_OUT(("Multiplexer: SendDataToHigherLayer: Error occured on data indication to %d", dlci));
|
||
}
|
||
else
|
||
{
|
||
if (bytes_accepted != 0)
|
||
{
|
||
if (bytes_accepted != buffer_length)
|
||
{
|
||
ERROR_OUT((" Multiplexer: SendDataToHigherLayer: Error: "
|
||
"The upper layer thinks he can accept partial packets!!!"));
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
** Packet can NOT be sent up, trash it.
|
||
*/
|
||
WARNING_OUT(("MPLEX: PollReceiver: packet received with illegal DLCI = %d", dlci));
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* DLCI Multiplexer::GetDLCI (
|
||
* LPBYTE buffer_address,
|
||
* USHORT length)
|
||
*
|
||
* Functional Description
|
||
* This function returns the dlci of the packet.
|
||
*
|
||
* Formal Parameters
|
||
* buffer_address (i) - Buffer address
|
||
* length (i) - Number of bytes in packet
|
||
*
|
||
* Return Value
|
||
* dlci
|
||
*
|
||
* Side Effects
|
||
* None
|
||
*
|
||
* Caveats
|
||
* None
|
||
*/
|
||
DLCI Multiplexer::GetDLCI (
|
||
LPBYTE buffer_address,
|
||
USHORT buffer_size)
|
||
{
|
||
DLCI dlci;
|
||
|
||
if (buffer_size < 2)
|
||
return (ILLEGAL_DLCI);
|
||
|
||
dlci = *(buffer_address + ADDRESS_BYTE_HIGH) & 0xfc;
|
||
dlci <<= 2;
|
||
dlci |= ((*(buffer_address + ADDRESS_BYTE_LOW) & 0xf0) >> 4);
|
||
|
||
return (dlci);
|
||
}
|
||
|