blob: f8fb24e0575a0e317a642c3fd5257fa494fc62f3 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "auth.hpp"
#include "callback.hpp"
#include "connection.hpp"
#include "socket_connector.hpp"
#ifndef DATASTAX_INTERNAL_CONNECTION_CONNECTOR_HPP
#define DATASTAX_INTERNAL_CONNECTION_CONNECTOR_HPP
namespace datastax { namespace internal { namespace core {
class AuthResponseRequest;
class Config;
class ResponseMessage;
class RequestCallback;
/**
* Connection settings.
*/
struct ConnectionSettings {
/**
* Constructor. Initialize with default settings.
*/
ConnectionSettings();
/**
* Constructor. Initialize connection settings from a config object.
*
* @param config The config object.
*/
ConnectionSettings(const Config& config);
SocketSettings socket_settings;
uint64_t connect_timeout_ms;
AuthProvider::Ptr auth_provider;
unsigned int idle_timeout_secs;
unsigned int heartbeat_interval_secs;
bool no_compact;
String application_name;
String application_version;
String client_id;
};
/**
* A connector. This contains all the initialization code to connect a
* connection.
*/
class Connector
: public RefCounted<Connector>
, public ConnectionListener {
friend class StartupCallback;
public:
typedef SharedRefPtr<Connector> Ptr;
typedef Vector<Ptr> Vec;
typedef internal::Callback<void, Connector*> Callback;
enum ConnectionError {
CONNECTION_OK,
CONNECTION_CANCELED,
CONNECTION_ERROR_AUTH,
CONNECTION_ERROR_CONNECT,
CONNECTION_ERROR_CLOSE,
CONNECTION_ERROR_INTERNAL,
CONNECTION_ERROR_INVALID_OPCODE,
CONNECTION_ERROR_INVALID_PROTOCOL,
CONNECTION_ERROR_KEYSPACE,
CONNECTION_ERROR_RESPONSE,
CONNECTION_ERROR_SSL_HANDSHAKE,
CONNECTION_ERROR_SSL_VERIFY,
CONNECTION_ERROR_SOCKET,
CONNECTION_ERROR_TIMEOUT
};
public:
/**
* Constructor
*
* @param host The host to connect to.
* @param protocol_version The protocol version to use for the connection.
* @param callback A callback that is called when the connection is connected or
* if an error occurred.
*/
Connector(const Host::Ptr& host, ProtocolVersion protocol_version, const Callback& callback);
/**
* Set the keyspace to connect with. Calls "USE <keyspace>" after
* the connection is connected and protocol handshake is completed.
*
* @param keyspace A keyspace to register after connection.
* @return The connector to chain calls.
*/
Connector* with_keyspace(const String& keyspace);
/**
* Set the event types to register for during the protocol handshake.
*
* @param event_types A bit set of event types to register.
* @return The connector to chain calls.
*/
Connector* with_event_types(int event_types);
/**
* Set the connection listener to use after the connection is connected.
*
* @param listener A listener that handles connection events.
* @return The connector to chain calls.
*/
Connector* with_listener(ConnectionListener* listener);
/**
* Set the metrics object to use to record metrics.
*
* @param metrics A metrics object.
* @return The connector to chain calls.
*/
Connector* with_metrics(Metrics* metrics);
/**
* Set the connection and socket settings.
*
* @param The settings to use for connecting the connection.
* @return The connector to chain calls.
*/
Connector* with_settings(const ConnectionSettings& settings);
/**
* Connect the connection.
*
* @param loop An event loop to use for connecting the connection.
*/
void connect(uv_loop_t* loop);
/**
* Cancel the connection process.
*/
void cancel();
/**
* Release the connection from the connector. If not released in the callback
* the connection automatically be closed.
*
* @return The connection object for this connector. This returns a null object
* if the connection is not connected or an error occurred.
*/
Connection::Ptr release_connection();
public:
uv_loop_t* loop() { return loop_; }
const Address& address() const { return host_->address(); }
const ProtocolVersion protocol_version() const { return protocol_version_; }
bool is_ok() const { return error_code_ == CONNECTION_OK; }
bool is_canceled() const { return error_code_ == CONNECTION_CANCELED; }
bool is_invalid_protocol() const { return error_code_ == CONNECTION_ERROR_INVALID_PROTOCOL; }
bool is_auth_error() const { return error_code_ == CONNECTION_ERROR_AUTH; }
bool is_ssl_error() const {
return error_code_ == CONNECTION_ERROR_SSL_HANDSHAKE ||
error_code_ == CONNECTION_ERROR_SSL_VERIFY;
}
bool is_timeout_error() const { return error_code_ == CONNECTION_ERROR_TIMEOUT; }
bool is_keyspace_error() const { return error_code_ == CONNECTION_ERROR_KEYSPACE; }
bool is_critical_error() const {
return is_auth_error() || is_ssl_error() || is_invalid_protocol() || is_keyspace_error();
}
const StringMultimap& supported_options() const { return supported_options_; }
ConnectionError error_code() { return error_code_; }
const String& error_message() { return error_message_; }
SocketConnector::SocketError socket_error_code() { return socket_connector_->error_code(); }
const String& socket_error_message() { return socket_connector_->error_message(); }
CassError ssl_error_code() { return socket_connector_->ssl_error_code(); }
private:
void finish();
void on_error(ConnectionError code, const String& message);
void on_ready_or_set_keyspace();
void on_ready_or_register_for_events();
void on_supported(ResponseMessage* response);
void on_authenticate(const String& class_name);
void on_auth_challenge(const AuthResponseRequest* request, const String& token);
void on_auth_success(const AuthResponseRequest* request, const String& token);
virtual void on_close(Connection* connection);
void on_connect(SocketConnector* socket_connector);
void on_timeout(Timer* timer);
private:
Callback callback_;
uv_loop_t* loop_;
Host::Ptr host_;
Connection::Ptr connection_;
SocketConnector::Ptr socket_connector_;
Timer timer_;
ConnectionError error_code_;
String error_message_;
StringMultimap supported_options_;
ProtocolVersion protocol_version_;
String keyspace_;
int event_types_;
ConnectionListener* listener_;
Metrics* metrics_;
ConnectionSettings settings_;
};
}}} // namespace datastax::internal::core
#endif