B2BITS FIX Antenna C++ 2.32.0
Loading...
Searching...
No Matches
FIX Session

For basic information about FIX Session refer to the Session description section.

Session identifier

In earlier versions of FIX Antenna (2.10.14 and earlier) any session object could be uniquely identified by SenderCompId/TargetCompId pair. There were number of methods in external interface of FIX Antenna like Engine::createSession which took SenderCompId and TargetCompId parameters to identify session.

Starting from version 2.10.15.5 extra string identifier - SessionQualifier has been introduced in addition to SenderCompId/TargetCompId pair. The idea is to give user ability to create several sessions with the same SenderCompId and TargetCompId and to give ability to address these sessions by unique ID. To achieve this goal, Engine::SessionId structure was introduced. The structure consists of three string properties - sender_, target_ and qualifier_. Many of external methods still can be called with only SenderCompId and TargetCompId parameters. However, if user needs to create several sessions with the same SenderCompId/TargetCompId pair they first need to create Engine::SessionId structure by passing SenderCompId, TargetCompId and unique SessionQualifier to its constructor, and then call overloaded method, which takes Engine::SessionId structure as one of arguments, e.g.

Appl appl; // See "Application description" section
Engine::SessionId sid("Sender", "Target", "q1");
// create a session
Session * createSession(Application *pApp, const std::string &senderCompID, const std::string &targetCompID, FIXVersion appVer=NA, const SessionExtraParameters *pParam=NULL, const MessageStorageType storageType=default_storageType, UnderlyingProtocol underlyingProtocolType=FIX_TCP)
Creates a new FIX Session.
static FixEngine * singleton()
Returns an instance of this class.
FIX Session.
Definition B2BITS_Session.h:171
@ FIX42
FIX 4.2.
Definition B2BITS_PubEngineDefines.h:81
Session Identificator structure.
Definition B2BITS_SessionId.h:68

See section Sample for more details about using Session Qualifier and Engine::SessionId structure.

To establish several sessions with the same SenderCompId and TargetCompId, both Initiator and Acceptor should create several session objects, which differ from each other by SessionQualifier property. SessionQualifier property on Initiator side must be the same as SessionQualifier property of the corresponding session on acceptor side. When Initiator connects to Acceptor, it sends SessionQualifier along with SenderCompId and TargetCompId in logon message. The SessionQualifier tag in logon message is optional and can be configured in engine.properties file. You can find more details on how to configure the library in chapter Configuration. When Acceptor receives logon message with the SessionQualifier it searches for registered session with SessionId corresponding to received TargetCompId, SenderCompId and SessionQualifier. If the session is found it is associated with the incoming connection, otherwise connection is rejected.

If user creates session by passing only SenderCompId and TargetCompId parameters (without SessionQualifier), the Engine::SessionId structure is created and stored internally with empty qualifier_ property. If Acceptor registers a session without session qualifier it won't accept any incoming connection with session qualifier defined in logon message. And vice versa, if Acceptor has registered a session or several sessions with qualifiers, it won't accept connections from Initiators without SessionQualifier.

The FIX engine will automatically insert SessionQualifier tag into logon message if user creates session with qualifier on initiator side and SessionQualifier tag is appropriately configured in engine.properties. To configure SessionQualifier tag user needs to add the lines like below to config file (see chapter Configuration for more details)

Session.Default.LogonMessageSessionQualifierTag = 9012

User can also overload LogonMessageSessionQualifierTag property for any particular session like below

Session.Sender1/Target1.LogonMessageSessionQualifierTag = 9015

If user wish to define or overload some other properties for any session with session qualifier they can add a configuration line like in example below (see also Session configuration).

Session.Sender1/Target1/Q1.StorageType=null

Wherever possible, if SessionQualifier is defined for a session, the string representation of the session's identifier will consist of Sender, Target and SessionQualifier (separated by a delimiter). If SessionQualifier is not defined, it will be omitted in any output related to session identifier. This is done for backward compatibility. The possible affected places are log files (names and content), admin protocol messages, keys of message storage and so on.

External acceptor applications

If Acceptor application doesn't use FIX Antenna library it may define its own rules on how to determine correspondence between sessions on initiator and acceptor side. For example, it may distinguish sessions based on TCP port, which they are connected to. In this case, passing Session Qualifier in Logon message is not necessary and may even lead to rejection by acceptor side.

To disable passing Session Qualifier in Logon Message, it's enough just do not add the LogonMessageSessionQualifierTag parameter to configuration file. If user wants to disable passing Session Qualifier in Logon Message only for some particular session, they may add lines like below to configuration file. See chapter Configuration for more details on configuration parameters.

