public async ValueTask BindAsync(IPEndPoint endPoint) { await Task.FromResult(0); if (!Connected) { UdpClient = new UdpClient(endPoint); } _logger.LogInformation($"Start listening on {endPoint}"); //Open a thread to listen incoming packets. Tasks.Enqueue(Task.Run(async() => { while (true) { var receive = await UdpClient.ReceiveAsync(); _logger.LogInformation($"Incoming from {receive.RemoteEndPoint}"); //Add remote to route if (!Route.ContainsKey(receive.RemoteEndPoint)) { _logger.LogInformation($"Adding {receive.RemoteEndPoint} to route"); Route.AddOrUpdate(receive.RemoteEndPoint, _ => { var instance = new SelectiveRepeatProtoClientClientServerInstance(_logger); PendingInstance.Enqueue(instance); return(instance); }, (_, instance) => instance); var r = Route[receive.RemoteEndPoint]; //Open a new thread to process pending sends. Tasks.Enqueue(Task.Run(async() => { while (true) { //Wait until new window comes out while (r.CurrentReceiveWindowSize == 0) { await Task.Delay(10); } //Process the received data for (byte i = 1; i <= r.CurrentReceiveWindowSize; i++) { byte[] value; while (!r.WaitingForConfirmReceive.TryGetValue(i, out value)) { await Task.Delay(10); } r.PendingReceive.Enqueue(value[4..]); } //Switch window _logger.LogInformation("Receive window switched."); r.CurrentReceiveNamespace = r.CurrentReceiveNamespace == 0 ? 1 : 0; r.WaitingForConfirmReceive.Clear(); r.CurrentReceiveWindowSize = 0; } })); }