private async Task RecievePacket(UdpReceiveResult packet) { long startAbsolutePosition; switch ((CommandCode)packet.Buffer[0]) { case CommandCode.ConnectAck: lock (this) { state = ClientSocketState.Working; Monitor.Pulse(this); } LastRecieved = DateTime.Now; Console.WriteLine($"Connect acked"); break; case CommandCode.Data: Console.WriteLine($"Incoming data"); startAbsolutePosition = BitConverter.ToInt64(packet.Buffer, 1); LastRecieved = DateTime.Now; bool added; lock (RecieveBuffer) { try { added = RecieveBuffer.TryAdd(packet.Buffer, 9, packet.Buffer.Length - 9, startAbsolutePosition); } catch (ArgumentOutOfRangeException) { break; } Monitor.PulseAll(RecieveBuffer); } Console.WriteLine($"Data got, added:{added}"); if (added) { byte[] message = new byte[1 + 8 + 8]; message[0] = (byte)CommandCode.DataAck; Array.Copy(packet.Buffer, 1, message, 1, 8); byte[] length = BitConverter.GetBytes((long)(packet.Buffer.Length - 9)); Array.Copy(length, 0, message, 1 + 8, 8); await udpclient.SendAsync(message, message.Length, packet.RemoteEndPoint); } else { byte[] message = { (byte)CommandCode.Overloaded }; await udpclient.SendAsync(message, message.Length, packet.RemoteEndPoint); } break; case CommandCode.DataAck: startAbsolutePosition = BitConverter.ToInt64(packet.Buffer, 1); long dataBytesCount = BitConverter.ToInt64(packet.Buffer, 1 + 8); LastRecieved = DateTime.Now; LastSend = DateTime.Now + overloadedPause; // For next data to be sent w/o timeout failedSendAttempts = 0; Console.WriteLine($"Data ack got pos: {startAbsolutePosition} count: {dataBytesCount}"); lock (SendBuffer) { SendBuffer.DisposeElements(startAbsolutePosition, (int)dataBytesCount); Monitor.PulseAll(SendBuffer); } break; case CommandCode.Overloaded: LastRecieved = DateTime.Now; LastSend = DateTime.Now + overloadedPause; // For next data to be sent after pause failedSendAttempts = 0; break; default: throw new ArgumentOutOfRangeException(); } }