📄 select.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*****************************************************************************/
/** Microsoft Windows **/
/*****************************************************************************/
/*
select.c
select related winsock2 functions
FILE HISTORY:
OmarM 16-Oct-2000
*/
#include "winsock2p.h"
#include "windev.h"
// structure to allow optimizing the predominant case of select'ing on one or two sockets
typedef struct _STACK_SOCK_FD {
u_int osf_count_select1;
SOCKET osf_array_select1;
u_int osf_count_select2;
SOCKET osf_array_select2;
u_int osf_count_map1;
SOCKET osf_array_map1;
u_int osf_count_map2;
SOCKET osf_array_map2;
} STACK_SOCK_FD;
#define STACK_FDS_SIZE 2 // Number of select sockets supported on stack
void DerefFds(fd_set *pFds, int *pcRefs) {
u_int i;
__try {
if (pFds) {
for (i = 0; (i < pFds->fd_count) && (*pcRefs > 0); i++) {
DerefSocketHandle(pFds->fd_array[i]);
(*pcRefs)--;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
; // don't need to do anything here yet.
}
} // DerefFds()
int CopyFds(fd_set **pNewSelect, fd_set **pNewMap, fd_set *pUserFds, int *pcTotal, int *pcRefs,
WsProvider **ppProv, STACK_SOCK_FD * pStackFds) {
int Err;
u_int cCount, i;
WsSocket *pSock;
fd_set *pSelect;
fd_set *pMap;
BOOL bFromHeap;
Err = 0;
pSelect = NULL;
bFromHeap = TRUE;
__try {
if (pUserFds && (cCount = pUserFds->fd_count)) {
i = cCount * sizeof(SOCKET) + sizeof(int);
if (STACK_FDS_SIZE >= cCount) {
pSelect = (fd_set *)pStackFds;
bFromHeap = FALSE;
} else {
pSelect = LocalAlloc(LPTR, i*2); // allocate enough for pSelect and pMap
}
if (NULL == pSelect) {
Err = WSA_NOT_ENOUGH_MEMORY;
} else {
pMap = (fd_set *)((DWORD)pSelect + i);
*pcTotal += cCount;
pMap->fd_count = cCount;
pSelect->fd_count = cCount;
for (i = 0; i < cCount; i++) {
if (Err = RefSocketHandle(pUserFds->fd_array[i], &pSock)) {
break;
} else {
(*pcRefs)++;
pMap->fd_array[i] = pSock->hWSPSock;
pSelect->fd_array[i] = pSock->hWSPSock;
if (*ppProv) {
if (*ppProv != pSock->pProvider) {
Err = WSAEINVAL;
break;
}
} else
*ppProv = pSock->pProvider;
}
}
if (0 == Err) {
*pNewSelect = pSelect;
*pNewMap = pMap;
}
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
Err = WSAEFAULT;
}
if ((Err) && (bFromHeap) && (pSelect)) {
LocalFree(pSelect);
}
return Err;
} // CopyFds()
//
// Map select results from WSP socket contexts to WS2 user socket handles
//
void ResultFds(fd_set *pUser, fd_set *pSelect, fd_set *pMap) {
u_int i, j;
u_int n, m;
if (pUser && pSelect && pMap) {
n = pSelect->fd_count;
m = pMap->fd_count;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
if (pSelect->fd_array[i] == pMap->fd_array[j]) {
pSelect->fd_array[i] = pUser->fd_array[j];
break;
}
}
}
pUser->fd_count = n;
for (i = 0; i < n; i++) {
pUser->fd_array[i] = pSelect->fd_array[i];
}
} else if (pUser) {
__try {
pUser->fd_count = 0;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
; // don't need to do anything here yet.
}
}
} // ResultFds
int WSAAPI select (
IN int nfds,
IN OUT fd_set *readfds,
IN OUT fd_set *writefds,
IN OUT fd_set *exceptfds,
IN const struct timeval FAR * timeout) {
WsProvider *pProv;
int Err;
int i;
fd_set * Select[3];
fd_set * Map[3]; // auxillary array to help map from WSP socket context to WS2 user handle.
fd_set * User[3];
STACK_SOCK_FD StackFds[3]; // stack allocated space to avoid heap allocations for small select requests
int cTotal, cRefs, cReady;
struct timeval Time, *pTime;
cTotal = cRefs = 0;
Err = 0;
for (i = 0; i < 3; i++) {
Select[i] = Map[i] = NULL;
}
User[0] = readfds;
User[1] = writefds;
User[2] = exceptfds;
cReady = SOCKET_ERROR;
// copy timeout to make sure that we don't crash in lower layers b/c of
// bad timeout address...
if (pTime = (struct timeval *)timeout) {
__try {
pTime = &Time;
memcpy(&Time, timeout, sizeof(Time));
}
__except(EXCEPTION_EXECUTE_HANDLER) {
Err = WSAEFAULT;
}
}
if (! Err) {
pProv = NULL;
for (i = 0; (i < 3) && (0 == Err); i++) {
Err = CopyFds(&Select[i], &Map[i], User[i], &cTotal, &cRefs, &pProv, &StackFds[i]);
}
if (!Err) {
if (!cTotal || !pProv) {
Err = WSAEINVAL;
} else {
cReady = pProv->ProcTable.lpWSPSelect(nfds, Select[0], Select[1], Select[2],
pTime, &Err);
}
}
}
// cleanup
for (i=0; i<3; i++) {
DerefFds(User[i], &cRefs);
ResultFds(User[i], Select[i], Map[i]);
if ((Select[i]) && (Select[i] != (fd_set *)&StackFds[i])) {
LocalFree(Select[i]);
}
}
if (SOCKET_ERROR == cReady) {
SetLastError(Err);
}
return cReady;
} // select()
int __WSAFDIsSet (
SOCKET fd,
FD_SET FAR * set) {
int i = (set->fd_count & 0xFFFF);
while (i--)
if (set->fd_array[i] == fd)
return 1;
return 0;
} // __WSAFDIsSet()
int WPUFDIsSet(
SOCKET s,
FD_SET FAR * set){
return __WSAFDIsSet(s, set);
} // WPUFDIsSet()
int WSAAPI WSAEventSelect(
IN SOCKET s,
IN WSAEVENT hEventObject,
IN long lNetworkEvents) {
int Err, Status;
WsSocket *pSock;
if (! (Err = RefSocketHandle(s, &pSock))) {
Status = pSock->pProvider->ProcTable.lpWSPEventSelect(pSock->hWSPSock,
hEventObject, lNetworkEvents, &Err);
if (Status && ! Err)
Err = WSASYSCALLFAILURE;
DerefSocket(pSock);
}
if (Err) {
Status = SOCKET_ERROR;
SetLastError(Err);
} else
Status = 0;
return Status;
} // WSAEventSelect()
int WSAAPI WSAEnumNetworkEvents(
IN SOCKET s,
IN WSAEVENT hEventObject,
OUT LPWSANETWORKEVENTS lpNetworkEvents) {
int Err, Status;
WsSocket *pSock;
if (! (Err = RefSocketHandle(s, &pSock))) {
Status = pSock->pProvider->ProcTable.lpWSPEnumNetworkEvents(
pSock->hWSPSock, hEventObject, lpNetworkEvents, &Err);
if (Status && ! Err)
Err = WSASYSCALLFAILURE;
DerefSocket(pSock);
}
if (Err) {
Status = SOCKET_ERROR;
SetLastError(Err);
} else
Status = 0;
return Status;
} // WSAEnumNetworkEvents()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -