internal static int FillFdSetFromSocketList(ref Interop.libc.fd_set fdset, IList socketList) { if (socketList == null || socketList.Count == 0) { return(0); } int maxFd = -1; for (int i = 0; i < socketList.Count; i++) { var socket = socketList[i] as Socket; if (socket == null) { throw new ArgumentException(SR.Format(SR.net_sockets_select, socketList[i].GetType().FullName, typeof(System.Net.Sockets.Socket).FullName), "socketList"); } int fd = socket._handle.FileDescriptor; fdset.Set(fd); if (fd > maxFd) { maxFd = fd; } } return(maxFd + 1); }
// Transform the list socketList such that the only sockets left are those // with a file descriptor contained in the array "fileDescriptorArray". internal static void FilterSocketListUsingFdSet(ref Interop.libc.fd_set fdset, IList socketList) { if (socketList == null || socketList.Count == 0) { return; } lock (socketList) { for (int i = socketList.Count - 1; i >= 0; i--) { var socket = (Socket)socketList[i]; if (!fdset.IsSet(socket._handle.FileDescriptor)) { socketList.RemoveAt(i); } } } }
public static unsafe SocketError Select(IList checkRead, IList checkWrite, IList checkError, int microseconds) { var readSet = new Interop.libc.fd_set(); int maxReadFd = Socket.FillFdSetFromSocketList(ref readSet, checkRead); var writeSet = new Interop.libc.fd_set(); int maxWriteFd = Socket.FillFdSetFromSocketList(ref writeSet, checkWrite); var errorSet = new Interop.libc.fd_set(); int maxErrorFd = Socket.FillFdSetFromSocketList(ref errorSet, checkError); int nfds = 0; Interop.libc.fd_set* readfds = null; Interop.libc.fd_set* writefds = null; Interop.libc.fd_set* errorfds = null; if (maxReadFd != 0) { readfds = &readSet; nfds = maxReadFd; } if (maxWriteFd != 0) { writefds = &writeSet; if (maxWriteFd > nfds) { nfds = maxWriteFd; } } if (maxErrorFd != 0) { errorfds = &errorSet; if (maxErrorFd > nfds) { nfds = maxErrorFd; } } int socketCount; if (microseconds != -1) { var tv = new Interop.libc.timeval(microseconds); socketCount = Interop.libc.select(nfds, readfds, writefds, errorfds, &tv); } else { socketCount = Interop.libc.select(nfds, readfds, writefds, errorfds, null); } GlobalLog.Print("Socket::Select() Interop.libc.select returns socketCount:" + socketCount); if (socketCount == -1) { return SocketError.SocketError; // TODO: should this be SCH.GetLastSocketError()? } Socket.FilterSocketListUsingFdSet(ref readSet, checkRead); Socket.FilterSocketListUsingFdSet(ref writeSet, checkWrite); Socket.FilterSocketListUsingFdSet(ref errorSet, checkError); return (SocketError)socketCount; }
public static unsafe SocketError Poll(SafeCloseSocket handle, int microseconds, SelectMode mode, out bool status) { var fdset = new Interop.libc.fd_set(); fdset.Set(handle.FileDescriptor); // TODO: this should probably be 0 if readfds, writefds, and errorfds are all null int nfds = handle.FileDescriptor + 1; Interop.libc.fd_set* readfds = mode == SelectMode.SelectRead ? &fdset : null; Interop.libc.fd_set* writefds = mode == SelectMode.SelectWrite ? &fdset : null; Interop.libc.fd_set* errorfds = mode == SelectMode.SelectError ? &fdset : null; int socketCount = 0; if (microseconds != -1) { var tv = new Interop.libc.timeval(microseconds); socketCount = Interop.libc.select(nfds, readfds, writefds, errorfds, &tv); } else { socketCount = Interop.libc.select(nfds, readfds, writefds, errorfds, null); } if (socketCount == -1) { status = false; return SocketError.SocketError; // TODO: should this be SCH.GetLastSocketError()? } status = fdset.IsSet(handle.FileDescriptor); return (SocketError)socketCount; }