|
|
#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_T123PSTN);
/* X224.cpp
* * Copyright (c) 1994 by DataBeam Corporation, Lexington, KY * * Abstract: * * Private Instance Variables: * Default_PDU_Size - Default PDU size, if no arb. is done * Data_Request_Memory_Manager - Memory manager * Lower_Layer_Prepend - Number of bytes prepended to packet by * lower layer * Lower_Layer_Append - Number of bytes appended to packet byt * lower layer * Shutdown_Receiver - TRUE if we aren't to receive any more * packets from the lower layer * Shutdown_Transmitter - TRUE if we aren't to transmit any more * packets * Data_Request_Queue - Queue that keeps the pending user data * requests * Data_Indication_Queue - Queue that holds the pending user data * indications * Data_Indication_Memory_Pool - List that holds available data * indication buffers. * * Active_Data_Indication - Address of packet structure. This * packet holds the current data indication * that we are reassembling * m_pT123 - Address of owner object. Used for * callbacks * m_pQ922 - Address of lower layer. * m_nMsgBase - Message base to be used for owner * callbacks * Maximum_PDU_Size - Max. PDU size * Arbitrated_PDU_Size - Max. arbitrated packet size. * Identifier - Identifier passed to lower layer to * register ourselves. * Data_Indication_Queue_Size - Number of data indications we will * buffer * Data_Indication_Reassembly_Active - Flag set if we are in the middle * of a packet reassembly. * State - Holds the current state of the object * Packet_Pending - Tells which packet will be sent next. * Reject_Cause - The reason why the error packet was sent * Packet_Size_Respond - Set to TRUE if we are to send a TPDU * size element in the CC packet * Error_Buffer - Address of error buffer. * Error_Buffer_Length - Length of error buffer. * * m_nLocalLogicalHandle - Local transport connection id. * m_nRemoteLogicalHandle - Remote transport connection id. * User_Data_Pending - Set to the size of the last packet that * the user attempted to pass to us, that * we couldn't accept because we ran out * of memory. * * Caveats: * None. * * Authors: * James W. Lawwill */
#include <windowsx.h>
#include "x224.h"
/*
* CLayerX224::CLayerX224 ( * PTransportResources transport_resources, * IObject * owner_object, * IProtocolLayer * lower_layer, * USHORT message_base, * USHORT logical_handle, * USHORT identifier, * USHORT data_indication_queue_size, * USHORT default_PDU_size, * PMemoryManager dr_memory_manager, * BOOL * initialization_success) * * Public * * Functional Description: * This is the Transport constructor. This routine initializes all * variables and allocates the buffers needed to operate. */ CLayerX224::CLayerX224 ( T123 *owner_object, CLayerQ922 *pQ922, // lower layer
USHORT message_base, LogicalHandle logical_handle, ULONG identifier, USHORT data_indication_queue_size, USHORT default_PDU_size, PMemoryManager dr_memory_manager, BOOL *initialization_success ) : m_pT123(owner_object), m_nMsgBase(message_base), m_pQ922(pQ922) { TRACE_OUT(("CLayerX224::CLayerX224"));
ProtocolLayerError error;
m_nLocalLogicalHandle = logical_handle; Identifier = identifier; Default_PDU_Size = default_PDU_size; Data_Request_Memory_Manager = dr_memory_manager; *initialization_success = TRUE;
Shutdown_Receiver = FALSE; Shutdown_Transmitter = FALSE; Reject_Cause = 0;
/*
** Find the maximum packet size */ m_pQ922->GetParameters( &Maximum_PDU_Size, &Lower_Layer_Prepend, &Lower_Layer_Append);
Arbitrated_PDU_Size = Default_PDU_Size;
/*
** Figure out what our largest PDU could be. We will use this value to ** arbitrate the maximum PDU size. */ Maximum_PDU_Size = (USHORT)GetMaxTPDUSize (Maximum_PDU_Size);
/*
** Register with the lower layer, so we can send and receive packets. */ error = m_pQ922->RegisterHigherLayer( identifier, Data_Request_Memory_Manager, (IProtocolLayer *) this);
if (error != PROTOCOL_LAYER_NO_ERROR) { ERROR_OUT(("X224: constructor: Error registering with lower layer")); *initialization_success = FALSE; }
/*
** Prepare for buffer allocation */ Data_Indication_Queue_Size = data_indication_queue_size; Error_Buffer = NULL;
/*
** Set member variables appropriately */ Active_Data_Indication = NULL; Data_Indication_Reassembly_Active = FALSE; Packet_Pending = TRANSPORT_NO_PACKET; User_Data_Pending = 0;
m_nRemoteLogicalHandle = 0; Packet_Size_Respond = FALSE;
if (*initialization_success == FALSE) State = FAILED_TO_INITIALIZE; else State = NO_CONNECTION; }
/*
* CLayerX224::~CLayerX224 (void) * * Public * * Functional Description: * This is the Transport destructor. This routine cleans up everything. */ CLayerX224::~CLayerX224(void) { TRACE_OUT(("CLayerX224::~CLayerX224"));
PMemory lpMemory; PTMemory lptMem; /*
** Notify the lower layer that we are terminating */ m_pQ922->RemoveHigherLayer(Identifier);
/*
** Go thru the data request queue and delete the structures held in the ** queue. */ Data_Request_Queue.reset(); while (Data_Request_Queue.iterate ((PDWORD_PTR) &lpMemory)) { Data_Request_Memory_Manager-> FreeMemory (lpMemory); }
/*
** Go thru the data indication queue and delete the structures held in the ** queue. */ Data_Indication_Queue.reset(); while (Data_Indication_Queue.iterate ((PDWORD_PTR) &lptMem)) delete lptMem;
/*
** Go thru the data request free structure pool and delete the structures ** held in the pool. */ Data_Indication_Memory_Pool.reset(); while (Data_Indication_Memory_Pool.iterate ((PDWORD_PTR) &lptMem)) delete lptMem;
/*
** If there is a data indication active, delete that structure. */ delete Active_Data_Indication;
/*
** If the error buffer holds a packet, delete it */ delete [] Error_Buffer;
return; }
/*
* TransportError CLayerX224::ConnectRequest (void) * * Public * * Functional Description: * This function initiates a connect request. */ TransportError CLayerX224::ConnectRequest (void) { TRACE_OUT(("CLayerX224::ConnectRequest"));
if (State != NO_CONNECTION) { ERROR_OUT(("Transport: Illegal ConnectRequest packet")); return (TRANSPORT_CONNECT_REQUEST_FAILED); }
Packet_Pending = CONNECTION_REQUEST_PACKET; return (TRANSPORT_NO_ERROR); }
/*
* TransportError CLayerX224::ShutdownReceiver (void) * * Public * * Functional Description: * This function stops us from receiving any more packets from the lower * layer */ void CLayerX224::ShutdownReceiver (void) { TRACE_OUT(("CLayerX224::ShutdownReceiver"));
Shutdown_Receiver = TRUE; }
/*
* TransportError CLayerX224::EnableReceiver (void) * * Public * * Functional Description: * This function permits us to send packets to the user application. */ void CLayerX224::EnableReceiver (void) { TRACE_OUT(("CLayerX224::EnableReceiver"));
Shutdown_Receiver = FALSE; }
/*
* TransportError CLayerX224::ShutdownTransmitter (void) * * Public * * Functional Description: * This function keeps us from transmitting any more packets */ void CLayerX224::ShutdownTransmitter (void) { TRACE_OUT(("CLayerX224::ShutdownTransmitter"));
Shutdown_Transmitter = TRUE; }
/*
* TransportError CLayerX224::PurgeRequest (void) * * Public * * Functional Description: * This function removes all packets from out output queue that aren't * active */ void CLayerX224::PurgeRequest (void) { TRACE_OUT(("CLayerX224::PurgeRequest"));
DWORD entries; DWORD keep_counter = 0; PMemory memory; LPBYTE packet_address; DWORD i;
if (Data_Request_Queue.isEmpty() == FALSE) { entries = Data_Request_Queue.entries ();
/*
** Go thru packets looking for the last PDU in the SDU */ Data_Request_Queue.reset(); while (Data_Request_Queue.iterate ((PDWORD_PTR) &memory)) { keep_counter++; packet_address = memory -> GetPointer (); if (*(packet_address + 2) == EOT_BIT) break; }
TRACE_OUT(("PurgeRequest: Removing %d packets", entries-keep_counter)); for (i=keep_counter; i<entries; i++) { Data_Request_Memory_Manager->FreeMemory ((PMemory) Data_Request_Queue.removeLast ()); } } return; }
/*
* TransportError CLayerX224::ConnectResponse (void) * * Public * * Functional Description: * This function initiates a connect response. */ TransportError CLayerX224::ConnectResponse (void) { TRACE_OUT(("CLayerX224::ConnectResponse"));
if (State != RECEIVED_CONNECT_REQUEST_PACKET) { ERROR_OUT(("Transport: Illegal ConnectResponse packet")); return (TRANSPORT_CONNECT_RESPONSE_FAILED); }
Packet_Pending = CONNECTION_CONFIRM_PACKET; return (TRANSPORT_NO_ERROR); }
/*
* TransportError CLayerX224::DisconnectRequest (void) * * Public * * Functional Description: * This function initiates a disconnect request. */ TransportError CLayerX224::DisconnectRequest (void) { TRACE_OUT(("CLayerX224::DisconnectRequest"));
if (State == SENT_CONNECT_REQUEST_PACKET) { /*
** The connection is being rejected, send out the DISCONNECT ** packet and wait for termination */ Packet_Pending = DISCONNECT_REQUEST_PACKET; } else { /*
** Normal disconnects don't send any notification to the remote site. ** It depends on the Network layer to terminate the link. */ m_pQ922->RemoveHigherLayer(Identifier);
m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); }
return (TRANSPORT_NO_ERROR); }
/*
* TransportError CLayerX224::DataIndication ( * LPBYTE packet_address, * ULONG buffer_size, * PULong packet_length) * * Public * * Functional Description: * This function is called by the lower layer when it has a packet for us. */ ProtocolLayerError CLayerX224::DataIndication ( LPBYTE packet_address, ULONG packet_length, PULong bytes_accepted) { TRACE_OUT(("CLayerX224::DataIndication"));
ULONG remainder_length; USHORT class_request; USHORT packet_type; USHORT length; USHORT destination_reference; LegacyTransportData transport_data; BOOL packet_accepted; ULONG user_accepted; UChar eot; PTMemory packet; TMemoryError packet_error; LPBYTE temp_address; BOOL use_default_PDU_size;
*bytes_accepted = 0; packet_accepted = FALSE;
/*
** If the receiver is shutdown, don't accept any data */ if (Shutdown_Receiver) return (PROTOCOL_LAYER_NO_ERROR);
/*
** The packet must be at least 2 bytes long */ if (packet_length < 2) { ERROR_OUT(("X224: DataIndication: Invalid packet received from lower layer: length = %d", packet_length)); return (PROTOCOL_LAYER_NO_ERROR); }
remainder_length = packet_length; temp_address = packet_address; packet_address++; packet_type = *(packet_address++) & TPDU_CODE_MASK; remainder_length -= 2;
switch (packet_type) { case CONNECTION_REQUEST_PACKET: packet_accepted = TRUE;
/*
** There should be at least 5 bytes remaining in this packet */ if (remainder_length < 5) { ERROR_OUT(("X224: DataIndication: CR: Invalid packet received from lower layer: length = %d", packet_length)); break; }
/*
** Increment the packet address by 2 to get past the DST_REF */ packet_address += 2; m_nRemoteLogicalHandle = *(packet_address++); m_nRemoteLogicalHandle <<= 8; m_nRemoteLogicalHandle |= *(packet_address++); remainder_length -= 4;
/*
** Look at the class request to make sure it is 0 */ class_request = *(packet_address++) >> 4; remainder_length -= 1; if (class_request != 0) { ERROR_OUT(("X224: DataIndication: CR packet: Illegal class request")); ErrorPacket ( temp_address, (USHORT) (packet_length - remainder_length)); break; } use_default_PDU_size = TRUE;
while (remainder_length != 0) { switch (*(packet_address++)) { case TPDU_SIZE: length = *(packet_address++); remainder_length -= 1; if (length != 1) { TRACE_OUT(("X224: DataIndication: CR packet: Illegal TPDU_Size length"));
ErrorPacket ( temp_address, (USHORT) (packet_length - remainder_length)); break; }
/*
** Figure out the actual PDU size */ Arbitrated_PDU_Size = (1 << *(packet_address++)); remainder_length -= 1; TRACE_OUT(("X224: CR_Packet: Packet size = %d", Arbitrated_PDU_Size)); if (Arbitrated_PDU_Size > Maximum_PDU_Size) { Packet_Size_Respond = TRUE; Arbitrated_PDU_Size = Maximum_PDU_Size; } if (AllocateBuffers() == FALSE) { m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); } use_default_PDU_size = FALSE; break;
default: ERROR_OUT(("X224: DataIndication: CR packet Unsupported parameter 0x%x", *(packet_address - 1))); length = *(packet_address++); remainder_length--;
packet_address += length; remainder_length -= length; break; } remainder_length--; }
/*
** If the initiator wants to use the default PDU size, we need to ** check the default size with the Max. size to make sure it is ** valid for us. */ if (use_default_PDU_size) { if (Default_PDU_Size > Maximum_PDU_Size) { Packet_Size_Respond = TRUE; Arbitrated_PDU_Size = Maximum_PDU_Size; } if (AllocateBuffers() == FALSE) { m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); } }
State = RECEIVED_CONNECT_REQUEST_PACKET;
/*
** Notify the owner that the remote site wants to start a ** connection */ m_pT123->OwnerCallback(m_nMsgBase + TPRT_CONNECT_INDICATION, (void *) m_nLocalLogicalHandle); TRACE_OUT(("X224: DataInd: ConnectRequest: max pkt = %d", Arbitrated_PDU_Size)); break;
case CONNECTION_CONFIRM_PACKET: packet_accepted = TRUE;
/*
** There should be at least 5 bytes remaining in this packet */ if (remainder_length < 5) { ERROR_OUT(("X224: DataIndication: CC: Invalid packet received from lower layer: length = %d", packet_length)); break; }
destination_reference = *(packet_address++); destination_reference <<= 8; destination_reference |= *(packet_address++); remainder_length -= 2; if (destination_reference != m_nLocalLogicalHandle) { ERROR_OUT(("X224: DataIndication: CC packet: DST-REF incorrect")); ErrorPacket ( temp_address, (USHORT) (packet_length - remainder_length)); break; }
m_nRemoteLogicalHandle = *(packet_address++); m_nRemoteLogicalHandle <<= 8; m_nRemoteLogicalHandle |= *(packet_address++);
class_request = *(packet_address++) >> 4; remainder_length -= 3; if (class_request != 0) { ERROR_OUT(("X224: DataIndication: CR packet: Illegal class request")); ErrorPacket ( temp_address, (USHORT) (packet_length - remainder_length)); break; } use_default_PDU_size = TRUE;
while (remainder_length != 0) { switch (*(packet_address++)) { case TPDU_SIZE: length = *(packet_address++); remainder_length -= 1; if (length != 1) { ERROR_OUT(("X224: DataIndication: CR packet: Illegal TPDU_Size length"));
ErrorPacket ( temp_address, (USHORT) (packet_length - remainder_length)); } Arbitrated_PDU_Size = (1 << *(packet_address++)); remainder_length -= 1; TRACE_OUT(("X224: CC_Packet: Packet size = %d", Arbitrated_PDU_Size)); use_default_PDU_size = FALSE;
/*
** Allocate the buffers */ if (AllocateBuffers() == FALSE) { m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); } break;
default: ERROR_OUT(("X224: DataIndication: CC packet Unsupported parameter")); length = *(packet_address++); remainder_length--;
packet_address += length; remainder_length -= length; break; } remainder_length--; } if (use_default_PDU_size) { if (AllocateBuffers () == FALSE) { m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); } }
State = CONNECTION_ACTIVE;
/*
** Notify the owner that the connect request has been confirmed */ m_pT123->OwnerCallback(m_nMsgBase + TPRT_CONNECT_CONFIRM, (void *) m_nLocalLogicalHandle); TRACE_OUT(("X224: DataInd: ConnectConfirm max pkt = %d", Arbitrated_PDU_Size)); break;
case DISCONNECT_REQUEST_PACKET: TRACE_OUT(("X224: DataIndication: Disconnect req. received"));
/*
** Notify the owner that a disconnect has been requested. This ** message is only valid during establishment of the connection. */ m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); packet_accepted = TRUE; break;
case ERROR_PACKET: TRACE_OUT(("X224: DataIndication: ERROR REQUEST received"));
/*
** Notify the owner that the remote site has detected an error in ** one of our packets. */ m_pT123->OwnerCallback(m_nMsgBase + TPRT_DISCONNECT_INDICATION, (void *) m_nLocalLogicalHandle); packet_accepted = TRUE; break;
case DATA_PACKET: if ((Data_Indication_Reassembly_Active == FALSE) && Data_Indication_Memory_Pool.isEmpty()) { break; }
packet_accepted = TRUE;
/*
** There should be at least 1 bytes remaining in this packet */ if (remainder_length < 1) { ERROR_OUT(("X224: DataIndication: DATA: Invalid packet " "received from lower layer: length = %d", packet_length)); break; }
eot = *(packet_address++); remainder_length--;
/*
** The EOT_BIT is set if this is the last TPDU of the TSDU */ if ((eot & EOT_BIT) == EOT_BIT) { if (Data_Indication_Reassembly_Active == FALSE) { /*
** If the remote site has passed us an empty packet, ** just return */ if (remainder_length == 0) break;
/*
** If this is a single packet and there aren't any ** other packets preceeding it, try to send it to the ** user without copying it into our own buffers */ if (Data_Indication_Queue.isEmpty()) { transport_data.logical_handle = m_nLocalLogicalHandle; transport_data.pbData = packet_address; transport_data.cbDataSize = remainder_length;
/*
** Issue the user callback to give the user the data. */ user_accepted = ::NotifyT120(TRANSPORT_DATA_INDICATION, &transport_data);
/*
** If the user appliction does NOT accept the packet ** shutdown the receiver and wait for the user ** to re-enable it. */ if (user_accepted == TRANSPORT_NO_ERROR) break; else Shutdown_Receiver = TRUE; }
/*
** Put the packet into the DataIndication queue */ packet = (PTMemory) Data_Indication_Memory_Pool.get (); packet_error = packet->Append (packet_address, remainder_length); switch (packet_error) { case TMEMORY_NO_ERROR: Data_Indication_Queue.append ((DWORD_PTR) packet); break;
case TMEMORY_NONFATAL_ERROR: case TMEMORY_FATAL_ERROR: packet_accepted = FALSE; break; } } else { /*
** Add this PDU to the currently active SDU */ packet_error = Active_Data_Indication -> Append ( packet_address, remainder_length);
switch (packet_error) { case TMEMORY_NO_ERROR: Data_Indication_Reassembly_Active = FALSE; Data_Indication_Queue.append ((DWORD_PTR) Active_Data_Indication); Active_Data_Indication = NULL;
/*
** Call PollReceiver (), it will attempt to pass ** the packet on up to the user. */ PollReceiver(); break;
case TMEMORY_NONFATAL_ERROR: case TMEMORY_FATAL_ERROR: packet_accepted = FALSE; break; } } } else { /*
** If the remote site is passing us a zero-length packet, ** just return */ if (remainder_length == 0) break;
/*
** This is NOT the last packet in the incoming SDU, copy it ** into the data indication buffer and wait for the next packet */ if (Data_Indication_Reassembly_Active == FALSE) { Data_Indication_Reassembly_Active = TRUE; Active_Data_Indication = (PTMemory) Data_Indication_Memory_Pool.get (); }
packet_error = Active_Data_Indication -> Append ( packet_address, remainder_length); switch (packet_error) { case TMEMORY_NO_ERROR: break;
case TMEMORY_NONFATAL_ERROR: case TMEMORY_FATAL_ERROR: packet_accepted = FALSE; break; } } break;
default: ERROR_OUT(("X224: Illegal packet")); break; }
if (packet_accepted) *bytes_accepted = packet_length;
return (PROTOCOL_LAYER_NO_ERROR); }
/*
* ProtocolLayerError CLayerX224::PollTransmitter ( * ULONG, * USHORT, * USHORT * pending_data, * USHORT *) * * Public * * Functional Description: * This function is called periodically to give X224 a chance to transmit * data. */ ProtocolLayerError CLayerX224::PollTransmitter ( ULONG_PTR, USHORT, USHORT * pending_data, USHORT *) { // TRACE_OUT(("CLayerX224::PollTransmitter"));
LPBYTE packet_address; ULONG bytes_accepted; USHORT counter; USHORT packet_size; ULONG total_length; USHORT packet_length; PMemory memory; BOOL continue_loop = TRUE;
while (continue_loop) { switch (Packet_Pending) { case CONNECTION_REQUEST_PACKET: /*
** Add up the packet length, don't forget the 1 byte ** for the Length Indicator */ total_length = CONNECT_REQUEST_HEADER_SIZE + TPDU_ARBITRATION_PACKET_SIZE + 1 + Lower_Layer_Prepend + Lower_Layer_Append;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) { continue_loop = FALSE; break; }
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = CONNECT_REQUEST_HEADER_SIZE + TPDU_ARBITRATION_PACKET_SIZE; *(packet_address++) = CONNECTION_REQUEST_PACKET;
/*
** The following 2 bytes are the destination reference */ *(packet_address++) = 0; *(packet_address++) = 0; *(packet_address++) = (BYTE)(m_nLocalLogicalHandle >> 8); *(packet_address++) = (BYTE)(m_nLocalLogicalHandle & 0xff);
/*
** The following byte is the Class/Options */ *(packet_address++) = 0;
/*
** Add TPDU arbitration data */ *(packet_address++) = TPDU_SIZE; *(packet_address++) = 1;
/*
** Code our maximum PDU size into the X224 scheme */ Arbitrated_PDU_Size = Maximum_PDU_Size; packet_size = Arbitrated_PDU_Size; counter = 0; while (packet_size > 1) { packet_size >>= 1; counter++; } *(packet_address++) = (unsigned char) counter;
/*
** Attempt to send the packet to the lower layer */ m_pQ922->DataRequest(Identifier, memory, &bytes_accepted);
/*
** We assume that the lower layer has a packet input ** interface, if it does not, there has been a major error. */ if (bytes_accepted == total_length) { Packet_Pending = TRANSPORT_NO_PACKET; State = SENT_CONNECT_REQUEST_PACKET; } else continue_loop = FALSE;
Data_Request_Memory_Manager -> FreeMemory (memory); break;
case CONNECTION_CONFIRM_PACKET: packet_length = CONNECT_CONFIRM_HEADER_SIZE; if (Packet_Size_Respond) packet_length += TPDU_ARBITRATION_PACKET_SIZE;
total_length = packet_length + 1 + Lower_Layer_Prepend + Lower_Layer_Append;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) { continue_loop = FALSE; break; }
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
/*
** Build the packet */ *(packet_address++) = (UChar) packet_length; *(packet_address++) = CONNECTION_CONFIRM_PACKET; *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle >> 8); *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle & 0xff); *(packet_address++) = (BYTE)(m_nLocalLogicalHandle >> 8); *(packet_address++) = (BYTE)(m_nLocalLogicalHandle & 0xff);
/*
** Set the Class/Options to 0 */ *(packet_address++) = 0;
/*
** Packet_Size_Respond is TRUE if we are suppose to respond ** to the TPDU element in the Connect Request packet */ if (Packet_Size_Respond) { /*
** Add TPDU arbitration data */ *(packet_address++) = TPDU_SIZE; *(packet_address++) = 1; packet_size = Arbitrated_PDU_Size; counter = 0; while (packet_size > 1) { packet_size >>= 1; counter++; } *(packet_address++) = (unsigned char) counter; }
/*
** Attempt to send the packet to the lower layer */ m_pQ922->DataRequest(Identifier, memory, &bytes_accepted);
if (bytes_accepted == total_length) { Packet_Pending = TRANSPORT_NO_PACKET; State = CONNECTION_ACTIVE; } else continue_loop = FALSE; Data_Request_Memory_Manager -> FreeMemory (memory); break;
case DISCONNECT_REQUEST_PACKET: /*
** Add 1 to the length for the Length Indicator */ total_length = DISCONNECT_REQUEST_HEADER_SIZE + 1 + Lower_Layer_Prepend + Lower_Layer_Append;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) { continue_loop = FALSE; break; }
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
TRACE_OUT(("X224: Sending Disconnect Request Packet")); *(packet_address++) = DISCONNECT_REQUEST_HEADER_SIZE; *(packet_address++) = DISCONNECT_REQUEST_PACKET; *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle >> 8); *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle & 0xff);
/*
** Set the source reference to 0, this packet will only ** be sent as a refusal to a Connect Request, therefore ** this value should be 0 */ *(packet_address++) = 0; *(packet_address++) = 0; *(packet_address++) = DISCONNECT_REASON_NOT_SPECIFIED;
/*
** Attempt to send packet to lower layer */ m_pQ922->DataRequest(Identifier, memory, &bytes_accepted);
if (bytes_accepted == total_length) { Packet_Pending = TRANSPORT_NO_PACKET; State = SENT_DISCONNECT_REQUEST_PACKET; } continue_loop = FALSE; Data_Request_Memory_Manager -> FreeMemory (memory); break;
case ERROR_PACKET: TRACE_OUT(("X224: Sending Error Packet")); total_length = ERROR_HEADER_SIZE + Error_Buffer_Length + 1 + 2 + Lower_Layer_Prepend + Lower_Layer_Append;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) { continue_loop = FALSE; break; }
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = ERROR_HEADER_SIZE + Error_Buffer_Length; *(packet_address++) = ERROR_PACKET; *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle >> 8); *(packet_address++) = (BYTE)(m_nRemoteLogicalHandle & 0xff); *(packet_address++) = Reject_Cause;
*(packet_address++) = INVALID_TPDU; *(packet_address++) = (UChar) Error_Buffer_Length; memcpy (packet_address, Error_Buffer, Error_Buffer_Length);
/*
** Attempt to send packet to lower layer */ m_pQ922->DataRequest(Identifier, memory, &bytes_accepted);
if (bytes_accepted == total_length) { delete [] Error_Buffer; Error_Buffer = NULL;
Packet_Pending = TRANSPORT_NO_PACKET; State = SENT_CONNECT_REQUEST_PACKET; } else continue_loop = FALSE; Data_Request_Memory_Manager -> FreeMemory (memory); break;
case TRANSPORT_NO_PACKET: if (Data_Request_Queue.isEmpty() == FALSE) { /*
** Get the next packet from the queue */ memory = (PMemory) Data_Request_Queue.read (); total_length = memory -> GetLength ();
m_pQ922->DataRequest(Identifier, memory, &bytes_accepted);
if (bytes_accepted == total_length) { Data_Request_Queue.get (); Data_Request_Memory_Manager -> FreeMemory (memory); } else continue_loop = FALSE; } else continue_loop = FALSE; break; } }
if (Data_Request_Queue.isEmpty()) *pending_data = 0; else *pending_data = PROTOCOL_USER_DATA;
return (PROTOCOL_LAYER_NO_ERROR); }
/*
* TransportError CLayerX224::DataRequest ( * ULONG, * LPBYTE packet_address, * USHORT packet_length, * USHORT * bytes_accepted) * * Public * * Functional Description: * This function takes a packet from the user and queues it for * transmission. */ ProtocolLayerError CLayerX224::DataRequest ( ULONG_PTR, LPBYTE packet_address, ULONG packet_length, PULong bytes_accepted) { TRACE_OUT(("CLayerX224::DataRequest"));
ULONG total_packet_size; ULONG packet_size; DataRequestQueue temporary_queue; PMemory memory; BOOL packet_failed = FALSE; LPBYTE address;
*bytes_accepted = 0;
if (Shutdown_Transmitter) return (PROTOCOL_LAYER_NO_ERROR);
total_packet_size = packet_length;
/*
** Create enough PDUs to hold the packet. We don't actually copy the ** packet into the new buffers until we know that we can get enough ** space. */ while (total_packet_size != 0) { if (total_packet_size > (ULONG) (Arbitrated_PDU_Size - DATA_PACKET_HEADER_SIZE)) { packet_size = Arbitrated_PDU_Size - DATA_PACKET_HEADER_SIZE; } else packet_size = total_packet_size;
total_packet_size -= packet_size;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, packet_size + DATA_PACKET_HEADER_SIZE + Lower_Layer_Prepend + Lower_Layer_Append); if (memory == NULL) { packet_failed = TRUE; break; }
temporary_queue.append ((DWORD_PTR) memory); }
/*
** If we were unable to allocate memory for the packet, release the memory ** that we did allocate. */ if (packet_failed) { temporary_queue.reset(); while (temporary_queue.iterate ((PDWORD_PTR) &memory)) { Data_Request_Memory_Manager->FreeMemory (memory); }
/*
** Set the User_Data_Pending flag to the packet_length so we can ** notify the user when buffer space is available. */ User_Data_Pending = packet_length; } else { User_Data_Pending = 0;
total_packet_size = packet_length;
/*
** Go thru each of the PDUs and actually create them. */ temporary_queue.reset(); while (temporary_queue.iterate ((PDWORD_PTR) &memory)) { if (total_packet_size > (ULONG) (Arbitrated_PDU_Size - DATA_PACKET_HEADER_SIZE)) { packet_size = Arbitrated_PDU_Size - DATA_PACKET_HEADER_SIZE; } else packet_size = total_packet_size;
address = memory -> GetPointer ();
memcpy ( address + DATA_PACKET_HEADER_SIZE + Lower_Layer_Prepend, packet_address + (USHORT) (packet_length - total_packet_size), packet_size);
total_packet_size -= packet_size;
/*
** This is the header for a data packet */ address += Lower_Layer_Prepend; *address = 2; *(address + 1) = DATA_PACKET; if (total_packet_size == 0) *(address + 2) = EOT_BIT; else *(address + 2) = 0;
/*
** Load the memory object into the queue */ Data_Request_Queue.append ((DWORD_PTR) memory); } *bytes_accepted = packet_length; }
return (PROTOCOL_LAYER_NO_ERROR); }
/*
* ProtocolLayerError CLayerX224::DataRequest ( * ULONG, * PMemory, * USHORT * bytes_accepted) * * Public * * Functional Description: * This function takes a packet from the user and queues it for * transmission. */ ProtocolLayerError CLayerX224::DataRequest ( ULONG_PTR, PMemory, PULong bytes_accepted) { *bytes_accepted = 0;
return (PROTOCOL_LAYER_ERROR); }
/*
* ProtocolLayerError CLayerX224::PollReceiver ( * ULONG) * * Public * * Functional Description: * This function should be called periodically to allow us to send received * packets to the user. */ ProtocolLayerError CLayerX224::PollReceiver(void) { // TRACE_OUT(("CLayerX224::PollReceiver"));
LegacyTransportData transport_data; ULONG packet_accepted; PTMemory packet; HPUChar packet_address; ULONG packet_length;
if (Shutdown_Receiver) return (PROTOCOL_LAYER_NO_ERROR);
/*
** If I have any packets in my receive buffers that ** need to go to higher layers, do it now */ while (Data_Indication_Queue.isEmpty () == FALSE) { packet = (PTMemory) Data_Indication_Queue.read (); packet -> GetMemory ( &packet_address, &packet_length); transport_data.logical_handle = m_nLocalLogicalHandle; transport_data.pbData = (LPBYTE) packet_address; transport_data.cbDataSize = packet_length;
packet_accepted = ::NotifyT120(TRANSPORT_DATA_INDICATION, &transport_data);
/*
** If the user returns anything but TRANSPORT_NO_ERROR, it could not ** accept the packet. We will try to send the packet again later. */ if (packet_accepted == TRANSPORT_NO_ERROR) { Data_Indication_Queue.get (); packet -> Reset (); Data_Indication_Memory_Pool.append ((DWORD_PTR) packet); } else { /*
** If the user appliction does NOT accept the packet ** shutdown the receiver and wait for the user to re-enable it. */ Shutdown_Receiver = TRUE; break; } }
return (PROTOCOL_LAYER_NO_ERROR); }
/*
* ProtocolLayerError CLayerX224::GetParameters ( * ULONG, * USHORT * packet_size) * * Public * * Functional Description: * This function returns the maximum allowable TSDU. */ ProtocolLayerError CLayerX224::GetParameters ( USHORT *, USHORT *, USHORT *) { return (PROTOCOL_LAYER_NO_ERROR); }
/*
* ProtocolLayerError CLayerX224::RegisterHigherLayer ( * ULONG, * PMemoryManager, * IProtocolLayer *) * * Public * * Functional Description: * This function does nothing. The only reason it is here is because this * class inherits from ProtocolLayer and this function is pure virtual in * that class. */ ProtocolLayerError CLayerX224::RegisterHigherLayer ( ULONG_PTR, PMemoryManager, IProtocolLayer *) { return (PROTOCOL_LAYER_REGISTRATION_ERROR); }
/*
* ProtocolLayerError CLayerX224::RemoveHigherLayer ( * ULONG) * * Public * * Functional Description: * This function does nothing. The only reason it is here is because this * class inherits from ProtocolLayer and this function is pure virtual in * that class. */ ProtocolLayerError CLayerX224::RemoveHigherLayer ( ULONG_PTR) { return (PROTOCOL_LAYER_REGISTRATION_ERROR); }
/*
* BOOL CLayerX224::AllocateBuffers () * * Functional Description * This function allocates the data request and data indication buffers. * and sets up the memory pools necessary. It also sets up the Control * buffer for control packets. * * Formal Parameters * None * * Return Value * None. * * Side Effects * None * * Caveats * None */ BOOL CLayerX224::AllocateBuffers () { TRACE_OUT(("CLayerX224::AllocateBuffers"));
PTMemory packet; USHORT i; ULONG total_packet_size; TMemoryError error;
total_packet_size = MAXIMUM_USER_DATA_SIZE; for (i=0; i<Data_Indication_Queue_Size; i++) { DBG_SAVE_FILE_LINE packet = new TMemory ( total_packet_size, 0, &error);
if (error == TMEMORY_NO_ERROR) Data_Indication_Memory_Pool.append ((DWORD_PTR) packet); else { delete packet; return (FALSE); } }
return (TRUE); }
/*
* void CLayerX224::ErrorPacket ( * LPBYTE packet_address, * USHORT packet_length) * * Functional Description * This function stores the packet into our own error buffer and prepares * to send it out * * Formal Parameters * None * * Return Value * None. * * Side Effects * None * * Caveats * None */ void CLayerX224::ErrorPacket ( LPBYTE packet_address, USHORT packet_length) { TRACE_OUT(("CLayerX224::ErrorPacket"));
DBG_SAVE_FILE_LINE Error_Buffer = new BYTE[packet_length]; if (NULL != Error_Buffer) { Error_Buffer_Length = packet_length;
memcpy (Error_Buffer, packet_address, packet_length);
Packet_Pending = ERROR_PACKET; } }
/*
* void CLayerX224::CheckUserBuffers () * * Public * * Functional Description: * This function issues TRANSPORT_BUFFER_AVAILABLE_INDICATIONs to the * user if available. */ void CLayerX224::CheckUserBuffers () { // TRACE_OUT(("CLayerX224::CheckUserBuffers"));
ULONG user_data_size; ULONG buffer_size; ULONG full_size_buffers_needed; ULONG full_size_buffer_count; ULONG partial_buffer_size; ULONG partial_buffer_count;
if (User_Data_Pending == 0) return;
/*
** Determine the user data size in a packet, then determine ** how many buffers will be needed to accept that packet. */ user_data_size = Arbitrated_PDU_Size - DATA_PACKET_HEADER_SIZE; full_size_buffers_needed = User_Data_Pending / user_data_size;
/*
** Find out how many full size buffers are available */ if (full_size_buffers_needed != 0) { /*
** Increment full_size_buffers_needed to account for our priority ** value. */ buffer_size = Arbitrated_PDU_Size + Lower_Layer_Prepend + Lower_Layer_Append;
full_size_buffer_count = Data_Request_Memory_Manager -> GetBufferCount (buffer_size); if (full_size_buffer_count < full_size_buffers_needed) return; }
partial_buffer_size = User_Data_Pending % user_data_size; if (partial_buffer_size != 0) { if ((full_size_buffers_needed == 0) || (full_size_buffer_count == full_size_buffers_needed)) { buffer_size = partial_buffer_size + DATA_PACKET_HEADER_SIZE + Lower_Layer_Prepend + Lower_Layer_Append;
partial_buffer_count = Data_Request_Memory_Manager -> GetBufferCount (buffer_size);
if (full_size_buffers_needed == 0) { if (partial_buffer_count == 0) return; } else { if ((partial_buffer_count == full_size_buffer_count) || (partial_buffer_count == 0)) { return; } } } }
User_Data_Pending = 0;
::NotifyT120(TRANSPORT_BUFFER_EMPTY_INDICATION, (void *) m_nLocalLogicalHandle);
return; }
/*
* static ULONG CLayerX224::GetMaxTPDUSize ( * ULONG max_lower_layer_pdu) * * Public * * Functional Description: * This function accepts a value for the lower layer max. PDU size * and returns the max. PDU size that this Transport can support * based on it. X224 only suports max PDU sizes of 128, 256, 512, * 1024, and 2048. So, if the max_lower_layer_pdu is 260, the * Transport can only have a max pdu size of 256. */ ULONG CLayerX224::GetMaxTPDUSize ( ULONG max_lower_layer_pdu) { TRACE_OUT(("CLayerX224::GetMaxTPDUSize"));
ULONG max_tpdu_size;
if (max_lower_layer_pdu < 256) max_tpdu_size = 128; else if (max_lower_layer_pdu < 512) max_tpdu_size = 256; else if (max_lower_layer_pdu < 1024) max_tpdu_size = 512; else if (max_lower_layer_pdu < 2048) max_tpdu_size = 1024; else max_tpdu_size = 2048;
return (max_tpdu_size); }
|