Session.Default.LogonMessageSessionQualifierTag = 9012
Session.Sender1/Target1.LogonMessageSessionQualifierTag = 0

In this example, all sessions except "Sender1/Target1" will pass Session Qualifier as tag 9012 in Logon message.

Sample

The SessionQualifier sample application can be found in FA C++ package under "Samples/SessionQualifier" directory.

The sample application registers two sessions with ids Acceptor1@Initiator@1 and Acceptor1@Initiator@2 on acceptor side. Then two Initiator sessions with ids Initiator@Acceptor1@1 and Initiator@Acceptor1@2 establish simultaneous connections to corresponding acceptor sessions and send order messages and receive responses.

At the next step, initiator creates two sessions with ids Initiator@Acceptor2@1 and Initiator@Acceptor2@2 and connects to acceptor. Acceptor creates and registers corresponding sessions in onUnregisteredAcceptor handler. After having connections established, the initiator sessions send order messages and receive responses.

At the end, all sessions are closed.

The information about received logon and logout messages as well as content of orders and execution reports messages can be seen in console. Logs are collected in directory "bin/logs".

To run sample just enter "sample/SessionQualifier/bin" directory and start run_*.bat on Windows or run.sh on Linux. To run debug version use corresponding command files with letter 'D' at the end. Note, the debug binaries are not included in the package, user needs to build them before running.

Open issues

Routing messages to a session with SessionQualifier is not supported.

Session configuration

Session configuration is one of the most important part of the FIX Antenna. Configuration allows to enable or disable functionality. Configuration influences on performance (see Performance tuning). Please pay attention on how your session is configured.

There are two approaches to configure Session:

  1. Using engine.properties file (see Configuration)
  2. FIX Antenna API

Approaches can be combined. E.g. part of settings can be configured in engine.properties file, other settings can be configured using FIX Antenna API.

Session settings are being applied in the following order:

  1. Hardcoded defaults. Each parameter has hardcoded default value. See parameter description for details.
  2. Settings defined in the engine.properties file in the section "Session.Default".
    #
    # Settings for all sessions
    #
    Session.Default.StorageType = transient
    Session.Default.ConnectAddress = 10.0.0.1
    
  3. Settings defined in the engine.properties file in the section "Session.<Sender/Target>".
    #
    # Settings for sessions which have SenderCompID = Sender1 and TargetCompID = Target1
    #
    Session.Sender1/Target1.StorageType = transient
    Session.Sender1/Target1.ConnectAddress = 10.0.0.1
    
  4. Settings defined in the engine.properties file in the section Session.<Sender/Target/SessionQualifier> if session has been created with SessionQualifier.
    #
    # Settings for sessions which have SenderCompID = Sender1, TargetCompID = Target1 and 
    # SessionQualifier = Q1.
    #
    Session.Sender1/Target1/Q1.StorageType = transient
    Session.Sender1/Target1/Q1.ConnectAddress = 10.0.0.1
    
  5. FIX Antenna API.
    params.validation_.isEnabled_ = true;
    Engine::Session* session = Engine::FixEngine::singleton()->createSession( &app, "Sender1", "Target1", Engine::FIX44, &params );
    @ FIX44
    FIX 4.4.
    Definition B2BITS_PubEngineDefines.h:84
    TriBool isEnabled_
    Option to enable message validation.
    Definition B2BITS_SessionParameters.h:85
    TriBool checkRequiredGroupFields_
    This parameter controls the validation of required fields in repeating group.
    Definition B2BITS_SessionParameters.h:130
    Session's extra parameters.
    Definition B2BITS_SessionParameters.h:77
    ValidationParameters validation_
    Validation parameters.
    Definition B2BITS_SessionParameters.h:550

FIX Antenna API has highest priority. Settings set by C/C++/NET code cannot be changed by engine.properties file.

Note
Defining session settings in the engine.properties file does not create session itself. Settings in the engine.properties file are applied upon Engine::FixEngine::createSession method call.

Example

If engine.properties file contains following settings:

# 
# Settings for all sessions
#
Session.Default.StorageType = transient

#
# Settings for all sessions Sender1@Target1
#
Session.Sender1/Target1.StorageType = persistent
Session.Sender1/Target1.ConnectAddress = 10.0.0.1

#
# Settings for session Sender1@Target1@Q1
#
Session.Sender1/Target1/Q1.Validation.LogIncomingMessages = false

... and code looks like this:

