1004 lines
30 KiB
C++
1004 lines
30 KiB
C++
#include "precomp.h"
|
||
DEBUG_FILEZONE(ZONE_T120_T123PSTN);
|
||
|
||
/* SCF.cpp
|
||
*
|
||
* Copyright (c) 1994-1995 by DataBeam Corporation, Lexington, KY
|
||
*
|
||
* Abstract:
|
||
* This is the implementation file for the CLayerSCF class
|
||
*
|
||
* Private Instance Variables:
|
||
* Remote_Call_Reference - List of active SCFCalls initiated by the
|
||
* remote site
|
||
* Call_Reference - List of active SCFCalls initiated locally
|
||
* DLCI_List - This list matches DLCIs to SCFCalls, its
|
||
* only real purpose is for DisconnectRequest()
|
||
* Message_List - List of OwnerCallback messages that can't
|
||
* be processed immediately.
|
||
* m_pT123 - Address of owner object
|
||
* m_pQ922 - Address of lower layer
|
||
* m_nMsgBase - Message base passed in by owner. Used in
|
||
* OwnerCallback
|
||
* Identifier - Identifier passed to lower layer
|
||
* Link_Originator - TRUE if we initiated the connection
|
||
* Maximum_Packet_Size - Maximum packet size transmittable
|
||
* DataLink_Struct - Address of structure holding DataLink parms
|
||
* Data_Request_Memory_Manager - Address of memory manager
|
||
* Lower_Layer_Prepend - Holds number of bytes prepended to packet
|
||
* by the lower layer
|
||
* Lower_Layer_Append - Holds number of bytes appended to packet by
|
||
* the lower layer
|
||
* Call_Reference_Base - This value holds the next call reference
|
||
* number.
|
||
*
|
||
* Caveats:
|
||
* None.
|
||
*
|
||
* Authors:
|
||
* James W. Lawwill
|
||
*/
|
||
#include "scf.h"
|
||
|
||
|
||
/*
|
||
* CLayerSCF::CLayerSCF (
|
||
* PTransportResources transport_resources,
|
||
* IObject * owner_object,
|
||
* IProtocolLayer * lower_layer,
|
||
* USHORT message_base,
|
||
* USHORT identifier,
|
||
* BOOL link_originator,
|
||
* PChar config_file)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This is the CLayerSCF constructor. This routine initializes all
|
||
* variables and allocates buffer space.
|
||
*/
|
||
CLayerSCF::CLayerSCF
|
||
(
|
||
T123 *owner_object,
|
||
CLayerQ922 *pQ922, // lower layer
|
||
USHORT message_base,
|
||
USHORT identifier,
|
||
BOOL link_originator,
|
||
PDataLinkParameters datalink_struct,
|
||
PMemoryManager data_request_memory_manager,
|
||
BOOL * initialized
|
||
)
|
||
:
|
||
Remote_Call_Reference (TRANSPORT_HASHING_BUCKETS),
|
||
Call_Reference (TRANSPORT_HASHING_BUCKETS),
|
||
DLCI_List (TRANSPORT_HASHING_BUCKETS),
|
||
m_pT123(owner_object),
|
||
m_nMsgBase(message_base),
|
||
m_pQ922(pQ922)
|
||
{
|
||
ProtocolLayerError error;
|
||
|
||
TRACE_OUT(("CLayerSCF::CLayerSCF"));
|
||
|
||
Link_Originator = (USHORT)link_originator;
|
||
Identifier = identifier;
|
||
Data_Request_Memory_Manager = data_request_memory_manager;
|
||
Call_Reference_Base = 1;
|
||
*initialized = TRUE;
|
||
|
||
|
||
/*
|
||
** Fill in the DataLink_Struct with the proposed values and the default
|
||
** values
|
||
*/
|
||
DataLink_Struct.k_factor = datalink_struct -> k_factor;
|
||
DataLink_Struct.default_k_factor = datalink_struct -> default_k_factor;
|
||
DataLink_Struct.n201 = datalink_struct -> n201;
|
||
DataLink_Struct.default_n201 = datalink_struct -> default_n201;
|
||
DataLink_Struct.t200 = datalink_struct -> t200;
|
||
DataLink_Struct.default_t200 = datalink_struct -> default_t200;
|
||
|
||
/*
|
||
** Find the maximum packet size
|
||
*/
|
||
m_pQ922->GetParameters(
|
||
&Maximum_Packet_Size,
|
||
&Lower_Layer_Prepend,
|
||
&Lower_Layer_Append);
|
||
|
||
/*
|
||
** Register with the lower layer
|
||
*/
|
||
error = m_pQ922->RegisterHigherLayer(
|
||
Identifier,
|
||
Data_Request_Memory_Manager,
|
||
(IProtocolLayer *) this);
|
||
|
||
if (error != PROTOCOL_LAYER_NO_ERROR)
|
||
{
|
||
ERROR_OUT(("Multiplexer: constructor: Error registering with lower layer"));
|
||
*initialized = FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* CLayerSCF::~CLayerSCF (void)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This is the CLayerSCF destructor. This routine cleans up everything.
|
||
*/
|
||
CLayerSCF::~CLayerSCF (void)
|
||
{
|
||
TRACE_OUT(("CLayerSCF::~CLayerSCF"));
|
||
|
||
PMessageStruct message;
|
||
PSCFCall lpSCFCall;
|
||
|
||
m_pQ922->RemoveHigherLayer(Identifier);
|
||
|
||
/*
|
||
** Delete all locally initiated calls
|
||
*/
|
||
Call_Reference.reset();
|
||
while (Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
delete lpSCFCall;
|
||
}
|
||
|
||
/*
|
||
** Delete all remotely initiated calls
|
||
*/
|
||
Remote_Call_Reference.reset();
|
||
while (Remote_Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
delete lpSCFCall;
|
||
}
|
||
|
||
/*
|
||
** Delete all passive owner callbacks
|
||
*/
|
||
Message_List.reset();
|
||
while (Message_List.iterate ((PDWORD_PTR) &message))
|
||
{
|
||
delete message;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* CLayerSCF::ConnectRequest (
|
||
* DLCI dlci,
|
||
* TransportPriority priority)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function initiates a connection with the remote site. As a result,
|
||
* we will create a SCFCall and tell it to initiate a connection.
|
||
*/
|
||
SCFError CLayerSCF::ConnectRequest (
|
||
DLCI dlci,
|
||
TransportPriority priority)
|
||
|
||
{
|
||
TRACE_OUT(("CLayerSCF::ConnectRequest"));
|
||
|
||
BOOL initialized;
|
||
CallReference call_reference;
|
||
SCFError return_value = SCF_NO_ERROR;
|
||
PSCFCall lpSCFCall;
|
||
|
||
|
||
/*
|
||
** Get the next valid local call reference value.
|
||
*/
|
||
call_reference = GetNextCallReference ();
|
||
|
||
if (call_reference == 0)
|
||
return (SCF_CONNECTION_FULL);
|
||
|
||
/*
|
||
** Create an SCFCall object to handle this call reference
|
||
*/
|
||
DBG_SAVE_FILE_LINE
|
||
lpSCFCall= new SCFCall(this,
|
||
m_pQ922,
|
||
call_reference << 8,
|
||
&DataLink_Struct,
|
||
Data_Request_Memory_Manager,
|
||
&initialized);
|
||
|
||
if (lpSCFCall != NULL)
|
||
{
|
||
if (initialized)
|
||
{
|
||
Call_Reference.insert ((DWORD_PTR) call_reference, (DWORD_PTR) lpSCFCall);
|
||
/*
|
||
** Register the DLCI and the call reference
|
||
*/
|
||
DLCI_List.insert ((DWORD_PTR) dlci, (DWORD_PTR) lpSCFCall);
|
||
|
||
lpSCFCall->ConnectRequest (call_reference, dlci, priority);
|
||
}
|
||
else
|
||
{
|
||
delete lpSCFCall;
|
||
return_value = SCF_MEMORY_ALLOCATION_ERROR;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return_value = SCF_MEMORY_ALLOCATION_ERROR;
|
||
}
|
||
|
||
return (return_value);
|
||
}
|
||
|
||
|
||
/*
|
||
* CLayerSCF::ConnectResponse (
|
||
* CallReference call_reference,
|
||
* DLCI dlci,
|
||
* BOOL valid_dlci)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This is the CLayerSCF destructor. This routine cleans up everything.
|
||
*/
|
||
SCFError CLayerSCF::ConnectResponse (
|
||
CallReference call_reference,
|
||
DLCI dlci,
|
||
BOOL valid_dlci)
|
||
|
||
{
|
||
TRACE_OUT(("CLayerSCF::ConnectResponse"));
|
||
|
||
PSCFCall lpSCFCall = NULL;
|
||
|
||
if (valid_dlci)
|
||
{
|
||
if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
|
||
DLCI_List.insert ((DWORD_PTR) dlci, (DWORD_PTR) lpSCFCall);
|
||
}
|
||
|
||
if(NULL != lpSCFCall)
|
||
{
|
||
lpSCFCall->ConnectResponse (valid_dlci);
|
||
return (SCF_NO_ERROR);
|
||
}
|
||
return (SCF_NO_SUCH_DLCI);
|
||
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
* SCFError CLayerSCF::DisconnectRequest (
|
||
* DLCI dlci)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function calls the SCFCall associated with the DLCI and starts
|
||
* the disconnect operation
|
||
*/
|
||
SCFError CLayerSCF::DisconnectRequest (
|
||
DLCI dlci)
|
||
|
||
{
|
||
TRACE_OUT(("CLayerSCF::DisconnectRequest"));
|
||
|
||
PSCFCall lpSCFCall;
|
||
|
||
if (DLCI_List.find ((DWORD_PTR) dlci, (PDWORD_PTR) &lpSCFCall) == FALSE)
|
||
return (SCF_NO_SUCH_DLCI);
|
||
|
||
lpSCFCall->DisconnectRequest ();
|
||
|
||
return (SCF_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* SCFError CLayerSCF::DataIndication (
|
||
* LPBYTE packet_address,
|
||
* ULONG buffer_size,
|
||
* PULong packet_length)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function is called by the lower layer when it has received a
|
||
* packet for us to process.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::DataIndication (
|
||
LPBYTE packet_address,
|
||
ULONG packet_length,
|
||
PULong bytes_accepted)
|
||
{
|
||
TRACE_OUT(("CLayerSCF::DataIndication"));
|
||
|
||
BOOL legal_packet;
|
||
CallReference call_reference;
|
||
USHORT length_call_reference;
|
||
USHORT message_type;
|
||
PSCFCall call;
|
||
USHORT remainder_length;
|
||
USHORT local;
|
||
BOOL initialized;
|
||
|
||
|
||
remainder_length = (USHORT) packet_length;
|
||
*bytes_accepted = packet_length;
|
||
|
||
if (*(packet_address+PROTOCOL_DISCRIMINATOR) != Q931_PROTOCOL_DISCRIMINATOR)
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
|
||
/*
|
||
** Get the call reference value
|
||
*/
|
||
call_reference = *(packet_address + CALL_REFERENCE_VALUE);
|
||
if (call_reference == 0)
|
||
{
|
||
ERROR_OUT(("CLayerSCF: DataIndication: illegal call reference value = 0"));
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
length_call_reference = *(packet_address + LENGTH_CALL_REFERENCE);
|
||
packet_address += CALL_REFERENCE_VALUE + length_call_reference;
|
||
remainder_length -= (CALL_REFERENCE_VALUE + length_call_reference);
|
||
|
||
|
||
/*
|
||
** Get the message type
|
||
*/
|
||
message_type = *(packet_address++);
|
||
remainder_length--;
|
||
|
||
switch (message_type)
|
||
{
|
||
case SETUP:
|
||
/*
|
||
** If the call reference is already active, return error
|
||
*/
|
||
if (Remote_Call_Reference.find ((DWORD) call_reference))
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: SETUP: call reference is already active"));
|
||
break;
|
||
}
|
||
|
||
if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 1)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: SETUP: call reference Originator bit is set incorrectly"));
|
||
break;
|
||
}
|
||
|
||
/*
|
||
** This is a new call reference, create a new SCFCall to handle
|
||
** the call. Since the remote site initiated the call, put this
|
||
** reference in the Remote array
|
||
*/
|
||
call= new SCFCall(this,
|
||
m_pQ922,
|
||
(call_reference << 8),
|
||
&DataLink_Struct,
|
||
Data_Request_Memory_Manager,
|
||
&initialized);
|
||
|
||
if (call != NULL)
|
||
{
|
||
if (initialized)
|
||
{
|
||
|
||
Remote_Call_Reference.insert ((DWORD_PTR) call_reference, (DWORD_PTR) call);
|
||
/*
|
||
** Allow the call to process the SETUP command
|
||
*/
|
||
legal_packet = call->ProcessSetup (call_reference, packet_address, remainder_length);
|
||
|
||
/*
|
||
** If the packet was illegal, remove the reference
|
||
*/
|
||
if (legal_packet == FALSE) {
|
||
delete call;
|
||
Remote_Call_Reference.remove ((DWORD) call_reference);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
delete call;
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
case CONNECT:
|
||
/*
|
||
** The call originator bit must be set to signify that we are
|
||
** the originators of the call
|
||
*/
|
||
if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 0)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: CONNECT: call reference Originator bit is set incorrectly"));
|
||
break;
|
||
}
|
||
|
||
/*
|
||
** If the call reference is not already active, return error
|
||
*/
|
||
call_reference &= CALL_ORIGINATOR_MASK;
|
||
if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: CONNECT: call reference is not already active = %x", call_reference));
|
||
break;
|
||
}
|
||
|
||
call->ProcessConnect (packet_address, remainder_length);
|
||
break;
|
||
|
||
case CONNECT_ACKNOWLEDGE:
|
||
/*
|
||
** If the call reference is already active, return error
|
||
*/
|
||
if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: CONNECT_ACK: call reference is not active"));
|
||
break;
|
||
}
|
||
|
||
/*
|
||
** The call originator bit should NOT be set
|
||
*/
|
||
if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 1)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: CONNECT_ACK: call reference Originator bit is set incorrectly"));
|
||
break;
|
||
}
|
||
|
||
call->ProcessConnectAcknowledge (packet_address, remainder_length);
|
||
break;
|
||
|
||
case RELEASE_COMPLETE:
|
||
local = call_reference & CALL_REFERENCE_ORIGINATOR;
|
||
call_reference &= CALL_ORIGINATOR_MASK;
|
||
|
||
/*
|
||
** If the call is local, check the Call_Reference list for validity
|
||
*/
|
||
if (local)
|
||
{
|
||
if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: RELEASE_COMPLETE: call reference is not already active"));
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
** If the call is remote, check the Call_Reference list for
|
||
** validity
|
||
*/
|
||
if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
{
|
||
TRACE_OUT(("CLayerSCF: DataIndication: RELEASE_COMPLETE: call reference is not already active"));
|
||
break;
|
||
}
|
||
}
|
||
|
||
call -> ProcessReleaseComplete (packet_address, remainder_length);
|
||
ProcessMessages ();
|
||
break;
|
||
|
||
case DISCONNECT:
|
||
case RELEASE:
|
||
case STATUS:
|
||
case STATUS_ENQUIRY:
|
||
TRACE_OUT(("CLayerSCF:DataIndication: Illegal command received = %x", message_type));
|
||
|
||
local = call_reference & CALL_REFERENCE_ORIGINATOR;
|
||
call_reference &= CALL_ORIGINATOR_MASK;
|
||
|
||
/*
|
||
** If the call is local, check the Call_Reference list for validity
|
||
*/
|
||
if (local)
|
||
{
|
||
if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
** If the call is remote, check the Call_Reference list for
|
||
** validity
|
||
*/
|
||
if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
|
||
break;
|
||
}
|
||
|
||
call -> DisconnectRequest ();
|
||
break;
|
||
|
||
default:
|
||
ERROR_OUT(("CLayerSCF:DataIndication: Unrecognized command received = %x", message_type));
|
||
break;
|
||
}
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError CLayerSCF::PollTransmitter (
|
||
* ULONG,
|
||
* USHORT data_to_transmit,
|
||
* USHORT * pending_data,
|
||
* USHORT *)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function should be called frequently to allow the SCF calls to
|
||
* transmit packets.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::PollTransmitter (
|
||
ULONG_PTR,
|
||
USHORT data_to_transmit,
|
||
USHORT * pending_data,
|
||
USHORT *)
|
||
{
|
||
// TRACE_OUT(("CLayerSCF::PollTransmitter"));
|
||
|
||
USHORT local_pending_data;
|
||
PSCFCall lpSCFCall;
|
||
|
||
*pending_data = 0;
|
||
|
||
/*
|
||
** Go through each of the locally originated calls and attempt to transmit
|
||
** data.
|
||
*/
|
||
Call_Reference.reset();
|
||
while (Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
lpSCFCall->PollTransmitter (data_to_transmit, &local_pending_data);
|
||
*pending_data |= local_pending_data;
|
||
}
|
||
|
||
|
||
/*
|
||
** Go through each of the remotely originated calls and attempt to transmit
|
||
** data.
|
||
*/
|
||
Remote_Call_Reference.reset();
|
||
while (Remote_Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
lpSCFCall-> PollTransmitter (data_to_transmit, &local_pending_data);
|
||
*pending_data |= local_pending_data;
|
||
}
|
||
|
||
ProcessMessages ();
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* SCFError CLayerSCF::DataRequest (
|
||
* ULONG,
|
||
* LPBYTE,
|
||
* ULONG,
|
||
* PULong)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function can not be called. This layer does not permit data
|
||
* requests from higher layers.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::DataRequest (
|
||
ULONG_PTR,
|
||
LPBYTE,
|
||
ULONG,
|
||
PULong)
|
||
{
|
||
return (PROTOCOL_LAYER_ERROR);
|
||
}
|
||
|
||
/*
|
||
* SCFError CLayerSCF::DataRequest (
|
||
* ULONG,
|
||
* PMemory,
|
||
* USHORT *)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function can not be called. This layer does not permit data
|
||
* requests from higher layers.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::DataRequest (
|
||
ULONG_PTR,
|
||
PMemory,
|
||
PULong)
|
||
{
|
||
return (PROTOCOL_LAYER_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* void CLayerSCF::PollReceiver (
|
||
* ULONG)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description
|
||
* This function only checks its passive callback list. If this function
|
||
* had a higher layer that it was passing data too, it would do that. But
|
||
* since it has no higher layer, it doesn't do much.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::PollReceiver(void)
|
||
{
|
||
ProcessMessages ();
|
||
|
||
return (PROTOCOL_LAYER_NO_ERROR);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* CallReference CLayerSCF::GetNextCallReference ()
|
||
*
|
||
* Functional Description
|
||
* This function searches the local call reference list for a valid call
|
||
* reference number. If it can not find one, it returns 0. Valid call
|
||
* references are 1-127.
|
||
*
|
||
* Formal Parameters
|
||
* None
|
||
*
|
||
* Return Value
|
||
* Call reference value
|
||
*
|
||
* Side Effects
|
||
* None
|
||
*
|
||
* Caveats
|
||
* None
|
||
*/
|
||
USHORT CLayerSCF::GetNextCallReference ()
|
||
{
|
||
USHORT call_reference;
|
||
|
||
if (Call_Reference.entries() == 127)
|
||
return (0);
|
||
|
||
call_reference = Call_Reference_Base;
|
||
Call_Reference_Base++;
|
||
if (Call_Reference_Base == 128)
|
||
Call_Reference_Base = 1;
|
||
|
||
while (Call_Reference.find ((DWORD) call_reference))
|
||
{
|
||
call_reference++;
|
||
if (call_reference == 128)
|
||
call_reference = 1;
|
||
}
|
||
|
||
return (call_reference);
|
||
}
|
||
|
||
|
||
/*
|
||
* ULONG CLayerSCF::OwnerCallback (
|
||
* USHORT message,
|
||
* ULONG parameter1,
|
||
* ULONG parameter2,
|
||
* PVoid parameter3)
|
||
*
|
||
* Functional Description
|
||
* This function is called by the SCFCall objects when they need to
|
||
* communicate a message to us. If the message can not be processed
|
||
* immediately, it is saved in a message structure and processed at a
|
||
* later time.
|
||
*
|
||
* Formal Parameters
|
||
* None
|
||
*
|
||
* Return Value
|
||
* Message dependent
|
||
*
|
||
* Side Effects
|
||
* None
|
||
*
|
||
* Caveats
|
||
* None
|
||
*/
|
||
ULONG CLayerSCF::OwnerCallback
|
||
(
|
||
ULONG message,
|
||
void *parameter1,
|
||
void *parameter2,
|
||
void *parameter3
|
||
)
|
||
{
|
||
TRACE_OUT(("CLayerSCF::OwnerCallback"));
|
||
|
||
ULONG actual_message;
|
||
CallReference call_reference;
|
||
PMessageStruct passive_message;
|
||
PNetworkConnectStruct connect_struct;
|
||
PSCFCall lpSCFCall;
|
||
|
||
/*
|
||
** The upper byte of the message is the call reference message that it
|
||
** represents
|
||
*/
|
||
call_reference = (CallReference) (message >> 8);
|
||
actual_message = message & 0xff;
|
||
|
||
switch (actual_message)
|
||
{
|
||
case NETWORK_CONNECT_CONFIRM:
|
||
|
||
/*
|
||
** A CONNECT_CONFIRM message is returned by the SCFCall when a call
|
||
** that we originated, has been established. We register the
|
||
** SCFCall with the DLCI and call the owner object.
|
||
*/
|
||
connect_struct = (PNetworkConnectStruct) parameter3;
|
||
connect_struct -> call_reference = call_reference;
|
||
|
||
if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
DLCI_List.insert ((DWORD_PTR) connect_struct->dlci, (DWORD_PTR) lpSCFCall);
|
||
}
|
||
|
||
m_pT123->OwnerCallback(m_nMsgBase + actual_message, 0, 0, parameter3);
|
||
break;
|
||
|
||
case NETWORK_CONNECT_INDICATION:
|
||
/*
|
||
** A CONNECT_INDICATION message is returned by the SCFCall when the
|
||
** remote SCF wants to create a new call. We will call the owner
|
||
** of this object to see if he will accept the DLCI requested.
|
||
*/
|
||
connect_struct = (PNetworkConnectStruct) parameter3;
|
||
connect_struct -> call_reference = call_reference;
|
||
|
||
m_pT123->OwnerCallback(m_nMsgBase + actual_message, 0, 0, parameter3);
|
||
break;
|
||
|
||
case NETWORK_DISCONNECT_INDICATION:
|
||
/*
|
||
** This message is received from the SCFCall when one side wants
|
||
** to terminate the call. We treat this message differently than
|
||
** the other messages because it involves the deletion of an
|
||
** SCFCall object. Don't forget, if we delete the object and then
|
||
** return to it at the end of this procedure, a GPF could occur.
|
||
*/
|
||
DBG_SAVE_FILE_LINE
|
||
passive_message = new MessageStruct;
|
||
if (NULL != passive_message)
|
||
{
|
||
passive_message -> message = message;
|
||
passive_message -> parameter1 = parameter1;
|
||
passive_message -> parameter2 = parameter2;
|
||
passive_message -> parameter3 = parameter3;
|
||
Message_List.append ((DWORD_PTR) passive_message);
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("CLayerSCF::OwnerCallback: cannot allocate MessageStruct"));
|
||
}
|
||
break;
|
||
|
||
default:
|
||
ERROR_OUT(("CLayerSCF: Illegal message: %x", actual_message));
|
||
break;
|
||
}
|
||
return (0);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError CLayerSCF::GetParameters (
|
||
* USHORT,
|
||
* USHORT *,
|
||
* USHORT *,
|
||
* USHORT *)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description
|
||
* This function is not valid in this layer. It must exist because this
|
||
* class inherits from inherits from ProtocolLayer and it is a pure virtual
|
||
* function.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::GetParameters (
|
||
USHORT *,
|
||
USHORT *,
|
||
USHORT *)
|
||
{
|
||
return (PROTOCOL_LAYER_REGISTRATION_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError CLayerSCF::RegisterHigherLayer (
|
||
* USHORT,
|
||
* PMemoryManager,
|
||
* IProtocolLayer *)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description
|
||
* This function is not valid in this layer. It must exist because this
|
||
* class inherits from inherits from ProtocolLayer and it is a pure virtual
|
||
* function.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::RegisterHigherLayer (
|
||
ULONG_PTR,
|
||
PMemoryManager,
|
||
IProtocolLayer *)
|
||
{
|
||
return (PROTOCOL_LAYER_REGISTRATION_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* ProtocolLayerError CLayerSCF::RemoveHigherLayer (
|
||
* USHORT)
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description
|
||
* This function is not valid in this layer. It must exist because this
|
||
* class inherits from inherits from ProtocolLayer and it is a pure virtual
|
||
* function.
|
||
*/
|
||
ProtocolLayerError CLayerSCF::RemoveHigherLayer (
|
||
ULONG_PTR)
|
||
{
|
||
return (PROTOCOL_LAYER_REGISTRATION_ERROR);
|
||
}
|
||
|
||
|
||
/*
|
||
* void CLayerSCF::ProcessMessages ()
|
||
*
|
||
* Functional Description
|
||
* This function is called periodically to check its passive messages.
|
||
* Passive messages occur when the SCF gets a callback but can't process
|
||
* it immediately. Therefore, it puts the message and its parameters in
|
||
* a structure and saves the message for later.
|
||
*
|
||
* Formal Parameters
|
||
* None
|
||
*
|
||
* Return Value
|
||
* Message dependent
|
||
*
|
||
* Side Effects
|
||
* None
|
||
*
|
||
* Caveats
|
||
* None
|
||
*/
|
||
void CLayerSCF::ProcessMessages ()
|
||
{
|
||
// TRACE_OUT(("CLayerSCF::ProcessMessages"));
|
||
|
||
PMessageStruct message;
|
||
CallReference call_reference;
|
||
ULONG actual_message;
|
||
USHORT call_originator;
|
||
USHORT cause;
|
||
DLCI dlci;
|
||
BOOL call_reference_valid;
|
||
void *parameter1;
|
||
void *parameter2;
|
||
PSCFCall lpSCFCall;
|
||
|
||
/*
|
||
** Go thru each message in the list
|
||
*/
|
||
while (Message_List.isEmpty() == FALSE)
|
||
{
|
||
/*
|
||
** Remote the first message from the list
|
||
*/
|
||
message = (PMessageStruct) Message_List.get ();
|
||
|
||
call_reference = (CallReference) ((message -> message) >> 8);
|
||
actual_message = (message -> message) & 0xff;
|
||
parameter1 = message -> parameter1;
|
||
parameter2 = message -> parameter2;
|
||
|
||
switch (actual_message)
|
||
{
|
||
case NETWORK_DISCONNECT_INDICATION:
|
||
/*
|
||
** This message is received from the SCFCall when one side
|
||
** wants to terminate the call. We treat this message
|
||
** differently than the other messages because it involves the
|
||
** deletion of an SCFCall object.
|
||
*/
|
||
dlci = (DLCI) parameter1;
|
||
call_originator = (USHORT) (((ULONG_PTR) parameter2) >> 16);
|
||
cause = (USHORT) ((ULONG_PTR) parameter2) & 0xffff;
|
||
|
||
/*
|
||
** dlci is 0 if the SCFCall was never assigned a DLCI by the
|
||
** remote site.
|
||
*/
|
||
if (dlci != 0)
|
||
DLCI_List.remove ((DWORD) dlci);
|
||
|
||
/*
|
||
** If the SCFCall was the call originator, its reference is
|
||
** in Call_Reference, otherwise it is in Remote_Call_Reference.
|
||
**
|
||
** Check the Call_Reference list to make sure that the
|
||
** call_reference is valid. The way passive owner callbacks
|
||
** work, it is possible to receive a DISCONNECT for a callback
|
||
** that was already disconnected.
|
||
*/
|
||
call_reference_valid = FALSE;
|
||
if (call_originator)
|
||
{
|
||
if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
delete lpSCFCall;
|
||
Call_Reference.remove ((DWORD) call_reference);
|
||
call_reference_valid = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
|
||
{
|
||
delete lpSCFCall;
|
||
Remote_Call_Reference.remove ((DWORD_PTR) call_reference);
|
||
call_reference_valid = TRUE;
|
||
}
|
||
}
|
||
|
||
if (call_reference_valid)
|
||
{
|
||
/*
|
||
** If the cause of the disconnect was because the Requested
|
||
** channel was unavailable, we will tell the owner of this
|
||
** layer to retry the connection.
|
||
*/
|
||
if (cause == REQUESTED_CHANNEL_UNAVAILABLE)
|
||
{
|
||
parameter2 = (void *) ((((ULONG_PTR) call_originator) << 16) | TRUE);
|
||
}
|
||
else
|
||
{
|
||
parameter2 = (void *) ((((ULONG_PTR) call_originator) << 16) | FALSE);
|
||
}
|
||
|
||
/*
|
||
** Let the owner of this object know that a disconnect has
|
||
** occured.
|
||
*/
|
||
m_pT123->OwnerCallback(m_nMsgBase + NETWORK_DISCONNECT_INDICATION,
|
||
parameter1, parameter2);
|
||
}
|
||
break;
|
||
}
|
||
|
||
/*
|
||
** Delete the message structure
|
||
*/
|
||
delete message;
|
||
}
|
||
}
|
||
|