/// <summary> /// Opens the connection /// </summary> private async Task OpenAsyncInternal(Logger logger) { //switch state to connecting if not done so int state = Interlocked.CompareExchange(ref _connectionState, 1, 0); if (state == 1) return; if (state == 2) throw new ObjectDisposedException("Connection disposed before opening!"); try { //create TCP connection _client = new TcpClient(); await _client.ConnectAsync(_address, _cluster.Config.Port).ConfigureAwait(false); _writeStream = _client.GetStream(); _readStream = _client.GetStream(); logger.LogVerbose("TCP connection to {0} is opened", Address); //start readloop StartReadingAsync(); //get compression option _allowCompression = false; //assume false unless if (_cluster.Config.AllowCompression) { //check wether compression is supported by getting compression options from server var options = new OptionsFrame(); var supported = await SendRequestAsync(options, logger, 1, true).ConfigureAwait(false) as SupportedFrame; if (supported == null) throw new ProtocolException(0, "Expected Supported frame not received"); IList<string> compressionOptions; //check if options contain compression if (supported.SupportedOptions.TryGetValue("COMPRESSION", out compressionOptions)) { //check wether snappy is supported _allowCompression = compressionOptions.Contains("snappy"); } //dispose supported frame supported.Dispose(); } //submit startup frame var startup = new StartupFrame(_cluster.Config.CqlVersion); if (_allowCompression) { logger.LogVerbose("Enabling Snappy Compression."); startup.Options["COMPRESSION"] = "snappy"; } Frame response = await SendRequestAsync(startup, logger, 1, true).ConfigureAwait(false); //authenticate if required var auth = response as AuthenticateFrame; if (auth != null) { logger.LogVerbose("Authentication requested, attempting to provide credentials", Address); //check if _username is actually set if (_cluster.Config.Username == null || _cluster.Config.Password == null) throw new UnauthorizedException("No credentials provided"); //dispose AuthenticateFrame response.Dispose(); var cred = new CredentialsFrame(_cluster.Config.Username, _cluster.Config.Password); response = await SendRequestAsync(cred, logger, 1, true).ConfigureAwait(false); } //check if ready if (!(response is ReadyFrame)) throw new ProtocolException(0, "Expected Ready frame not received"); //dispose ready frame response.Dispose(); using (logger.ThreadBinding()) { if (OnConnectionChange != null) OnConnectionChange(this, new ConnectionChangeEvent { Connected = true }); } logger.LogInfo("{0} is opened and ready for use", this); } catch (Exception ex) { using (logger.ThreadBinding()) { Dispose(true, ex); throw; } } }
/// <summary> /// Startups the connection using the required message exchange /// </summary> /// <param name="logger">The logger.</param> /// <returns></returns> /// <exception cref="ProtocolException">0;Expected Ready frame not received</exception> private async Task StartupAsync(Logger logger) { //submit startup frame var startup = new StartupFrame(_config.CqlVersion); if (_allowCompression) { logger.LogVerbose("Enabling Snappy Compression."); startup.Options["COMPRESSION"] = "snappy"; } Frame response = await SendRequestAsyncInternal(startup, logger, 1, CancellationToken.None).AutoConfigureAwait(); //authenticate if required var auth = response as AuthenticateFrame; if (auth != null) await AuthenticateAsync(auth, logger).AutoConfigureAwait(); //no authenticate frame, so ready frame must be received else if (!(response is ReadyFrame)) throw new ProtocolException(response.ProtocolVersion, 0, "Expected Ready frame not received", response.TracingId); //dispose ready frame response.Dispose(); }