You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1449 lines
47 KiB
1449 lines
47 KiB
#include "precomp.h"
|
|
DEBUG_FILEZONE(ZONE_T120_T123PSTN);
|
|
|
|
/* TransportController.cpp
|
|
*
|
|
* Copyright (c) 1993-1995 by DataBeam Corporation, Lexington, KY
|
|
*
|
|
* Abstract:
|
|
* This is the implementation file for the TransportController class
|
|
*
|
|
* Private Instance Variables:
|
|
* Logical_Connection_List - This list uses the LogicalHandle
|
|
* as a key and a pointer to a
|
|
* TransportConnectionStruct as the value. This
|
|
* structure holds all of the pertinent information
|
|
* about the connection.
|
|
* Protocol_Stacks - This list uses the physical handle as a key and
|
|
* a pointer to a pointer to a object as the value.
|
|
* Sometimes we need to find the T123 object
|
|
* associated with a physical handle
|
|
* Message_List - Owner callback calls are placed in this list if
|
|
* we can not process them immediately.
|
|
* Controller - Address of the PSTNController
|
|
* Emergency_Shutdown - Set to TRUE if we have encountered a situation
|
|
* where the integrity of the Transport has been
|
|
* compromised. As a result, all connections will
|
|
* be purged.
|
|
* Poll_Active - Set to TRUE while we are in a PollReceiver() or
|
|
* PollTransmitter() call. This solves our re-
|
|
* entrancy problems.
|
|
*
|
|
* Caveats:
|
|
* None
|
|
*
|
|
* Author:
|
|
* James W. Lawwill
|
|
*/
|
|
#include "tprtcore.h"
|
|
|
|
|
|
/*
|
|
* TransportController::TransportController (
|
|
* PTransportResources transport_resources)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* TransportController constructor. We instantiate the PSTNController
|
|
* and initialize the T123 class.
|
|
*/
|
|
TransportController::TransportController(void)
|
|
:
|
|
Protocol_Stacks (TRANSPORT_HASHING_BUCKETS),
|
|
Logical_Connection_List (TRANSPORT_HASHING_BUCKETS)
|
|
{
|
|
TRACE_OUT(("TransportController::TransportController"));
|
|
|
|
Emergency_Shutdown = FALSE;
|
|
Poll_Active = FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportController::~TransportController (void)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This is the TransportController destructor. All allocated memory is
|
|
* released and all lists are cleared
|
|
*/
|
|
TransportController::~TransportController (void)
|
|
{
|
|
TRACE_OUT(("TransportController::~TransportController"));
|
|
|
|
Reset (FALSE);
|
|
}
|
|
|
|
|
|
TransportError TransportController::CreateTransportStack
|
|
(
|
|
BOOL fCaller,
|
|
HANDLE hCommLink,
|
|
HANDLE hevtClose,
|
|
PLUGXPRT_PARAMETERS *pParams
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::CreateTransportStack"));
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
ComPort *comport = new ComPort(this, PHYSICAL_LAYER_MESSAGE_BASE,
|
|
pParams,
|
|
hCommLink,
|
|
hevtClose);
|
|
if (NULL != comport)
|
|
{
|
|
TransportError rc = CreateT123Stack(hCommLink, fCaller, comport, pParams);
|
|
if (TRANSPORT_NO_ERROR == rc)
|
|
{
|
|
ComPortError cperr = comport->Open();
|
|
if (COMPORT_NO_ERROR == cperr)
|
|
{
|
|
return TRANSPORT_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
ERROR_OUT(("TransportController::CreateTransportStack: cannot open comm port"));
|
|
return TRANSPORT_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
ERROR_OUT(("TransportController::CreateTransportStack: cannot allocate ComPort"));
|
|
return TRANSPORT_MEMORY_FAILURE;
|
|
}
|
|
|
|
|
|
TransportError TransportController::CloseTransportStack
|
|
(
|
|
HANDLE hCommLink
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::CloseTransportStack"));
|
|
|
|
/*
|
|
** If for some reason we get an error on the ConnectRequest(),
|
|
** take the physical connection down.
|
|
*/
|
|
T123 *t123 = NULL;
|
|
if (Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
|
|
{
|
|
RemoveLogicalConnections (hCommLink);
|
|
|
|
/*
|
|
** Remove the T123 object from the lists and
|
|
** delete the object
|
|
*/
|
|
Transmitter_List.remove((DWORD_PTR) t123);
|
|
Protocol_Stacks.remove((DWORD_PTR) hCommLink);
|
|
delete t123;
|
|
}
|
|
|
|
// find the physical layer through the physical handle
|
|
ComPort *comport;
|
|
if (! g_pComPortList2->find((DWORD_PTR) hCommLink, (PDWORD_PTR) &comport))
|
|
{
|
|
WARNING_OUT(("TransportController::CloseTransportStack: cannot find comport for hCommLink=%d", hCommLink));
|
|
return TRANSPORT_PHYSICAL_LAYER_NOT_FOUND;
|
|
}
|
|
ASSERT(NULL != comport);
|
|
|
|
// close and delete the device
|
|
// g_pComPortList2->remove((DWORD) hCommLink); // removed in handling "delete event"
|
|
comport->Release();
|
|
|
|
return TRANSPORT_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::ConnectRequest (
|
|
* TransportAddress transport_address,
|
|
* TransportPriority transport_priority,
|
|
* LogicalHandle * logical_handle)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function initiates a connection. It passes the transport address
|
|
* to the PSTN Controller. It will either deny the request or accept the
|
|
* request and call us back when the physical connection is established.
|
|
*
|
|
* We return the transport connection handle in the logical_handle
|
|
* address. Although we return this transport number to the user, it
|
|
* is not ready for data transfer until the user receives the
|
|
* TRANSPORT_CONNECT_INDICATION message via the callback. At that point,
|
|
* the logical connection is up and running.
|
|
*/
|
|
TransportError TransportController::ConnectRequest
|
|
(
|
|
LogicalHandle *logical_handle,
|
|
HANDLE hCommLink, // physical handle
|
|
TransportPriority transport_priority
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::CreateConnection"));
|
|
|
|
*logical_handle = GetNextLogicalHandle();
|
|
if (INVALID_LOGICAL_HANDLE == *logical_handle)
|
|
{
|
|
ERROR_OUT(("TransportController::ConnectRequest: cannot allocate logical handle"));
|
|
return TRANSPORT_MEMORY_FAILURE;
|
|
}
|
|
|
|
// find the physical layer through the physical handle
|
|
ComPort *comport;
|
|
if (! g_pComPortList2->find((DWORD_PTR) hCommLink, (PDWORD_PTR) &comport))
|
|
{
|
|
ERROR_OUT(("TransportController::ConnectRequest: cannot find comport for hCommLink=%d", hCommLink));
|
|
return TRANSPORT_PHYSICAL_LAYER_NOT_FOUND;
|
|
}
|
|
ASSERT(NULL != comport);
|
|
|
|
/*
|
|
** Register the connection handle in out Logical_Connection_List. After the
|
|
** physical connection is established, we will create a T123 object
|
|
** and request a logical connection to the remote site.
|
|
**
|
|
** This structure contains the information necessary to maintain the
|
|
** logical connection.
|
|
**
|
|
** The t123_connection_requested is set to TRUE when we have issued
|
|
** a ConnectRequest() to the T123 object for this logical connection.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
PLogicalConnectionStruct pConn = new LogicalConnectionStruct;
|
|
if (pConn == NULL)
|
|
{
|
|
ERROR_OUT(("TransportController::ConnectRequest: cannot to allocate LogicalConnectionStruct"));
|
|
return (TRANSPORT_MEMORY_FAILURE);
|
|
}
|
|
|
|
pConn->fCaller = TRUE;
|
|
pConn->comport = comport;
|
|
pConn->t123 = NULL;
|
|
pConn->t123_connection_requested = FALSE;
|
|
pConn->t123_disconnect_requested = FALSE;
|
|
pConn->priority = transport_priority;
|
|
pConn->hCommLink = hCommLink;
|
|
Logical_Connection_List.insert((DWORD_PTR) *logical_handle, (DWORD_PTR) pConn);
|
|
|
|
return NewConnection(hCommLink, TRUE, comport);
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::ConnectResponse (
|
|
* LogicalHandle logical_handle)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is called by the user in response to a
|
|
* TRANSPORT_CONNECT_INDICATION callback from us. By making this call the
|
|
* user is accepting the call. If the user does not want to accept the
|
|
* he should call DisconnectRequest ();
|
|
*/
|
|
TransportError TransportController::ConnectResponse
|
|
(
|
|
LogicalHandle logical_handle
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::ConnectResponse"));
|
|
|
|
PLogicalConnectionStruct pConn;
|
|
PT123 t123;
|
|
|
|
/*
|
|
** If this is an invalid handle, return error
|
|
*/
|
|
if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
|
|
return (TRANSPORT_NO_SUCH_CONNECTION);
|
|
|
|
t123 = pConn -> t123;
|
|
|
|
/*
|
|
** If the user calls this function before the T123 object is created, that
|
|
** is an error
|
|
*/
|
|
return (t123 != NULL) ? t123->ConnectResponse(logical_handle) : TRANSPORT_NO_SUCH_CONNECTION;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::DisconnectRequest (
|
|
* LogicalHandle logical_handle,
|
|
* BOOL trash_packets)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function issues a Disconnect request to the T123 object (if it
|
|
* exists). If T123 does not exist, it hangs up the physical connection.
|
|
*/
|
|
TransportError TransportController::DisconnectRequest
|
|
(
|
|
LogicalHandle logical_handle,
|
|
UINT_PTR trash_packets
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::DisconnectRequest"));
|
|
|
|
PhysicalHandle physical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
BOOL transport_found;
|
|
PT123 t123;
|
|
PMessageStruct passive_message;
|
|
TransportError rc = TRANSPORT_NO_ERROR;
|
|
|
|
/*
|
|
** If the logical connection handle is not registered, return error
|
|
*/
|
|
if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn) == FALSE)
|
|
return (TRANSPORT_NO_SUCH_CONNECTION);
|
|
|
|
TRACE_OUT(("TPRTCTRL: DisconnectRequest for logical handle %d", logical_handle));
|
|
|
|
/*
|
|
** Calling this function during a callback from this transport
|
|
** is a re-entrancy problem. In this case, we add a message to
|
|
** our Message_List and process the request later.
|
|
*/
|
|
if (! Poll_Active)
|
|
{
|
|
/*
|
|
** We set the t123_disconnect_requested to TRUE at this point so
|
|
** that when we get the TPRT_DISCONNECT_INDICATION message back
|
|
** from the t123 object, we will know who originated the
|
|
** operation. If we originated the operation locally, we do not
|
|
** issue a TRANSPORT_DISCONNECT_INDICATION to the user.
|
|
*/
|
|
pConn -> t123_disconnect_requested = TRUE;
|
|
|
|
/*
|
|
** If a T123 object is associated with this object, issue a disconnect
|
|
*/
|
|
t123 = pConn -> t123;
|
|
if (t123 != NULL)
|
|
{
|
|
t123 -> DisconnectRequest (logical_handle, trash_packets);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
** This occurs if the user wants to terminate the connection
|
|
** before it comes all the way up
|
|
**
|
|
** Remove the transport connection handle from the
|
|
** Logical_Connection_List
|
|
*/
|
|
Logical_Connection_List.remove (logical_handle);
|
|
delete pConn;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
** If we are in the middle of a PollReceiver() or PollTransmitter(),
|
|
** and this function is being called during a callback from this
|
|
** transport, save the message and process it later.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
passive_message = new MessageStruct;
|
|
if (passive_message != NULL)
|
|
{
|
|
passive_message -> message = TPRT_DISCONNECT_REQUEST;
|
|
passive_message -> parameter1 = (void *) logical_handle;
|
|
passive_message -> parameter2 = (void *) trash_packets;
|
|
Message_List.append ((DWORD_PTR) passive_message);
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("TransportController::DisconnectRequest: cannot allocate MessageStruct"));
|
|
rc = TRANSPORT_MEMORY_FAILURE;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::EnableReceiver (void)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function allows data packets to be sent to the user application.
|
|
* Prior to this call, we must have sent a data packet to the user and
|
|
* the user must not have been able to accept it. When this happens, the
|
|
* user must issue this call to re-enable TRANSPORT_DATA_INDICATIONs.
|
|
* callbacks.
|
|
*/
|
|
void TransportController::EnableReceiver(void)
|
|
{
|
|
TRACE_OUT(("TransportController::EnableReceiver"));
|
|
|
|
PT123 t123;
|
|
PLogicalConnectionStruct pConn;
|
|
|
|
/*
|
|
** Go through each of the Transports and enable the receivers
|
|
*/
|
|
Logical_Connection_List.reset();
|
|
while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn))
|
|
{
|
|
t123 = pConn -> t123;
|
|
|
|
/*
|
|
** If the protocol stack pointer is set to NULL, then we have not
|
|
** realized that the socket is up and functional.
|
|
*/
|
|
if (t123 != NULL)
|
|
{
|
|
t123 -> EnableReceiver ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::DataRequest (
|
|
* LogicalHandle logical_handle,
|
|
* LPBYTE user_data,
|
|
* ULONG user_data_length)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is used to send a data packet to the remote site.
|
|
* This function passes the request to the T123 stack associated with
|
|
* the transport connection handle
|
|
*/
|
|
TransportError TransportController::DataRequest
|
|
(
|
|
LogicalHandle logical_handle,
|
|
LPBYTE user_data,
|
|
ULONG user_data_length
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::DataRequest"));
|
|
|
|
PLogicalConnectionStruct pConn;
|
|
PT123 t123;
|
|
|
|
/*
|
|
** Verify that this connection exists and is ready for data
|
|
*/
|
|
if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
|
|
{
|
|
WARNING_OUT(("TPRTCTRL: DataRequest: Illegal logical_handle"));
|
|
return (TRANSPORT_NO_SUCH_CONNECTION);
|
|
}
|
|
|
|
/*
|
|
** Attempt to send that data to the T123 Layer
|
|
*/
|
|
t123 = pConn -> t123;
|
|
return (t123 != NULL) ? t123->DataRequest(logical_handle, user_data, user_data_length) :
|
|
TRANSPORT_NOT_READY_TO_TRANSMIT;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransportError TransportController::PurgeRequest (
|
|
* LogicalHandle logical_handle)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is called to remove data from our output queues. The
|
|
* user application usually calls this to speed up the disconnect process.
|
|
*/
|
|
TransportError TransportController::PurgeRequest
|
|
(
|
|
LogicalHandle logical_handle
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::PurgeRequest"));
|
|
|
|
PLogicalConnectionStruct pConn;
|
|
PT123 t123;
|
|
|
|
/*
|
|
** If the transport connection handle is not registered, return error
|
|
*/
|
|
if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
|
|
return (TRANSPORT_NO_SUCH_CONNECTION);
|
|
|
|
t123 = pConn -> t123;
|
|
return (t123 != NULL) ? t123->PurgeRequest(logical_handle) : TRANSPORT_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::PollReceiver (void)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is called to give us a chance to process incoming data
|
|
*/
|
|
void TransportController::PollReceiver(void)
|
|
{
|
|
// TRACE_OUT(("TransportController::PollReceiver"));
|
|
|
|
PT123 t123;
|
|
|
|
if (! Poll_Active)
|
|
{
|
|
ProcessMessages ();
|
|
Poll_Active = TRUE;
|
|
|
|
if (! Transmitter_List.isEmpty())
|
|
{
|
|
Transmitter_List.reset();
|
|
while (Transmitter_List.iterate((PDWORD_PTR) &t123))
|
|
{
|
|
t123-> PollReceiver ();
|
|
}
|
|
|
|
/*
|
|
** The following code removes the first t123 object from the
|
|
** list and puts it at the end of the list. This attempts to
|
|
** give the t123 objects equal access to the user application.
|
|
** If we did not do this, one t123 object would always be able
|
|
** to send its data to the user application and other t123
|
|
** objects would be locked out.
|
|
*/
|
|
Transmitter_List.append (Transmitter_List.get ());
|
|
}
|
|
Poll_Active = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::PollReceiver (
|
|
* PhysicalHandle physical_handle)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function gives the t123 object associated with this physical
|
|
* handle a chance to process incoming data.
|
|
*/
|
|
void TransportController::PollReceiver
|
|
(
|
|
PhysicalHandle physical_handle
|
|
)
|
|
{
|
|
// TRACE_OUT(("TransportController::PollReceiver"));
|
|
|
|
PT123 t123;
|
|
|
|
if (! Poll_Active)
|
|
{
|
|
ProcessMessages ();
|
|
Poll_Active = TRUE;
|
|
|
|
/*
|
|
** See if there is a t123 object associated with this
|
|
** physical handle
|
|
*/
|
|
if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
|
|
{
|
|
if (t123->PollReceiver() == PROTOCOL_LAYER_ERROR)
|
|
{
|
|
Transmitter_List.remove((DWORD_PTR) t123);
|
|
Protocol_Stacks.remove((DWORD_PTR) physical_handle);
|
|
delete t123;
|
|
}
|
|
}
|
|
|
|
Poll_Active = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::PollTransmitter (void)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function processes output data to remote sites. This
|
|
* function MUST be called on a REGULAR and FREQUENT basis so that
|
|
* we can maintain the physical connections in a timely manner.
|
|
*/
|
|
void TransportController::PollTransmitter(void)
|
|
{
|
|
// TRACE_OUT(("TransportController::PollTransmitter"));
|
|
|
|
if (! Poll_Active)
|
|
{
|
|
PT123 t123;
|
|
|
|
Poll_Active = TRUE;
|
|
|
|
/*
|
|
** Allow each t123 object to transmit any data it has available.
|
|
*/
|
|
Transmitter_List.reset();
|
|
while (Transmitter_List.iterate ((PDWORD_PTR) &t123))
|
|
{
|
|
t123->PollTransmitter ();
|
|
}
|
|
|
|
Poll_Active = FALSE;
|
|
ProcessMessages ();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::PollTransmitter (
|
|
* PhysicalHandle physical_handle)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
*/
|
|
void TransportController::PollTransmitter
|
|
(
|
|
PhysicalHandle physical_handle
|
|
)
|
|
{
|
|
// TRACE_OUT(("TransportController::PollTransmitter"));
|
|
|
|
PT123 t123;
|
|
|
|
if (! Poll_Active)
|
|
{
|
|
Poll_Active = TRUE;
|
|
|
|
/*
|
|
** See if there is a t123 object associated with this
|
|
** physical handle
|
|
*/
|
|
if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
|
|
{
|
|
t123->PollTransmitter();
|
|
}
|
|
|
|
Poll_Active = FALSE;
|
|
ProcessMessages ();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* PhysicalHandle TransportController::GetPhysicalHandle (
|
|
* LogicalHandle logical_handle);
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function returns the physical handle associated with the
|
|
* logical handle.
|
|
*/
|
|
PhysicalHandle TransportController::GetPhysicalHandle (
|
|
LogicalHandle logical_handle)
|
|
{
|
|
TRACE_OUT(("TransportController::GetPhysicalHandle"));
|
|
|
|
PhysicalHandle physical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
|
|
if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
|
|
{
|
|
physical_handle = pConn -> hCommLink;
|
|
}
|
|
else
|
|
{
|
|
physical_handle = 0;
|
|
}
|
|
|
|
return (physical_handle);
|
|
}
|
|
|
|
|
|
/*
|
|
* ULONG TransportController::OwnerCallback (
|
|
* CallbackMessage message,
|
|
* ULONG parameter1,
|
|
* ULONG parameter2,
|
|
* PVoid parameter3)
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is called by the PSTNController and the T123 object(s).
|
|
* This function is called when a significant event occurs. This gives the
|
|
* lower objects the ability to communicate with the higher layer.
|
|
*/
|
|
ULONG_PTR TransportController::OwnerCallback
|
|
(
|
|
ULONG message,
|
|
void *parameter1,
|
|
void *parameter2,
|
|
void *parameter3
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::OwnerCallback"));
|
|
|
|
PMessageStruct passive_message;
|
|
LogicalHandle logical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
LegacyTransportID transport_identifier;
|
|
ULONG_PTR return_value = 0;
|
|
PT123 t123;
|
|
|
|
message = message - TRANSPORT_CONTROLLER_MESSAGE_BASE;
|
|
|
|
switch (message)
|
|
{
|
|
case TPRT_CONNECT_INDICATION:
|
|
/*
|
|
** The TPRT_CONNECT_INDICATION message comes from a T123
|
|
** object when the remote site is attempting to make a
|
|
** logical connection with us. We issue a callback to the
|
|
** user to notify him of the request
|
|
*/
|
|
|
|
// LONCHANC: we automatically accept the call
|
|
ConnectResponse((LogicalHandle) parameter1);
|
|
|
|
transport_identifier.logical_handle = (LogicalHandle) parameter1;
|
|
|
|
if (Logical_Connection_List.find((DWORD_PTR) parameter1, (PDWORD_PTR) &pConn))
|
|
{
|
|
transport_identifier.hCommLink = pConn->hCommLink;
|
|
}
|
|
else
|
|
{
|
|
transport_identifier.hCommLink = NULL;
|
|
}
|
|
|
|
TRACE_OUT(("TPRTCTRL: CONNECT_INDICATION: physical_handle = %d",
|
|
transport_identifier.hCommLink));
|
|
|
|
::NotifyT120(TRANSPORT_CONNECT_INDICATION, &transport_identifier);
|
|
break;
|
|
|
|
case TPRT_CONNECT_CONFIRM:
|
|
/*
|
|
** The TPRT_CONNECT_CONFIRM message comes from a T123 object
|
|
** when a logical connection that we requested is up and
|
|
** running. We notify the user of this by issuing a callback.
|
|
*/
|
|
transport_identifier.logical_handle = (LogicalHandle) parameter1;
|
|
|
|
if (Logical_Connection_List.find((DWORD_PTR) parameter1, (PDWORD_PTR) &pConn))
|
|
{
|
|
transport_identifier.hCommLink = pConn->hCommLink;
|
|
}
|
|
else
|
|
{
|
|
transport_identifier.hCommLink = NULL;
|
|
}
|
|
|
|
TRACE_OUT(("TPRTCTRL: CONNECT_CONFIRM: physical_handle = %d",
|
|
transport_identifier.hCommLink));
|
|
|
|
::NotifyT120(TRANSPORT_CONNECT_CONFIRM, &transport_identifier);
|
|
break;
|
|
|
|
case REQUEST_TRANSPORT_CONNECTION:
|
|
/*
|
|
** This message is issued when a T123 object is making a new
|
|
** logical connection and needs a new logical handle.
|
|
**
|
|
** If we return INVALID_LOGICAL_HANDLE, we wer not able to
|
|
** get a handle.
|
|
*/
|
|
logical_handle = GetNextLogicalHandle();
|
|
if (logical_handle == INVALID_LOGICAL_HANDLE)
|
|
{
|
|
return_value = INVALID_LOGICAL_HANDLE;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Register the new transport connection handle in the
|
|
** Logical_Connection_List
|
|
**
|
|
** Parameter1 holds the physical handle
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
pConn = new LogicalConnectionStruct;
|
|
if (pConn != NULL)
|
|
{
|
|
Logical_Connection_List.insert (logical_handle, (DWORD_PTR) pConn);
|
|
pConn->fCaller = FALSE;
|
|
pConn->hCommLink = (PhysicalHandle) parameter1;
|
|
Protocol_Stacks.find((DWORD_PTR) parameter1, (PDWORD_PTR) &t123);
|
|
pConn -> t123 = t123;
|
|
|
|
/*
|
|
** Set the t123_connection_requested to TRUE. We didn't
|
|
** actually make a ConnectRequest() but the T123 object does
|
|
** know about the connection
|
|
*/
|
|
pConn -> t123_connection_requested = TRUE;
|
|
pConn -> t123_disconnect_requested = FALSE;
|
|
return_value = logical_handle;
|
|
}
|
|
else
|
|
{
|
|
TRACE_OUT(("TPRTCTRL: Unable to allocate memory "
|
|
"for connection"));
|
|
return_value = INVALID_LOGICAL_HANDLE;
|
|
}
|
|
break;
|
|
|
|
/*
|
|
** The following messages can NOT be processed during the callback.
|
|
** They are passive messages, that is they must be saved and
|
|
** processed at a later time. The BROKEN_CONNECTION and
|
|
** TPRT_DISCONNECT_INDICATION messages involve destroying t123
|
|
** objects. If we deleted an object here and then returned to
|
|
** the object, this would cause a GPF. Therefore these messages
|
|
** are processed later.
|
|
**
|
|
** The NEW_CONNECTION callback is processed later because we want
|
|
** to process certain messages in the order they were received. If
|
|
** we received a NEW_CONNECTION followed by a BROKEN_CONNECTION
|
|
** followed by a NEW_CONNECTION, and we only processed the
|
|
** NEW_CONNECTION messages as they were received, it would really
|
|
** confuse the code.
|
|
*/
|
|
case TPRT_DISCONNECT_INDICATION:
|
|
case BROKEN_CONNECTION:
|
|
DBG_SAVE_FILE_LINE
|
|
passive_message = new MessageStruct;
|
|
if (passive_message != NULL)
|
|
{
|
|
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(("TPRTCTRL: TPRT_DISCONNECT_INDICATION: cannot allocate MessageStruct"));
|
|
Emergency_Shutdown = TRUE;
|
|
}
|
|
break;
|
|
|
|
case NEW_CONNECTION:
|
|
/*
|
|
** If we can not allocate the memory needed to store this
|
|
** message, we need to return a non-zero value to the
|
|
** calling routine.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
passive_message = new MessageStruct;
|
|
if (passive_message != NULL)
|
|
{
|
|
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(("TPRTCTRL: NEW_CONNECTION: cannot allocate MessageStruct"));
|
|
return_value = 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ERROR_OUT(("TPRTCTRL: OwnerCallback: Illegal message = %lx", message));
|
|
break;
|
|
}
|
|
return (return_value);
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::ProcessMessages (void)
|
|
*
|
|
* Functional Description
|
|
* This function is called periodically to process any passive owner
|
|
* callbacks. If an owner callback can not be processed immediately,
|
|
* it is put into the Message_List and processed at a later time.
|
|
*
|
|
* Formal Parameters
|
|
* None
|
|
*
|
|
* Return Value
|
|
* None
|
|
*
|
|
* Side Effects
|
|
* None
|
|
*
|
|
* Caveats
|
|
* None
|
|
*/
|
|
void TransportController::ProcessMessages(void)
|
|
{
|
|
// TRACE_OUT(("TransportController::ProcessMessages"));
|
|
|
|
ULONG message;
|
|
PMessageStruct message_struct;
|
|
IProtocolLayer *physical_layer;
|
|
void *parameter1;
|
|
void *parameter2;
|
|
void *parameter3;
|
|
|
|
LogicalHandle logical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
PhysicalHandle physical_handle;
|
|
BOOL save_message = FALSE;
|
|
LegacyTransportID transport_identifier;
|
|
PT123 t123;
|
|
BOOL link_originator;
|
|
BOOL disconnect_requested;
|
|
ComPort *comport;
|
|
|
|
/*
|
|
** This routine can not be called during a callback from this transport.
|
|
** In other words this code is not re-entrant.
|
|
*/
|
|
if (Poll_Active)
|
|
return;
|
|
|
|
/*
|
|
** Emergency_Shutdown can occur if we unsuccessfully attempt to allocate
|
|
** memory. In this situation, we shutdown the entire Transport
|
|
*/
|
|
if (Emergency_Shutdown)
|
|
{
|
|
Reset (TRUE);
|
|
Emergency_Shutdown = FALSE;
|
|
}
|
|
|
|
/*
|
|
** Go thru the Message_List until it is empty or until a message
|
|
** can not be processed.
|
|
*/
|
|
while ((! Message_List.isEmpty ()) && (! save_message))
|
|
{
|
|
/*
|
|
** Look at the first message in the Message_List.
|
|
*/
|
|
message_struct = (PMessageStruct) Message_List.read ();
|
|
message = (message_struct -> message) - TRANSPORT_CONTROLLER_MESSAGE_BASE;
|
|
parameter1 = message_struct -> parameter1;
|
|
parameter2 = message_struct -> parameter2;
|
|
parameter3 = message_struct -> parameter3;
|
|
|
|
switch (message)
|
|
{
|
|
case NEW_CONNECTION:
|
|
ASSERT(0); // impossible
|
|
/*
|
|
** This message is issued by the PSTNController to notify us
|
|
** a new physical connection exists or that a previously
|
|
** requested connection is going to be muxed over a
|
|
** currently active physical connection
|
|
**
|
|
** Parameter1 is the physical handle
|
|
** Parameter2 is a BOOL used to tell us if
|
|
** Parameter3 is the address of the physical layer handling
|
|
** this connection.
|
|
*/
|
|
physical_handle = (PhysicalHandle) parameter1;
|
|
link_originator = (BOOL) (DWORD_PTR)parameter2;
|
|
comport = (ComPort *) parameter3;
|
|
|
|
TRACE_OUT(("TPRTCTRL: ProcessMessage NEW_CONNECTION: Physical: handle = %ld", physical_handle));
|
|
|
|
if (TRANSPORT_NO_ERROR != NewConnection(physical_handle, link_originator, comport))
|
|
{
|
|
save_message = TRUE;
|
|
}
|
|
break;
|
|
|
|
case BROKEN_CONNECTION:
|
|
ASSERT(0); // impossible
|
|
/*
|
|
** This message is issued by the PSTNController when a
|
|
** physical connection has been broken.
|
|
**
|
|
** parameter1 = physical_handle
|
|
*/
|
|
physical_handle = (PhysicalHandle) parameter1;
|
|
|
|
TRACE_OUT(("TPRTCTRL: BROKEN_CONNECTION: phys_handle = %lx", physical_handle));
|
|
|
|
/*
|
|
** RemoveLogicalConnections() terminates all logical
|
|
** connections associated with this physical handle.
|
|
** There may be logical connections in our list even
|
|
** though a T123 does not exist for the physical handle
|
|
*/
|
|
TRACE_OUT(("TPRTCTRL: RemoveLogicalConnections: phys_handle = %lx", physical_handle));
|
|
RemoveLogicalConnections (physical_handle);
|
|
|
|
/*
|
|
** Check to see if there is a t123 stack associated
|
|
** with this physical handle.
|
|
*/
|
|
if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
|
|
{
|
|
/*
|
|
** Remove the T123 protocol stacks from our lists and
|
|
** delete it.
|
|
*/
|
|
Transmitter_List.remove((DWORD_PTR) t123);
|
|
Protocol_Stacks.remove((DWORD_PTR) physical_handle);
|
|
delete t123;
|
|
}
|
|
break;
|
|
|
|
case TPRT_DISCONNECT_REQUEST:
|
|
/*
|
|
** This message occurs when a DisconnectRequest() was received
|
|
** during a PollReceiver() call. We can NOT process the
|
|
** DisconnectRequest() during our callback to the user
|
|
** application, but we can queue the message and process it
|
|
** now
|
|
*/
|
|
DisconnectRequest((LogicalHandle) parameter1, (BOOL) (DWORD_PTR)parameter2);
|
|
break;
|
|
|
|
case TPRT_DISCONNECT_INDICATION:
|
|
/*
|
|
** This message is received from a T123 object when a logical
|
|
** connection is terminated. If the logical connection
|
|
** handle passed in parameter1 is INVALID_LOGICAL_HANDLE,
|
|
** the T123 object is telling us to terminate it.
|
|
**
|
|
** parameter1 = logical_handle
|
|
** parameter2 = physical_handle
|
|
** parameter3 = BOOL - TRUE if we requested this
|
|
** disconnection.
|
|
*/
|
|
logical_handle = (LogicalHandle) parameter1;
|
|
physical_handle = (PhysicalHandle) parameter2;
|
|
|
|
/*
|
|
** Check the physical_handle to make sure it is valid
|
|
*/
|
|
if (! Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
|
|
{
|
|
ERROR_OUT(("TPRTCTRL: ProcessMessages: DISCONNECT_IND **** Illegal Physical Handle = %ld", physical_handle));
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** If the logical_handle is INVALID_LOGICAL_HANDLE, the
|
|
** T123 object is telling us to delete it.
|
|
*/
|
|
if (logical_handle == INVALID_LOGICAL_HANDLE)
|
|
{
|
|
TRACE_OUT(("TPRTCTRL: Protocol stack deleted - phys handle = %ld", physical_handle));
|
|
|
|
/*
|
|
** Find out the value of parameter3 before we
|
|
** delete the t123 object.
|
|
*/
|
|
disconnect_requested = *((BOOL *) parameter3);
|
|
|
|
/*
|
|
** Call RemoveLogicalConnections() to remove all logical
|
|
** connections associated with this physical handle.
|
|
*/
|
|
RemoveLogicalConnections (physical_handle);
|
|
|
|
/*
|
|
** Remove the T123 object from the lists and delete the
|
|
** object
|
|
*/
|
|
Transmitter_List.remove((DWORD_PTR) t123);
|
|
Protocol_Stacks.remove((DWORD_PTR) physical_handle);
|
|
delete t123;
|
|
}
|
|
else
|
|
if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
|
|
{
|
|
/*
|
|
** This specifies that a logical connection needs to be
|
|
** removed. We remove it from the Logical_Connection_List
|
|
** and notify the user of the disconnection
|
|
*/
|
|
Logical_Connection_List.remove (logical_handle);
|
|
|
|
if (! pConn->t123_disconnect_requested)
|
|
{
|
|
transport_identifier.logical_handle = logical_handle;
|
|
transport_identifier.hCommLink = physical_handle;
|
|
|
|
::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
|
|
}
|
|
delete pConn;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ERROR_OUT(("TPRTCTRL: ProcessMessages: Illegal message = %lx", message));
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** If save_message is TRUE, the message needs to be re-processed at a
|
|
** later time.
|
|
*/
|
|
if (! save_message)
|
|
{
|
|
delete ((PMessageStruct) Message_List.get ());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::Reset (
|
|
* BOOL notify_user)
|
|
*
|
|
* Functional Description
|
|
* This function deletes all stacks and TCs. If the notify_user flag is
|
|
* set to TRUE, it makes a callback to the user.
|
|
*
|
|
* Formal Parameters
|
|
* notify_user (i) - Notify User flag
|
|
*
|
|
* Return Value
|
|
* None
|
|
*
|
|
* Side Effects
|
|
* None
|
|
*
|
|
* Caveats
|
|
* None
|
|
*/
|
|
void TransportController::Reset
|
|
(
|
|
BOOL notify_user
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::Reset"));
|
|
|
|
LogicalHandle logical_handle;
|
|
PMessageStruct message_struct;
|
|
LegacyTransportID transport_identifier;
|
|
PhysicalHandle physical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
PT123 t123;
|
|
|
|
TRACE_OUT(("TPRTCTRL: reset: notify_user = %d", notify_user));
|
|
|
|
/*
|
|
** Delete all of the stacks
|
|
*/
|
|
Protocol_Stacks.reset();
|
|
while (Protocol_Stacks.iterate((PDWORD_PTR) &t123))
|
|
{
|
|
delete t123;
|
|
}
|
|
|
|
Protocol_Stacks.clear ();
|
|
Transmitter_List.clear ();
|
|
|
|
/*
|
|
** Empty the message list
|
|
*/
|
|
while (! Message_List.isEmpty ())
|
|
{
|
|
delete ((PMessageStruct) Message_List.get ());
|
|
}
|
|
|
|
/*
|
|
** Empty the Logical_Connection_List
|
|
*/
|
|
Logical_Connection_List.reset();
|
|
while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
|
|
{
|
|
if (pConn != NULL)
|
|
{
|
|
physical_handle = pConn->hCommLink;
|
|
delete pConn;
|
|
}
|
|
else
|
|
{
|
|
physical_handle = 0;
|
|
}
|
|
|
|
if (notify_user)
|
|
{
|
|
transport_identifier.logical_handle = logical_handle;
|
|
transport_identifier.hCommLink = physical_handle;
|
|
|
|
::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
|
|
}
|
|
}
|
|
Logical_Connection_List.clear ();
|
|
}
|
|
|
|
|
|
/*
|
|
* BOOL TransportController::NewConnection (
|
|
* PhysicalHandle physical_handle,
|
|
* BOOL link_originator,
|
|
* IProtocolLayer * physical_layer)
|
|
*
|
|
* Functional Description
|
|
* This function is called when a new physical connection is created. It
|
|
* creates a T123 object if necessary.
|
|
*
|
|
* Formal Parameters
|
|
* physical_handle (i) - physical handle of the new physical connection
|
|
* link_originator (i) - TRUE if we initiated the connection.
|
|
* physical_layer (i) - Address of the physical layer.
|
|
*
|
|
* Return Value
|
|
* TRUE, if the new connection was successfully executed.
|
|
*
|
|
* Side Effects
|
|
* None
|
|
*
|
|
* Caveats
|
|
* None
|
|
*/
|
|
TransportError TransportController::CreateT123Stack
|
|
(
|
|
PhysicalHandle hCommLink,
|
|
BOOL link_originator, // fCaller
|
|
ComPort *comport,
|
|
PLUGXPRT_PARAMETERS *pParams
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::CreateT123Stack"));
|
|
|
|
TransportError rc = TRANSPORT_NO_ERROR;
|
|
|
|
/*
|
|
** Do we need to create a new t123 stack for this physical connection.
|
|
*/
|
|
T123 *t123 = NULL;
|
|
if (! Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
|
|
{
|
|
BOOL initialized;
|
|
DBG_SAVE_FILE_LINE
|
|
t123 = new T123(this,
|
|
TRANSPORT_CONTROLLER_MESSAGE_BASE,
|
|
link_originator,
|
|
comport,
|
|
hCommLink,
|
|
pParams,
|
|
&initialized);
|
|
if (t123 != NULL && initialized)
|
|
{
|
|
/*
|
|
** Put the T123 object into the Protocol_Stacks
|
|
** and Transmitter_List arrays
|
|
*/
|
|
Protocol_Stacks.insert((DWORD_PTR) hCommLink, (DWORD_PTR) t123);
|
|
Transmitter_List.append((DWORD_PTR) t123);
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("TPRTCTRL: CreateT123Stack: cannot allocate T123"));
|
|
delete t123;
|
|
rc = TRANSPORT_MEMORY_FAILURE;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
TransportError TransportController::NewConnection
|
|
(
|
|
PhysicalHandle hCommLink,
|
|
BOOL link_originator,
|
|
ComPort *comport
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::NewConnection"));
|
|
|
|
LogicalHandle logical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
BOOL initialized;
|
|
T123 *t123;
|
|
TransportError rc;
|
|
|
|
if (! Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
|
|
{
|
|
ERROR_OUT(("TransportController::NewConnection: cannot find T123 stack, hCommLink=%d", hCommLink));
|
|
return TRANSPORT_NO_T123_STACK;
|
|
}
|
|
|
|
/*
|
|
** Go through each of the logical connections to find the
|
|
** ones that are waiting for this physical connection to be
|
|
** established. The PSTNController object issues a
|
|
** NEW_CONNECTION callback for each logical connection that
|
|
** needs to be initiated.
|
|
*/
|
|
Logical_Connection_List.reset();
|
|
while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
|
|
{
|
|
/*
|
|
** Compare the physical handles, if they are the same,
|
|
** check to see if this logical connection has already issued
|
|
** a ConnectRequest() to the T123 object.
|
|
*/
|
|
if (hCommLink == pConn->hCommLink)
|
|
{
|
|
/*
|
|
** See if this connection has already issued a ConnectRequest
|
|
*/
|
|
if (! pConn->t123_connection_requested)
|
|
{
|
|
/*
|
|
** Fill in the transport structure.
|
|
*/
|
|
pConn->t123 = t123;
|
|
pConn->comport = comport;
|
|
pConn->t123_connection_requested = TRUE;
|
|
|
|
/*
|
|
** Issue a Connect Request to the T123 object
|
|
*/
|
|
rc = t123->ConnectRequest(logical_handle, pConn->priority);
|
|
|
|
/*
|
|
** If for some reason we get an error on the ConnectRequest(),
|
|
** take the physical connection down.
|
|
*/
|
|
if (rc != TRANSPORT_NO_ERROR)
|
|
{
|
|
RemoveLogicalConnections (hCommLink);
|
|
|
|
/*
|
|
** Remove the T123 object from the lists and
|
|
** delete the object
|
|
*/
|
|
Transmitter_List.remove((DWORD_PTR) t123);
|
|
Protocol_Stacks.remove((DWORD_PTR) hCommLink);
|
|
delete t123;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRANSPORT_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*
|
|
* LogicalHandle TransportController::GetNextLogicalHandle (void);
|
|
*
|
|
* Functional Description
|
|
* This function returns an available logical handle
|
|
*
|
|
* Formal Parameters
|
|
* None
|
|
*
|
|
* Return Value
|
|
* The next available logical handle
|
|
*
|
|
* Side Effects
|
|
* None
|
|
*
|
|
* Caveats
|
|
* None
|
|
*/
|
|
LogicalHandle TransportController::GetNextLogicalHandle (void)
|
|
{
|
|
LogicalHandle logical_handle = 1;
|
|
|
|
/*
|
|
** Go thru the Logical_Connection_list, looking for the first
|
|
** available entry
|
|
*/
|
|
while (Logical_Connection_List.find (logical_handle) &&
|
|
(logical_handle != INVALID_LOGICAL_HANDLE))
|
|
{
|
|
logical_handle++;
|
|
}
|
|
|
|
return (logical_handle);
|
|
}
|
|
|
|
|
|
/*
|
|
* void TransportController::RemoveLogicalConnections (
|
|
* PhysicalHandle physical_handle)
|
|
*
|
|
* Functional Description
|
|
* This function removes all logical connections associated with the
|
|
* passed in physical handle
|
|
*
|
|
* Formal Parameters
|
|
* physical_handle (i) - PSTNController generated physical handle
|
|
*
|
|
* Return Value
|
|
* None
|
|
*
|
|
* Side Effects
|
|
* None
|
|
*
|
|
* Caveats
|
|
* None
|
|
*/
|
|
void TransportController::RemoveLogicalConnections
|
|
(
|
|
PhysicalHandle physical_handle
|
|
)
|
|
{
|
|
TRACE_OUT(("TransportController::RemoveLogicalConnections"));
|
|
|
|
LogicalHandle logical_handle;
|
|
PLogicalConnectionStruct pConn;
|
|
LegacyTransportID transport_identifier;
|
|
|
|
/*
|
|
** Go thru each logical connection to see if it is associated with the
|
|
** specified physical handle.
|
|
*/
|
|
Logical_Connection_List.reset();
|
|
while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
|
|
{
|
|
/*
|
|
** If the physical handle is used by the logical connection,
|
|
** delete the structure and remove it from the Logical_Connection_List
|
|
*/
|
|
if (physical_handle == pConn->hCommLink)
|
|
{
|
|
Logical_Connection_List.remove(logical_handle);
|
|
|
|
/*
|
|
** Notify the user that the logical connection is no longer valid
|
|
** If the user had previously issued a DisconnectRequest(), don't
|
|
** issue the TRANSPORT_DISCONNECT_INDICATION callback. The user
|
|
** isn't expecting a callback.
|
|
*/
|
|
if (! pConn->t123_disconnect_requested)
|
|
{
|
|
transport_identifier.logical_handle = logical_handle;
|
|
transport_identifier.hCommLink = physical_handle;
|
|
|
|
::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
|
|
}
|
|
delete pConn;
|
|
|
|
/*
|
|
** Since we removed an entry from the Logical_Connection_List,
|
|
** reset the iterator.
|
|
*/
|
|
Logical_Connection_List.reset ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|