Windows2003-3790/inetsrv/iis/svcs/smtp/server/conn.hxx
2020-09-30 16:53:55 +02:00

428 lines
12 KiB
C++

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name :
gibcli.hxx
Abstract:
This module defines the CLIENT_CONNECTION class.
This object maintains information about a new client connection
Author:
Rohan Phillips ( Rohanp ) 11-Dec-1995
Project:
Gibraltar Services Common Code
Revision History:
Richard Kamicar ( rkamicar ) 31-Dec-1995
Moved to common directory, filled in more
--*/
# ifndef _GEN_CLIENT_HXX_
# define _GEN_CLIENT_HXX_
/************************************************************
* Include Headers
************************************************************/
//
// Redefine the type to indicate that this is a call-back function
//
typedef ATQ_COMPLETION PFN_ATQ_COMPLETION;
/************************************************************
* Symbolic Constants
************************************************************/
//
// Valid & Invalid Signatures for Client Connection object
// (Ims Connection USed/FRee)
//
# define CLIENT_CONNECTION_SIGNATURE_VALID 'CONN'
# define CLIENT_CONNECTION_SIGNATURE_FREE 'CONF'
//
// POP3 requires a minimum of 10 minutes before a timeout
// (SMTP doesn't specify, but might as well follow POP3)
//
# define MINIMUM_CONNECTION_IO_TIMEOUT (10 * 60) // 10 minutes
//
//
# define DEFAULT_CONNECTION_IO_TIMEOUT MINIMUM_CONNECTION_IO_TIMEOUT
# define DEFAULT_REQUEST_BUFFER_SIZE (512) // 512 bytes
# define MAX_HOST_NAME_LEN (40)
const MAX_READ_BUFF_SIZE = 1024;
const MAX_MESSAGE_BUFF_SIZE = 1024; // outgoing message
const char CR = '\015';
const char LF = '\012';
static const char *CRLF = "\015\012";
/************************************************************
* Type Definitions
************************************************************/
//
// parameter block used to initialize connections
//
typedef struct _CLIENT_CONN_PARAMS
{
SOCKET sClient;
PSOCKADDR pAddrLocal;
PSOCKADDR pAddrRemote;
PATQ_CONTEXT pAtqContext;
PVOID pEndpointObject;
PIIS_ENDPOINT pEndpoint;
PVOID pvInitialBuff;
DWORD cbInitialBuff;
} CLIENT_CONN_PARAMS, *PCLIENT_CONN_PARAMS;
/*++
class CLIENT_CONNECTION
This class is used for keeping track of individual client
connections established with the server.
It maintains the state of the connection being processed.
In addition it also encapsulates data related to Asynchronous
thread context used for processing the request.
--*/
class CLIENT_CONNECTION
{
public:
//-------------------------------------------------------------------------
// Virtual methods that will be defined by derived classes (more below).
//
virtual BOOL StartSession( void);
virtual char * IsLineComplete(IN OUT const char * pchRecvd, IN DWORD cbRecvd);
//-------------------------------------------------------------------------
private:
ULONG m_signature; // signature on object for sanity check
DWORD m_ClientId; //unique identifier for client
//
// This request came in through the secure port
//
BOOL m_fSecurePort;
//
// Connection Related data
//
SOCKET m_sClient; // socket for this connection
//
// Socket Family this connection came in on
//
USHORT m_sSocketFamily;
//
// time when this object was created in milliseconds.
//
DWORD m_msStartingTime;
//
// Addresses of machines' network addresses through which this
// connection got established.
//
CHAR m_pchLocalHostName[MAX_HOST_NAME_LEN];
CHAR m_pchLocalPortName[sizeof("65536")];
CHAR m_pchRemoteHostName[MAX_HOST_NAME_LEN];
protected:
//
// The overlapped structure for reads (one outstanding read at a time)
// -- writes will dynamically allocate them
//
OVERLAPPED m_Overlapped;
//
// Data required for IO operations
//
PATQ_CONTEXT m_pAtqContext;
//
// server instance. Both are referenced.
//
//PSMTP_SERVER_INSTANCE m_pInstance;
PIIS_ENDPOINT m_pSmtpEndpoint;
//
// server instance - statistics object.
//
//LPSMTP_SERVER_STATISTICS m_pSmtpStats;
//
// context returned on a non-acceptex completion
//
SOCKADDR_IN m_saClient; // socket address for the client
PVOID m_atqEndpointObject;
char m_recvBuffer[MAX_READ_BUFF_SIZE];
DWORD m_cbReceived;
PVOID m_pvInitial; // initial request read
DWORD m_cbInitial; // count of bytes of initial request
DWORD m_dwCmdBytesRecv;
DWORD m_dwCmdBytesSent;
BOOL m_DoCleanup;
SOCKET QuerySocket( VOID) const
{ return ( m_sClient); }
//
// Functions for processing client connection at various states
//
BOOL ReceiveRequest( IN DWORD cbWritten,
OUT LPBOOL pfFullRequestRecvd);
const CHAR * QueryLocalHostName( VOID) const
{ return m_pchLocalHostName; }
const CHAR * QueryLocalPortName( VOID) const
{ return m_pchLocalPortName; }
const CHAR * PassWord( VOID) const
{ return NULL; }
DWORD QueryIoTimeout( VOID) const
{ return ( DEFAULT_CONNECTION_IO_TIMEOUT); }
PATQ_CONTEXT QueryAtqContext( VOID) const
{ return ( m_pAtqContext); }
LPOVERLAPPED QueryAtqOverlapped( void ) const
{ return ( m_pAtqContext == NULL ? NULL : &m_pAtqContext->Overlapped ); }
public:
CLIENT_CONNECTION(
IN SOCKET sClient,
IN const SOCKADDR_IN * psockAddrRemote,
IN const SOCKADDR_IN * psockAddrLocal = NULL,
IN PATQ_CONTEXT pAtqContext = NULL,
IN PVOID pvInitialRequest = NULL,
IN DWORD cbInitialData = 0)
: m_signature(CLIENT_CONNECTION_SIGNATURE_VALID),
m_DoCleanup(TRUE)
{
Initialize( sClient, psockAddrRemote, psockAddrLocal,
pAtqContext, pvInitialRequest, cbInitialData);
}
virtual ~CLIENT_CONNECTION(VOID)
{
Cleanup();
// Invalidate the signature. since this connection is trashed.
m_signature = CLIENT_CONNECTION_SIGNATURE_FREE;
}
BOOL
Initialize(
IN SOCKET sClient,
IN const SOCKADDR_IN * psockAddrRemote,
IN const SOCKADDR_IN * psockAddrLocal = NULL,
IN PATQ_CONTEXT pAtqContext = NULL,
IN PVOID pvInitialRequest = NULL,
IN DWORD cbInitialData = 0);
VOID Cleanup(VOID);
BOOL m_Destroy;
//
// IsValid()
// o Checks the signature of the object to determine
// if this is a valid ICLIENT_CONNECTION object.
//
// Returns: TRUE on success and FALSE if invalid.
//
BOOL IsValid( VOID) const
{ return ( m_signature == CLIENT_CONNECTION_SIGNATURE_VALID); }
void SetAtqContext (PATQ_CONTEXT pNewContext)
{
m_pAtqContext = pNewContext;
}
VOID StartProcessingTimer(void)
{m_msStartingTime = GetTickCount();}
DWORD QueryProcessingTime( VOID) const
{ return ( GetTickCount() - m_msStartingTime); }
virtual LPCSTR QueryRcvBuffer( VOID) const
{ return ((LPCSTR) m_recvBuffer); }
virtual LPSTR QueryMRcvBuffer(VOID) // modifiable string
{ return (LPSTR) m_recvBuffer; }
const char * QueryClientHostName( VOID) const
{ return m_pchRemoteHostName; }
const DWORD QueryClientId(void) const
{return m_ClientId;}
DWORD QueryRequestLen( VOID) const
{ return ( m_cbReceived); }
void SetClientId(DWORD Id) {m_ClientId = Id;}
//-------------------------------------------------------------------------
// Virtual method that MUST be defined by derived classes.
//
// Processes a completed IO on the connection for the client.
//
// -- Calls and maybe called from the Atq functions.
//
virtual BOOL ProcessClient(
IN DWORD cbWritten,
IN DWORD dwCompletionStatus,
IN OUT OVERLAPPED * lpo
) = 0;
//-------------------------------------------------------------------------
//
// Disconnect this client
//
// dwErrorCode is used only when there is server level error
//
VOID virtual DisconnectClient( IN DWORD dwErrorCode = NO_ERROR);
//
// Wrapper functions for common File operations
// ( Used to hide the ATQ and reference counting)
//
BOOL virtual ReadFile( LPVOID pvBuffer, DWORD cbSize = MAX_READ_BUFF_SIZE );
//
// The first (pair) WriteFile does a synchronous write.
// The second does an async write..
//
BOOL virtual WriteFile( IN LPVOID pvBuffer, IN DWORD cbSize );
BOOL virtual WriteFile( IN LPVOID lpvBuffer, IN DWORD cbSize, IN OVERLAPPED *lpo);
LPCTSTR virtual QueryClientUserName( VOID );
BOOL TransmitFile(
IN HANDLE hFile,
IN LARGE_INTEGER & liSize,
IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers = NULL);
//
// jstamerj 1998/11/03 20:14:04:
// A wrapper around atq's PostCompletionStatus
//
BOOL virtual PostCompletionStatus( IN DWORD dwBytes );
//
// should be called before processing new command
//
void ResetCommandCounters( void )
{
m_dwCmdBytesRecv = m_dwCmdBytesSent = 0;
}
//
// should be called after IsLineComplete
//
void SetCommandBytesRecv( DWORD dw )
{
m_dwCmdBytesRecv = dw;
}
//
// should be called after each successful WriteFile/send
//
void AddCommandBytesSent( DWORD dw )
{
InterlockedExchangeAdd((LONG *) &m_dwCmdBytesSent, (LONG)dw);
}
//
// should be called after each successful WriteFile/send
//
void AddCommandBytesRecv( DWORD dw )
{
InterlockedExchangeAdd((LONG *) &m_dwCmdBytesRecv, (LONG)dw);
}
BOOL AddToAtqHandles(HANDLE hClient, PVOID EndPointObj, DWORD TimeOut, ATQ_COMPLETION pfnCompletion)
{
return ( AtqAddAsyncHandle( &m_pAtqContext, EndPointObj,
this, pfnCompletion, TimeOut,
hClient));
}
USHORT QuerySocketFamily( VOID ) const
{ return m_sSocketFamily; }
PIIS_ENDPOINT QuerySmtpEndpoint( VOID ) const
{ _ASSERT(m_pSmtpEndpoint != NULL); return m_pSmtpEndpoint; }
DWORD QueryLocalIPAddress( VOID ) const
{ return 0; }
static BOOL WriteSocket( IN SOCKET sock, IN LPVOID pBuffer, IN DWORD cbSize );
public:
//
// LIST_ENTRY object for storing client connections in a list.
//
LIST_ENTRY m_listEntry;
LIST_ENTRY & QueryListEntry( VOID)
{ return ( m_listEntry); }
# if DBG
virtual VOID Print( VOID) const;
# endif // DBG
}; // class ICLIENT_CONNECTION
typedef CLIENT_CONNECTION * PCLIENT_CONNECTION;
//
// Auxiliary functions
//
INT ShutAndCloseSocket( IN SOCKET sock);
# endif
/************************ End of File ***********************/