|
|
#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_T123PSTN); /* SCFCall.cpp
* * Copyright (c) 1994-1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This class is instantiated by the SCF class. For each call that the * local site or remote site initiates, a SCFCall object is instantiated. * SCF can can manage 254 different calls simultaneously. For each call * there is a specific Q.933 based protocol that must occur to make the * connection valid. This object sends and receives the Q.933 packets. * * Private Instance Variables: * m_pSCF - Address of the owner of this object * Lower_Layer - Address of the layer below this layer * m_nMsgBase - The owner of this object gives it a base * number to use for OwnerCallbacks () * Maximum_Packet_Size - Maximum transmittable packet size * Packet_Pending - Tells which packet is to be transmitted * next. * Link_Originator - TRUE is this site initiated the call * * Write_Buffer - Address of write buffer * Send_Priority - TRUE if we are suppose to respond to the * priority requested by the remote site * * Call_Reference - Call reference number of this call. * DLCI - Holds the suggested and confirmed DLCI for * this call. * Priority - Holds the suggested and confirmed priority * for this call. * * State - Holds the current state of the call. * Release_Cause - Reason the the breakup of the link. * Default_Priority - Default priority of a non-specified call. * * T303_Timeout - T303 timeout value. * T303_Handle - System timer handle to T303 timer * T303_Active - TRUE if the timer is currently active * T303_Count - Number of T303 Timeouts * * T313_Timeout - T313 timeout value * T313_Handle - System timer handle to T313 timer * T313_Active - TRUE if the timer is currently active. * * Caveats: * None. * * Authors: * James W. Lawwill */ #include "scf.h"
#include "scfcall.h"
/*
* SCFCall::SCFCall ( * PTransportResources transport_resources, * IObject * owner_object * IProtocolLayer * lower_layer, * USHORT message_base, * PDataLinkParameters datalink_struct, * PMemoryManager data_request_memory_manager, * BOOL * initialized) * * Public * * Functional Description: * This is the SCFCall constructor. This routine initializes all * variables and allocates write buffer space. */ SCFCall::SCFCall ( CLayerSCF *owner_object, IProtocolLayer * lower_layer, USHORT message_base, PDataLinkParameters datalink_struct, PMemoryManager data_request_memory_manager, BOOL * initialized) { TRACE_OUT(("SCFCall::SCFCall"));
m_pSCF = owner_object; Lower_Layer = lower_layer; m_nMsgBase = message_base; Data_Request_Memory_Manager = data_request_memory_manager; *initialized = TRUE;
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;
/*
** T200 is represented in milliseconds, we need to convert it to ** tenths of seconds. */ DataLink_Struct.t200 = datalink_struct->t200 / 100; DataLink_Struct.default_t200 = datalink_struct->default_t200 / 100;
Lower_Layer -> GetParameters ( &Maximum_Packet_Size, &Lower_Layer_Prepend, &Lower_Layer_Append);
Packet_Pending = NO_PACKET; Link_Originator = FALSE; State = NOT_CONNECTED; Received_Priority = FALSE; Received_K_Factor = FALSE; Received_N201 = FALSE; Received_T200 = FALSE; DLC_Identifier = 0;
T303_Active = FALSE; T313_Active = FALSE; /*
** Get configuration data */ T303_Timeout = DEFAULT_T303_TIMEOUT; T313_Timeout = DEFAULT_T313_TIMEOUT; Default_Priority = DEFAULT_PRIORITY; }
/*
* SCFCall::~SCFCall (void) * * Public * * Functional Description: * This is the SCFCall destructor. This routine cleans up the mess */ SCFCall::~SCFCall (void) { if (T303_Active) { StopTimerT303 (); }
if (T313_Active) { StopTimerT313 (); } }
/*
* SCFCall::ConnectRequest ( * CallReference call_reference, * DLCI dlci, * USHORT priority) * * Public * * Functional Description: * This function is called when SCF wants to initiate a call. * As a result, we queue a SETUP command to be sent out. */ SCFCallError SCFCall::ConnectRequest( CallReference call_reference, DLCI dlci, TransportPriority priority) { TRACE_OUT(("SCFCall::ConnectRequest")); Call_Reference = call_reference; DLC_Identifier = dlci; Priority = priority; Link_Originator = TRUE;
if (State == NOT_CONNECTED) Packet_Pending = SETUP;
return (SCFCALL_NO_ERROR); }
/*
* SCFCallError SCFCall::ConnectResponse ( * BOOL valid_dlci) * * Public * * Functional Description: * This function is called in response to a NETWORK_CONNECT_INDICATION * callback to the owner of this object. Previously, the remote site * sent us a SETUP packet with a suggested DLCI. This DLCI is sent to * the owner in the NETWORK_CONNECT_INDICATION call. The owner calls * this function with a BOOL , telling us if the DLCI was valid. */ SCFCallError SCFCall::ConnectResponse ( BOOL valid_dlci) { TRACE_OUT(("SCFCall::ConnectResponse")); if (valid_dlci) { /*
** This DLCI can be used in a link. If the remote site did not ** request a priority, we set it to Default_Priority */ if (Priority == 0xffff) Priority = Default_Priority;
Packet_Pending = CONNECT;
} else { /*
** Queue up a RELEASE COMPLETE packet */ Packet_Pending = RELEASE_COMPLETE; Release_Cause = REQUESTED_CHANNEL_UNAVAILABLE; }
return (SCFCALL_NO_ERROR); }
/*
* SCFCallError SCFCall::DisconnectRequest () * * Public * * Functional Description: * This function is called when the SCF wants to terminate the call */ SCFCallError SCFCall::DisconnectRequest () { TRACE_OUT(("SCFCall::DisconnectRequest")); /*
** Queue up the Release Complete */ if (State != NOT_CONNECTED) { Packet_Pending = RELEASE_COMPLETE; Release_Cause = NORMAL_USER_DISCONNECT; }
return (SCFCALL_NO_ERROR); }
/*
* BOOL SCFCall::ProcessSetup ( * CallReference call_reference, * LPBYTE packet_address, * USHORT packet_length) * * Public * * Functional Description: * This function processes an incoming SETUP packet */ BOOL SCFCall::ProcessSetup ( CallReference call_reference, LPBYTE packet_address, USHORT packet_length) { USHORT length; BOOL packet_successful; USHORT remainder_length; USHORT n201; USHORT k_factor; USHORT t200; NetworkConnectStruct connect_struct;
TRACE_OUT(("SCFCall::ProcessSetup"));
if (State != NOT_CONNECTED) return (FALSE);
Call_Reference = call_reference; packet_successful = TRUE; remainder_length = packet_length;
/*
** Bearer capability element */ if (*(packet_address++) != BEARER_CAPABILITY) return (FALSE); remainder_length--;
length = *(packet_address++); remainder_length--; if (length != 3) return (FALSE);
/*
** Verify that the Bearer Capability is correct */ if (*(packet_address) != (EXTENSION | CODING_STANDARD | INFORMATION_TRANSFER_CAPABILITY)) { return (FALSE); } if (*(packet_address + 1) != (EXTENSION | TRANSFER_MODE)) { return (FALSE); } if (*(packet_address + 2) != (EXTENSION | LAYER_2_IDENT | USER_INFORMATION_LAYER_2)) { return (FALSE); } packet_address += length; remainder_length -= length;
/*
** DLCI element */ if (*(packet_address++) != DLCI_ELEMENT) return (FALSE); remainder_length--;
length = *(packet_address++); if (length != 2) return (FALSE); remainder_length--; /*
** If the Preferred/Exclusive bit is set, its illegal */ if (((*(packet_address) & PREFERRED_EXCLUSIVE) == PREFERRED_EXCLUSIVE) || ((*(packet_address + 1) & EXTENSION) == 0)) { return (FALSE); } DLC_Identifier = (*(packet_address) & 0x3f) << 4; DLC_Identifier |= ((*(packet_address + 1) & 0x78) >> 3);
packet_address += length; remainder_length -= length;
Priority = 0xffff;
/*
** Go thru each of the elements and decode them */ while (remainder_length) { switch (*(packet_address++)) { case X213_PRIORITY: length = *(packet_address++); remainder_length--; if (((*(packet_address) & EXTENSION) == 1) || ((*(packet_address + 1) & EXTENSION) == 0)) { ERROR_OUT(("SCFCall: ProcessSetup: SETUP packet: Illegal X.213 priority")); return (FALSE); } Priority = (*packet_address & 0x0f); packet_address += length; remainder_length -= length; Received_Priority = TRUE; break;
case LINK_LAYER_CORE_PARAMETERS: length = *(packet_address++); remainder_length -= (length + 1); while (length) { switch (*(packet_address++)) { case FMIF_SIZE: /*
** N201 is a Q922 parameter. It is the number of ** maximum information bytes in a packet */ n201 = ((*packet_address << 7) | (*(packet_address + 1) & 0x7f)); if ((*(packet_address+1) & EXTENSION) == EXTENSION) { length -= 2; packet_address += 2; } else { packet_address += 4; length -= 4; }
/*
** If the requested n201 value is less than our ** value, it will be our new N201, otherwise send ** our N201 back as the arbitrated value. */ if (n201 < DataLink_Struct.n201) DataLink_Struct.n201 = n201; Received_N201 = TRUE; TRACE_OUT(("SCFCALL: ProcessSetup: n201 = %d", DataLink_Struct.n201)); break;
default: while ((*(packet_address++) & EXTENSION) == 0) length--; length--; break; } length--; } break;
case LINK_LAYER_PROTOCOL_PARAMETERS: length = *(packet_address++); remainder_length -= (length + 1); while (length) { switch (*(packet_address++)) { case TRANSMIT_WINDOW_SIZE_IDENTIFIER: /*
** The Window size is the maximum number of ** outstanding packets at any one time */ k_factor = *packet_address & 0x7f; packet_address++; length--;
/*
** If the requested k_factor value is less than our ** value, it will be our new k_factor, otherwise ** send our k_factor back as the arbitrated value. */ if (k_factor < DataLink_Struct.k_factor) DataLink_Struct.k_factor = k_factor; Received_K_Factor = TRUE; TRACE_OUT(("SCFCALL: ProcessSetup: k_factor = %d", DataLink_Struct.k_factor)); break;
case RETRANSMISSION_TIMER_IDENTIFIER: /*
** t200 is the timeout value before retransmission */ t200 = ((*packet_address << 7) | (*(packet_address + 1) & 0x7f)); packet_address += 2; length -= 2;
/*
** If the requested t200 value is too small, ** value, it will be our new T200, otherwise ** send our T200 back as the arbitrated value. */ if (t200 > DataLink_Struct.t200) DataLink_Struct.t200 = t200; Received_T200 = TRUE; TRACE_OUT(("SCFCALL: ProcessSetup: t200 = %d", DataLink_Struct.t200)); break;
default: while ((*(packet_address++) & EXTENSION) == 0) length--; length--; break; } length--; } break;
case END_TO_END_DELAY: case CALLING_PARTY_SUBADDRESS: case CALLED_PARTY_SUBADDRESS: default: TRACE_OUT(("SCFCall: ProcessSetup: SETUP packet: Option 0x%x" "requested, but not supported", *(packet_address-1))); length = *(packet_address);
packet_address += (length + 1); remainder_length -= (length + 1); break; } remainder_length--; } if (Received_N201 == FALSE) DataLink_Struct.n201 = DataLink_Struct.default_n201; if (Received_K_Factor == FALSE) DataLink_Struct.k_factor = DataLink_Struct.default_k_factor; if (Received_T200 == FALSE) DataLink_Struct.t200 = DataLink_Struct.default_t200;
if (packet_successful) { /*
** If the packet was successfully decoded, tell the owner the requested ** DLCI and priority. */ connect_struct.dlci = DLC_Identifier; connect_struct.priority = Priority; connect_struct.datalink_struct = &DataLink_Struct;
/*
** Convert t200 into milliseconds */ DataLink_Struct.t200 *= 100; m_pSCF->OwnerCallback(m_nMsgBase + NETWORK_CONNECT_INDICATION, 0, 0, &connect_struct); DataLink_Struct.t200 /= 100; } return (packet_successful); }
/*
* BOOL SCFCall::ProcessConnect ( * LPBYTE packet_address, * USHORT packet_length) * * Public * * Functional Description: * This function processes an incoming CONNECT packet */ BOOL SCFCall::ProcessConnect ( LPBYTE packet_address, USHORT packet_length) { TRACE_OUT(("SCFCall::ProcessConnect"));
BOOL packet_successful; USHORT length; DLCI exclusive_dlci; USHORT remainder_length; USHORT k_factor; USHORT t200; if (State != SETUP_SENT) { ERROR_OUT(("SCFCall: ProcessConnect: Call in wrong state")); return (FALSE); }
remainder_length = packet_length; packet_successful = TRUE;
/*
** DLCI element */ if (*(packet_address++) != DLCI_ELEMENT) { ERROR_OUT(("SCFCall: ProcessConnect: DLCI_ELEMENT not in packet")); return (FALSE); } remainder_length--;
length = *(packet_address++); if (length != 2) { ERROR_OUT(("SCFCall: ProcessConnect: DLCI length must be 2")); return (FALSE); } remainder_length--; /*
** If the Preferred/Exclusive bit is not set, its illegal */ if (((*(packet_address) & PREFERRED_EXCLUSIVE) == 0) || ((*(packet_address + 1) & EXTENSION) == 0)) { ERROR_OUT(("SCFCall: CONNECT: Illegal DLCI")); return (FALSE); } /*
** Get the DLCI */ exclusive_dlci = (*(packet_address) & 0x3f) << 4; exclusive_dlci |= ((*(packet_address + 1) & 0x78) >> 3);
packet_address += length; remainder_length -= length;
/*
** Go thru each of the elements and decode them */ while (remainder_length != 0) { switch (*(packet_address++)) { case X213_PRIORITY: length = *(packet_address++); remainder_length--; if ((*(packet_address) & EXTENSION) == 0) { ERROR_OUT(("SCFCall: DataIndication: CONNECT packet: Illegal X.213 priority")); return (FALSE); } Priority = (*packet_address & 0x0f); packet_address += length; remainder_length -= length; break;
case LINK_LAYER_CORE_PARAMETERS: length = *(packet_address++); remainder_length -= (length + 1); while (length) { switch (*(packet_address++)) { case FMIF_SIZE: /*
** FMIF_Size is the max. number of bytes allowed in ** a information packet */ DataLink_Struct.n201 = ((*packet_address << 7) | (*(packet_address + 1) & 0x7f)); if ((*(packet_address+1) & EXTENSION) == EXTENSION) { length -= 2; packet_address += 2; } else { packet_address += 4; length -= 4; }
Received_N201 = TRUE; TRACE_OUT(("SCFCALL: ProcessConnect: n201 = %d", DataLink_Struct.n201)); break;
default: while ((*(packet_address++) & EXTENSION) == 0) length--; length--; break; } length--; } break;
case LINK_LAYER_PROTOCOL_PARAMETERS: length = *(packet_address++); remainder_length -= (length + 1); while (length) { switch (*(packet_address++)) { case TRANSMIT_WINDOW_SIZE_IDENTIFIER: /*
** The Window size is the maximum number of ** outstanding packets at any one time */ k_factor = *packet_address & 0x7f; packet_address++; length--;
DataLink_Struct.k_factor = k_factor; Received_K_Factor = TRUE; TRACE_OUT(("SCFCALL: ProcessConnect: k_factor = %d", DataLink_Struct.k_factor)); break;
case RETRANSMISSION_TIMER_IDENTIFIER: /*
** t200 is the timeout value before retransmission */ t200 = ((*packet_address << 7) | (*(packet_address + 1) & 0x7f)); packet_address += 2; length -= 2;
DataLink_Struct.t200 = t200; Received_T200 = TRUE; TRACE_OUT(("SCFCALL: ProcessConnect: t200 = %d", DataLink_Struct.t200)); break;
default: while ((*(packet_address++) & EXTENSION) == 0) length--; length--; break; } length--; } break;
case END_TO_END_DELAY: case CALLING_PARTY_SUBADDRESS: case CALLED_PARTY_SUBADDRESS: default: TRACE_OUT(("SCFCall: DataIndication: CONNECT packet: Option " "requested, but not supported", *(packet_address-1))); length = *(packet_address++); remainder_length--;
packet_address += length; remainder_length -= length; break; } remainder_length--; }
if (Received_N201 == FALSE) DataLink_Struct.n201 = DataLink_Struct.default_n201; if (Received_K_Factor == FALSE) DataLink_Struct.k_factor = DataLink_Struct.default_k_factor; if (Received_T200 == FALSE) DataLink_Struct.t200 = DataLink_Struct.default_t200;
/*
** If the packet was successfully decoded, queue up the CONNECT ACK */ if (packet_successful) { Packet_Pending = CONNECT_ACKNOWLEDGE; StopTimerT303 (); }
return (packet_successful); }
/*
* BOOL SCFCall::ProcessConnectAcknowledge ( * LPBYTE, * USHORT) * * Public * * Functional Description: * This function processes an incoming CONNECT ACK packet * */ BOOL SCFCall::ProcessConnectAcknowledge ( LPBYTE, USHORT) { TRACE_OUT(("SCFCall::ProcessConnectAcknowledge"));
if (State != CONNECT_SENT) return (FALSE);
StopTimerT313 ();
return (TRUE); }
/*
* BOOL SCFCall::ProcessReleaseComplete ( * LPBYTE packet_address, * USHORT) * * Public * * Functional Description: * This function processes an incoming RELEASE COMPLETE */ BOOL SCFCall::ProcessReleaseComplete ( LPBYTE packet_address, USHORT) { TRACE_OUT(("SCFCall::ProcessReleaseComplete"));
USHORT cause;
if (State == NOT_CONNECTED) return (FALSE);
if (*(packet_address++) == CAUSE) { packet_address++; if ((*(packet_address++) & EXTENSION) == 0) packet_address++;
cause = *(packet_address++) & (~EXTENSION); TRACE_OUT(("SCFCall: Disconnect: cause = %d", cause)); }
State = NOT_CONNECTED;
/*
** Tell the owner about the Disconnection */ m_pSCF->OwnerCallback(m_nMsgBase + NETWORK_DISCONNECT_INDICATION, (void *) DLC_Identifier, (void *) (ULONG_PTR)(((Link_Originator << 16) | cause))); return (TRUE); }
/*
* void SCFCall::PollTransmitter ( * USHORT data_to_transmit, * USHORT * pending_data); * * Public * * Functional Description: * This function is called to transmit any queued up packets */ void SCFCall::PollTransmitter ( USHORT data_to_transmit, USHORT * pending_data) { // TRACE_OUT(("SCFCall::PollTransmitter"));
NetworkConnectStruct connect_struct;
if (data_to_transmit & PROTOCOL_CONTROL_DATA) { switch (Packet_Pending) { case SETUP: SendSetup (); break;
case CONNECT: SendConnect (); break;
case CONNECT_ACKNOWLEDGE: SendConnectAcknowledge (); if (Packet_Pending != CONNECT_ACKNOWLEDGE) { /*
** If the CONNECT ACK packet was sent, notify the owner */ connect_struct.dlci = DLC_Identifier; connect_struct.priority = Priority; connect_struct.datalink_struct = &DataLink_Struct;
/*
** Convert t200 to milliseconds */ DataLink_Struct.t200 *= 100; m_pSCF->OwnerCallback(m_nMsgBase + NETWORK_CONNECT_CONFIRM, 0, 0, &connect_struct); DataLink_Struct.t200 /= 100; } break;
case RELEASE_COMPLETE: SendReleaseComplete (); if (Packet_Pending != RELEASE_COMPLETE) { /*
** If the RELEASE COMPLETE packet was sent, notify ** the owner */ m_pSCF->OwnerCallback(m_nMsgBase + NETWORK_DISCONNECT_INDICATION, (void *) DLC_Identifier, (void *) ((((ULONG_PTR) Link_Originator) << 16) | Release_Cause)); } break; } if (Packet_Pending != NO_PACKET) *pending_data = PROTOCOL_CONTROL_DATA; else *pending_data = 0; }
return; }
/*
* void SCFCall::SendSetup (void); * * Functional Description * This function attempts to send out a SETUP packet. The T303 timer * is started. If a CONNECT is not received before the timer expires, * we terminate the link. * * Formal Parameters * None * * Return Value * None * * Side Effects * If this function is able to send a SETUP packet to the lower layer, * it sets the Packet_Pending variable to NO_PACKET * * Caveats * None */ void SCFCall::SendSetup (void) { TRACE_OUT(("SCFCall::SendSetup"));
LPBYTE packet_address; ULONG bytes_accepted; USHORT total_length; PMemory memory;
total_length = SETUP_PACKET_SIZE + Lower_Layer_Prepend + Lower_Layer_Append;
memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) return;
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = Q931_PROTOCOL_DISCRIMINATOR; *(packet_address++) = 1; *(packet_address++) = (UChar) Call_Reference; *(packet_address++) = SETUP;
/*
** Bearer Capability */ *(packet_address++) = BEARER_CAPABILITY; *(packet_address++) = 3; *(packet_address++) = EXTENSION | CODING_STANDARD | INFORMATION_TRANSFER_CAPABILITY; *(packet_address++) = EXTENSION | TRANSFER_MODE; *(packet_address++) = EXTENSION | LAYER_2_IDENT | USER_INFORMATION_LAYER_2; /*
** DLCI */ *(packet_address++) = DLCI_ELEMENT; *(packet_address++) = 2; *(packet_address++) = (DLC_Identifier >> 4); *(packet_address++) = EXTENSION | ((DLC_Identifier & 0x0f) << 3);
/*
** Link Layer Core Parameters */ *(packet_address++) = LINK_LAYER_CORE_PARAMETERS; *(packet_address++) = 3; *(packet_address++) = FMIF_SIZE; *(packet_address++) = (DataLink_Struct.n201 >> 7); *(packet_address++) = EXTENSION | (DataLink_Struct.n201 & 0x7f);
/*
** Link Layer Protocol Parameters */ *(packet_address++) = LINK_LAYER_PROTOCOL_PARAMETERS; *(packet_address++) = 5; *(packet_address++) = TRANSMIT_WINDOW_SIZE_IDENTIFIER; *(packet_address++) = EXTENSION | DataLink_Struct.k_factor; *(packet_address++) = RETRANSMISSION_TIMER_IDENTIFIER; *(packet_address++) = (DataLink_Struct.t200 >> 7) & 0x7f; *(packet_address++) = EXTENSION | (DataLink_Struct.t200 & 0x7f);
/*
** X.213 Priority */ *(packet_address++) = X213_PRIORITY; *(packet_address++) = 2; *(packet_address++) = (UChar) Priority;
/*
** The next byte contains the lowest priority acceptable, 0 */ *(packet_address++) = EXTENSION | 0;
/*
** Attempt to send the packet down */ Lower_Layer -> DataRequest ( 0, memory, &bytes_accepted); if (bytes_accepted == total_length) { T303_Count = 0; Packet_Pending = NO_PACKET; State = SETUP_SENT; StartTimerT303 (); } Data_Request_Memory_Manager -> FreeMemory (memory); }
/*
* void SCFCall::SendConnect (void); * * Functional Description * This function attempts to send out a CONNECT packet. The T313 timer * is started. If a CONNECT ACK is not received before the timer expires, * we terminate the link. * * Formal Parameters * None * * Return Value * None * * Side Effects * If this function is able to send a CONNECT packet to the lower layer, * it sets the Packet_Pending variable to NO_PACKET * * Caveats * None * */ void SCFCall::SendConnect (void) { TRACE_OUT(("SCFCall::SendConnect"));
LPBYTE packet_address; LPBYTE length_address; ULONG bytes_accepted; USHORT total_length; PMemory memory;
total_length = CONNECT_PACKET_BASE_SIZE + Lower_Layer_Prepend + Lower_Layer_Append;
if (Received_N201) total_length += 5;
if (Received_K_Factor || Received_T200) { total_length += 2;
if (Received_K_Factor) total_length += 2; if (Received_T200) total_length += 3; } if (Received_Priority) total_length += 3;
/*
** Prepare the CONNECT command and send it to the lower layer */ memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) return;
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = Q931_PROTOCOL_DISCRIMINATOR; *(packet_address++) = 1; *(packet_address++) = REMOTE_CALL_REFERENCE | Call_Reference; *(packet_address++) = CONNECT;
/*
** DLCI */ *(packet_address++) = DLCI_ELEMENT; *(packet_address++) = 2; *(packet_address++) = PREFERRED_EXCLUSIVE | (DLC_Identifier >> 4); *(packet_address++) = EXTENSION | ((DLC_Identifier & 0x0f) << 3);
if (Received_N201) { /*
** Link Layer Core Parameters */ *(packet_address++) = LINK_LAYER_CORE_PARAMETERS; *(packet_address++) = 3; *(packet_address++) = FMIF_SIZE; *(packet_address++) = (DataLink_Struct.n201 >> 7); *(packet_address++) = EXTENSION | (DataLink_Struct.n201 & 0x7f); } else DataLink_Struct.n201 = DataLink_Struct.default_n201;
if (Received_K_Factor || Received_T200) { /*
** Link Layer Protocol Parameters */ *(packet_address++) = LINK_LAYER_PROTOCOL_PARAMETERS; length_address = packet_address; *(packet_address++) = 0; if (Received_K_Factor) { *length_address += 2; *(packet_address++) = TRANSMIT_WINDOW_SIZE_IDENTIFIER; *(packet_address++) = EXTENSION | DataLink_Struct.k_factor; } if (Received_T200) { *length_address += 3; *(packet_address++) = RETRANSMISSION_TIMER_IDENTIFIER; *(packet_address++) = (DataLink_Struct.t200 >> 7) & 0x7f; *(packet_address++) = EXTENSION | (DataLink_Struct.t200 & 0x7f); } } if (Received_K_Factor == FALSE) DataLink_Struct.k_factor = DataLink_Struct.default_k_factor; if (Received_T200 == FALSE) DataLink_Struct.t200 = DataLink_Struct.default_t200;
if (Received_Priority) { /*
** X.213 Priority */ *(packet_address++) = X213_PRIORITY; *(packet_address++) = 1; *(packet_address++) = (BYTE) (EXTENSION | Priority); } /*
** Attempt to send the packet to the lower layer */ Lower_Layer -> DataRequest ( 0, memory, &bytes_accepted); if (bytes_accepted == total_length) { StartTimerT313 (); Packet_Pending = NO_PACKET; State = CONNECT_SENT; } Data_Request_Memory_Manager -> FreeMemory (memory); }
/*
* void SCFCall::SendConnectAcknowledge (void); * * Functional Description * This function attempts to send out a CONNECT ACKNOWLEDGE packet * * Formal Parameters * None * * Return Value * None * * Side Effects * If this function is able to send the packet to the lower layer, * it sets the Packet_Pending variable to NO_PACKET * * Caveats * None * */ void SCFCall::SendConnectAcknowledge (void) { TRACE_OUT(("SCFCall::SendConnectAcknowledge"));
LPBYTE packet_address; USHORT total_length; PMemory memory; ULONG bytes_accepted;
total_length = CONNECT_ACK_PACKET_SIZE + Lower_Layer_Prepend + Lower_Layer_Append; /*
** Prepare the command and send it to the lower layer */ memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) return;
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = Q931_PROTOCOL_DISCRIMINATOR; *(packet_address++) = 1; *(packet_address++) = (UChar) Call_Reference; *(packet_address++) = CONNECT_ACKNOWLEDGE;
Lower_Layer -> DataRequest ( 0, memory, &bytes_accepted); if (bytes_accepted == total_length) { State = CALL_ESTABLISHED; Packet_Pending = NO_PACKET; } Data_Request_Memory_Manager -> FreeMemory (memory); }
/*
* void SCFCall::SendReleaseComplete (void); * * Functional Description * This function attempts to send out a RELEASE COMPLETE packet * * Formal Parameters * None * * Return Value * None * * Side Effects * If this function is able to send a RELEASE COMPLETE packet to the lower * layer, it sets the Packet_Pending variable to NO_PACKET * * Caveats * None * */ void SCFCall::SendReleaseComplete (void) { TRACE_OUT(("SCFCall::SendReleaseComplete"));
LPBYTE packet_address; ULONG bytes_accepted; USHORT total_length; PMemory memory;
total_length = RELEASE_COMPLETE_PACKET_SIZE + Lower_Layer_Prepend + Lower_Layer_Append; /*
** Prepare the command and send it to the lower layer */ memory = Data_Request_Memory_Manager -> AllocateMemory ( NULL, total_length); if (memory == NULL) return;
packet_address = memory -> GetPointer (); packet_address += Lower_Layer_Prepend;
*(packet_address++) = Q931_PROTOCOL_DISCRIMINATOR; *(packet_address++) = 1; if (Link_Originator) *(packet_address++) = (UChar) Call_Reference; else *(packet_address++) = 0x80 | Call_Reference; *(packet_address++) = RELEASE_COMPLETE;
/*
** Append the CAUSE for the link breakup */ *(packet_address++) = CAUSE; *(packet_address++) = 2; *(packet_address++) = EXTENSION; *(packet_address++) = EXTENSION | Release_Cause;
Lower_Layer -> DataRequest ( 0, memory, &bytes_accepted); if (bytes_accepted == total_length) { State = NOT_CONNECTED; Packet_Pending = NO_PACKET; } Data_Request_Memory_Manager -> FreeMemory (memory); }
/*
* void SCFCall::StartTimerT303 (void); * * Functional Description * This function Starts the T303 Timer. This is started when we send * out the SETUP packet. It is stopped when we receive a CONNECT * packet. If it expires we terminate the link. * * Formal Parameters * None * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::StartTimerT303 (void) { TRACE_OUT(("SCFCall::StartTimerT303"));
if (T303_Active) StopTimerT303 ();
T303_Handle = g_pSystemTimer->CreateTimerEvent( T303_Timeout, TIMER_EVENT_ONE_SHOT, this, (PTimerFunction) &SCFCall::T303Timeout);
T303_Active = TRUE;
}
/*
* void SCFCall::StopTimerT303 (void); * * Functional Description * This function stops the T303 Timer. This is called when we receive * the CONNECT packet. As a result, we stop the timer. * * Formal Parameters * None * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::StopTimerT303 (void) { TRACE_OUT(("SCFCall::StopTimerT303"));
if (T303_Active) { g_pSystemTimer->DeleteTimerEvent(T303_Handle); T303_Active = FALSE; } }
/*
* void SCFCall::T303Timeout ( * TimerEventHandle); * * Functional Description * This function is called by the System timer when the T303 timeout * expires. As a result, we terminate the link. * * Formal Parameters * None used * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::T303Timeout ( TimerEventHandle) { TRACE_OUT(("SCFCall: T303Timeout"));
if (T303_Count >= 1) State = NOT_CONNECTED;
T303_Count++;
Packet_Pending = RELEASE_COMPLETE; Release_Cause = NORMAL_USER_DISCONNECT; }
/*
* void SCFCall::StartTimerT313 (void); * * Functional Description * This function Starts the T313 Timer. This is started when we send * out the CONNECT packet. It is stopped when we receive a CONNECT ACK * packet. If it expires we terminate the link. * * Formal Parameters * None * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::StartTimerT313 (void) { TRACE_OUT(("SCFCall: StartTimerT313"));
if (T313_Active) StopTimerT313 ();
T313_Handle = g_pSystemTimer->CreateTimerEvent( T313_Timeout, TIMER_EVENT_ONE_SHOT, this, (PTimerFunction) &SCFCall::T313Timeout);
T313_Active = TRUE; }
/*
* void SCFCall::StopTimerT313 (void); * * Functional Description * This function stops the T313 Timer. This is called when we receive * the CONNECT ACK packet. As a result, we stop the timer. * * Formal Parameters * None * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::StopTimerT313 (void) { TRACE_OUT(("SCFCall: StopTimerT313"));
if (T313_Active) { g_pSystemTimer->DeleteTimerEvent(T313_Handle); T313_Active = FALSE; } }
/*
* void SCFCall::T313Timeout ( * TimerEventHandle); * * Functional Description * This function is called by the System timer when the T313 timeout * expires. As a result, we terminate the link. * * Formal Parameters * None used * * Return Value * None * * Side Effects * None * * Caveats * None * */ void SCFCall::T313Timeout ( TimerEventHandle) { TRACE_OUT(("SCFCall: T313Timeout"));
State = NOT_CONNECTED; Packet_Pending = RELEASE_COMPLETE; Release_Cause = NORMAL_USER_DISCONNECT; }
|