private async Task <bool> PerformDiscoveryAndSelectProtocolAsync(
            VoiceGatewayReady ready,
            CancellationToken cancellationToken = default)
        {
            Debug.Assert(EndPoint != null);

            var bytesSent = await _discoverySocket.SendToAsync(
                DiscoveryPacket, SocketFlags.None, EndPoint);

            if (bytesSent != 70)
            {
                return(false);
            }

            var result = await _discoverySocket.ReceiveFromAsync(
                _discoveryPacketResponse, SocketFlags.None, EndPoint);

            if (result.ReceivedBytes != 70)
            {
                return(false);
            }

            if (!TryGetLocalEndPoint(
                    _discoveryPacketResponse, out var endpoint))
            {
                return(false);
            }

            _logger.LogTrace(
                "Discovery endpoint returned {ClientAddress}", endpoint);

            ClientEndPointUpdated?.Invoke(this, endpoint);
            ClientEndPoint = endpoint;

            return(await SendSelectProtocolAsync(ready, cancellationToken));
        private ValueTask <bool> SendSelectProtocolAsync(
            VoiceGatewayReady ready,
            CancellationToken cancellationToken = default)
        {
            if (!ready.Modes.HasFlag(EncryptionModes.XSalsa20_Poly1305_Lite))
            {
                ThrowInvalidOperationException(
                    "xsalsa20_poly1305_lite not supported");
            }

            // ClientEndPoint should be definitely assigned by this point due
            // to discovery or from being passed in as a ctor param
            Debug.Assert(ClientEndPoint != null);

            bool lockTaken = false;

            _logger.LogTrace("Queueing SelectProtocol");

            try
            {
                _writerSpinLock.Enter(ref lockTaken);

                var buffer = new ArrayBufferWriter <byte>(DefaultBufferSize);
                _writer.Reset(buffer);

                Payload.WriteSelectProtocol(_writer, ClientEndPoint,
                                            EncryptionModes.XSalsa20_Poly1305_Lite);
                _writer.Flush();

                return(QueuePayloadAsync(buffer, cancellationToken));
            }
            finally
            {
                if (lockTaken)
                {
                    _writerSpinLock.Exit();
                }
            }
        }
Ejemplo n.º 3
0
        public static bool TryReadReady(ref Utf8JsonReader reader,
                                        out VoiceGatewayReady ready)
        {
            ready = default;

            if (!reader.TryReadToken(JsonTokenType.StartObject))
            {
                return(false);
            }

            int read = 0;

            while (reader.TryReadToken(JsonTokenType.PropertyName))
            {
                if (reader.ValueTextEquals(SsrcPropertyName))
                {
                    if (!reader.TryReadToken(JsonTokenType.Number) ||
                        !reader.TryGetUInt32(out var ssrc))
                    {
                        return(false);
                    }

                    ready.Ssrc = ssrc;
                    read++;
                }
                else if (reader.ValueTextEquals(IpPropertyName))
                {
                    if (!reader.TryReadToken(JsonTokenType.String))
                    {
                        return(false);
                    }

                    if (reader.HasValueSequence)
                    {
                        reader.ValueSequence.CopyTo(ready.RawIp);
                    }
                    else
                    {
                        reader.ValueSpan.CopyTo(ready.RawIp);
                    }

                    read++;
                }
                else if (reader.ValueTextEquals(PortPropertyName))
                {
                    if (!reader.TryReadToken(JsonTokenType.Number) ||
                        !reader.TryGetInt32(out var port))
                    {
                        return(false);
                    }

                    ready.Port = port;
                    read++;
                }
                else if (reader.ValueTextEquals(ModesPropertyName))
                {
                    if (!reader.TryReadToken(JsonTokenType.StartArray))
                    {
                        return(false);
                    }

                    while (TryReadEncryptionMode(ref reader, out var mode))
                    {
                        ready.Modes |= mode;
                    }

                    if (!reader.TryReadToken(JsonTokenType.EndArray))
                    {
                        return(false);
                    }

                    read++;
                }
                else
                {
                    if (!reader.TrySkip())
                    {
                        return(false);
                    }
                }
            }

            return(reader.TryReadToken(JsonTokenType.EndObject) &&
                   read == 4);