Esempio n. 1
0
        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
        }