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.
 
 
 
 
 
 

368 lines
6.6 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
Globals.c
Abstract:
This module manages client connections. An (almost) unlimited set
of worker threads handle client requests in parallel, with each
thread associated with an individual client.
Author:
Charles K. Moore (keithmo) 24-July-1994
Revision History:
--*/
#include "rnrsvcp.h"
#pragma hdrstop
//
// Private constants.
//
#define MAX_THREADS 200
//
// Private globals.
//
CRITICAL_SECTION RnrpLock;
SOCKET RnrpActiveSockets[MAX_THREADS];
HANDLE RnrpActiveThreads[MAX_THREADS];
DWORD RnrpNumActive;
//
// Private prototypes.
//
DWORD
RnrpWorkerThread(
LPVOID Param
);
VOID
RnrpHandleTransfer(
SOCKET ClientSocket
);
//
// Public functions.
//
APIERR
RnrClientInitialize(
VOID
)
/*++
Routine Description:
Performs any necessary client initialization.
Return Value:
APIERR - NO_ERROR if successful, Win32 error code if not.
--*/
{
//
// Setup the global data.
//
InitializeCriticalSection( &RnrpLock );
RnrpNumActive = 0;
//
// Success!
//
return NO_ERROR;
} // RnrClientInitialize
VOID
RnrClientTerminate(
VOID
)
/*++
Routine Description:
Performs any necessary client cleanup.
--*/
{
DWORD Index;
DWORD WaitCount;
//
// Close sockets belonging to active clients. Setting the
// RnrpActiveSockets entries to INVALID_SOCKET will prevent
// the worker threads from closing their own thread handles
// and removing the corresponding RnrpActiveSockets and
// RnrpActiveThreads array entries.
//
EnterCriticalSection( &RnrpLock );
for( Index = 0 ; Index < RnrpNumActive ; Index++ ) {
closesocket( RnrpActiveSockets[Index] );
RnrpActiveSockets[Index] = INVALID_SOCKET;
}
LeaveCriticalSection( &RnrpLock );
//
// Wait for the worker threads to terminate. Note that it's
// OK to reference RnrpNumActive and RnrpActiveThreads outside
// the critical section lock. Since the worker threads will
// be unable to find their client sockets in RnrpActiveSockets,
// they won't be updating RnrpNumActive or RnrpActiveThreads.
//
for( Index = 0 ; Index < RnrpNumActive ; Index += MAXIMUM_WAIT_OBJECTS ) {
WaitCount = min( MAXIMUM_WAIT_OBJECTS, ( RnrpNumActive - Index ) );
WaitForMultipleObjects( WaitCount,
&RnrpActiveThreads[Index],
TRUE,
INFINITE );
}
//
// Destroy the client list lock.
//
DeleteCriticalSection( &RnrpLock );
} // RnrClientTerminate
VOID
RnrClientHandler(
SOCKET ClientSocket
)
/*++
Routine Description:
Services a connection request from a client.
Arguments:
ClientSocket - The newly accepted socket from the client.
--*/
{
DWORD Index;
DWORD ThreadId;
APIERR err;
//
// See if there's room for another client.
//
EnterCriticalSection( &RnrpLock );
if( RnrShutdownInProgress ) {
//
// The service is shutting down. Just close the client
// socket and get out.
//
closesocket( ClientSocket );
} else if( RnrpNumActive == ( MAX_THREADS - 1 ) ) {
//
// No room for additional clients.
//
RNR_LOG0( RNR_EVENT_TOO_MANY_CLIENTS,
0 );
closesocket( ClientSocket );
} else {
Index = RnrpNumActive++;
//
// Create the worker thread.
//
RnrpActiveSockets[Index] = ClientSocket;
RnrpActiveThreads[Index] = CreateThread( NULL,
0,
&RnrpWorkerThread,
(LPVOID)ClientSocket,
0,
&ThreadId );
if( RnrpActiveThreads[Index] == NULL ) {
err = GetLastError();
RNR_LOG0( RNR_EVENT_CANNOT_CREATE_WORKER_THREAD,
err );
closesocket( ClientSocket );
RnrpNumActive--;
}
}
LeaveCriticalSection( &RnrpLock );
} // RnrClientHandler
//
// Private functions.
//
DWORD
RnrpWorkerThread(
LPVOID Param
)
/*++
Routine Description:
This worker thread will
Arguments:
Param - The creation parameter passed into CreateThread. This is
actually the client socket handle.
Returns:
DWORD - Thread exit code (always zero).
--*/
{
DWORD Index;
SOCKET ClientSocket;
//
// Grab the client socket handle.
//
ClientSocket = (SOCKET)Param;
//
// Let RnrpHandleTransfer do the grunt work.
//
RnrpHandleTransfer( ClientSocket );
//
// Find the client socket in the active socket array. If found,
// close the corresponding thread handle and remove the socket
// and thread array entries.
//
EnterCriticalSection( &RnrpLock );
for( Index = 0 ; Index < RnrpNumActive ; Index++ ) {
if( RnrpActiveSockets[Index] == ClientSocket ) {
CloseHandle( RnrpActiveThreads[Index] );
//
// Remove the socket & thread array entries.
//
RnrpNumActive--;
memmove( &RnrpActiveSockets[Index],
&RnrpActiveSockets[Index+1],
( RnrpNumActive - Index ) * sizeof(SOCKET) );
memmove( &RnrpActiveThreads[Index],
&RnrpActiveThreads[Index+1],
( RnrpNumActive - Index ) * sizeof(HANDLE) );
break;
}
}
LeaveCriticalSection( &RnrpLock );
return 0;
} // RnrpWorkerThread
VOID
RnrpHandleTransfer(
SOCKET ClientSocket
)
/*++
Routine Description:
Services a transfer request for a single client.
Arguments:
ClientSocket - The socket.
--*/
{
INT result;
BYTE buffer[1024];
//
// Loop echoing data back to the client.
//
while ( TRUE ) {
result = recv( ClientSocket, buffer, sizeof(buffer), 0 );
if( result <= 0 ) {
//
// Connection terminated gracefully or receive failure.
//
break;
}
result = send( ClientSocket, buffer, result, 0 );
if( result < 0 ) {
//
// Send failure.
//
break;
}
}
//
// Close the connected socket.
//
closesocket( ClientSocket );
} // RnrpHandleTransfer