B2BITS FIX Antenna C++  2.27.0
FIX Session

Table of Contents

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

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.

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 );

... 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

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

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

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.

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 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();

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:

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()

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:

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