MySQL Connector/C++ 9.3.0
MySQL connector library for C and C++ applications
All Classes Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
settings.h
1/*
2 * Copyright (c) 2017, 2024, Oracle and/or its affiliates.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0, as
6 * published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms, as
10 * designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have either included with
14 * the program or referenced in the documentation.
15 *
16 * Without limiting anything contained in the foregoing, this file,
17 * which is part of Connector/C++, is also subject to the
18 * Universal FOSS Exception, version 1.0, a copy of which can be found at
19 * https://oss.oracle.com/licenses/universal-foss-exception.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 * See the GNU General Public License, version 2.0, for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31#ifndef MYSQLX_COMMON_SETTINGS_H
32#define MYSQLX_COMMON_SETTINGS_H
33
34/*
35 Classes and code handling session settings. They are used to process session
36 creation options, check their consistency and present the settings in the
37 form expected by CDK.
38
39 Known session options and their values are defined
40 in mysql_common_constants.h header as SESSION_OPTION_LIST() and accompanying
41 macros.
42*/
43
44#include "../common_constants.h"
45#include "value.h"
46
47PUSH_SYS_WARNINGS
48#include <vector>
49#include <map>
50#include <bitset>
51#include <sstream>
52POP_SYS_WARNINGS
53
54
55namespace cdk {
56namespace ds {
57
58class Multi_source;
59struct Attr_processor;
60
61}}
62
63
64namespace mysqlx {
65
66MYSQLX_ABI_BEGIN(2,0)
67
68namespace common {
69
70
71/*
72 Class for storing session configuration settings.
73*/
74
75class PUBLIC_API Settings_impl
76{
77public:
78
79 /*
80 Enumerations with available session options and their values.
81 */
82
83#define SETTINGS_OPT_ENUM_str(X,N) X = N,
84#define SETTINGS_OPT_ENUM_num(X,N) X = N,
85#define SETTINGS_OPT_ENUM_any(X,N) X = N,
86#define SETTINGS_OPT_ENUM_bool(X,N) X = N,
87
88 enum Session_option_impl{
89 SESSION_OPTION_LIST(SETTINGS_OPT_ENUM)
90 LAST
91 };
92
93
94
95 /*
96 Enumerations with available client options and their values.
97 */
98
99#define CLIENT_OPT_IMPL_ENUM_str(X,N) X = -N,
100#define CLIENT_OPT_IMPL_ENUM_bool(X,N) X = -N,
101#define CLIENT_OPT_IMPL_ENUM_num(X,N) X = -N,
102#define CLIENT_OPT_IMPL_ENUM_any(X,N) X = -N,
103
104 enum Client_option_impl {
105 CLIENT_OPTION_LIST(CLIENT_OPT_IMPL_ENUM)
106 };
107
108
109
110 static const char* option_name(int opt);
111
112
113#define SETTINGS_VAL_ENUM(X,N) X = N,
114
115 enum class SSL_mode {
116 SSL_MODE_LIST(SETTINGS_VAL_ENUM)
117 LAST
118 };
119
120 static const char* ssl_mode_name(SSL_mode mode);
121
122
123 enum class Auth_method {
124 AUTH_METHOD_LIST(SETTINGS_VAL_ENUM)
125 LAST
126 };
127
128 static const char* auth_method_name(Auth_method method);
129
130 enum class Compression_mode {
131 COMPRESSION_MODE_LIST(SETTINGS_VAL_ENUM)
132 LAST
133 };
134
135 static const char* compression_mode_name(Compression_mode mode);
136
137protected:
138
139 using Value = common::Value;
140 using opt_val_t = std::pair<int, Value>;
141 // TODO: use multimap instead?
142 using option_list_t = std::vector<opt_val_t>;
143 using connection_attr = std::map<std::string,std::string>;
144 using iterator = option_list_t::const_iterator;
145
146public:
147
148 /*
149 Examine settings stored in this object.
150 */
151
152 bool has_option(int) const;
153 const Value& get(int) const;
154
155
156 // Iterating over options stored in this object.
157
158 iterator begin() const
159 {
160 return m_data.m_options.cbegin();
161 }
162
163 iterator end() const
164 {
165 return m_data.m_options.cend();
166 }
167
168 /*
169 Clear individual or all settings.
170 */
171
172 void clear();
173 void erase(int);
174
175 /*
176 Session options include connection options that specify data source
177 (one or many) for which given session is created. This method initializes
178 CDK Multi_source object to describe the data source(s) based on the
179 connection options.
180 */
181
182 void get_data_source(cdk::ds::Multi_source&);
183
184 void get_attributes(cdk::ds::Attr_processor&);
185
186 // Set options based on URI
187
188 void set_from_uri(const std::string &);
189
190 // Set Client options based on JSON object
191
192 void set_client_opts(const std::string &);
193
194 // Set Client options from othe Settings object
195
196 void set_client_opts(const Settings_impl &);
197
198 /*
199 Public API has no methods to directly set individual options. Instead,
200 to change session settings implementation should create a Setter object
201 and use its methods to do the changes. A Settings_impl::Setter object
202 provides "transactional" semantics for changing session options -- only
203 consistent option changes modify the original Settings_impl object.
204
205 Note: This Setter class is defined in "implementation" header
206 common/settings.h. The public API leaves it undefined.
207 */
208
209 class Setter;
210
211protected:
212
213 struct PUBLIC_API Data
214 {
215 Data()
216 {
217 init_connection_attr();
218 }
219 DLL_WARNINGS_PUSH
220 option_list_t m_options;
221 connection_attr m_connection_attr;
222 DLL_WARNINGS_POP
223 unsigned m_host_cnt = 0;
224 bool m_user_priorities = false;
225 bool m_ssl_ca = false;
226 SSL_mode m_ssl_mode = SSL_mode::LAST;
227 bool m_tcpip = false; // set to true if TCPIP connection was specified
228 bool m_sock = false; // set to true if socket connection was specified
229 bool m_tls_vers = false;
230 bool m_tls_ciphers = false;
231 bool m_compression_algorithms = false;
232
233 void erase(int);
234 void init_connection_attr();
235 void clear_connection_attr();
236
237 };
238
239 Data m_data;
240
241};
242
243
244#define SETTINGS_OPT_NAME_str(X,N) case N: return #X;
245#define SETTINGS_OPT_NAME_bool(X,N) case N: return #X;
246#define SETTINGS_OPT_NAME_num(X,N) case N: return #X;
247#define SETTINGS_OPT_NAME_any(X,N) case N: return #X;
248#define SETTINGS_OPT_NAME_bool(X,N) case N: return #X;
249
250
251#define CLIENT_OPT_NAME_str(X,N) case -N: return #X;
252#define CLIENT_OPT_NAME_bool(X,N) case -N: return #X;
253#define CLIENT_OPT_NAME_num(X,N) case -N: return #X;
254#define CLIENT_OPT_NAME_any(X,N) case -N: return #X;
255
256
257inline
258const char* Settings_impl::option_name(int opt)
259{
260 switch (opt)
261 {
262 SESSION_OPTION_LIST(SETTINGS_OPT_NAME)
263 CLIENT_OPTION_LIST(CLIENT_OPT_NAME)
264 default:
265 return nullptr;
266 }
267}
268
269
270#define SETTINGS_VAL_NAME(X,N) case N: return #X;
271
272inline
273const char* Settings_impl::ssl_mode_name(SSL_mode mode)
274{
275 switch (unsigned(mode))
276 {
277 SSL_MODE_LIST(SETTINGS_VAL_NAME)
278 default:
279 return nullptr;
280 }
281}
282
283inline
284const char* Settings_impl::auth_method_name(Auth_method method)
285{
286 switch (unsigned(method))
287 {
288 AUTH_METHOD_LIST(SETTINGS_VAL_NAME)
289 default:
290 return nullptr;
291 }
292}
293
294inline
295const char* Settings_impl::compression_mode_name(Compression_mode mode)
296{
297 switch (unsigned(mode))
298 {
299 COMPRESSION_MODE_LIST(SETTINGS_VAL_NAME)
300 default:
301 return nullptr;
302 }
303}
304
305/*
306 Note: For options that can repeat, returns the last value.
307*/
308
309inline
310const common::Value& Settings_impl::get(int opt) const
311{
312 using std::find_if;
313
314 auto it = find_if(m_data.m_options.crbegin(), m_data.m_options.crend(),
315 [opt](opt_val_t el) -> bool { return el.first == opt; }
316 );
317
318 static Value null_value;
319
320 if (it == m_data.m_options.crend())
321 return null_value;
322
323 return it->second;
324}
325
326
327inline
328bool Settings_impl::has_option(int opt) const
329{
330 // For options whose value is a list, we return true if we know the option
331 // was set even if no actual values are stored in m_options, which is the
332 // case when option value is an empty list.
333
334 switch (opt)
335 {
336 case Session_option_impl::TLS_VERSIONS:
337 if (m_data.m_tls_vers)
338 return true;
339 break;
340
341 case Session_option_impl::TLS_CIPHERSUITES:
342 if (m_data.m_tls_ciphers)
343 return true;
344 break;
345
346 case Session_option_impl::COMPRESSION_ALGORITHMS:
347 if (m_data.m_compression_algorithms)
348 return true;
349 break;
350
351 default:
352 break;
353 }
354
355 return m_data.m_options.cend() !=
356 find_if(m_data.m_options.cbegin(), m_data.m_options.cend(),
357 [opt](opt_val_t el) -> bool { return el.first == opt; }
358 );
359
360}
361
362
363inline
364void Settings_impl::erase(int opt)
365{
366 m_data.erase(opt);
367}
368
369
370/*
371 Note: Removes all occurrences of the given option. Also updates the context
372 used for checking option consistency.
373*/
374
375inline
376void Settings_impl::Data::erase(int opt)
377{
378 remove_from(m_options,
379 [opt](opt_val_t el) -> bool
380 {
381 return el.first == opt;
382 }
383 );
384
385 /*
386 TODO: removing HOST from multi-host settings can leave "orphaned"
387 PORT/PRIORITY settings. Do we correctly detect that?
388 */
389
390 switch (opt)
391 {
392 case Session_option_impl::HOST:
393 m_host_cnt = 0;
394 FALLTHROUGH;
395 case Session_option_impl::PORT:
396 if (0 == m_host_cnt)
397 m_tcpip = false;
398 break;
399 case Session_option_impl::SOCKET:
400 m_sock = false;
401 break;
402 case Session_option_impl::PRIORITY:
403 m_user_priorities = false;
404 break;
405 case Session_option_impl::SSL_CA:
406 m_ssl_ca = false;
407 break;
408 case Session_option_impl::SSL_MODE:
409 m_ssl_mode = SSL_mode::LAST;
410 break;
411 case Session_option_impl::CONNECTION_ATTRIBUTES:
412 clear_connection_attr();
413 break;
414 default:
415 break;
416 }
417}
418
419
420} // common namespace
421
422MYSQLX_ABI_END(2,0)
423
424} // mysqlx namespace
425
426#endif
427