params.validation_.isEnabled_ = true;
Engine::Session* session1 = engine->createSession( &app, Engine::SessionId( "Sender2", "Target2" ), Engine::FIX44 );
Engine::Session* session2 = engine->createSession( &app, Engine::SessionId( "Sender1", "Target1", "Q2" ), Engine::FIX44 );
Engine::Session* session3 = engine->createSession( &app, Engine::SessionId( "Sender1", "Target1", "Q1" ), Engine::FIX44 );
Engine::Session* session4 = engine->createSession( &app, Engine::SessionId( "Sender1", "Target1", "Q3" ), Engine::FIX44, &params );
FIX Engine interface.
Definition B2BITS_FixEngine.h:202

... then sessions will be configured in the following way:

SessionStorageTypeConnectAddressMessage validationLogIncomingMessages
session1 (Sender2@Target2)transient0.0.0.0 (NIC will be chosen by OS)disabledtrue
session2 (Sender1@Target1@Q2)persistent10.0.0.1disabledtrue
session3 (Sender1@Target1@Q1)persistent10.0.0.1disabledfalse
session4 (Sender1@Target1@Q3)persistent10.0.0.1enabledtrue

List of the session setting names for engine.properties files can be found in the B2BITS_FAProperties.h file namespace Engine::SessionParameters.

Persistent session

Persistent session is a session with persistent storage. According to the FIX protocol session is responsible for outgoing message flow. This means that any time counterparty may request retransmission of the previously sent messages. In the result session must store all sent messages to some storage. In case of persistent session messages are stored to the file. This guarantees that session can recover its state (sent messages and latest sequence numbers) after failure (e.g. after crash) by the cost of performance. To guarantee consistency the store and forward approach is used (refer to the Store-and-forward section for more details). Use instruction below to create persistent session.

// For session works over FIXT11
@ FIXT11_TCP
simple TCP socket with FIXT.1.1 session protocol
Definition B2BITS_PubEngineDefines.h:517
@ FIX50
FIX 5.0.
Definition B2BITS_PubEngineDefines.h:85
const MessageStorageType persistent_storageType
File storage - slow and safe.
Definition B2BITS_PubEngineDefines.h:435

Session state is stored on a disk and can be restored after failure. The following information is stored for a session:

  • Session parameters (SenderCompID, TargetCompID, FIX version, etc.)
  • Session incoming and outgoing sequence numbers
  • Incoming messages (optional)
  • Outgoing messages

Transient session

Transient session is a session with transient storage i.e. in contrast to persistent session (refer to the Persistent session section) messages are stored in memory. This type of session is faster however all information about session will be lost in case of failure. Use instruction below to create transient session.

// For session works over FIXT11
const MessageStorageType transient_storageType
Memory storage - fast but dangerous.
Definition B2BITS_PubEngineDefines.h:441

This session type is recommended when recovery after failure is not required i.e. when every time session is connected from scratch. This applicable for market data sessions, when client has to subscribe and request snapshot on every logon and hence recovery is not required. Another example is when persistent already exists in application so having yet another storage of recovery information is redundant. In the latter case application is responsible to restore session state after creation and before connect (refer to the Session::setInSeqNum and Session::setOutSeqNum methods).

Session state

Session state is a set of parameters that defines session behavior. The most important session state’s parameter is session status. Session changes its state based on the event, which can be originated from the FIX messages flow, timer or user actions. The session state can be obtained using the Engine::Session::getState() method, which returns Session::State.

Below is the list of session statuses with explanations.

  • INITIAL - The session has been created, but has not been connected yet
  • WAIT_FOR_CONNECT - The session is initialized TCP connection process and waits for completion.
  • WAIT_FOR_FIRST_LOGON - The session has been connected as an Acceptor and is waiting for the first Logon message
  • WAIT_FOR_CONFIRM_LOGON - The session has been connected as an Initiator, the first Logon message has been sent and it is waiting for the confirming Logon message
  • SWITCH_CONNECTION - The session is in process of changing connection from primary to backup (or back)
  • ESTABLISHED - The session is established
  • WAIT_FOR_CONFIRM_LOGOUT - The Session is terminating and waiting for Logout confirmation.
  • RECONNECT - The session-initiator has detected the telecommunication link error and is trying to re-establish the link
  • CORRECTLY_TERMINATED - The session has been correctly terminated
  • NON_GRACEFULLY_TERMINATED - The session has been non-gracefully terminated

Below is the basic static finite state machine for Session.

dot_inline_dotgraph_2.png

To convert the Engine::Session::State enum value to a string value, use the Engine::Session::state2string() method.

Sequence number handling

The session is always assigned with two separated sequence numbers:

  • Incoming sequence number is a counter for incoming message
  • Outgoing sequence number is a counter for outgoing message

Incoming and outgoing sequence numbers start from 1 when the session is created from scratch. After the correct session termination sequence numbers are reset to 1. If connection is terminated non-gracefully sequence numbers will continue after it is restored.

Both sides must maintain these two values and ensure that they are in sync.

