SessionFactory.cpp
Go to the documentation of this file.
1/****************************************************************************
2** Copyright (c) 2001-2014
3**
4** This file is part of the QuickFIX FIX Engine
5**
6** This file may be distributed under the terms of the quickfixengine.org
7** license as defined by quickfixengine.org and appearing in the file
8** LICENSE included in the packaging of this file.
9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12**
13** See http://www.quickfixengine.org/LICENSE for licensing information.
14**
15** Contact ask@quickfixengine.org if any conditions of this licensing are
16** not clear to you.
17**
18****************************************************************************/
19
20#ifdef _MSC_VER
21#include "stdafx.h"
22#else
23#include "config.h"
24#endif
25
26#include "Utility.h"
27#include "Values.h"
29#include "SessionFactory.h"
30#include "SessionSettings.h"
31#include "Session.h"
32
33#include <memory>
34
35namespace FIX
36{
40
42 const Dictionary& settings ) throw( ConfigError )
43{
44 std::string connectionType = settings.getString( CONNECTION_TYPE );
45 if ( connectionType != "acceptor" && connectionType != "initiator" )
46 throw ConfigError( "Invalid ConnectionType" );
47
48 if( connectionType == "acceptor" && settings.has(SESSION_QUALIFIER) )
49 throw ConfigError( "SessionQualifier cannot be used with acceptor." );
50
51 bool useDataDictionary = true;
52 if ( settings.has( USE_DATA_DICTIONARY ) )
53 useDataDictionary = settings.getBool( USE_DATA_DICTIONARY );
54
55 std::string defaultApplVerID;
56 if( sessionID.isFIXT() )
57 {
58 if( !settings.has(DEFAULT_APPLVERID) )
59 {
60 throw ConfigError("ApplVerID is required for FIXT transport");
61 }
62 defaultApplVerID = Message::toApplVerID( settings.getString(DEFAULT_APPLVERID) );
63 }
64
65 DataDictionaryProvider dataDictionaryProvider;
66 if( useDataDictionary )
67 {
68 if( sessionID.isFIXT() )
69 {
70 processFixtDataDictionaries(sessionID, settings, dataDictionaryProvider);
71 }
72 else
73 {
74 processFixDataDictionary(sessionID, settings, dataDictionaryProvider);
75 }
76 }
77
78 bool useLocalTime = false;
79 if( settings.has(USE_LOCAL_TIME) )
80 useLocalTime = settings.getBool( USE_LOCAL_TIME );
81
82 int startDay = -1;
83 int endDay = -1;
84 try
85 {
86 startDay = settings.getDay( START_DAY );
87 endDay = settings.getDay( END_DAY );
88 }
89 catch( ConfigError & ) {}
90 catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
91
92 UtcTimeOnly startTime;
93 UtcTimeOnly endTime;
94 try
95 {
97 ( settings.getString( START_TIME ) );
99 ( settings.getString( END_TIME ) );
100 }
101 catch ( FieldConvertError & e ) { throw ConfigError( e.what() ); }
102
103 TimeRange utcSessionTime
104 ( startTime, endTime, startDay, endDay );
105 TimeRange localSessionTime
106 ( LocalTimeOnly(startTime.getHour(), startTime.getMinute(), startTime.getSecond()),
107 LocalTimeOnly(endTime.getHour(), endTime.getMinute(), endTime.getSecond()),
108 startDay, endDay );
109 TimeRange sessionTimeRange = useLocalTime ? localSessionTime : utcSessionTime;
110
111 if( startDay >= 0 && endDay < 0 )
112 throw ConfigError( "StartDay used without EndDay" );
113 if( endDay >= 0 && startDay < 0 )
114 throw ConfigError( "EndDay used without StartDay" );
115
116 HeartBtInt heartBtInt( 0 );
117 if ( connectionType == "initiator" )
118 {
119 heartBtInt = HeartBtInt( settings.getInt( HEARTBTINT ) );
120 if ( heartBtInt <= 0 ) throw ConfigError( "Heartbeat must be greater than zero" );
121 }
122
123 SmartPtr<Session> pSession;
124 pSession.reset( new Session( m_application, m_messageStoreFactory,
125 sessionID, dataDictionaryProvider, sessionTimeRange,
126 heartBtInt, m_pLogFactory ) );
127
128 pSession->setSenderDefaultApplVerID(defaultApplVerID);
129
130 int logonDay = startDay;
131 int logoutDay = endDay;
132 try
133 {
134 logonDay = settings.getDay( LOGON_DAY );
135 logoutDay = settings.getDay( LOGOUT_DAY );
136 }
137 catch( ConfigError & ) {}
138 catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
139
140 UtcTimeOnly logonTime( startTime );
141 UtcTimeOnly logoutTime( endTime );
142 try
143 {
145 ( settings.getString( LOGON_TIME ) );
146 }
147 catch( ConfigError & ) {}
148 catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
149 try
150 {
152 ( settings.getString( LOGOUT_TIME ) );
153 }
154 catch( ConfigError & ) {}
155 catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
156
157 TimeRange utcLogonTime
158 ( logonTime, logoutTime, logonDay, logoutDay );
159 TimeRange localLogonTime
160 ( LocalTimeOnly(logonTime.getHour(), logonTime.getMinute(), logonTime.getSecond()),
161 LocalTimeOnly(logoutTime.getHour(), logoutTime.getMinute(), logoutTime.getSecond()),
162 logonDay, logoutDay );
163 TimeRange logonTimeRange = useLocalTime ? localLogonTime : utcLogonTime;
164
165 if( !sessionTimeRange.isInRange(logonTime, logonDay) )
166 throw ConfigError( "LogonTime must be between StartTime and EndTime" );
167 if( !sessionTimeRange.isInRange(logoutTime, logoutDay) )
168 throw ConfigError( "LogoutTime must be between StartTime and EndTime" );
169 pSession->setLogonTime( logonTimeRange );
170
171 if ( settings.has( SEND_REDUNDANT_RESENDREQUESTS ) )
172 pSession->setSendRedundantResendRequests( settings.getBool( SEND_REDUNDANT_RESENDREQUESTS ) );
173 if ( settings.has( CHECK_COMPID ) )
174 pSession->setCheckCompId( settings.getBool( CHECK_COMPID ) );
175 if ( settings.has( CHECK_LATENCY ) )
176 pSession->setCheckLatency( settings.getBool( CHECK_LATENCY ) );
177 if ( settings.has( MAX_LATENCY ) )
178 pSession->setMaxLatency( settings.getInt( MAX_LATENCY ) );
179 if ( settings.has( LOGON_TIMEOUT ) )
180 pSession->setLogonTimeout( settings.getInt( LOGON_TIMEOUT ) );
181 if ( settings.has( LOGOUT_TIMEOUT ) )
182 pSession->setLogoutTimeout( settings.getInt( LOGOUT_TIMEOUT ) );
183 if ( settings.has( RESET_ON_LOGON ) )
184 pSession->setResetOnLogon( settings.getBool( RESET_ON_LOGON ) );
185 if ( settings.has( RESET_ON_LOGOUT ) )
186 pSession->setResetOnLogout( settings.getBool( RESET_ON_LOGOUT ) );
187 if ( settings.has( RESET_ON_DISCONNECT ) )
188 pSession->setResetOnDisconnect( settings.getBool( RESET_ON_DISCONNECT ) );
189 if ( settings.has( REFRESH_ON_LOGON ) )
190 pSession->setRefreshOnLogon( settings.getBool( REFRESH_ON_LOGON ) );
191 if ( settings.has( MILLISECONDS_IN_TIMESTAMP ) )
192 pSession->setTimestampPrecision(3);
193 if ( settings.has( TIMESTAMP_PRECISION ) )
194 pSession->setTimestampPrecision(settings.getInt( TIMESTAMP_PRECISION ) );
195 if ( settings.has( PERSIST_MESSAGES ) )
196 pSession->setPersistMessages( settings.getBool( PERSIST_MESSAGES ) );
197 if ( settings.has( VALIDATE_LENGTH_AND_CHECKSUM ) )
198 pSession->setValidateLengthAndChecksum( settings.getBool( VALIDATE_LENGTH_AND_CHECKSUM ) );
199
200 return pSession.release();
201}
202
204{
205 delete pSession;
206}
207
208ptr::shared_ptr<DataDictionary> SessionFactory::createDataDictionary(const SessionID& sessionID,
209 const Dictionary& settings,
210 const std::string& settingsKey) throw(ConfigError)
211{
212 ptr::shared_ptr<DataDictionary> pDD;
213 std::string path = settings.getString( settingsKey );
214 Dictionaries::iterator i = m_dictionaries.find( path );
215 if ( i != m_dictionaries.end() )
216 {
217 pDD = i->second;
218 }
219 else
220 {
221 bool preserveMsgFldsOrder = false;
222 if( settings.has( PRESERVE_MESSAGE_FIELDS_ORDER ) )
223 preserveMsgFldsOrder = settings.getBool( PRESERVE_MESSAGE_FIELDS_ORDER );
224 pDD = ptr::shared_ptr<DataDictionary>(new DataDictionary( path, preserveMsgFldsOrder ));
225 m_dictionaries[ path ] = pDD;
226 }
227
228 ptr::shared_ptr<DataDictionary> pCopyOfDD = ptr::shared_ptr<DataDictionary>(new DataDictionary(*pDD));
229
230 if( settings.has( VALIDATE_FIELDS_OUT_OF_ORDER ) )
231 pCopyOfDD->checkFieldsOutOfOrder( settings.getBool( VALIDATE_FIELDS_OUT_OF_ORDER ) );
232 if( settings.has( VALIDATE_FIELDS_HAVE_VALUES ) )
233 pCopyOfDD->checkFieldsHaveValues( settings.getBool( VALIDATE_FIELDS_HAVE_VALUES ) );
234 if( settings.has( VALIDATE_USER_DEFINED_FIELDS ) )
235 pCopyOfDD->checkUserDefinedFields( settings.getBool( VALIDATE_USER_DEFINED_FIELDS ) );
236 if( settings.has( ALLOW_UNKNOWN_MSG_FIELDS ) )
237 pCopyOfDD->allowUnknownMsgFields( settings.getBool( ALLOW_UNKNOWN_MSG_FIELDS ) );
238
239 return pCopyOfDD;
240}
241
243 const Dictionary& settings,
244 DataDictionaryProvider& provider) throw(ConfigError)
245{
246 ptr::shared_ptr<DataDictionary> pDataDictionary = createDataDictionary(sessionID, settings, TRANSPORT_DATA_DICTIONARY);
247 provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
248
249 for(Dictionary::const_iterator data = settings.begin(); data != settings.end(); ++data)
250 {
251 const std::string& key = data->first;
252 const std::string frontKey = key.substr(0, strlen(APP_DATA_DICTIONARY));
253 if( frontKey == string_toUpper(APP_DATA_DICTIONARY) )
254 {
256 {
257 provider.addApplicationDataDictionary(Message::toApplVerID(settings.getString(DEFAULT_APPLVERID)),
258 createDataDictionary(sessionID, settings, APP_DATA_DICTIONARY));
259 }
260 else
261 {
262 std::string::size_type offset = key.find('.');
263 if( offset == std::string::npos )
264 throw ConfigError(std::string("Malformed ") + APP_DATA_DICTIONARY + ": " + key);
265 std::string beginStringQualifier = key.substr(offset+1);
266 provider.addApplicationDataDictionary(Message::toApplVerID(beginStringQualifier),
267 createDataDictionary(sessionID, settings, key));
268 }
269 }
270 }
271}
272
274 const Dictionary& settings,
275 DataDictionaryProvider& provider) throw(ConfigError)
276{
277 ptr::shared_ptr<DataDictionary> pDataDictionary = createDataDictionary(sessionID, settings, DATA_DICTIONARY);
278 provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
279 provider.addApplicationDataDictionary(Message::toApplVerID(sessionID.getBeginString()), pDataDictionary);
280}
281}
Represents a data dictionary for a version of FIX.
Queries for DataDictionary based on appropriate version of FIX.
For storage and retrieval of key/value pairs.
Definition Dictionary.h:37
iterator const_iterator
Definition Dictionary.h:45
Time only represented in local time.
Definition FieldTypes.h:743
static ApplVerID toApplVerID(const BeginString &value)
Definition Message.h:307
void processFixtDataDictionaries(const SessionID &sessionID, const Dictionary &settings, DataDictionaryProvider &provider)
void processFixDataDictionary(const SessionID &sessionID, const Dictionary &settings, DataDictionaryProvider &provider)
ptr::shared_ptr< DataDictionary > createDataDictionary(const SessionID &sessionID, const Dictionary &settings, const std::string &settingsKey)
void destroy(Session *pSession)
Session * create(const SessionID &sessionID, const Dictionary &settings)
Maintains the state and implements the logic of a FIX session.
Definition Session.h:46
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition SessionID.h:31
Keeps track of when session is active.
Definition TimeRange.h:35
static bool isInRange(const UtcTimeOnly &start, const UtcTimeOnly &end, const DateTime &time)
Definition TimeRange.h:43
Time only represented in UTC.
Definition FieldTypes.h:685
const char LOGOUT_TIMEOUT[]
const char USE_LOCAL_TIME[]
const char LOGON_TIMEOUT[]
const char SEND_REDUNDANT_RESENDREQUESTS[]
const char APP_DATA_DICTIONARY[]
const char CHECK_COMPID[]
const char CONNECTION_TYPE[]
const char ALLOW_UNKNOWN_MSG_FIELDS[]
const char SESSION_QUALIFIER[]
const char HEARTBTINT[]
const char PRESERVE_MESSAGE_FIELDS_ORDER[]
const char END_DAY[]
const char REFRESH_ON_LOGON[]
const char DATA_DICTIONARY[]
const char USE_DATA_DICTIONARY[]
const char RESET_ON_LOGOUT[]
const char VALIDATE_USER_DEFINED_FIELDS[]
const char CHECK_LATENCY[]
const char LOGOUT_DAY[]
const char LOGON_DAY[]
const char TRANSPORT_DATA_DICTIONARY[]
std::string string_toUpper(const std::string &value)
Definition Utility.cpp:53
const char VALIDATE_FIELDS_HAVE_VALUES[]
const char VALIDATE_FIELDS_OUT_OF_ORDER[]
const char START_TIME[]
const char LOGOUT_TIME[]
const char LOGON_TIME[]
const char RESET_ON_LOGON[]
const char VALIDATE_LENGTH_AND_CHECKSUM[]
const char DEFAULT_APPLVERID[]
const char END_TIME[]
const char PERSIST_MESSAGES[]
const char RESET_ON_DISCONNECT[]
const char MAX_LATENCY[]
const char START_DAY[]
const char MILLISECONDS_IN_TIMESTAMP[]
const char TIMESTAMP_PRECISION[]
Application is not configured correctly
Definition Exceptions.h:88
int getSecond() const
Return the second portion of the time (0-59)
Definition FieldTypes.h:148
int getMinute() const
Return the minute portion of the time (0-59)
Definition FieldTypes.h:142
int getHour() const
Return the hour portion of the time (0-23)
Definition FieldTypes.h:136
Unable to convert field into its native format.
Definition Exceptions.h:67
static std::string convert(const UtcTimeOnly &value, int precision=0)

Generated on Thu May 22 2025 08:23:50 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001