void OnPollServer(Poll handle, PollStatus status) { Socket socket = this.serverContext.Socket.Accept(); IntPtr socketHandle = TestHelper.GetHandle(socket); const PollMask Mask = PollMask.Readable | PollMask.Writable | PollMask.Disconnect; Poll poll = this.loop .CreatePoll(socketHandle) .Start(Mask, this.OnPollConnection); Timer timer = this.loop.CreateTimer(); var context = new ConnectionContext(socket, poll, true) { TimerHandle = timer, EventMask = Mask, OpenHandles = 2 }; timer.UserToken = context; poll.UserToken = context; this.serverContext.ConnectionCount++; if (this.serverContext.ConnectionCount < NumberOfClients) { return; } DestroyServerContext(this.serverContext); }
void StartClient() { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var anyEndPoint = new IPEndPoint(IPAddress.Loopback, IPEndPoint.MinPort); socket.Bind(anyEndPoint); IntPtr handle = TestHelper.GetHandle(socket); const PollMask Mask = PollMask.Readable | PollMask.Writable | PollMask.Disconnect; Poll poll = this.loop.CreatePoll(handle).Start(Mask, this.OnPollConnection); Timer timer = this.loop.CreateTimer(); var context = new ConnectionContext(socket, poll, false) { TimerHandle = timer, EventMask = Mask, OpenHandles = 2 }; timer.UserToken = context; poll.UserToken = context; // Kick off the connect try { socket.Connect(this.endPoint); } catch (SocketException exception) { if (!IsErrorAgain(exception)) { throw; } } }
// Calling uv_poll_start() on a handle that is already active is fine. // Doing so will update the events mask that is being watched for. internal static void PollStart(IntPtr handle, PollMask mask) { Debug.Assert(handle != IntPtr.Zero); int result = uv_poll_start(handle, (int)mask, Poll.PollCallback); ThrowIfError(result); }
/// <summary> /// SOCKETFUNCTION implementation. /// </summary> /// <param name="easy"></param> /// <param name="sockfd"></param> /// <param name="what"></param> /// <param name="userp"></param> /// <param name="socketp"></param> /// <returns></returns> private int HandleSocket(IntPtr easy, IntPtr sockfd, CURLpoll what, IntPtr userp, IntPtr socketp) { Logger.LogTrace( $"Called {nameof(CURLMoption.SOCKETFUNCTION)}. We need to poll for {what} on socket {sockfd}."); switch (what) { case CURLpoll.IN: case CURLpoll.OUT: case CURLpoll.INOUT: //#if !UNITY PollMask events = 0; if (what != CURLpoll.IN) { events |= PollMask.Writable; } if (what != CURLpoll.OUT) { events |= PollMask.Readable; } Logger.LogTrace($"Polling socket {sockfd} using libuv with mask {events}."); _socketMap.GetOrCreatePoll(sockfd, _loop).Start(events, (poll, status) => { CURLcselect flags = 0; if (status.Mask.HasFlag(PollMask.Readable)) { flags |= CURLcselect.IN; } if (status.Mask.HasFlag(PollMask.Writable)) { flags |= CURLcselect.OUT; } Logger.LogTrace($"Finished polling socket {sockfd}."); CurlNative.Multi.SocketAction(_multiHandle, sockfd, flags, out int _); CheckMultiInfo(); }); break; case CURLpoll.REMOVE: Logger.LogTrace($"Removing poll of socket {sockfd}."); _socketMap.RemovePoll(sockfd); break; //#else // break; //#endif default: throw new ArgumentOutOfRangeException(nameof(what)); } return(0); }
public Poll Start(PollMask eventMask, Action <Poll, PollStatus> callback) { Contract.Requires(callback != null); this.Validate(); this.pollCallback = callback; NativeMethods.PollStart(this.InternalHandle, eventMask); return(this); }
// Calling uv_poll_start() on a handle that is already active is fine. // Doing so will update the events mask that is being watched for. internal static void PollStart(IntPtr handle, PollMask mask) { Contract.Requires(handle != IntPtr.Zero); int result = uv_poll_start(handle, (int)mask, Poll.PollCallback); if (result < 0) { throw CreateError((uv_err_code)result); } }
public Poll Start(PollMask eventMask, Action <Poll, PollStatus> callback) { if (callback is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.callback); } Validate(); _pollCallback = callback; NativeMethods.PollStart(InternalHandle, eventMask); return(this); }
internal PollStatus(PollMask mask, Exception error) { this.Mask = mask; this.Error = error; }
void OnPollConnection(Poll handle, PollStatus status) { var context = (ConnectionContext)handle.UserToken; PollMask pollMask = status.Mask; PollMask newEvents = context.EventMask; var random = new Random(10); if ((pollMask & PollMask.Readable) == PollMask.Readable) { int action = random.Next() % 7; if (action == 0 || action == 1) { // Read a couple of bytes. var buffer = new byte[74]; int count = TryReceive(context.Socket, buffer); if (count > 0) { context.Receive += count; } else { // Got FIN. context.ReceiveFinished = true; newEvents &= ~PollMask.Readable; } } else if (action == 2 || action == 3) { // Read until EAGAIN. var buffer = new byte[931]; int count = TryReceive(context.Socket, buffer); while (count > 0) { context.Receive += count; count = TryReceive(context.Socket, buffer); } if (count == 0) { // Got FIN. context.ReceiveFinished = true; newEvents &= ~PollMask.Readable; } } else if (action == 4) { // Ignore. } else if (action == 5) { // Stop reading for a while. Restart in timer callback. newEvents &= ~PollMask.Readable; if (!context.TimerHandle.IsActive) { context.DelayedEventMask = PollMask.Readable; context.TimerHandle.Start(this.OnTimerDelay, 10, 0); } else { context.DelayedEventMask |= PollMask.Readable; } } else if (action == 6) { // Fudge with the event mask. context.PollHandle.Start(PollMask.Writable, this.OnPollConnection); context.PollHandle.Start(PollMask.Readable, this.OnPollConnection); context.EventMask = PollMask.Readable; } } if ((pollMask & PollMask.Writable) == PollMask.Writable && !this.deplux && context.IsServerConnection) { // We have to send more bytes. int action = random.Next() % 7; if (action == 0 || action == 1) { // Send a couple of bytes. var buffer = new byte[103]; int send = Math.Min(TransferBytes - context.Sent, buffer.Length); int count = TrySend(context.Socket, buffer, send); if (count < 0) { this.spuriousWritableWakeups++; } else { context.Sent += count; this.validWritableWakeups++; } } else if (action == 2 || action == 3) { // Send until EAGAIN. var buffer = new byte[1234]; int send = Math.Min(TransferBytes - context.Sent, buffer.Length); int count = TrySend(context.Socket, buffer, send); if (count < 0) { this.spuriousWritableWakeups++; } else { context.Sent += count; this.validWritableWakeups++; } while (context.Sent < TransferBytes) { send = Math.Min(TransferBytes - context.Sent, buffer.Length); count = TrySend(context.Socket, buffer, send); if (count < 0) { break; } else { context.Sent += count; } } } else if (action == 4) { // Ignore. } else if (action == 5) { // Stop sending for a while. Restart in timer callback. newEvents &= ~PollMask.Writable; if (!context.TimerHandle.IsActive) { context.DelayedEventMask = PollMask.Writable; context.TimerHandle.Start(this.OnTimerDelay, 100, 0); } else { context.DelayedEventMask |= PollMask.Writable; } } else if (action == 6) { // Fudge with the event mask. context.PollHandle.Start(PollMask.Readable, this.OnPollConnection); context.PollHandle.Start(PollMask.Writable, this.OnPollConnection); context.EventMask = PollMask.Writable; } } else { // Nothing more to write. Send FIN. context.Socket.Shutdown(SocketShutdown.Send); context.SentFinished = true; newEvents &= ~PollMask.Writable; } if ((pollMask & PollMask.Disconnect) == PollMask.Disconnect) { context.Disconnected = true; newEvents &= ~PollMask.Disconnect; } if (context.SentFinished || context.ReceiveFinished || context.Disconnected) { if (context.SentFinished || context.ReceiveFinished) { this.DestroyConnectionContext(context); } else { /* Poll mask changed. Call uv_poll_start again. */ context.EventMask = newEvents; context.PollHandle.Start(newEvents, this.OnPollConnection); } } }
internal PollStatus(PollMask mask, Exception error) { Mask = mask; Error = error; }