488 lines
12 KiB
C++
488 lines
12 KiB
C++
/*++
|
|
|
|
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_PIPELINED 0x00080000 // set if connection is pipelined (HTTP 1.1)
|
|
#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
|
|
|
|
// 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 LPSTR lpszAddress,
|
|
OUT LPSTR * lplpszMappedName
|
|
);
|
|
|
|
//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
|
|
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;
|
|
|
|
#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;
|
|
}
|
|
|
|
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 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 SetPipelined(VOID) {
|
|
m_dwFlags |= SF_PIPELINED;
|
|
}
|
|
|
|
VOID ResetPipelined(VOID) {
|
|
m_dwFlags &= ~SF_PIPELINED;
|
|
}
|
|
|
|
BOOL IsPipelined(VOID) {
|
|
return (m_dwFlags & SF_PIPELINED) ? TRUE : FALSE;
|
|
}
|
|
|
|
BOOL Match(DWORD dwFlags) {
|
|
return ((m_dwFlags & dwFlags) == dwFlags) ? TRUE : FALSE;
|
|
}
|
|
|
|
BOOL MatchTunnelSemantics(DWORD dwFlags) {
|
|
return ((m_dwFlags & SF_TUNNEL) == (dwFlags & SF_TUNNEL)) ? TRUE : FALSE;
|
|
}
|
|
|
|
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);
|
|
|
|
virtual
|
|
DWORD
|
|
Connect(
|
|
IN LONG Timeout,
|
|
IN INT Retries,
|
|
IN DWORD 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);
|
|
|
|
VOID
|
|
SetExpiryTime(
|
|
IN DWORD dwTimeout = GlobalKeepAliveSocketTimeout
|
|
) {
|
|
m_dwTimeout = GetTickCount() + dwTimeout;
|
|
}
|
|
|
|
DWORD GetExpiryTime(VOID) const {
|
|
return m_dwTimeout;
|
|
}
|
|
|
|
BOOL HasExpired(
|
|
IN DWORD dwTime = GetTickCount()
|
|
) {
|
|
return (m_dwTimeout == 0)
|
|
? FALSE
|
|
: ((dwTime > m_dwTimeout) ? TRUE : FALSE);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
DWORD
|
|
CreateSocket(
|
|
IN DWORD dwFlags,
|
|
IN int nFamily = AF_INET,
|
|
IN int nType = SOCK_STREAM,
|
|
IN int nProtocol = IPPROTO_TCP
|
|
);
|
|
|
|
DWORD GetSockName(PSOCKADDR psaSockName);
|
|
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);
|
|
}; |