private void OperationCompleted(object o, SocketAsyncEventArgs args) { if (args.SocketError != SocketError.Success || (args.LastOperation == SocketAsyncOperation.Receive && args.BytesTransferred == 0)) { OnError?.Invoke(args); } else { var data = args.GetUserToken <BufferData>(); switch (args.LastOperation) { case SocketAsyncOperation.Send: data.ByteCount += args.BytesTransferred; // We've transferred less bytes than we should have if (data.Length > data.ByteCount) { args.SetBuffer(data.BaseOffset + data.ByteCount, data.Length - data.ByteCount); // TODO: test if multiple send operations will collide (if the packet was only sent partially, and another packet is getting sent between the two parts) // TODO: create a queue for sending async, if it collides? SendAsync(args); return; } OnSend?.Invoke(args); break; case SocketAsyncOperation.Receive: // This value may change in the middle of processing, causing odd behavior var receiveAfter = AutoReceive; if (ProcessInputBuffer(data, args)) { return; } if (receiveAfter) { ReceiveAsync(); } break; case SocketAsyncOperation.Connect: OnConnect?.Invoke(args); break; case SocketAsyncOperation.Accept: OnAccept?.Invoke(new LengthedSocket(args.AcceptSocket, SizeHeaderLength, CountSize)); break; } } TeardownEventArgs(args); }
private void TeardownEventArgs(SocketAsyncEventArgs args) { switch (args.LastOperation) { case SocketAsyncOperation.Receive: case SocketAsyncOperation.Send: BufferManager.FreeBuffer(args.GetUserToken <BufferData>()); args.SetBuffer(null, 0, 0); args.UserToken = null; break; case SocketAsyncOperation.Connect: args.RemoteEndPoint = null; break; } args.AcceptSocket = null; args.Completed -= OperationCompleted; lock (_socketAsyncEventArgsPool) _socketAsyncEventArgsPool.Push(args); }