using System; using System.Collections.Generic; using System.Text; using System.Collections; using System.Runtime.InteropServices; namespace Augi { /// /// Static class providing Socket.Select method. This is neccessary because .NET implementation is not valid. /// public static class SocketSelect { #region public static void Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds) /// /// Determines the status of one or more sockets. /// /// An IList of Socket instances to check for readability. /// An IList of Socket instances to check for writability. /// An IList of Socket instances to check for errors. /// The time-out value, in microseconds. A -1 value indicates an infinite time-out. public static void Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds) { if ((((checkRead == null) || (checkRead.Count == 0)) && ((checkWrite == null) || (checkWrite.Count == 0))) && ((checkError == null) || (checkError.Count == 0))) { throw new ArgumentNullException(); } if ((checkRead != null) && (checkRead.Count > 0x10000)) { throw new ArgumentOutOfRangeException("checkRead"); } if ((checkWrite != null) && (checkWrite.Count > 0x10000)) { throw new ArgumentOutOfRangeException("checkWrite"); } if ((checkError != null) && (checkError.Count > 0x10000)) { throw new ArgumentOutOfRangeException("checkError"); } IntPtr[] readfds = SocketListToFileDescriptorSet(checkRead); IntPtr[] writefds = SocketListToFileDescriptorSet(checkWrite); IntPtr[] exceptfds = SocketListToFileDescriptorSet(checkError); TimeValue socketTime = null; if (microSeconds != -1) { socketTime = new TimeValue(); MicrosecondsToTimeValue((long)((ulong)microSeconds), socketTime); } if (select(0, readfds, writefds, exceptfds, socketTime) == -1) { throw new System.Net.Sockets.SocketException(); } SelectFileDescriptor(checkRead, readfds); SelectFileDescriptor(checkWrite, writefds); SelectFileDescriptor(checkError, exceptfds); } #endregion #region private static IntPtr[] SocketListToFileDescriptorSet(IList socketList) private static IntPtr[] SocketListToFileDescriptorSet(IList socketList) { if ((socketList == null) || (socketList.Count == 0)) { return null; } IntPtr[] ptrArray = new IntPtr[socketList.Count + 1]; ptrArray[0] = (IntPtr)socketList.Count; for (int i = 0; i < socketList.Count; i++) { if (!(socketList[i] is System.Net.Sockets.Socket)) { throw new ArgumentException("socketList"); } ptrArray[i + 1] = ((System.Net.Sockets.Socket)socketList[i]).Handle; } return ptrArray; } #endregion #region private static void MicrosecondsToTimeValue(long microSeconds, TimeValue socketTime) private static void MicrosecondsToTimeValue(long microSeconds, TimeValue socketTime) { socketTime.Seconds = (int)(microSeconds / 0xf4240L); socketTime.Microseconds = (int)(microSeconds % 0xf4240L); } #endregion #region private static void SelectFileDescriptor(IList socketList, IntPtr[] fileDescriptorSet) private static void SelectFileDescriptor(IList socketList, IntPtr[] fileDescriptorSet) { if ((socketList != null) && (socketList.Count != 0)) { if (((int)fileDescriptorSet[0]) == 0) { socketList.Clear(); } else { lock (socketList) { for (int i = 0; i < socketList.Count; i++) { System.Net.Sockets.Socket socket = socketList[i] as System.Net.Sockets.Socket; int num2 = 0; while (num2 < ((int)fileDescriptorSet[0])) { if (fileDescriptorSet[num2 + 1] == socket.Handle) { break; } num2++; } if (num2 == ((int)fileDescriptorSet[0])) { socketList.RemoveAt(i--); } } } } } } #endregion #region internal struct TimeValue /*[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] internal struct TimeValue { public int Seconds; public int Microseconds; }*/ [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] internal class TimeValue { public int Seconds; public int Microseconds; } #endregion #region select [DllImport("ws2_32.dll", SetLastError = true)] internal static extern int select([In] int ignoredParameter, [In, Out] IntPtr[] readfds, [In, Out] IntPtr[] writefds, [In, Out] IntPtr[] exceptfds, [In] TimeValue timeout); #endregion } }