There are two types of sequence numbers desync:

Resetting sequence number

To reset message sequence numbers on each Logon following approach should be used:

std::string const SENDER = "l_sender";
std::string const TARGET = "l_target";
//
// Start of the day
//
params.useAsyncConnect_ = true;
MySessionListener listener;
Engine::Session* session = Engine::FixEngine::singleton()->createSession( &listener, SENDER, TARGET, Engine::FIX44, &params );
session->connect( 30, "localhost", 9900 );
//
// ... receive and process market data
//
//
// End of day
//
session->disconnect();
session->waitForTerminated();
session->release();
@ FSNR_ALWAYS
Reset sequence number at every Logon.
Definition B2BITS_PubEngineDefines.h:124
ForceSeqNumResetMode forceSeqNumReset_
Force SeqNum reset mode.
Definition B2BITS_SessionParameters.h:355

FIX Antenna also supports resetting message sequence numbers once per 24 hour of continuous work. This feature can be enabled using ResetSeqNumAfter24hours configuration option.

Late delivery vs rejecting

When session connection is lost, the initiator tries to reconnect, which may take some time (or even infinity), and the acceptor waits for reconnect. For both sides message delivery is impossible. FIX Antenna provides two different approaches to message handling in this case:

  • Late delivery (default mode) means that all outgoing messages are stored in outgoing queue and sent once connection is reestablished (utilizing resend request logic).
  • Message rejecting means that after some reasonable period of time messages are rejected i.e. they are removed from outgoing queue and reject message is sent to the message originator.

The Engine::SessionExtraParameters::enableMessageRejecting_ parameter controls if message rejecting is enabled or not (by default it is disabled). The MessageTimeToLive property specifies how long the session waits for connection restore (i.e. before rejecting the message). If the connection is not restored during the MessageTimeToLive interval - the session starts rejecting messages by calling Engine::Application::onMsgRejectEvent() for each rejected message.

Events

Derive an object from the EventListener class and register it using the Engine::FixEngine::registerEventListener method to monitor engine events (see the Engine::Event class).

It is vital to call the Engine::FixEngine::unregisterEventListener method before calling the Engine::FixEngine::destroy method.

Use C++ RTTI or the Event::getType method to detect the exact type of the received event.

For example:

class Listener : public Engine::EventListener {
public:
virtual void onNotification (const Engine::Notification &aNotification){
clog << "Notification: " << *aNotification.what() << endl << endl;
}
virtual void onWarning (const Engine::Warning &aWarning){
clog << "Warning: " << *aWarning.what() << endl << endl;
}
virtual void onError (const Engine::Error &aError){
clog << "Error: " << *aError.what() << endl << endl;
}
};
Listener listener;
// ... - business logic
// must be done before FixEngine::destroy()
Represents error event.
Definition B2BITS_Event.h:182
virtual const std::string * what() const
Describes the event.
Basic Event Listener.
Definition B2BITS_Event.h:236
virtual void onWarning(const Engine::Warning &warning)=0
This method is called when the FixEngine generates a warning.
virtual void onError(const Engine::Error &error)=0
This method is called when the FixEngine reports an error.
virtual void onNotification(const Engine::Notification &notification)=0
This method is called when the FixEngine generates a notification.
bool unregisterEventListener(Engine::EventListener *apListener)
Unregisters the given EventListener.
static void destroy()
Destroys the instance of this class.
void registerEventListener(Engine::EventListener *apListener)
Registers the given EventListener with FixEngine.
Represents notification event.
Definition B2BITS_Event.h:122
virtual const std::string * what() const
Describes the event.
Represents warning event.
Definition B2BITS_Event.h:152
virtual const std::string * what() const
Describes the event.

Message validation

Engine::Session supports automatic incoming/outgoing message validation. Validation can be switched on/off. If validation is on, all incoming messages will be validated and reject message will be sent on invalid incoming message. On invalid outgoing message Utils::Exception exception will be raised by Engine::Session::put. Following are available validation options:

  • Empty field values validation. If enabled, engine rejects messages with empty field values. Empty means field value is defined but it equals to empty string.
  • Field value format validation. If enabled, engine validates field value according to field type and list of possible values.
  • Check for unknown fields. If enabled, engine rejects messages with undefined fields inside.
  • Check for repeating group leading tag value. If enabled, engine compares passed repeating group leading tag value with actual group size.
  • Required field validation. If enabled, engine rejects messages which have fields with undefined value required by protocol.
  • Check required field in the repeating group. Enables required field validation inside repeating group.

By default validation is disabled. There are two ways to enable/configure it:

Note
Settings configured by API override settings configured by engine.properties file.
See also
Explicit Message validation, Session configuration