475 lines
12 KiB
C++
475 lines
12 KiB
C++
|
/**********************************************************************/
|
|||
|
/** Microsoft Windows NT **/
|
|||
|
/** Copyright(c) Microsoft Corp., 1994 **/
|
|||
|
/**********************************************************************/
|
|||
|
|
|||
|
/*
|
|||
|
connect.cxx
|
|||
|
|
|||
|
This module contains the connection accept routine called by the connection
|
|||
|
thread.
|
|||
|
|
|||
|
|
|||
|
FILE HISTORY:
|
|||
|
Johnl 08-Aug-1994 Lifted from FTP server
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#include "w3p.hxx"
|
|||
|
|
|||
|
//
|
|||
|
// Private prototypes.
|
|||
|
//
|
|||
|
|
|||
|
BOOL
|
|||
|
CreateClient(
|
|||
|
IN PCLIENT_CONN_PARAMS ClientParam
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
SendError(
|
|||
|
SOCKET socket,
|
|||
|
DWORD ids
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Private functions.
|
|||
|
//
|
|||
|
|
|||
|
/*******************************************************************
|
|||
|
|
|||
|
NAME: W3OnConnect
|
|||
|
|
|||
|
SYNOPSIS: Handles the incoming connection indication from the
|
|||
|
connection thread
|
|||
|
|
|||
|
|
|||
|
ENTRY: sNew - New client socket
|
|||
|
|
|||
|
HISTORY:
|
|||
|
KeithMo 09-Mar-1993 Created.
|
|||
|
Johnl 02-Aug-1994 Reworked from FTP server
|
|||
|
|
|||
|
********************************************************************/
|
|||
|
|
|||
|
VOID W3OnConnect( SOCKET sNew,
|
|||
|
SOCKADDR_IN * psockaddr, //Should be SOCKADDR *
|
|||
|
PVOID pEndpointContext,
|
|||
|
PVOID pAtqEndpointObject )
|
|||
|
{
|
|||
|
|
|||
|
PIIS_ENDPOINT pEndpoint = (PIIS_ENDPOINT)pEndpointContext;
|
|||
|
INT cbAddr = sizeof( sockaddr );
|
|||
|
|
|||
|
CLIENT_CONN_PARAMS clientParams;
|
|||
|
SOCKADDR sockaddr;
|
|||
|
|
|||
|
if ( !((W3_IIS_SERVICE*)g_pInetSvc)->GetReferenceCount() )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
W3_IIS_SERVICE::ReferenceW3Service( g_pInetSvc );
|
|||
|
|
|||
|
DBG_ASSERT( sNew != INVALID_SOCKET );
|
|||
|
|
|||
|
g_pW3Stats->IncrConnectionAttempts();
|
|||
|
|
|||
|
IF_DEBUG( SOCKETS )
|
|||
|
{
|
|||
|
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"connect received from %s, socket = %d\n",
|
|||
|
inet_ntoa( psockaddr->sin_addr ),
|
|||
|
sNew ));
|
|||
|
}
|
|||
|
|
|||
|
if ( getsockname( sNew,
|
|||
|
&sockaddr,
|
|||
|
&cbAddr ) != 0 )
|
|||
|
{
|
|||
|
//SendError( sNew, IDS_HTRESP_DENIED );
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We've got a new connection. Add this to the work list
|
|||
|
//
|
|||
|
|
|||
|
clientParams.sClient = sNew;
|
|||
|
clientParams.pEndpointObject = pAtqEndpointObject;
|
|||
|
clientParams.pAtqContext = NULL;
|
|||
|
clientParams.pAddrLocal = &sockaddr;
|
|||
|
clientParams.pAddrRemote = (PSOCKADDR)psockaddr;
|
|||
|
clientParams.pvInitialBuff = NULL;
|
|||
|
clientParams.cbInitialBuff = 0;
|
|||
|
clientParams.pEndpoint = (PIIS_ENDPOINT)pEndpointContext;
|
|||
|
|
|||
|
if ( CreateClient( &clientParams ) )
|
|||
|
{
|
|||
|
W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
error_exit:
|
|||
|
|
|||
|
W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
|
|||
|
CloseSocket( sNew );
|
|||
|
|
|||
|
} // W3OnConnect
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
W3OnConnectEx(
|
|||
|
VOID * patqContext,
|
|||
|
DWORD cbWritten,
|
|||
|
DWORD err,
|
|||
|
OVERLAPPED * lpo
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL fAllowConnection = FALSE;
|
|||
|
PVOID pvBuff;
|
|||
|
SOCKADDR * psockaddrLocal;
|
|||
|
SOCKADDR * psockaddrRemote;
|
|||
|
SOCKET sNew;
|
|||
|
PIIS_ENDPOINT pEndpoint;
|
|||
|
PW3_SERVER_INSTANCE pInstance;
|
|||
|
CLIENT_CONN_PARAMS clientParams;
|
|||
|
|
|||
|
if ( err || !lpo )
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"[W3OnConnectEx] Completion failed with error %d, Atq context %lx\n",
|
|||
|
err,
|
|||
|
patqContext ));
|
|||
|
|
|||
|
AtqCloseSocket( (PATQ_CONTEXT) patqContext, FALSE );
|
|||
|
AtqFreeContext( (PATQ_CONTEXT) patqContext, TRUE );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( !((W3_IIS_SERVICE*)g_pInetSvc)->GetReferenceCount() )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
W3_IIS_SERVICE::ReferenceW3Service( g_pInetSvc );
|
|||
|
|
|||
|
g_pW3Stats->IncrConnectionAttempts();
|
|||
|
|
|||
|
IF_DEBUG( SOCKETS )
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"[W3OnConnectEx] connection received\n" ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get AcceptEx parameters
|
|||
|
//
|
|||
|
|
|||
|
AtqGetAcceptExAddrs( (PATQ_CONTEXT) patqContext,
|
|||
|
&sNew,
|
|||
|
&pvBuff,
|
|||
|
(PVOID*)&pEndpoint,
|
|||
|
&psockaddrLocal,
|
|||
|
&psockaddrRemote );
|
|||
|
|
|||
|
IF_DEBUG( CONNECTION )
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"[W3OnConnectEx] New connection, AtqCont = %lx, buf = %lx, endp %x written = %d\n",
|
|||
|
patqContext,
|
|||
|
pvBuff,
|
|||
|
pEndpoint,
|
|||
|
cbWritten ));
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the timeout for future IOs on this context
|
|||
|
//
|
|||
|
|
|||
|
AtqContextSetInfo( (PATQ_CONTEXT) patqContext,
|
|||
|
ATQ_INFO_TIMEOUT,
|
|||
|
W3_DEF_CONNECTION_TIMEOUT );
|
|||
|
|
|||
|
//
|
|||
|
// We've got a new connection. Add this to the work list
|
|||
|
//
|
|||
|
|
|||
|
clientParams.sClient = sNew;
|
|||
|
clientParams.pEndpointObject = NULL;
|
|||
|
clientParams.pAtqContext = (PATQ_CONTEXT)patqContext;
|
|||
|
clientParams.pAddrLocal = psockaddrLocal;
|
|||
|
clientParams.pAddrRemote = psockaddrRemote;
|
|||
|
clientParams.pvInitialBuff = pvBuff;
|
|||
|
clientParams.cbInitialBuff = cbWritten;
|
|||
|
clientParams.pEndpoint = pEndpoint;
|
|||
|
|
|||
|
if ( CreateClient( &clientParams ) )
|
|||
|
{
|
|||
|
W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This will also close the socket
|
|||
|
//
|
|||
|
|
|||
|
DBG_REQUIRE( AtqCloseSocket( (PATQ_CONTEXT) patqContext, FALSE ));
|
|||
|
AtqFreeContext( (PATQ_CONTEXT) patqContext, TRUE );
|
|||
|
|
|||
|
W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // W3OnConnectEx
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************
|
|||
|
|
|||
|
NAME: CreateClient
|
|||
|
|
|||
|
SYNOPSIS: Creates a new connection object that manages the
|
|||
|
client requests
|
|||
|
|
|||
|
ENTRY: sNew - New client socket
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HISTORY:
|
|||
|
KeithMo 09-Mar-1993 Created.
|
|||
|
Johnl 02-Aug-1994 Reworked from FTP server
|
|||
|
|
|||
|
********************************************************************/
|
|||
|
|
|||
|
BOOL
|
|||
|
CreateClient(
|
|||
|
IN PCLIENT_CONN_PARAMS ClientParam
|
|||
|
)
|
|||
|
{
|
|||
|
APIERR err = NO_ERROR;
|
|||
|
CLIENT_CONN * pConn = NULL;
|
|||
|
BOOL fGranted;
|
|||
|
PATQ_CONTEXT patqContext = ClientParam->pAtqContext;
|
|||
|
|
|||
|
pConn = CLIENT_CONN::Alloc( ClientParam );
|
|||
|
|
|||
|
if( pConn == NULL ||
|
|||
|
!pConn->IsValid() )
|
|||
|
{
|
|||
|
err = pConn ? GetLastError() : ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
|
|||
|
if ( patqContext )
|
|||
|
{
|
|||
|
DBG_REQUIRE( AtqCloseSocket( patqContext, TRUE ));
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// We only have a context at this point if we're using AcceptEx
|
|||
|
//
|
|||
|
|
|||
|
if ( patqContext )
|
|||
|
{
|
|||
|
//
|
|||
|
// Associate the Client connection object with this socket handle
|
|||
|
// for future completions
|
|||
|
//
|
|||
|
|
|||
|
AtqContextSetInfo( patqContext,
|
|||
|
ATQ_INFO_COMPLETION_CONTEXT,
|
|||
|
(ULONG_PTR) pConn );
|
|||
|
|
|||
|
IF_DEBUG( CONNECTION )
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"[CreateClient] Setting Atq context %lx context to Conn object %lx\n",
|
|||
|
patqContext,
|
|||
|
pConn ));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Kickstart the process. This will do an async read to get the
|
|||
|
// client's header or it will start processing the receive buffer
|
|||
|
// if AcceptEx is being used.
|
|||
|
//
|
|||
|
|
|||
|
ReferenceConn( pConn );
|
|||
|
DBG_REQUIRE( pConn->DoWork( 0,
|
|||
|
NO_ERROR,
|
|||
|
NULL ));
|
|||
|
DereferenceConn( pConn );
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
const CHAR * apszSubStrings[1];
|
|||
|
|
|||
|
DBG_ASSERT( ClientParam->pAddrRemote->sa_family == AF_INET );
|
|||
|
apszSubStrings[0] = inet_ntoa( ((SOCKADDR_IN *)ClientParam->pAddrRemote)->sin_addr );
|
|||
|
|
|||
|
g_pInetSvc->LogEvent( W3_EVENT_CANNOT_CREATE_CLIENT_CONN,
|
|||
|
1,
|
|||
|
apszSubStrings,
|
|||
|
err );
|
|||
|
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"cannot create client object, error %lu\n",
|
|||
|
err ));
|
|||
|
|
|||
|
if ( pConn )
|
|||
|
{
|
|||
|
CLIENT_CONN::Free( pConn );
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
} // CreateClient
|
|||
|
|
|||
|
#if 0
|
|||
|
BOOL
|
|||
|
SendError(
|
|||
|
SOCKET socket,
|
|||
|
DWORD ids
|
|||
|
)
|
|||
|
{
|
|||
|
STR strResponse;
|
|||
|
|
|||
|
if ( !strResponse.Resize( 512 ) ||
|
|||
|
!HTTP_REQ_BASE::BuildExtendedStatus( &strResponse,
|
|||
|
HT_FORBIDDEN,
|
|||
|
NO_ERROR,
|
|||
|
ids ))
|
|||
|
{
|
|||
|
DBGPRINTF((DBG_CONTEXT,
|
|||
|
"[SendError] Failed to build status (error %d)\n",
|
|||
|
GetLastError()));
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do a synchronous send
|
|||
|
//
|
|||
|
|
|||
|
send( socket,
|
|||
|
strResponse.QueryStr(),
|
|||
|
strResponse.QueryCB(),
|
|||
|
0 );
|
|||
|
|
|||
|
return TRUE ;
|
|||
|
} // SendError
|
|||
|
#endif
|
|||
|
|
|||
|
/*******************************************************************
|
|||
|
|
|||
|
NAME: CloseSocket
|
|||
|
|
|||
|
SYNOPSIS: Closes the specified socket. This is just a thin
|
|||
|
wrapper around the "real" closesocket() API.
|
|||
|
|
|||
|
ENTRY: sock - The socket to close.
|
|||
|
|
|||
|
RETURNS: SOCKERR - 0 if successful, !0 if not.
|
|||
|
|
|||
|
HISTORY:
|
|||
|
KeithMo 26-Apr-1993 Created.
|
|||
|
|
|||
|
********************************************************************/
|
|||
|
SOCKERR CloseSocket( SOCKET sock )
|
|||
|
{
|
|||
|
SOCKERR serr = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Close the socket.
|
|||
|
//
|
|||
|
|
|||
|
#if 0
|
|||
|
shutdown( sock, 1 ); // Davidtr sez not needed
|
|||
|
#endif
|
|||
|
|
|||
|
if( closesocket( sock ) != 0 )
|
|||
|
{
|
|||
|
serr = WSAGetLastError();
|
|||
|
}
|
|||
|
|
|||
|
IF_DEBUG( SOCKETS )
|
|||
|
{
|
|||
|
if( serr == 0 )
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"closed socket %d\n",
|
|||
|
sock ));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DBGPRINTF(( DBG_CONTEXT,
|
|||
|
"cannot close socket %d, error %d\n",
|
|||
|
sock,
|
|||
|
serr ));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return serr;
|
|||
|
|
|||
|
} // CloseSocket
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
/*******************************************************************
|
|||
|
|
|||
|
NAME: DBG_CHECK_UnbalancedThreadToken
|
|||
|
|
|||
|
SYNOPSIS: Check for unbalanced Thread Token, this function will
|
|||
|
try to make a open thread token call, it should fail, otherwise,
|
|||
|
somebody forgets to release the thread token.
|
|||
|
|
|||
|
ENTRY:
|
|||
|
|
|||
|
RETURNS: NONE
|
|||
|
|
|||
|
HISTORY:
|
|||
|
LeiJin 9/4/1997 Created.
|
|||
|
|
|||
|
********************************************************************/
|
|||
|
|
|||
|
VOID DBG_CHECK_UnbalancedThreadToken(
|
|||
|
IN const char * pszFilePath,
|
|||
|
IN int nLineNum
|
|||
|
)
|
|||
|
{
|
|||
|
HANDLE hToken = (HANDLE)0;
|
|||
|
BOOL fRet = FALSE;
|
|||
|
|
|||
|
fRet = OpenThreadToken(GetCurrentThread(),
|
|||
|
TOKEN_QUERY, // the very minimum operation on a thread token
|
|||
|
FALSE, // FALSE, the access check is performed using the
|
|||
|
// security context for the calling thread.
|
|||
|
&hToken);
|
|||
|
if (fRet == TRUE)
|
|||
|
{
|
|||
|
DBGPRINTF((DBG_CONTEXT, "File %s, Line %d, OpenThreadToken() succeeded, found a token.\n",
|
|||
|
pszFilePath,
|
|||
|
nLineNum));
|
|||
|
DBG_ASSERT(FALSE);
|
|||
|
CloseHandle(hToken);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DWORD err = GetLastError();
|
|||
|
|
|||
|
if (err != ERROR_NO_TOKEN)
|
|||
|
{
|
|||
|
DBGPRINTF((DBG_CONTEXT, "File %s, Line %d, OpenThreadToken() failed, err = %lu.\n",
|
|||
|
pszFilePath,
|
|||
|
nLineNum));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
#endif //debug
|