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
}
}