|
|
/*++
Copyright (c) 1995-1997 Microsoft Corporation
Module Name:
icsocket.hxx
Abstract:
Contains types, manifests, prototypes for Internet Socket Class (ICSocket) functions and methods (in common\icsocket.cxx)
Author:
Richard L Firth (rfirth) 24-May-1995
Revision History:
24-May-1995 rfirth Created
20-March-1996 arthurbi Created the CSOCKET class.
08-Apr-1997 rfirth Changed to ICSocket class (Internet CSocket to avoid issues with MFC). Base socket implementation. Secure sockets is a derived class in ssocket.hxx/.cxx
--*/
//
// manifests
//
#define HOST_INADDR_ANY 0x00000000
#define HOST_INADDR_NONE 0xffffffff
#define HOST_INADDR_LOOPBACK 0x0100007f
//
// common flags for ConnectSocket(), SocketSend(), SocketReceive(),
// SocketDataAvailable()
//
#define SF_ENCRYPT 0x00000001 // encrypt data (send)
#define SF_DECRYPT 0x00000002 // decrypt data (receive)
#define SF_EXPAND 0x00000004 // input buffer can be expanded to fit (receive)
#define SF_COMPRESS 0x00000008 // input buffer can be compressed to fit (receive)
#define SF_RECEIVE_ALL 0x00000010 // loop until buffer full/all data received (receive)
#define SF_INDICATE 0x00000020 // provide status callbacks
#define SF_NON_BLOCKING 0x00000040 // socket is non-blocking
#define SF_WAIT 0x00000080 // wait for data if non-blocking
#define SF_IGNORE_CONNRESET 0x00000100 // SPX_SUPPORT
#define SF_SENDING_DATA 0x00000200 // data is being sent through the socket, errors may now apply.
#define SF_SCH_REDO 0x00000400 // schannel is redone.
#define SF_CONNECTIONLESS 0x00000800 // send/receive datagrams
#define SF_EXPEDITED 0x00001000 // function expected to complete quickly (test with select())
#define SF_AUTHORIZED 0x00002000 // set if we added an authorization header
#define SF_RANDOM 0x00004000 // set if we connect to address list entry chosen at random
#define SF_FORCE 0x00008000 // set if the name must be resolved (ResolveHost)
#define SF_SECURE 0x00010000 // set if this is a secure (SSL/PCT) socket object
#define SF_NO_WAIT 0x00020000 // set if one-shot operation required (Receive)
#define SF_KEEP_ALIVE 0x00040000 // set if connection is keep-alive
#define SF_GLOBAL_KA_POOL 0x00080000 // set if connection is in the global keep-alive pool
#define SF_PERUSER 0x00100000 // set if authorization header is added so response marked per-user in shared cache
#define SF_AUTHENTICATED 0x00200000 // set if authentication was successful on this socket.
#define SF_TUNNEL 0x00400000 // set if this connection is a nested CONNECT directly to a proxy
#define SF_OVERLAPPED 0x00800000 // set if overlapped socket
//
// types
//
//
// SOCKET_BUFFER_ID - which socket buffer we are dealing with
//
typedef enum { ReceiveBuffer = SO_RCVBUF, SendBuffer = SO_SNDBUF } SOCKET_BUFFER_ID;
//
// timeout types for SetSocketTimeout
//
#define SEND_TIMEOUT 1
#define RECEIVE_TIMEOUT 0
//
// macros
//
#define IS_VALID_NON_LOOPBACK_IP_ADDRESS(address) \
(((address) != HOST_INADDR_ANY) \ && ((address) != HOST_INADDR_NONE) \ && ((address) != HOST_INADDR_LOOPBACK))
//
// prototypes
//
LPSTR MapNetAddressToName( IN INTERNET_HANDLE_OBJECT* pSessionObject, IN LPSOCKADDR lpSockAddr );
//DWORD
//GetServiceAddress(
// IN LPSTR HostName,
// IN DWORD Port,
// OUT LPADDRESS_INFO_LIST AddressList
// );
//
//BOOL
//IsNetAddress(
// IN LPSTR lpszAddress
// );
//
//#if INET_DEBUG
//
//DEBUG_FUNCTION
//VOID
//InitializeAddressList(
// IN LPADDRESS_INFO_LIST AddressList
// );
//
//DEBUG_FUNCTION
//VOID
//FreeAddressList(
// IN LPADDRESS_INFO_LIST AddressList
// );
//
//DEBUG_FUNCTION
//BOOL
//IsAddressListEmpty(
// IN LPADDRESS_INFO_LIST AddressList
// );
//
//#else
//
//#define InitializeAddressList(AddressList) \ // (AddressList)->AddressCount = 0; \ // (AddressList)->Addresses = NULL
//
//#define FreeAddressList(AddressList) \ // if ((AddressList)->AddressCount != 0) { \ // (AddressList)->Addresses = (LPCSADDR_INFO)FREE_MEMORY((HLOCAL)((AddressList)->Addresses)); \ // (AddressList)->AddressCount = 0; \ // }
//
//#define IsAddressListEmpty(AddressList) \ // (((AddressList)->AddressCount == 0) ? TRUE : FALSE)
//
//#endif // INET_DEBUG
//
//DWORD
//DestinationAddressFromAddressList(
// IN LPADDRESS_INFO_LIST lpAddressList,
// IN DWORD dwIndex,
// OUT LPBYTE lpbDestinationAddress,
// IN OUT LPDWORD lpdwDestinationAddressLength
// );
//
//DWORD
//InterfaceAddressFromSocket(
// IN SOCKET Socket,
// OUT LPBYTE lpbInterfaceAddress,
// IN OUT LPDWORD lpdwInterfaceAddressLength
// );
//
// classes
//
//
// forward references
//
class CFsm_SocketConnect; class CFsm_SocketSend; class CFsm_SocketReceive; class CServerInfo;
//
// ICSocket - abstracts a TCP/IP connection
//
class ICSocket {
protected:
LIST_ENTRY m_List; // keep-alive list
DWORD m_dwTimeout; // keep-alive expiry
BOOL m_fTimeoutWraps; LONG m_ReferenceCount; SOCKET m_Socket; DWORD m_dwFlags; INTERNET_PORT m_Port; // needed for keep-alive
INTERNET_PORT m_SourcePort; BOOL m_bAborted; DWORD m_SocksAddress; INTERNET_PORT m_SocksPort; //HINTERNET m_hRequest;
CFsm* _pCurrentFsm; CWrapOverlapped* _lpWrapOverlappedSend; CWrapOverlapped* _lpWrapOverlappedRecv;
BOOL m_fIsSecureSocket;
#if INET_DEBUG
#define ICSOCKET_SIGNATURE 0x6b636f53 // "Sock"
DWORD m_Signature;
#define SIGN_ICSOCKET() \
m_Signature = ICSOCKET_SIGNATURE
#define CHECK_ICSOCKET() \
INET_ASSERT((m_Signature == ICSOCKET_SIGNATURE) || (m_Signature == SECURE_SOCKET_SIGNATURE))
#else
#define SIGN_ICSOCKET() \
/* NOTHING */
#define CHECK_ICSOCKET() \
/* NOTHING */
#endif
public:
ICSocket();
virtual ~ICSocket();
VOID Destroy( VOID );
PLIST_ENTRY List(VOID) { return &m_List; }
PLIST_ENTRY Next(VOID) { return m_List.Flink; }
BOOL IsOnList(VOID) { return ((m_List.Flink == NULL) && (m_List.Blink == NULL)) ? FALSE : TRUE; } CFsm* GetAndSetCurrentFsm(CFsm* pCurrent) { /*
CFsm* pTemp = _pCurrentFsm; _pCurrentFsm = pCurrent; return pTemp; */ // ICSocket race possible?
return (CFsm *)InterlockedExchangePointer((PVOID*)&_pCurrentFsm, (PVOID)pCurrent); } VOID Reference( VOID );
BOOL Dereference( VOID );
LONG ReferenceCount(VOID) const { return m_ReferenceCount; }
BOOL IsValid(VOID) { return (m_Socket != INVALID_SOCKET) ? TRUE : FALSE; }
BOOL IsInvalid(VOID) { return !IsValid(); }
BOOL IsOpen(VOID) { return IsValid(); }
BOOL IsClosed(VOID) { return !IsOpen(); }
SOCKET GetSocket(VOID) const { return m_Socket; }
VOID SetSocket(SOCKET Socket) { m_Socket = Socket; }
BOOL IsSecureSocket(VOID) const { return m_fIsSecureSocket; }
BOOL IsNonBlocking(VOID) { return (m_dwFlags & SF_NON_BLOCKING) ? TRUE : FALSE; }
BOOL IsSecure(VOID) const { return (m_dwFlags & SF_SECURE) ? TRUE : FALSE; }
VOID SetEncryption(VOID) { m_dwFlags |= SF_ENCRYPT | SF_DECRYPT; }
VOID ResetEncryption(VOID) { m_dwFlags &= ~(SF_ENCRYPT | SF_DECRYPT); }
DWORD GetFlags(VOID) const { return m_dwFlags; }
VOID SetAuthorized(VOID) { m_dwFlags |= SF_AUTHORIZED; }
BOOL IsAuthorized(VOID) { return (m_dwFlags & SF_AUTHORIZED) ? TRUE : FALSE; }
VOID SetAuthenticated(VOID) { m_dwFlags |= SF_AUTHENTICATED; }
BOOL IsAuthenticated(VOID) { return (m_dwFlags & SF_AUTHENTICATED) ? TRUE : FALSE; }
VOID SetPerUser (VOID) { m_dwFlags |= SF_PERUSER; }
BOOL IsPerUser(VOID) { return (m_dwFlags & SF_PERUSER) ? TRUE : FALSE; }
VOID SetKeepAlive(VOID) { m_dwFlags |= SF_KEEP_ALIVE; }
VOID ResetKeepAlive(VOID) { m_dwFlags &= ~SF_KEEP_ALIVE; }
BOOL IsKeepAlive(VOID) { return (m_dwFlags & SF_KEEP_ALIVE) ? TRUE : FALSE; }
VOID SetInGlobalKeepAlivePool(VOID) { m_dwFlags |= SF_GLOBAL_KA_POOL; }
VOID ResetInGlobalKeepAlivePool(VOID) { m_dwFlags &= ~SF_GLOBAL_KA_POOL; }
BOOL IsInGlobalKeepAlivePool(VOID) const { return (m_dwFlags & SF_GLOBAL_KA_POOL) ? TRUE : FALSE; }
// check if desired flags are a subset of the socket flags
BOOL Match(DWORD dwFlags) { return ((m_dwFlags & dwFlags) == dwFlags) ? TRUE : FALSE; }
virtual BOOL MatchSecureProtocolSemantics( DWORD dwFlags, LPSTR pszHostName = NULL, DWORD dwSecureProtocols = 0, DWORD dwSecureFlags = 0) {
UNREFERENCED_PARAMETER(pszHostName); UNREFERENCED_PARAMETER(dwSecureProtocols); UNREFERENCED_PARAMETER(dwSecureFlags); return (dwFlags & (SF_TUNNEL | SF_SECURE)) ? FALSE : TRUE; }
VOID SetPort(INTERNET_PORT Port) { m_Port = Port; }
INTERNET_PORT GetPort(VOID) const { return m_Port; }
VOID SetSourcePort(VOID);
VOID SetSourcePort(INTERNET_PORT Port) { m_SourcePort = Port; }
INTERNET_PORT GetSourcePort(VOID) const { return m_SourcePort; }
VOID SetAborted(VOID) { m_bAborted = TRUE; }
BOOL IsAborted(VOID) const { return m_bAborted; }
DWORD GetServiceAddress( IN LPSTR HostName, IN DWORD Port );
DWORD Connect( IN LONG ConnectTimeout, IN INT Retries, IN DWORD dwFlags );
virtual DWORD Connect( IN LONG ConnectTimeout, IN INT Retries, IN LONG, // SendTimeout
IN LONG, // RecvTimeout
IN DWORD dwFlags ) { return Connect(ConnectTimeout, Retries, dwFlags); }
DWORD SocketConnect( IN LONG Timeout, IN INT Retries, IN DWORD dwFlags, IN CServerInfo *pServerInfo );
DWORD Connect_Start( IN CFsm_SocketConnect * Fsm );
DWORD Connect_Continue( IN CFsm_SocketConnect * Fsm );
DWORD Connect_Error( IN CFsm_SocketConnect * Fsm );
DWORD Connect_Finish( IN CFsm_SocketConnect * Fsm );
int SocksConnect( IN LPSOCKADDR_IN pSockaddr, IN INT nLen );
virtual DWORD Disconnect( IN DWORD dwFlags = 0 );
DWORD Close( VOID );
DWORD Abort( VOID );
DWORD Shutdown( IN DWORD dwControl );
BOOL IsReset( VOID );
virtual DWORD Send( IN LPVOID lpBuffer, IN DWORD dwBufferLength, IN DWORD dwFlags );
DWORD Send_Start( IN CFsm_SocketSend * Fsm );
virtual DWORD Receive( IN OUT LPVOID* lplpBuffer, IN OUT LPDWORD lpdwBufferLength, IN OUT LPDWORD lpdwBufferRemaining, IN OUT LPDWORD lpdwBytesReceived, IN DWORD dwExtraSpace, IN DWORD dwFlags, OUT LPBOOL lpbEof );
DWORD Receive_Start( IN CFsm_SocketReceive * Fsm );
DWORD Receive_Continue( IN CFsm_SocketReceive * Fsm );
DWORD Receive_Finish( IN CFsm_SocketReceive * Fsm );
DWORD SetTimeout( IN DWORD Type, IN int Timeout );
DWORD SetLinger( IN BOOL Linger, IN int Timeout );
DWORD SetNonBlockingMode( IN BOOL bNonBlocking );
DWORD GetBufferLength( IN SOCKET_BUFFER_ID SocketBufferId );
DWORD GetBufferLength( IN SOCKET_BUFFER_ID SocketBufferId, OUT LPDWORD lpdwBufferLength );
DWORD SetBufferLength( IN SOCKET_BUFFER_ID SocketBufferId, IN DWORD dwBufferLength );
DWORD SetSendCoalescing( IN BOOL bOnOff );
// This code needs to handle system time roll over.
// SetExpireTime is passed the duration, and we calculate the ultimate time
// However, this may result in a rollover -- e.g. if the current time is
// 0xffffff00, the ultimate time could be 0x000000fd
// HasExpired is passed the current tick count, however, and in the past
// would return TRUE immediately.
// Thus we set a flag is we need to wait for system time rollover to happen,
VOID SetExpiryTime( IN DWORD dwTimeout = GlobalKeepAliveSocketTimeout ) { DWORD dw = GetTickCountWrap(); m_dwTimeout = dw + dwTimeout; m_fTimeoutWraps = (m_dwTimeout < dw); }
DWORD GetExpiryTime(VOID) const { return m_dwTimeout; }
BOOL HasExpired( IN DWORD dwTime = GetTickCountWrap() ) { if (m_fTimeoutWraps) { m_fTimeoutWraps = ((LONG)dwTime < 0); } return ((m_dwTimeout == 0) || m_fTimeoutWraps) ? FALSE : (dwTime > m_dwTimeout); }
DWORD DataAvailable( OUT LPDWORD lpdwDataAvailable );
DWORD DataAvailable2( OUT LPVOID lpBuffer, IN DWORD dwBufferLength, OUT LPDWORD lpdwBytesAvailable );
DWORD WaitForReceive( IN DWORD Timeout );
DWORD AllocateQueryBuffer( OUT LPVOID * lplpBuffer, OUT LPDWORD lpdwBufferLength );
VOID FreeQueryBuffer( IN LPVOID lpBuffer );
DWORD EnableSocks( IN LPSTR lpSocksHost, IN INTERNET_PORT ipSocksPort );
BOOL IsSocks(VOID) { return m_SocksAddress != 0; }
#if 0
DWORD CreateSocket( IN DWORD dwFlags, IN int nFamily, IN int nType, IN int nProtocol ); #endif
DWORD GetSockName( IN PSOCKADDR psaSockName, IN int SockNameSize );
DWORD Listen( VOID );
DWORD DirectConnect( IN PSOCKADDR psaRemoteSock );
DWORD SelectAccept( IN ICSocket & acceptSocket, IN DWORD dwTimeout );
DWORD GetBytesAvailable( OUT LPDWORD lpdwBytesAvailable );
//VOID
//SetServiceAddress(
// IN LPADDRESS_INFO_LIST AddressList
// )
//{
// m_fOwnAddressList = FALSE;
// m_AddressList.Addresses = AddressList->Addresses;
// m_AddressList.AddressCount = AddressList->AddressCount;
//}
//DWORD
//GetServiceAddress(
// IN LPSTR HostName OPTIONAL,
// IN LPSTR ServiceName OPTIONAL,
// IN LPGUID ServiceGuid OPTIONAL,
// IN DWORD NameSpace,
// IN DWORD Port,
// IN DWORD ProtocolCharacteristics
// )
//{
// return ::GetServiceAddress(
// HostName,
// ServiceName,
// ServiceGuid,
// NameSpace,
// Port,
// ProtocolCharacteristics,
// &m_AddressList
// );
//}
//
// friend functions
//
friend ICSocket * ContainingICSocket( LPVOID lpAddress );
DWORD AssociateWithCompletionPort( VOID );
BOOL MatchOverlappedSemantics( IN DWORD dwSocketFlags ); };
|