428 lines
9.4 KiB
C++
428 lines
9.4 KiB
C++
/*
|
|
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, version 2.0, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is also distributed with certain software (including
|
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
|
* as designated in a particular file or component or in included license
|
|
* documentation. The authors of MySQL hereby grant you an
|
|
* additional permission to link the program and your derivative works
|
|
* with the separately licensed software that they have included with
|
|
* MySQL.
|
|
*
|
|
* Without limiting anything contained in the foregoing, this file,
|
|
* which is part of MySQL Connector/C++, is also subject to the
|
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License, version 2.0, for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef MYSQLX_COMMON_SETTINGS_H
|
|
#define MYSQLX_COMMON_SETTINGS_H
|
|
|
|
/*
|
|
Classes and code handling session settings. They are used to process session
|
|
creation options, check their consistency and present the settings in the
|
|
form expected by CDK.
|
|
|
|
Known session options and their values are defined
|
|
in mysql_common_constants.h header as SESSION_OPTION_LIST() and accompanying
|
|
macros.
|
|
*/
|
|
|
|
#include "../common_constants.h"
|
|
#include "value.h"
|
|
|
|
PUSH_SYS_WARNINGS
|
|
#include <vector>
|
|
#include <map>
|
|
#include <bitset>
|
|
#include <sstream>
|
|
POP_SYS_WARNINGS
|
|
|
|
|
|
namespace cdk {
|
|
namespace ds {
|
|
|
|
class Multi_source;
|
|
struct Attr_processor;
|
|
|
|
}}
|
|
|
|
|
|
namespace mysqlx {
|
|
|
|
MYSQLX_ABI_BEGIN(2,0)
|
|
|
|
namespace common {
|
|
|
|
|
|
/*
|
|
Class for storing session configuration settings.
|
|
*/
|
|
|
|
class PUBLIC_API Settings_impl
|
|
{
|
|
public:
|
|
|
|
/*
|
|
Enumerations with available session options and their values.
|
|
*/
|
|
|
|
#define SETTINGS_OPT_ENUM_str(X,N) X = N,
|
|
#define SETTINGS_OPT_ENUM_num(X,N) X = N,
|
|
#define SETTINGS_OPT_ENUM_any(X,N) X = N,
|
|
#define SETTINGS_OPT_ENUM_bool(X,N) X = N,
|
|
|
|
enum Session_option_impl{
|
|
SESSION_OPTION_LIST(SETTINGS_OPT_ENUM)
|
|
LAST
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
Enumerations with available client options and their values.
|
|
*/
|
|
|
|
#define CLIENT_OPT_IMPL_ENUM_str(X,N) X = -N,
|
|
#define CLIENT_OPT_IMPL_ENUM_bool(X,N) X = -N,
|
|
#define CLIENT_OPT_IMPL_ENUM_num(X,N) X = -N,
|
|
#define CLIENT_OPT_IMPL_ENUM_any(X,N) X = -N,
|
|
|
|
enum Client_option_impl {
|
|
CLIENT_OPTION_LIST(CLIENT_OPT_IMPL_ENUM)
|
|
};
|
|
|
|
|
|
|
|
static const char* option_name(int opt);
|
|
|
|
|
|
#define SETTINGS_VAL_ENUM(X,N) X = N,
|
|
|
|
enum class SSL_mode {
|
|
SSL_MODE_LIST(SETTINGS_VAL_ENUM)
|
|
LAST
|
|
};
|
|
|
|
static const char* ssl_mode_name(SSL_mode mode);
|
|
|
|
|
|
enum class Auth_method {
|
|
AUTH_METHOD_LIST(SETTINGS_VAL_ENUM)
|
|
LAST
|
|
};
|
|
|
|
static const char* auth_method_name(Auth_method method);
|
|
|
|
enum class Compression_mode {
|
|
COMPRESSION_MODE_LIST(SETTINGS_VAL_ENUM)
|
|
LAST
|
|
};
|
|
|
|
static const char* compression_mode_name(Compression_mode mode);
|
|
|
|
protected:
|
|
|
|
using Value = common::Value;
|
|
using opt_val_t = std::pair<int, Value>;
|
|
// TODO: use multimap instead?
|
|
using option_list_t = std::vector<opt_val_t>;
|
|
using connection_attr = std::map<std::string,std::string>;
|
|
using iterator = option_list_t::const_iterator;
|
|
|
|
public:
|
|
|
|
/*
|
|
Examine settings stored in this object.
|
|
*/
|
|
|
|
bool has_option(int) const;
|
|
const Value& get(int) const;
|
|
|
|
|
|
// Iterating over options stored in this object.
|
|
|
|
iterator begin() const
|
|
{
|
|
return m_data.m_options.cbegin();
|
|
}
|
|
|
|
iterator end() const
|
|
{
|
|
return m_data.m_options.cend();
|
|
}
|
|
|
|
/*
|
|
Clear individual or all settings.
|
|
*/
|
|
|
|
void clear();
|
|
void erase(int);
|
|
|
|
/*
|
|
Session options include connection options that specify data source
|
|
(one or many) for which given session is created. This method initializes
|
|
CDK Multi_source object to describe the data source(s) based on the
|
|
connection options.
|
|
*/
|
|
|
|
void get_data_source(cdk::ds::Multi_source&);
|
|
|
|
void get_attributes(cdk::ds::Attr_processor&);
|
|
|
|
// Set options based on URI
|
|
|
|
void set_from_uri(const std::string &);
|
|
|
|
// Set Client options based on JSON object
|
|
|
|
void set_client_opts(const std::string &);
|
|
|
|
// Set Client options from othe Settings object
|
|
|
|
void set_client_opts(const Settings_impl &);
|
|
|
|
/*
|
|
Public API has no methods to directly set individual options. Instead,
|
|
to change session settings implementation should create a Setter object
|
|
and use its methods to do the changes. A Settings_impl::Setter object
|
|
provides "transactional" semantics for changing session options -- only
|
|
consistent option changes modify the original Settings_impl object.
|
|
|
|
Note: This Setter class is defined in "implementation" header
|
|
common/settings.h. The public API leaves it undefined.
|
|
*/
|
|
|
|
class Setter;
|
|
|
|
protected:
|
|
|
|
struct PUBLIC_API Data
|
|
{
|
|
Data()
|
|
{
|
|
init_connection_attr();
|
|
}
|
|
DLL_WARNINGS_PUSH
|
|
option_list_t m_options;
|
|
connection_attr m_connection_attr;
|
|
DLL_WARNINGS_POP
|
|
unsigned m_host_cnt = 0;
|
|
bool m_user_priorities = false;
|
|
bool m_ssl_ca = false;
|
|
SSL_mode m_ssl_mode = SSL_mode::LAST;
|
|
bool m_tcpip = false; // set to true if TCPIP connection was specified
|
|
bool m_sock = false; // set to true if socket connection was specified
|
|
bool m_tls_vers = false;
|
|
bool m_tls_ciphers = false;
|
|
bool m_compression_algorithms = false;
|
|
|
|
void erase(int);
|
|
void init_connection_attr();
|
|
void clear_connection_attr();
|
|
|
|
};
|
|
|
|
Data m_data;
|
|
|
|
};
|
|
|
|
|
|
#define SETTINGS_OPT_NAME_str(X,N) case N: return #X;
|
|
#define SETTINGS_OPT_NAME_bool(X,N) case N: return #X;
|
|
#define SETTINGS_OPT_NAME_num(X,N) case N: return #X;
|
|
#define SETTINGS_OPT_NAME_any(X,N) case N: return #X;
|
|
#define SETTINGS_OPT_NAME_bool(X,N) case N: return #X;
|
|
|
|
|
|
#define CLIENT_OPT_NAME_str(X,N) case -N: return #X;
|
|
#define CLIENT_OPT_NAME_bool(X,N) case -N: return #X;
|
|
#define CLIENT_OPT_NAME_num(X,N) case -N: return #X;
|
|
#define CLIENT_OPT_NAME_any(X,N) case -N: return #X;
|
|
|
|
|
|
inline
|
|
const char* Settings_impl::option_name(int opt)
|
|
{
|
|
switch (opt)
|
|
{
|
|
SESSION_OPTION_LIST(SETTINGS_OPT_NAME)
|
|
CLIENT_OPTION_LIST(CLIENT_OPT_NAME)
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
#define SETTINGS_VAL_NAME(X,N) case N: return #X;
|
|
|
|
inline
|
|
const char* Settings_impl::ssl_mode_name(SSL_mode mode)
|
|
{
|
|
switch (unsigned(mode))
|
|
{
|
|
SSL_MODE_LIST(SETTINGS_VAL_NAME)
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
inline
|
|
const char* Settings_impl::auth_method_name(Auth_method method)
|
|
{
|
|
switch (unsigned(method))
|
|
{
|
|
AUTH_METHOD_LIST(SETTINGS_VAL_NAME)
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
inline
|
|
const char* Settings_impl::compression_mode_name(Compression_mode mode)
|
|
{
|
|
switch (unsigned(mode))
|
|
{
|
|
COMPRESSION_MODE_LIST(SETTINGS_VAL_NAME)
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Note: For options that can repeat, returns the last value.
|
|
*/
|
|
|
|
inline
|
|
const common::Value& Settings_impl::get(int opt) const
|
|
{
|
|
using std::find_if;
|
|
|
|
auto it = find_if(m_data.m_options.crbegin(), m_data.m_options.crend(),
|
|
[opt](opt_val_t el) -> bool { return el.first == opt; }
|
|
);
|
|
|
|
static Value null_value;
|
|
|
|
if (it == m_data.m_options.crend())
|
|
return null_value;
|
|
|
|
return it->second;
|
|
}
|
|
|
|
|
|
inline
|
|
bool Settings_impl::has_option(int opt) const
|
|
{
|
|
// For options whose value is a list, we return true if we know the option
|
|
// was set even if no actual values are stored in m_options, which is the
|
|
// case when option value is an empty list.
|
|
|
|
switch (opt)
|
|
{
|
|
case Session_option_impl::TLS_VERSIONS:
|
|
if (m_data.m_tls_vers)
|
|
return true;
|
|
break;
|
|
|
|
case Session_option_impl::TLS_CIPHERSUITES:
|
|
if (m_data.m_tls_ciphers)
|
|
return true;
|
|
break;
|
|
|
|
case Session_option_impl::COMPRESSION_ALGORITHMS:
|
|
if (m_data.m_compression_algorithms)
|
|
return true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return m_data.m_options.cend() !=
|
|
find_if(m_data.m_options.cbegin(), m_data.m_options.cend(),
|
|
[opt](opt_val_t el) -> bool { return el.first == opt; }
|
|
);
|
|
|
|
}
|
|
|
|
|
|
inline
|
|
void Settings_impl::erase(int opt)
|
|
{
|
|
m_data.erase(opt);
|
|
}
|
|
|
|
|
|
/*
|
|
Note: Removes all occurrences of the given option. Also updates the context
|
|
used for checking option consistency.
|
|
*/
|
|
|
|
inline
|
|
void Settings_impl::Data::erase(int opt)
|
|
{
|
|
remove_from(m_options,
|
|
[opt](opt_val_t el) -> bool
|
|
{
|
|
return el.first == opt;
|
|
}
|
|
);
|
|
|
|
/*
|
|
TODO: removing HOST from multi-host settings can leave "orphaned"
|
|
PORT/PRIORITY settings. Do we correctly detect that?
|
|
*/
|
|
|
|
switch (opt)
|
|
{
|
|
case Session_option_impl::HOST:
|
|
m_host_cnt = 0;
|
|
FALLTHROUGH;
|
|
case Session_option_impl::PORT:
|
|
if (0 == m_host_cnt)
|
|
m_tcpip = false;
|
|
break;
|
|
case Session_option_impl::SOCKET:
|
|
m_sock = false;
|
|
break;
|
|
case Session_option_impl::PRIORITY:
|
|
m_user_priorities = false;
|
|
break;
|
|
case Session_option_impl::SSL_CA:
|
|
m_ssl_ca = false;
|
|
break;
|
|
case Session_option_impl::SSL_MODE:
|
|
m_ssl_mode = SSL_mode::LAST;
|
|
break;
|
|
case Session_option_impl::CONNECTION_ATTRIBUTES:
|
|
clear_connection_attr();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
} // common namespace
|
|
|
|
MYSQLX_ABI_END(2,0)
|
|
|
|
} // mysqlx namespace
|
|
|
|
#endif
|
|
|