Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

507 lines
14 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name :
xportcon.cxx
Abstract:
This module defines the member functions of XPORT_CONNECTIONS
which keeps track of information about connections for
different transports.
Author:
Murali R. Krishnan ( MuraliK ) 07-March-1995
Environment:
Win32 -- User Mode
Project:
Internet Services Common DLL
Functions Exported:
TS_XPORT_CONNECTIONS::Cleanup()
TS_XPORT_CONNECTIONS::EstablishListenConnections()
TS_XPORT_CONNECTIONS::StartListenPumps()
TS_XPORT_CONNECTIONS::StopListenPumps()
TS_XPORT_CONNECTIONS::GetListenSockets()
Revision History:
--*/
/************************************************************
* Include Headers
************************************************************/
# include <tcpdllp.hxx>
# include "conninfo.hxx"
/************************************************************
* Functions
************************************************************/
BOOL
TS_XPORT_CONNECTIONS::Cleanup( VOID)
/*++
This function cleansup the TS_XPORT_CONNECTIONS object.
It attempts to stop all the connection threads in each of the
ConnectionInfo object. Destroys the connection info objects and
deletes the array of connection info objects maintained.
Returns:
TRUE if successful and false if there are any errors.
--*/
{
IF_DEBUG( DLL_CONNECTION) {
DBGPRINTF( ( DBG_CONTEXT,
" Deleting the TS_XPORT_CONNECTIONS object %08x.\n",
this));
}
if ( m_ppConnectionInfo != NULL) {
PTS_CONNECTION_INFO_BASE * ppConnInfo;
StopListenPumps();
// return value is ignored. since all objects will be destroyed.
//
// Delete the individual Connection objects
//
for( ppConnInfo = m_ppConnectionInfo;
ppConnInfo < m_ppConnectionInfo + m_nXports;
ppConnInfo++) {
if ( *ppConnInfo != NULL) {
delete ( *ppConnInfo);
*ppConnInfo = NULL;
}
} // for
delete [] m_ppConnectionInfo;
m_ppConnectionInfo = NULL;
m_nXports = 0;
} // if ( m_ppConnectionInfo)
return ( TRUE);
} // TS_XPORT_CONNECTIONS::Cleanup()
BOOL
TS_XPORT_CONNECTIONS::EstablishListenConnections(
IN CONST TCHAR * pszServiceName,
IN PCSADDR_INFO pcsAddrInfo,
IN DWORD nAddresses,
OUT LPDWORD lpdwNumEstablished,
IN DWORD nListenBacklog,
IN BOOL fUseAcceptEx )
/*++
This function allocates nAddress TS_CONNECTION_INFO objects, one
each for one of the protocol addresses specified in the array
of Protocol addresses ( pcsAddrInfo).
It also creates listen sockets for each of the connection objects.
Arguments:
pszServiceName - Name of the service (i.e., W3Svc, GopherSvc etc).
Should correspond to the name specified to the RNR
API SetService during setup
pcsAddrInfo pointer to an array of CSADDR_INFO object, which
contain the protocol addresses to bind the
listen sockets to.
nAddresses number of addresses present in pcsAddrInfo
lpdwNumEstablished pointer to a DWORD, which on return will contain
the number of valid listen sockets established.
nListenBacklog number of backlogs for listen socket.
fUseAcceptEx TRUE if the connections are coming in on AcceptEx
(as opposed to thread per socket listens)
Returns:
TRUE on successfully establishing listen sockets for all the addresses
specified.
FALSE if there is a failure to create at least one listen socket.
The caller can ignore failures in establishing sockets if desired.
--*/
{
DWORD dwError = NO_ERROR;
DBG_ASSERT( lpdwNumEstablished != NULL);
DBG_ASSERT( nAddresses > 0);
IF_DEBUG( DLL_CONNECTION) {
DBGPRINTF( ( DBG_CONTEXT,
" EstablishListenSockets( %08x, %ul, %08x) called.\n",
pcsAddrInfo, nAddresses, lpdwNumEstablished));
}
*lpdwNumEstablished = 0; // Set this to nothing initially
DBG_ASSERT( m_ppConnectionInfo == NULL && m_nXports == 0);
//
// Allocate the TS_CONNECTION_INFO objects
//
m_ppConnectionInfo = new PTS_CONNECTION_INFO_BASE[ nAddresses];
if ( m_ppConnectionInfo == NULL) {
dwError = ERROR_NOT_ENOUGH_MEMORY;
} else {
PTS_CONNECTION_INFO_BASE * ppConnInfo;
PCSADDR_INFO pcsAddrScan;
ZeroMemory( m_ppConnectionInfo,
nAddresses*sizeof(PTS_CONNECTION_INFO));
m_nXports = nAddresses;
for( ppConnInfo = m_ppConnectionInfo, pcsAddrScan = pcsAddrInfo;
ppConnInfo < m_ppConnectionInfo + m_nXports;
ppConnInfo++, pcsAddrScan++) {
DBG_ASSERT( pcsAddrScan < pcsAddrInfo + nAddresses);
//
// Create a new PTS_CONNECTION_INFO object
//
if ( fUseAcceptEx ) {
*ppConnInfo = new TS_ACCEPTEX_CONNECTION_INFO();
} else {
*ppConnInfo = new TS_CONNECTION_INFO();
}
if ( *ppConnInfo == NULL) {
//
// The error is memory error. If there is a memory error,
// mostly all the subsequent operations will also fail.
// Indicate the cause of failure and stop creating new objects.
//
DBGPRINTF( ( DBG_CONTEXT,
"Creating Connection %d failed.",
ppConnInfo - m_ppConnectionInfo));
dwError = ERROR_NOT_ENOUGH_MEMORY;
break;
}
//
// Create a new Listen socket
//
dwError = ( (*ppConnInfo)->
CreateListenSocket( pcsAddrScan->LocalAddr.lpSockaddr,
pcsAddrScan->
LocalAddr.iSockaddrLength,
pcsAddrScan->iSocketType,
pcsAddrScan->iProtocol,
nListenBacklog )
);
if ( dwError == NO_ERROR) {
*lpdwNumEstablished += 1;
} else {
DBGPRINTF( ( DBG_CONTEXT,
" %08x::CreateListenSocket( Index = %d) failed."
" Error = %u\n",
ppConnInfo - m_ppConnectionInfo,
*ppConnInfo, dwError));
}
} // for
}
if ( dwError ) {
SetLastError( dwError);
}
return ( nAddresses == *lpdwNumEstablished);
} // TS_XPORT_CONNECTIONS::EstablishListenConnections()
BOOL
TS_XPORT_CONNECTIONS::StartListenPumps(
IN PFN_CONNECT_CALLBACK pfnConnect,
IN ATQ_COMPLETION pfnConnectEx,
IN ATQ_COMPLETION pfnIOCompletion,
IN DWORD cbAcceptExReceiveBuffer,
IN const CHAR * pszRegParamKey,
OUT LPDWORD lpdwNumStarted
) const
/*++
This function starts the listening threads on each of the connections
established by TS_XPORT_CONNECTIONS::EstablishListenConnections.
One listen thread is scheduled per transport in question.
Arguments:
pfnConnect pointer to Function which will be called on a new
connection being established.
pfnConnectEx
Connection callback to use if AcceptEx is available
pfnIOCompletion
Async IO completion routine to use if AcceptEx is available
cbAcceptexReceiveBuffer
count of bytes of buffer to be used for initial receive
(If 0 no receive buffer isallocated).
lpdwNumStarted pointer to DWORD which if not NULL, on return will contain
the count of threads started.
A user may choose to stop the threads and connections
if *lpdwNumStarted < QueryNumTransports()
since one thread is started per transport.
Returns:
TRUE when connections are established already and all the connection
threads are started successfully.
FALSE if even one connection thread could not be started.
Check the value in *lpdwNumStarted to find the number of threads that
failed.
--*/
{
DBG_ASSERT( lpdwNumStarted != NULL);
IF_DEBUG( DLL_CONNECTION) {
DBGPRINTF( ( DBG_CONTEXT,
" StartConnectionPumps() called with Function( %08x).\n",
pfnConnect));
}
*lpdwNumStarted = 0; // Set this to nothing initially
if ( m_ppConnectionInfo != NULL) {
PTS_CONNECTION_INFO_BASE * ppConnInfo;
for( ppConnInfo = m_ppConnectionInfo;
ppConnInfo < m_ppConnectionInfo + m_nXports;
ppConnInfo++) {
//
// start off a thread to watch new connections
//
DBG_ASSERT( *ppConnInfo != NULL);
if ( !( *ppConnInfo)->StartConnectionPump( pfnConnect,
pfnConnectEx,
pfnIOCompletion,
cbAcceptExReceiveBuffer,
pszRegParamKey )
) {
DBG_CODE(
DWORD err = GetLastError();
DBGPRINTF( ( DBG_CONTEXT,
" StartConnectionPumps( Index = %d) failed."
" Error =%u\n",
ppConnInfo - m_ppConnectionInfo, err));
SetLastError( err);
);
} else {
*lpdwNumStarted += 1;
}
} // for
}
return ( m_nXports == *lpdwNumStarted);
} // TS_XPORT_CONNECTIONS::StartListenPumps()
BOOL
TS_XPORT_CONNECTIONS::StopListenPumps( VOID ) const
/*++
This function stops all the connection threads that are running.
Returns:
TRUE on success ( when all the threads had stopped.
FALSE if there is a failure in at least one of the threads from
being stopped.
--*/
{
BOOL fStop = TRUE; // Did the connection thread stop?
IF_DEBUG( DLL_CONNECTION) {
DBGPRINTF( ( DBG_CONTEXT,
" StopConnectionPumps() called\n"
));
}
if ( m_ppConnectionInfo != NULL) {
PTS_CONNECTION_INFO_BASE * ppConnInfo;
for( ppConnInfo = m_ppConnectionInfo;
ppConnInfo < m_ppConnectionInfo + m_nXports;
ppConnInfo++) {
//
// stop one thread after another.
//
DBG_ASSERT( *ppConnInfo != NULL);
if ( !( *ppConnInfo)->StopConnectionPump( )) {
DWORD err = GetLastError();
//
// What should we do when we fail ???
// For now ignore the failure.
// Ideally the blasting of connection
// object below, should take care of the scenario.
// Still it could be tougher to monitor the same.
// Later we may modify this code.... NYI
//
IF_DEBUG( DLL_CONNECTION) {
DBGPRINTF( ( DBG_CONTEXT,
" Failed to Stop Connection pump of"
" ConnInfo( %08x)( Error = %u). Ignoring...\n",
*ppConnInfo, err));
}
fStop = FALSE;
}
} // for
}
return ( fStop);
} // TS_XPORT_CONNECTIONS::StopListenPumps()
BOOL
TS_XPORT_CONNECTIONS::GetListenSockets(
IN OUT SOCKET * pSockets,
IN OUT LPDWORD pnSocketsMax) const
/*++
This function collects the socket numbers for the listen sockets established.
This should be called after EstablishListenConnections() returns success.
Arguments:
pSockets pointer to an array of socket entries to be filled in.
The maximum number of sockets that can be filled in is
specified by nSocketsMax.
pnSocketsMax pointer to DWORD containing the number of socket entries
during the call. On return contains the number of entries
copied or required.
Returns:
TRUE on success and FALSE on failure.
Use GetLastError() for further details.
--*/
{
DWORD nConn;
if ( pSockets == NULL || pnSocketsMax == NULL || *pnSocketsMax < m_nXports)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER);
return (FALSE);
}
for( nConn = 0; nConn < m_nXports; nConn++) {
pSockets[nConn] = m_ppConnectionInfo[nConn]->QueryListenSocket();
} // for
*pnSocketsMax = m_nXports;
return (TRUE);
} // TS_XPORT_CONNECTIONS::GetListenSockets()
# if DBG
VOID
TS_XPORT_CONNECTIONS::Print( VOID) const
{
DBGPRINTF( ( DBG_CONTEXT,
" Printing TS_XPORT_CONNECTIONS ( %08x). "
" Array of connection Info = %08x. Number of Xports = %d\n",
this, m_ppConnectionInfo, m_nXports));
if ( m_ppConnectionInfo != NULL) {
PTS_CONNECTION_INFO_BASE * ppConnInfo;
DBG_ASSERT( m_nXports > 0);
for( ppConnInfo = m_ppConnectionInfo;
ppConnInfo < m_ppConnectionInfo + m_nXports;
ppConnInfo++) {
(*ppConnInfo)->Print();
} // for
}
return;
} // TS_XPORT_CONNECTIONS::Print()
# endif // DBG
/************************ End of File ***********************/