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);
|
|||
|
}
|
|||
|
|