xbox-kernel/private/ntos/xnet/winsock/sockp.h
2020-09-30 17:17:25 +02:00

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