/// <summary>
        /// Отправляет специфический запрос содержащий токен авторизации. Ожидает ответ.
        /// </summary>
        private async Task <bool> AuthorizeAsync(SocketQueue socketQueue, byte[] bearerToken)
        {
            // Запрос на авторизацию по токену.
            var requestToSend = Message.CreateRequest("Auth/AuthorizeToken", new Arg[] { new Arg("token", bearerToken) });

            // Отправить запрос и получить ответ.
            object result = await ExecuteRequestAsync(requestToSend, returnType : typeof(bool), socketQueue).ConfigureAwait(false);

            return((bool)result);
        }
 /// <summary>
 /// Событие — обрыв сокета.
 /// </summary>
 private protected override void OnAtomicDisconnect(SocketQueue socketQueue)
 {
     // Установить Socket = null если в ссылке хранится экземпляр соединения в котором произошел обрыв.
     Interlocked.CompareExchange(ref _socket, null, socketQueue);
 }
        /// <summary>
        /// Выполнить подключение сокета если еще не подключен.
        /// </summary>
        private async Task <SocketQueue> ConnectIfNeededAsync()
        {
            // Копия volatile ссылки.
            SocketQueue socketQueue = Socket;

            // Fast-path.
            if (socketQueue != null)
            {
                return(socketQueue);
            }

            using (await _asyncLock.LockAsync().ConfigureAwait(false))
            {
                // Копия volatile ссылки.
                socketQueue = _socket;

                // Необходима повторная проверка.
                if (socketQueue == null)
                {
                    if (ServiceProvider == null)
                    {
                        var ioc = new ServiceCollection();
                        _iocConfigure?.Invoke(ioc);
                        ConfigureIoC(ioc);
                    }

                    // Новый сокет.
                    var ws = new MyClientWebSocket();

                    try
                    {
                        // Простое подключение веб-сокета.
                        await ws.ConnectAsync(_uri).ConfigureAwait(false);
                    }
                    catch
                    // Не удалось подключиться (сервер не запущен?).
                    {
                        ws.Dispose();
                        throw;
                    }

                    // Управляемая обвертка для сокета.
                    socketQueue = new SocketQueue(ws);

                    // Начать бесконечное чтение из сокета.
                    StartReceivingLoop(socketQueue);

                    // Копируем ссылку на публичный токен.
                    byte[] bearerTokenCopy = BearerToken;

                    // Если токен установлен то отправить его на сервер что-бы авторизовать текущее подключение.
                    if (bearerTokenCopy != null)
                    {
                        try
                        {
                            IsAuthorized = await AuthorizeAsync(socketQueue, bearerTokenCopy).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        // Обрыв соединения.
                        {
                            // Оповестить об обрыве.
                            AtomicDisconnect(socketQueue, ex);
                            throw;
                        }
                    }

                    Debug.WriteIf(IsAuthorized, "Соединение успешно авторизовано");

                    // Открыть публичный доступ к этому сокету.
                    // Установка этого свойства должно быть самым последним действием.
                    Interlocked.CompareExchange(ref _socket, socketQueue, null); // Записать только если в ссылке Null.
                }
                return(socketQueue);
            }
        }
 public SendJob(SocketQueue socketQueue, MemoryPoolStream memoryPoolStream)
 {
     SocketQueue      = socketQueue;
     MemoryPoolStream = memoryPoolStream;
 }