Exemple #1
0
        private static int AuthCallback(ref ConnectCredential[] creds, IntPtr cbdata)
        {
            AuthData authData = (AuthData)Marshal.PtrToStructure(cbdata, typeof(AuthData));

            for (int i = 0; i < creds.Length; i++)
            {
                ConnectCredential cred = creds[i];
                switch (cred.type)
                {
                case ConnectCredentialType.VIR_CRED_AUTHNAME:
                    // Fill the user name
                    cred.Result = authData.user_name;
                    break;

                case ConnectCredentialType.VIR_CRED_PASSPHRASE:
                    // Fill the password
                    cred.Result = authData.password;
                    break;

                default:
                    return(-1);
                }
            }
            return(0);
        }
        private async Task Reconnect(ConnectCredential reconnectCredential)
        {
            if (_isReconnecting)
            {
                return;
            }

            _isReconnecting = true;

            int tryNumber = 0;

            while (true)
            {
                try
                {
                    _logger.LogInformation("Performing reconnect");

                    await Task.Delay(_reconnectDelay);

                    await Disconnect();

                    if (reconnectCredential != null)
                    {
                        var subs = _subscriptions.Values.ToArray();
                        foreach (var sub in subs)
                        {
                            await Remove(sub);

                            sub.RenewId();
                            await Add(sub);
                        }

                        await Connect(reconnectCredential);
                    }

                    _logger.LogInformation("Reconnected");
                    break;
                }
                catch (Exception ex)
                {
                    _logger.LogException(ex);

                    if (tryNumber++ >= _maxReconnectsInRow)
                    {
                        _logger.LogInformation("Reconnect stopped");
                        break;
                    }
                }
            }

            _isReconnecting = false;
        }
        public async Task Connect(ConnectCredential connectCredential)
        {
            if (Connected)
            {
                _logger.LogWarning("Client already connected");
                return;
            }

            DisposeClient();
            _client = new ClientWebSocket();

            var connectTryNumber = 0;

            while (true)
            {
                try
                {
                    connectTryNumber++;
                    await _client.ConnectAsync(new Uri(connectCredential.Host), CancellationToken.None);

                    break;
                }
                catch (Exception ex)
                {
                    _logger.LogException(ex);
                    if (connectTryNumber > 3)
                    {
                        throw;
                    }
                }
            }
            _logger.LogInformation("Connection established");

            var resp = (await Receive()).First().String;

            _sessionId = GetSession(resp);
            _logger.LogInformation($"Session established: {_sessionId}");

            var connectMessage = new StompMessage(StompMessageCommand.CONNECT, new Headers
            {
                ["login"]    = connectCredential.Login,
                ["passcode"] = connectCredential.Passcode,
                ["domain"]   = connectCredential.Domain,
                ["language"] = "ru",
            });

            await SendMessage(connectMessage);

            foreach (var message in await ReceiveMessages())
            {
                _logger.LogMessage(message);
                ThrowOnErrorStompMessage(message);
            }

            Connected = true;

            foreach (var sub in _subscriptions.Values)
            {
                await Subscribe(sub);
            }

            _receiveLoop = Task.Run(async() =>
            {
                while (Connected)
                {
                    if (_client.State == WebSocketState.Open)
                    {
                        try
                        {
                            foreach (var m in await ReceiveMessages())
                            {
                                _logger.LogMessage(m);
                                ThrowOnErrorStompMessage(m);
                                foreach (var sub in _subscriptions.Values)
                                {
                                    await sub.ProcessMessage(m);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            var standardClosing = ex is IssPlusWebSocketClientReceiveException && ex.Message == "Tunnel closed";
                            if (!standardClosing)
                            {
                                _logger.LogException(ex);
                                var _ = Reconnect(connectCredential);
                                return;
                            }
                        }
                    }
                    else
                    {
                        await Task.Delay(1000);
                    }
                }
            });
        }