272 lines
8.3 KiB
C
272 lines
8.3 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sockp.h
|
|
|
|
Abstract:
|
|
|
|
Declarations internal to Winsock implementation
|
|
|
|
Revision History:
|
|
|
|
05/30/2000 davidx
|
|
Created it.
|
|
|
|
--*/
|
|
|
|
#ifndef _SOCKP_H
|
|
#define _SOCKP_H
|
|
|
|
//------------------------------------------------------------------------
|
|
// Per-thread Winsock data
|
|
//------------------------------------------------------------------------
|
|
|
|
typedef struct _WinsockThreadbuf {
|
|
CHAR* data;
|
|
UINT size;
|
|
} WinsockThreadbuf;
|
|
|
|
typedef struct _WinsockTlsData {
|
|
WinsockThreadbuf strbuf;
|
|
WinsockThreadbuf hostentbuf;
|
|
WinsockThreadbuf serventbuf;
|
|
WinsockThreadbuf protoentbuf;
|
|
} WinsockTlsData;
|
|
|
|
WinsockTlsData* SockAllocThreadData();
|
|
VOID SockFreeThreadData(WinsockTlsData* tlsData);
|
|
|
|
#if defined(BUILD_FOR_DEBUGGER)
|
|
|
|
INLINE WinsockTlsData* SockGetThreadData() {
|
|
return (WinsockTlsData*) DmGetCurrentDmtd()->WinSockData;
|
|
}
|
|
|
|
INLINE VOID SockSetThreadData(WinsockTlsData* tlsData) {
|
|
DmGetCurrentDmtd()->WinSockData = tlsData;
|
|
}
|
|
|
|
#else // !BUILD_FOR_DEBUGGER
|
|
|
|
extern __declspec(thread) WinsockTlsData* WinsockTlsDataPtr;
|
|
|
|
INLINE WinsockTlsData* SockGetThreadData() {
|
|
return WinsockTlsDataPtr;
|
|
}
|
|
|
|
INLINE VOID SockSetThreadData(WinsockTlsData* tlsData) {
|
|
WinsockTlsDataPtr = tlsData;
|
|
}
|
|
|
|
#endif // !BUILD_FOR_DEBUGGER
|
|
|
|
// Allocate per-thread temporary buffer
|
|
VOID* SockAllocThreadbuf(WinsockThreadbuf* buf, UINT size);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Map an API-level socket handle to
|
|
// a pointer to our internal socket data structure
|
|
//------------------------------------------------------------------------
|
|
|
|
INLINE PCB* SockLock(SOCKET s) {
|
|
PCB* pcb;
|
|
INT err;
|
|
LONG cookie;
|
|
|
|
// NOTE: We don't allow multiple threads to access the same
|
|
// socket simultaneously. If the app tries to do that, the first
|
|
// thread will succeed and other threads will get an error return.
|
|
|
|
if (s == 0 || s == INVALID_SOCKET) {
|
|
err = WSAENOTSOCK;
|
|
} else {
|
|
pcb = (PCB*) s;
|
|
cookie = InterlockedCompareExchange(
|
|
&pcb->magicCookie,
|
|
BUSY_PCB_COOKIE,
|
|
ACTIVE_PCB_COOKIE);
|
|
|
|
if (cookie == ACTIVE_PCB_COOKIE) return pcb;
|
|
err = (cookie == BUSY_PCB_COOKIE) ? WSAEINPROGRESS : WSAENOTSOCK;
|
|
}
|
|
|
|
#if DBG
|
|
#if !defined(BUILD_FOR_DEBUGGER)
|
|
if (err == WSAEINPROGRESS) {
|
|
WARNING_("Thread contention on socket handle: tid = %x, socket = %x",
|
|
GetCurrentThreadId(), s);
|
|
} else
|
|
#endif
|
|
{
|
|
WARNING_("Invalid socket handle: socket = %x, error = %d", s, err);
|
|
}
|
|
#endif
|
|
|
|
SetLastError(err);
|
|
return NULL;
|
|
}
|
|
|
|
INLINE VOID SockUnlock(PCB* pcb) {
|
|
pcb->magicCookie = ACTIVE_PCB_COOKIE;
|
|
}
|
|
|
|
//
|
|
// Socket address length
|
|
//
|
|
#define SOCKADDRLEN ((INT) sizeof(SOCKADDR_IN))
|
|
|
|
//
|
|
// Network stack initialization state
|
|
//
|
|
extern LONG XnetInitState;
|
|
|
|
#define XNETSTATE_INVALID 0 // not initialized
|
|
#define XNETSTATE_READY 1 // successfully initialized
|
|
|
|
//
|
|
// Find a supported protocol that matches the specified parameters
|
|
//
|
|
INT
|
|
MatchTcpipProtocol(
|
|
IN INT af,
|
|
IN INT type,
|
|
IN INT protocol,
|
|
OUT const WSAPROTOCOL_INFOW** protoinfo
|
|
);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Prolog and epilog code for Winsock API functions
|
|
//------------------------------------------------------------------------
|
|
|
|
INT SockEnterApiSlow(WinsockTlsData** tlsData);
|
|
|
|
#if DBG
|
|
|
|
#define SOCKTRACE_WSAStartup BIT(0)
|
|
#define SOCKTRACE_WSACleanup BIT(0)
|
|
#define SOCKTRACE_socket BIT(1)
|
|
#define SOCKTRACE_closesocket BIT(1)
|
|
#define SOCKTRACE_shutdown BIT(1)
|
|
#define SOCKTRACE_setsockopt BIT(2)
|
|
#define SOCKTRACE_getsockopt BIT(2)
|
|
#define SOCKTRACE_ioctlsocket BIT(2)
|
|
#define SOCKTRACE_WSARecv BIT(3)
|
|
#define SOCKTRACE_WSARecvFrom BIT(3)
|
|
#define SOCKTRACE_recv BIT(3)
|
|
#define SOCKTRACE_recvfrom BIT(3)
|
|
#define SOCKTRACE_WSASend BIT(4)
|
|
#define SOCKTRACE_WSASendTo BIT(4)
|
|
#define SOCKTRACE_send BIT(4)
|
|
#define SOCKTRACE_sendto BIT(4)
|
|
#define SOCKTRACE_bind BIT(5)
|
|
#define SOCKTRACE_connect BIT(5)
|
|
#define SOCKTRACE_listen BIT(5)
|
|
#define SOCKTRACE_accept BIT(5)
|
|
#define SOCKTRACE_getsockname BIT(5)
|
|
#define SOCKTRACE_getpeername BIT(5)
|
|
#define SOCKTRACE_select BIT(6)
|
|
#define SOCKTRACE_WSAGetOverlappedResult BIT(6)
|
|
#define SOCKTRACE_WSACancelOverlappedIO BIT(6)
|
|
#define SOCKTRACE_inet_addr BIT(7)
|
|
#define SOCKTRACE_inet_ntoa BIT(7)
|
|
#define SOCKTRACE_gethostbyaddr BIT(7)
|
|
#define SOCKTRACE_gethostbyname BIT(7)
|
|
#define SOCKTRACE_gethostname BIT(7)
|
|
#define SOCKTRACE_getprotoby_ BIT(7)
|
|
#define SOCKTRACE_getprotobyname BIT(7)
|
|
#define SOCKTRACE_getprotobynumber BIT(7)
|
|
#define SOCKTRACE_getservby_ BIT(7)
|
|
#define SOCKTRACE_getservbyname BIT(7)
|
|
#define SOCKTRACE_getservbyport BIT(7)
|
|
#define SOCKTRACE_WSAEnumProtocols BIT(7)
|
|
#define SOCKTRACE_XnetInitialize BIT(8)
|
|
#define SOCKTRACE_XnetCleanup BIT(8)
|
|
#define SOCKTRACE_XnetGetIpAddress BIT(8)
|
|
|
|
extern INT _winsockTraceFlag;
|
|
|
|
#define WinsockApiProlog_(_apiname, _result) \
|
|
static const CHAR* fname_ = #_apiname; \
|
|
WinsockTlsData* tlsData; \
|
|
INT err; \
|
|
if (_winsockTraceFlag & SOCKTRACE_##_apiname) { \
|
|
DbgPrint("Entering %s...\n", fname_); \
|
|
} \
|
|
err = (XnetInitState == XNETSTATE_INVALID) ? WSASYSNOTREADY : \
|
|
((tlsData = SockGetThreadData()) != NULL) ? NO_ERROR : \
|
|
SockEnterApiSlow(&tlsData); \
|
|
WinsockApiCheckError_(_result)
|
|
|
|
#define WinsockApiPrologLight_(_apiname) \
|
|
static const CHAR* fname_ = #_apiname; \
|
|
if (_winsockTraceFlag & SOCKTRACE_##_apiname) { \
|
|
DbgPrint("Entering %s...\n", fname_); \
|
|
}
|
|
|
|
#define WinsockApiWarnError_(_err) { \
|
|
if ((_err) != WSA_IO_PENDING && \
|
|
(_err) != WSA_IO_INCOMPLETE && \
|
|
(_err) != WSAETIMEDOUT && \
|
|
(_err) != WSAEWOULDBLOCK) { \
|
|
WARNING_("%s failed: %d", fname_, _err); \
|
|
} \
|
|
}
|
|
|
|
#define WinsockApiParamCheck_(_exp) { \
|
|
if (!(_exp)) { \
|
|
DbgPrint("%s: %s\n", fname_, #_exp); \
|
|
RIP("bad winsock parameters\n"); \
|
|
} \
|
|
}
|
|
|
|
#else // !DBG
|
|
|
|
#define WinsockApiProlog_(_apiname, _result) \
|
|
WinsockTlsData* tlsData; \
|
|
INT err; \
|
|
err = (XnetInitState == XNETSTATE_INVALID) ? WSASYSNOTREADY : \
|
|
((tlsData = SockGetThreadData()) != NULL) ? NO_ERROR : \
|
|
SockEnterApiSlow(&tlsData); \
|
|
WinsockApiCheckError_(_result)
|
|
|
|
#define WinsockApiPrologLight_(_apiname)
|
|
#define WinsockApiWarnError_(_err)
|
|
#define WinsockApiParamCheck_(_exp)
|
|
|
|
#endif // !DBG
|
|
|
|
#define WinsockApiReturnError_(_err, _result) { \
|
|
WinsockApiWarnError_(_err); \
|
|
SetLastError(_err); \
|
|
return (_result); \
|
|
}
|
|
|
|
#define WinsockApiCheckError_(_result) { \
|
|
if (err != NO_ERROR) { \
|
|
WinsockApiReturnError_(err, _result); \
|
|
} \
|
|
}
|
|
|
|
#define WinsockApiPrologSockLock_(_apiname, _result) \
|
|
PCB* pcb; \
|
|
WinsockApiProlog_(_apiname, _result); \
|
|
pcb = SockLock(s); \
|
|
if (!pcb) return (_result)
|
|
|
|
#define WinsockApiExitSockUnlock_(_resultOk, _resultErr) \
|
|
exit: SockUnlock(pcb); \
|
|
WinsockApiCheckError_(_resultErr); \
|
|
return (_resultOk)
|
|
|
|
#define WinsockApiGotoExit_(_err) \
|
|
{ err = (_err); goto exit; }
|
|
|
|
#define MapNtStatusToWinsockError_(_err) \
|
|
((_err) = NT_SUCCESS(_err) ? NO_ERROR : RtlNtStatusToDosError(_err))
|
|
|
|
#endif // !_SOCKP_H
|
|
|