void TryAsyncIO(AsyncIOResult ar, Boolean sync) { int read; if (handle == -1) { AsyncIOSetCompleted(ar, sync, new ObjectDisposedException(objectname)); return; } if (ar.Operation == 1) { read = send(handle, ref ar.Buffer[ar.Offset], (UIntPtr)ar.Length, ar.Flags); } else if (ar.Operation == 2) { Boolean wasBlocking = Blocking; Blocking = false; read = accept4(handle, IntPtr.Zero, IntPtr.Zero, 0x80000); var err = read == -1 ? Marshal.GetLastWin32Error() : 0; Blocking = wasBlocking; if (read != -1) { ar.Transferred = read; AsyncIOSetCompleted(ar, sync, null); } else if (err != 11) { AsyncIOSetCompleted(ar, sync, new PosixException(err, "accept4")); } return; } else { read = recv(handle, ref ar.Buffer[ar.Offset], (UIntPtr)ar.Length, ar.Flags); if (read == 0 && ar.Operation == 0) { AsyncIOSetCompleted(ar, sync, null); return; } } if (read == -1 && Marshal.GetLastWin32Error() == 11) { read = 0; } if (read < 0) { AsyncIOSetCompleted(ar, sync, new PosixException(ar.Operation == 1 ? "send" : "recv")); } else { ar.Offset += read; ar.Length -= read; ar.Transferred += read; if (ar.Length <= 0 || (ar.Transferred > 0 && ar.Operation == 0)) { AsyncIOSetCompleted(ar, sync, null); } } }
void AsyncIOSetCompleted(AsyncIOResult ar, Boolean synchronous, Exception error) { AsyncIOResult call = null; lock (this) { if (ar.Operation == 1) { if (sendqhead == ar) { sendqhead = call = ar.Next; } if (sendqtail == ar) { sendqtail = null; } } else { if (recvqhead == ar) { recvqhead = call = ar.Next; } if (recvqtail == ar) { recvqtail = null; } } ar.Next = null; } ar.SetCompleted(synchronous, error); if (call != null) { TryAsyncIO(call, false); if (!call.IsCompleted) { EpollWait(); //request was queued while this one was completing (synchronously, possibly chained) } } }
IAsyncResult BeginAsyncIO(int op, byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || size < 0 || offset + size > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (handle == -1) { throw new ObjectDisposedException(objectname); } AsyncIOResult ar = new AsyncIOResult(callback, state) { Socket = this, Buffer = buffer, Offset = offset, Length = size, Flags = ConvertFlags(socketFlags) | 0x40, //flags | MSG_DONTWAIT Operation = op, }; Boolean first = false; lock (this) { if (op == 1) { if (sendqtail == null) { first = true; sendqhead = ar; asyncwritebusy = 1; } else { sendqtail.Next = ar; } sendqtail = ar; } else { if (recvqtail == null) { first = true; recvqhead = ar; asyncreadbusy = 1; } else { recvqtail.Next = ar; } recvqtail = ar; } } if (first) { TryAsyncIO(ar, true); if (op == 1) { asyncwritebusy = 0; } else { asyncreadbusy = 0; } if (!ar.IsCompleted || ar.Next != null) { EpollWait(); } } return(ar); }