fix8  version 1.4.0
Open Source C++ FIX Framework
configuration.hpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------------------------------
2 /*
3 
4 Fix8 is released under the GNU LESSER GENERAL PUBLIC LICENSE Version 3.
5 
6 Fix8 Open Source FIX Engine.
7 Copyright (C) 2010-16 David L. Dight <fix@fix8.org>
8 
9 Fix8 is free software: you can redistribute it and / or modify it under the terms of the
10 GNU Lesser General Public License as published by the Free Software Foundation, either
11 version 3 of the License, or (at your option) any later version.
12 
13 Fix8 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
14 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 You should have received a copy of the GNU Lesser General Public License along with Fix8.
17 If not, see <http://www.gnu.org/licenses/>.
18 
19 BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO
20 THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
21 COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
22 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
24 THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
25 YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
26 
27 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
28 HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
29 ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
30 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
31 NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
32 THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
33 HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 
35 */
36 //-------------------------------------------------------------------------------------------------
37 #ifndef FIX8_CONFIGURATION_HPP_
38 #define FIX8_CONFIGURATION_HPP_
39 
40 #ifdef FIX8_HAVE_OPENSSL
41 #include <openssl/ssl.h>
42 #else
43 #define SSL_VERIFY_PEER 0
44 #endif
45 
46 //-------------------------------------------------------------------------------------------------
47 namespace FIX8 {
48 
49 //-------------------------------------------------------------------------------------------------
51 struct Server
52 {
53  std::string _hostname;
55  Poco::Net::SocketAddress _addr;
57 
58  Server(const std::string& hostname, unsigned max_retries, const Poco::Net::SocketAddress& addr, bool reset_sequence_numbers)
59  : _hostname(hostname), _max_retries(max_retries), _retries(), _addr(addr), _reset_sequence_numbers(reset_sequence_numbers) {}
60 };
61 
62 //-------------------------------------------------------------------------------------------------
64 struct SslContext
65 {
66  std::string _private_key_file;
67  std::string _certificate_file;
69  std::string _ca_location;
72  int _verification_mode;
77  std::string _cipher_list;
78  bool _valid;
79 
80  SslContext(const std::string& private_key_file="", const std::string& certificate_file="", const std::string& ca_location="",
81  int verification_mode=SSL_VERIFY_PEER, int verification_depth=9, bool load_default_cas=false,
82  const std::string& cipher_list="ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")
83  : _private_key_file(private_key_file), _certificate_file(certificate_file), _ca_location(ca_location),
84  _verification_mode(verification_mode), _verification_depth(verification_depth), _load_default_cas(load_default_cas),
85  _cipher_list(cipher_list), _valid()
86  {
87  }
88 };
89 
90 //-------------------------------------------------------------------------------------------------
93 {
94  static RegExp _ipexp;
95 
97  using ConfigMap = std::map<const std::string, const XmlElement *>;
98  std::vector<ConfigMap> _groups;
99  std::vector<const XmlElement *> _allsessions;
100 
105  const XmlElement *find_element(const std::string& tag, const ConfigMap& from) const
106  { ConfigMap::const_iterator itr(from.find(tag)); return itr != from.end() ? itr->second : nullptr; }
107 
108 public:
110  {
114  };
115 
120  const XmlElement *find_group(group_types type, const std::string& tag) const
121  { return find_element(tag, _groups[type]); }
122 
123 protected:
129  bool from_or_default(const XmlElement *from, const f8String& tag, f8String& target) const
130  { return (from && from->GetAttr(tag, target)) || (_default && _default->GetAttr(tag, target)); }
131 
138  template<typename T>
139  T& get_string_field(const XmlElement *from, const std::string& tag, T& to) const
140  {
141  std::string val;
142  if (from_or_default(from, tag, val))
143  to.set(val);
144  return to;
145  }
146 
152  Tickval::ticks get_time_field(const XmlElement *from, const std::string& tag, bool timeonly=false) const
153  {
154  std::string time_str;
155  return from && from->GetAttr(tag, time_str) && time_str.size() == 8
156  ? time_parse(time_str.c_str(), 8, timeonly) : Tickval::errorticks();
157  }
158 
165  template<typename T>
166  T find_or_default(const XmlElement *from, const std::string& tag, const T def) const
167  {
168  if (from)
169  {
170  if (from->HasAttr(tag))
171  return from->FindAttr(tag, def);
172  if (_default)
173  return _default->FindAttr(tag, def);
174  }
175  return def;
176  }
177 
178 private:
184  unsigned load_map(const std::string& tag, ConfigMap& map_name, const bool is_session=false)
185  {
186  XmlElement::XmlSet slist;
187  if (_root->find(tag, slist))
188  {
189  for(const auto *pp : slist)
190  {
191  std::string name;
192  if (pp->GetAttr("name", name) && is_session ? pp->FindAttr("active", false) : true)
193  {
194  map_name.insert({name, pp});
195  if (is_session)
196  _allsessions.push_back(pp);
197  }
198  }
199  }
200 
201  return static_cast<unsigned>(map_name.size());
202  }
203 
204 public:
206 
210  Configuration(const std::string& xmlfile, bool do_process=false)
211  : _root(XmlElement::Factory(xmlfile)),
212  _default(_root ? _root->find("fix8/default") : nullptr),
213  _groups(g_count)
214  {
215  if (!exist(xmlfile))
216  throw ConfigurationError("config file not found", xmlfile);
217  if (do_process)
218  process();
219  }
220 
224  Configuration(std::istream& istr, bool do_process=false)
225  : _root(XmlElement::Factory(istr, "stream")),
226  _default(_root ? _root->find("fix8/default") : nullptr),
227  _groups(g_count)
228  {
229  if (do_process)
230  process();
231  }
232 
234  virtual ~Configuration() {}
235 
238  F8API int process();
239 
243  const XmlElement *get_session(const unsigned num) const
244  { return num < _allsessions.size() ? _allsessions[num] : nullptr; }
245 
249  F8API Connection::Role get_role(const XmlElement *from) const;
250 
255  F8API size_t get_addresses(const XmlElement *from, std::vector<Server>& target) const;
256 
260  F8API Poco::Net::SocketAddress get_address(const XmlElement *from) const;
261 
265  F8API Poco::Net::IPAddress get_ip(const XmlElement *from) const;
266 
274  template<typename T>
275  T get_logflags(const std::string& tag, const std::vector<std::string>& names,
276  const XmlElement *from, Logger::LogPositions *positions=nullptr) const;
277 
283  F8API std::string& get_logname(const XmlElement *from, std::string& to, const SessionID *sid=nullptr) const;
284 
289  unsigned get_connect_timeout(const XmlElement *from, const unsigned def=defaults::connect_timeout) const
290  { return find_or_default(from, "connect_timeout", def); }
291 
296  unsigned get_retry_interval(const XmlElement *from, const unsigned def=defaults::retry_interval) const
297  { return find_or_default(from, "login_retry_interval", def); }
298 
303  unsigned get_retry_count(const XmlElement *from, const int def=defaults::login_retries) const
304  {
305  const int rc(find_or_default(from, "login_retries", def));
306  if (rc < 0)
307  throw ConfigurationError("retry count must be >= 0");
308  return rc;
309  }
310 
315  unsigned get_tcp_recvbuf_sz(const XmlElement *from, const unsigned def=0) const
316  { return find_or_default(from, "tcp_recv_buffer", def); }
317 
322  unsigned get_tcp_sendbuf_sz(const XmlElement *from, const unsigned def=0) const
323  { return find_or_default(from, "tcp_send_buffer", def); }
324 
329  unsigned get_version(const XmlElement *from, const unsigned def=0) const
330  { return find_or_default(from, "fix_version", def); }
331 
336  unsigned get_tabsize(const XmlElement *from, const unsigned def=defaults::tabsize) const
337  { return find_or_default(from, "tabsize", def); }
338 
343  unsigned get_logfile_rotation(const XmlElement *from, const unsigned def=defaults::log_rotation) const
344  { return find_or_default(from, "rotation", def); }
345 
350  unsigned get_heartbeat_interval(const XmlElement *from, const unsigned def=defaults::hb_interval) const
351  { return find_or_default(from, "heartbeat_interval", def); }
352 
357  bool get_tcp_nodelay(const XmlElement *from, const bool def=true) const
358  { return find_or_default(from, "tcp_nodelay", def); }
359 
364  bool get_tcp_keepalive(const XmlElement *from, const bool def=false) const
365  { return find_or_default(from, "tcp_keepalive", def); }
366 
371  bool get_tcp_reuseaddr(const XmlElement *from, const bool def=false) const
372  { return find_or_default(from, "tcp_reuseaddr", def); }
373 
378  int get_tcp_linger(const XmlElement *from, const int def=-1) const
379  { return find_or_default(from, "tcp_linger", def); }
380 
385  bool get_silent_disconnect(const XmlElement *from, const bool def=false) const
386  { return find_or_default(from, "silent_disconnect", def); }
387 
392  bool get_enforce_compids_flag(const XmlElement *from, const bool def=true) const
393  { return find_or_default(from, "enforce_compids", def); }
394 
399  bool get_ignore_logon_sequence_check_flag(const XmlElement *from, const bool def=false) const
400  { return find_or_default(from, "ignore_logon_sequence_check", def); }
401 
406  bool get_no_chksum_flag(const XmlElement *from, const bool def=false) const
407  { return find_or_default(from, "no_chksum", def); }
408 
413  bool get_permissive_mode_flag(const XmlElement *from, const bool def=false) const
414  { return find_or_default(from, "permissive_mode", def); }
415 
420  bool get_reset_sequence_number_flag(const XmlElement *from, const bool def=false) const
421  { return find_or_default(from, "reset_sequence_numbers", def); }
422 
427  bool get_always_seqnum_assign(const XmlElement *from, const bool def=false) const
428  { return find_or_default(from, "always_seqnum_assign", def); }
429 
433  F8API ProcessModel get_process_model(const XmlElement *from) const;
434 
439  { default_appl_ver_id to; return get_string_field(from, "default_appl_ver_id", to); }
440 
445  { sender_comp_id to; return get_string_field(from, "sender_comp_id", to); }
446 
451  { target_comp_id to; return get_string_field(from, "target_comp_id", to); }
452 
453 #ifdef FIX8_HAVE_OPENSSL
454 
457  F8API SslContext get_ssl_context(const XmlElement *from) const;
458 #endif
459 
465  F8API Persister *create_persister(const XmlElement *from, const SessionID *sid=nullptr, bool flag=false) const;
466 
472  F8API Logger *create_logger(const XmlElement *from, const Logtype ltype, const SessionID *sid=nullptr) const;
473 
477  F8API Schedule create_schedule(const XmlElement *from) const;
478 
482  F8API Clients create_clients(const XmlElement *from) const;
483 
487  F8API Schedule create_login_schedule(const XmlElement *from) const;
488 
493 
498  F8API unsigned get_all_sessions(std::vector<const XmlElement *>& target, const Connection::Role role=Connection::cn_unknown) const;
499 
502  const XmlElement *get_root() const { return _root; }
503 };
504 
505 //-------------------------------------------------------------------------------------------------
506 
507 } // FIX8
508 
509 #endif // FIX8_CONFIGURATION_HPP_
const XmlElement * _default
bool _reset_sequence_numbers
bool get_permissive_mode_flag(const XmlElement *from, const bool def=false) const
unsigned _max_retries
unsigned _retries
T FindAttr(const std::string &what, const T defValue) const
Definition: xml.hpp:209
f8_thread delegated async logging class
Definition: logger.hpp:153
std::string _certificate_file
bool get_reset_sequence_number_flag(const XmlElement *from, const bool def=false) const
unsigned get_tcp_sendbuf_sz(const XmlElement *from, const unsigned def=0) const
F8API std::string & get_logname(const XmlElement *from, std::string &to, const SessionID *sid=nullptr) const
POSIX regex wrapper class.
Definition: f8utils.hpp:370
int _verification_mode
are used (see loadDefaultCAs).
Configuration(std::istream &istr, bool do_process=false)
bool get_silent_disconnect(const XmlElement *from, const bool def=false) const
T & get_string_field(const XmlElement *from, const std::string &tag, T &to) const
std::string _cipher_list
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
static const ticks & errorticks()
Definition: tickval.hpp:69
Base (ABC) Persister class.
Definition: persist.hpp:55
Class to hold server settings for failoverable sessions.
bool _load_default_cas
false
bool get_tcp_nodelay(const XmlElement *from, const bool def=true) const
F8API Schedule create_schedule(const XmlElement *from) const
bool get_tcp_keepalive(const XmlElement *from, const bool def=false) const
F8API Poco::Net::SocketAddress get_address(const XmlElement *from) const
unsigned get_tcp_recvbuf_sz(const XmlElement *from, const unsigned def=0) const
unsigned get_retry_interval(const XmlElement *from, const unsigned def=defaults::retry_interval) const
Role
Roles: acceptor, initiator or unknown.
Definition: connection.hpp:512
Quickfix style sessionid.
Definition: session.hpp:46
T find_or_default(const XmlElement *from, const std::string &tag, const T def) const
std::unordered_map< f8String, Client > Clients
Definition: session.hpp:182
ProcessModel
Supported session process models.
Definition: f8types.hpp:56
F8API Persister * create_persister(const XmlElement *from, const SessionID *sid=nullptr, bool flag=false) const
F8API size_t get_addresses(const XmlElement *from, std::vector< Server > &target) const
bool get_tcp_reuseaddr(const XmlElement *from, const bool def=false) const
int get_tcp_linger(const XmlElement *from, const int def=-1) const
std::vector< int > LogPositions
Definition: logger.hpp:176
A simple xml parser with Xpath style lookup.
Definition: xml.hpp:48
An bad or missing configuration parameter.
default_appl_ver_id get_default_appl_ver_id(const XmlElement *from) const
Tickval::ticks time_parse(const char *ptr, size_t len, bool timeonly=false)
Definition: field.hpp:978
F8API unsigned get_all_sessions(std::vector< const XmlElement * > &target, const Connection::Role role=Connection::cn_unknown) const
#define F8API
Definition: f8dll.h:60
unsigned get_heartbeat_interval(const XmlElement *from, const unsigned def=defaults::hb_interval) const
F8API Connection::Role get_role(const XmlElement *from) const
unsigned get_connect_timeout(const XmlElement *from, const unsigned def=defaults::connect_timeout) const
unsigned get_tabsize(const XmlElement *from, const unsigned def=defaults::tabsize) const
Tickval::ticks get_time_field(const XmlElement *from, const std::string &tag, bool timeonly=false) const
Server(const std::string &hostname, unsigned max_retries, const Poco::Net::SocketAddress &addr, bool reset_sequence_numbers)
std::set< const XmlElement *, EntityOrderComp > XmlSet
Definition: xml.hpp:74
const XmlElement * _root
std::string _private_key_file
decltype(f8_time_point::min().time_since_epoch().count()) ticks
Definition: tickval.hpp:66
Class to encapsulate a Fix8 configuration.
const XmlElement * get_root() const
F8API bool GetAttr(const std::string &what, std::string &target) const
Definition: xml.cpp:748
Poco::Net::SocketAddress _addr
unsigned load_map(const std::string &tag, ConfigMap &map_name, const bool is_session=false)
#define SSL_VERIFY_PEER
F8API Session_Schedule * create_session_schedule(const XmlElement *from) const
unsigned get_version(const XmlElement *from, const unsigned def=0) const
F8API Poco::Net::IPAddress get_ip(const XmlElement *from) const
virtual ~Configuration()
Dtor.
T get_logflags(const std::string &tag, const std::vector< std::string > &names, const XmlElement *from, Logger::LogPositions *positions=nullptr) const
unsigned get_logfile_rotation(const XmlElement *from, const unsigned def=defaults::log_rotation) const
unsigned get_retry_count(const XmlElement *from, const int def=defaults::login_retries) const
std::vector< const XmlElement * > _allsessions
const XmlElement * find_element(const std::string &tag, const ConfigMap &from) const
sender_comp_id get_sender_comp_id(const XmlElement *from) const
bool get_ignore_logon_sequence_check_flag(const XmlElement *from, const bool def=false) const
std::map< const std::string, const XmlElement * > ConfigMap
std::string _hostname
F8API Schedule create_login_schedule(const XmlElement *from) const
bool get_enforce_compids_flag(const XmlElement *from, const bool def=true) const
F8API Clients create_clients(const XmlElement *from) const
const XmlElement * get_session(const unsigned num) const
Configuration(const std::string &xmlfile, bool do_process=false)
std::string _ca_location
bool HasAttr(const std::string &what) const
Definition: xml.hpp:184
Class to hold SSL context for failoverable sessions.
std::vector< ConfigMap > _groups
F8API Logger * create_logger(const XmlElement *from, const Logtype ltype, const SessionID *sid=nullptr) const
SslContext(const std::string &private_key_file="", const std::string &certificate_file="", const std::string &ca_location="", int verification_mode=SSL_VERIFY_PEER, int verification_depth=9, bool load_default_cas=false, const std::string &cipher_list="ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")
static RegExp _ipexp
target_comp_id get_target_comp_id(const XmlElement *from) const
F8API ProcessModel get_process_model(const XmlElement *from) const
bool get_always_seqnum_assign(const XmlElement *from, const bool def=false) const
bool exist(const std::string &fname)
Definition: f8utils.hpp:1068
F8API const XmlElement * find(const std::string &what, const std::string *atag=nullptr, const std::string *aval=nullptr, const char delim='/') const
std::string f8String
Definition: f8types.hpp:47
bool get_no_chksum_flag(const XmlElement *from, const bool def=false) const
const XmlElement * find_group(group_types type, const std::string &tag) const
bool from_or_default(const XmlElement *from, const f8String &tag, f8String &target) const
XmlSet::const_iterator end() const
Definition: xml.hpp:336