private async Task ReceiveVoiceAsync(CancellationToken cancelToken) { var closeTask = cancelToken.Wait(); try { byte[] packet, decodingBuffer = null, nonce = null, result; int packetLength, resultOffset, resultLength; IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0); if ((_config.Mode & AudioMode.Incoming) != 0) { decodingBuffer = new byte[MaxOpusSize]; nonce = new byte[24]; } while (!cancelToken.IsCancellationRequested) { await Task.Delay(1); if (_udp.Available > 0) { #if !DOTNET5_4 packet = _udp.Receive(ref endpoint); #else //TODO: Is this really the only way to end a Receive call in DOTNET5_4? var receiveTask = _udp.ReceiveAsync(); var task = Task.WhenAny(closeTask, receiveTask).Result; if (task == closeTask) break; var udpPacket = receiveTask.Result; packet = udpPacket.Buffer; endpoint = udpPacket.RemoteEndPoint; #endif packetLength = packet.Length; if (packetLength > 0 && endpoint.Equals(_endpoint)) { if (State != ConnectionState.Connected) { if (packetLength != 70) return; string ip = Encoding.UTF8.GetString(packet, 4, 70 - 6).TrimEnd('\0'); int port = packet[68] | packet[69] << 8; SendSelectProtocol(ip, port); if ((_config.Mode & AudioMode.Incoming) == 0) return; //We dont need this thread anymore } else { //Parse RTP Data if (packetLength < 12) return; if (packet[0] != 0x80) return; //Flags if (packet[1] != 0x78) return; //Payload Type ushort sequenceNumber = (ushort)((packet[2] << 8) | packet[3] << 0); uint timestamp = (uint)((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8) | (packet[7] << 0)); uint ssrc = (uint)((packet[8] << 24) | (packet[9] << 16) | (packet[10] << 8) | (packet[11] << 0)); //Decrypt if (_isEncrypted) { if (packetLength < 28) //12 + 16 (RTP + Poly1305 MAC) return; Buffer.BlockCopy(packet, 0, nonce, 0, 12); int ret = SecretBox.Decrypt(packet, 12, packetLength - 12, decodingBuffer, nonce, _secretKey); if (ret != 0) continue; result = decodingBuffer; resultOffset = 0; resultLength = packetLength - 28; } else //Plain { result = packet; resultOffset = 12; resultLength = packetLength - 12; } /*if (_logLevel >= LogMessageSeverity.Debug) RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/ ulong userId; if (_ssrcMapping.TryGetValue(ssrc, out userId)) OnFrameReceived(userId, Channel.Id, result, resultOffset, resultLength); } } } } } catch (OperationCanceledException) { } catch (InvalidOperationException) { } //Includes ObjectDisposedException }