To shutdown the Engine the FIXForge::FIX::Engine::shutdown method is used.
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;try{ Engine::init(); // Session-related logic... Engine::shutdown();}catch(const EngineException& ex){ clog << "Exception: " << ex.what() << endl;}
Example:
Each FIX version has its own namespace that contains objects that are unique for the version, e.g.:
using namespace FIXForge::FIX::FIX40;Below is an example of a FIX message:

It is represented with the FIXForge::FIX::Message class.
To create a message the FIXForge::FIX::Message(const std::string& type, FIXForge::FIX::Version version) constructor is used.
To parse a message in the raw (tag=value) FIX format the FIXForge::FIX::Message(const std::string& rawMessage) constructor is used.
To validate a message the FIXForge::FIX::Message::validate method is used. This method checks for the presence of required fields.
There are several overloaded methods FIXForge::FIX::Message::toString() to simplify debugging and monitoring. To update the BodyLength (9) and CheckSum (10) fields the FIXForge::FIX::Message::updateCheckSum() method is used.
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;{ Message order("D", FIX_42); // New Order - Single (MsgType = D) order.updateCheckSum(); clog << "Order" << order << endl;}{ string rawMsg = "8=FIX.4.0\0x019=86\0x0135=D\0x0149=0\0x0156=0\0x0134=1\0x0152=99990909-17:17:17\0x0111=90001008\0x0121=1\0x0155=IBM\0x0154=1\0x0138=10\0x0140=1\0x0159=0\0x0110=191\0x01"; Message order(rawMsg); order.validate(); clog << order.toString() << endl; clog << order.toString(' ') << endl; clog << order.toString(Message::TAG_NAME | Message::TAG_NUMBER) << endl;}
To get a field value the FIXForge::FIX::Message::get method is used.
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;using namespace FIXForge::FIX::FIX40;Message order("D", FIX_40); // New Order - Singleorder.set(11, "Unique identifier of execution message");string ClOrdID = order.get(11);
To remove a field the FIXForge::FIX::Message::remove method is used.
The FIXForge::FIX::FIX42::Tags class contains the constants for the tag values. This class is defined for each FIX version namespace. The use of these constants makes the source code more readable.
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;using namespace FIXForge::FIX::FIX40;Message order("D", FIX_40); // New Order - Singleorder.set(Tags::ClOrdID, "90001008");order.set(Tags::Side, "1");order.set(Tags::TimeInForce, "0");
To create a session the FIXForge::FIX::Session's constructors are used.
To terminate the session the FIXForge::FIX::Session::shutdown method is used.
A session has one of two possible roles: Acceptor or Initiator.
Acceptor is the receiving party of the FIX session. It listens for the incoming connection on the pre-defined port. The acceptor has responsibility to perform first level authentication and formally declare the connection request "accepted" through transmission of an acknowledgment Logon message.
Initiator establishes the telecommunications link and initiates the session via transmission of the initial Logon message.
To obtain the current role the FIXForge::FIX::Session::getRole method is used.
To establish the session as Acceptor the FIXForge::FIX::Session::logonAsAcceptor method is used.
To establish the session as Initiator the FIXForge::FIX::Session::logonAsInitiator method is used.
To disconnect the session the FIXForge::FIX::Session::logout method is used.
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX; using namespace FIXForge::FIX::FIX40;const string SENDER_COMP_ID = "SenderCompID";const string TARGET_COMP_ID = "TargetCompID";const Version VERSION = FIX_40;const string HOST = "Localhost";int ACCEPTOR_PORT = Engine::instance()->getListenPort();ISessionListener listener;Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);acceptor.logonAsAcceptor(); initiator.logonAsInitiator(HOST, ACCEPTOR_PORT); // Sends the Logon message and waits for the acknowledgment Logon// Message exchange and processing ...acceptor.logout(); // Sends the Logout message and waits for the confirming Logoutinitiator.logout();acceptor.shutdown(); // Free resourcesinitiator.shutdown(); // Free resources
To receive incoming application-level messages it is necessary to override the FIXForge::FIX::ISessionListener::onInboundApplicationMsg method.
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;using namespace FIXForge::FIX::FIX42;class SessionListener : public ISessionListener{ public: virtual void onInboundApplicationMsg(const Message& msg, Session* sn){ clog << "Incoming application-level message: " << msg << endl; // processing of the application-level incoming message... }};const string SENDER_COMP_ID = "AcceptorAndInitiator_SND";const string TARGET_COMP_ID = "AcceptorAndInitiator_TRG";const Version VERSION = FIX_42;const string ACCEPTOR_HOST = "localhost";int ACCEPTOR_PORT = Engine::instance()->getListenPort();SessionListener listener;Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);acceptor.logonAsAcceptor();Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);initiator.logonAsInitiator(ACCEPTOR_HOST, ACCEPTOR_PORT);Message order("D", VERSION); order.set(Tags::ClOrdID, "Unique identifier for Order as assigned by the buy-side");order.set(Tags::HandlInst, "1");order.set(Tags::Symbol, "Ticker symbol");order.set(Tags::Side, "1");order.set(Tags::TransactTime, "20051012-22:10:11");order.set(Tags::OrdType, "1");order.validate();acceptor.send(&order);// continue the message exchange...acceptor.logout();initiator.logout();acceptor.shutdown(); initiator.shutdown();
Sequence numbers are initialized at the start of each FIX Session starting at 1 (one) and increment throughout the session. Each session establishes an independent incoming and outgoing sequence series. A single FIX session can exist across multiple sequential (not concurrent) physical connections. Parties can connect and disconnect multiple times while maintaining a single FIX session.
In other words, FIX Session is comprised of one or more FIX Connections.
Resetting the inbound and outbound sequence numbers back to 1, for whatever reason, constitutes the beginning of a new FIX session. Monitoring sequence numbers enables parties to gracefully synchronize applications when reconnecting during a FIX session.
To get or set the expected sequence number of the next incoming message the FIXForge::FIX::Session::getInSeqNum(), FIXForge::FIX::Session::setInSeqNum() methods are used.
To get or set the sequence number of the next outgoing message the FIXForge::FIX::Session::getOutSeqNum(), FIXForge::FIX::Session::setOutSeqNum() methods are used.
To disconnect the FIX Connection while maintaining a single FIX Session the FIXForge::FIX::Session::logout() method is used.
It is possible to continue the session later using the FIXForge::FIX::Session::logonAsAcceptor() or FIXForge::FIX::Session::logonAsInitiator() methods again.
To terminate a FIX Session the FIXForge::FIX::Session::shutdown() method is used.
The Engine automatically synchronizes sequence numbers when reconnecting during a FIX session on the base of the information previously stored in log files.
To synchronize sequence numbers manually FIXForge::FIX::Session::setInSeqNum() and FIXForge::FIX::Session::setOutSeqNum() methods are used (before FIXForge::FIX::Session::logonAsAcceptor() or FIXForge::FIX::Session::logonAsInitiator() method calls).

Some implementations of FIX protocol (FIX Dialects) expect that the FIX Session coincides with FIX Connection, in other words that the sequence numbers are reset back to 1 after the Logout messages exchange. To interact with such FIX dialects, the keepSequenceNumbersAfterLogout parameter of FIXForge::FIX::Session's constructor should be set to false.
In this case after FIXForge::FIX::Session::shutdown() method sequence numbers are set back to 1. Next time when the FIXForge::FIX::Session object is created incoming and outgoing sequence numbers will start from 1 (in other words, a new FIX Session will be created).
It is possible to specify the absolute path to the license file using the LicenseFile configuration setting.
For each FIX session two files are created:
When the FIXForge::FIX::Session object is created anew after the Engine's restart, FIX Session's state (the sequence numbers of last received and sent messages, previously sent messages, etc) is restored from these files.
To start a FIX session as a new one (so called "clean start"), it is necessary to remove the log files from the previous runs.
Connecting parties must bi-laterally agree as to when sessions are to be started/stopped and log files are backed up based upon individual system and time zone requirements.
When the FIX session is finished, the log files are not needed anymore. They can be backed up and later a new FIX session with the same SenderCompID and TargetCompID will start sequence numbers from 1. The usual practice is to backup the log files at the end of each business day (so called "End Of Day procedure") to start the sequence numbers from 1 at the beginning of the next day.
Example:
<?xml version="1.0" encoding="utf-8" ?><configuration> <configSections> <section name="FixEngine" type="System.Configuration.NameValueSectionHandler"/> </configSections> <FixEngine> <add key="Dialect" value="LavaDialect.xml"/> <add key="ListenPort" value="4500"/> <add key="Log.InboundMessages" value="true"/> <add key="Validate.NumberOfRepeatingGroupInstances" value="false"/> <add key="Validate.RequiredFields" value="true"/> <add key="Resending.QueueSize" value="2500"/> <add key="Validate.UnknownFields" value="true"/> <add key="Validate.UnknownMessages" value="true"/> </FixEngine> </configuration>
| Setting | Description | Default value |
|---|---|---|
| ConnectionRetries.Number | Number of attempts to restore the telecommunication link. | 3 |
| ConnectionRetries.Interval | The time interval between the attempts to restore the telecommunication link (in seconds). | 30 |
| Dialect | Specify the path to the XML file with the description of the FIX Dialect. | Empty |
| LicenseFile | Specify the path to the license file. | FIXForge.Cpp.FIX.Engine.lic |
| ListenPort | FIX Engine listens on this port for incoming connections. If '0' then only session-initiators can be created. If '-1' then the telecommunication level is disabled and only message parsing/assembling can be used. | 0 |
| Log.Directory | Inbound and outboundmessages, session's state data and the FIX Engine log file (FixEngine.log) are stored in this directory. | MsgStorage |
| Log.FlushFileAfterEachMessage | Option to flush output files after each logged message. | True |
| Log.InboundMessages | Option to log inbound messages. | True |
| Log.SessionSummary | Option to create a summary log file with inbound and outbound messages (in *.summary file). | True |
| Resending.QueueSize | Number of sent messages that are available for resending on counterparty's Resend Request <2> message. | 1000 |
| SSL.CertificateFile | The path to the SSL certificate file in (Privacy Enhanced Mail) Base64 encoded (.pem) format. | Empty |
| SSL.ListenPort | FIX Engine listens on this port for incoming SSL connections. If it is set to '0' then only SSL-based session-initiators can be created. If '-1' then the SSL encryption is disabled. | 0 |
| SSL.PrivateKeyFile | The path to the SSL private key file in (Privacy Enhanced Mail) Base64 encoded (.pem) format. | Empty |
| SSL.PrivateKeyPassword | The password to load private keys that are protected by a password. | Empty |
| SSL.VerifyPeer | Option to request client certificates and perform the certificate verification. | False |
| Validate.NumberOfRepeatingGroupInstances | Option to validate that the declared number of Repeating Group instances is equal to the actual one. | True |
| Validate.RequiredFields | Option to validate the presence of required fields in inbound and outbound messages. | False |
| Validate.UnknownFields | Option to validate the presence of unknown fields (fields that do not belong to the message in accordance with the FIX protocol or its FIX Dialect. | False |
| Validate.UnknownMessages | Option to validate the presence of unknown FIX messages (messages that do not belong to the message in accordance with the FIX protocol or its FIX Dialect. | False |
"215=2<SOH></a>216=2<SOH>217=Dest_1<SOH>216=4<SOH>217=Dest_2<SOH>"represents a repeating group with two repeating instances "delimited" by tag 216 (first field in the repeating group.). The NoRoutingIDs<215> field specifies the number of repeating group instances (2 in this case). This is so called NumberOfInstances field. The NumberOfInstances field must immediately precede the repeating group contents (repeating group instances).

The FIX repeating group is represented with the FIXForge::FIX::Group class.
To get the Group object that represents the existing repeating group of the message the FIXForge::FIX::Message::getGroup(int numberOfInstancesTag) method is used.
To create a new repeating group or modify the number of instances in the existing one the FIXForge::FIX::Message::setGroup(int numberOfInstancesTag, int numberOfInstances) method is used.
To remove a repeating group method FIXForge::FIX::Message::remove(int numberOfInstancesTag) is used.
The FIXForge::FIX::Group class works with fields and embedded repeating groups in the same manner as the FIXForge::FIX::Message class, but each method has an additional parameter that defines the index of the repeating group instance (starting from 0).
Note: To avoid memory leaks call FIXForge::FIX::Group::release().
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;using namespace FIXForge::FIX::FIX42;Message request("V", FIX_42);request.set(Tags::MDReqID, "ABSD");request.set(Tags::SubscriptionRequestType, 1);request.set(Tags::MarketDepth, 1);request.set(Tags::MDUpdateType, 1);request.set(Tags::AggregatedBook, "N");// create a repeating group NoMDEntryTypes with two instancesGroup* groupMDEntryTypes = request.setGroup(Tags::NoMDEntryTypes, 2);groupMDEntryTypes->set(Tags::MDEntryType, 0, "EntryType_1"); // first instancegroupMDEntryTypes->set(Tags::MDEntryType, 1, "EntryType_2"); // second instancegroupMDEntryTypes->release(); // to free resources// create a repeating group NoRelatedSym with two instancesGroup* groupRelatedSym = request.setGroup(Tags::NoRelatedSym, 2);groupRelatedSym->set(Tags::Symbol, 0, "EURUSD_0"); // first instancegroupRelatedSym->set(Tags::Symbol, 1, "EURUSD_1"); // second instancegroupRelatedSym->release(); // to free resourcesrequest.validate();clog << request << endl;
The states of the FIX session are listed below.
To be notified about the changes in the session stateoverwrite the FIXForge::FIX::ISessionListener::onStateChange method.
Example:
class Listener : public ISessionListener{public : virtual void Listener::onStateChange(Session::State newState, Session::State prevState, Session* sn){ clog << "\nSession's state is changed, prevState=" << Session::state2string(prevState) << ", newState=" << Session::state2string(newState) << endl; }};
The methods of the FIXForge::FIX::ISessionListener class are listed below.
| Method (Event handler) | Description |
|---|---|
| onStateChange | Session state is changed. |
| onError | Error condition is detected. |
| onInboundApplicationMsg | Application-level message is received from the counterparty. |
| onInboundSessionMsg | Session-level message is received from the counterparty. |
| onOutboundApplicationMsg | Application-level message will be sent to the counterparty. |
| onOutboundSessionMsg | Session-level message will be sent to the counterparty. |
| onResendRequest | Sent application-level message is about to be resent to the counterparty. |
| onWarning | Warning condition is detected. |
Example:
#include <FIXForge_FIXEngine.h>using namespace FIXForge::FIX;using namespace FIXForge::FIX::FIX43;const string SENDER_COMP_ID = "CustomLogonMessage_SND";const string TARGET_COMP_ID = "CustomLogonMessage_TRG";const Version VERSION = FIX_43;const int HBI = 30;const string USERNAME = "USER_NAME";const string PASSWORD = "PASSWORD";int port = Engine::instance()->getListenPort();ISessionListener listener;Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);acceptor.logonAsAcceptor();Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);Message customLogonMsg("A", FIX_43);customLogonMsg.set(Tags::Username, USERNAME);customLogonMsg.set(Tags::Password, PASSWORD);initiator.logonAsInitiator("localhost", port, HBI, &customLogonMsg);// message exchange and processing ...acceptor.logout();initiator.logout();acceptor.shutdown();initiator.shutdown();
FIX dialect represents a customized messages dictionary of single FIX messaging specification (of, simply, FIX version). FIXForge Engine accepts dialects descriptions as part of its configuration settings. In particular, a FixEngine.Dialect FixEngine.Dialect configuration parameter specifies specifies a path to the dialects definitions.
Definition of a single FIX dialect is built on describing changes into standard FIX version. Currently customization consists in ability to expand set of messages with new ones, to enlarge messages and repeating groups with new fields and subgroups. It's also possible to replace regular fields with repeating groups and vise versa. However, there's no way to exclude any message, tag and/or group as they are from containing entity.
FIXForge Engine supports dialects for local use in bounds of a single FIX session as well as allows to substitute standard FIX dictionaries used everywhere in the Engine.
Below is step-by-step explanation of how dialect can be defined using XML-based description used by FIXForge Engine (for more information take a look at Dialect definition XML schema).
Basic dialects description file structure:
<?xmlversion="1.0" encoding="utf-8"?><!-- Root of dialects descriptions. May contain engine-wise as well as per-session dialects descriptions. --><Dialect xmlns="http://onixs.biz/fix/dialects"><!-- FIX field defines single dialect description. Attribute 'version' defines version of FIX messaging specification which is being customized. --> <FIX version="4.0"> <!-- Changes into single message structure go here (as well as new messages definitions). --> <Message type="D"> <!-- Tags and groups which enlarge or modify message. --> <Field tag="526" name="SecondaryClOrdID"/> </Message> </FIX></Dialect>
To add new field to a FIX Message add the corresponding Field entity to the description of FIX message in dialects descriptions file.
Note: inclusion of Field element for already registered (e.g. standard) field or group causes FIXForge Engine to overwrite its attribute. In such way existent field attributes can be modified. This behavior allows to make a mandatory field or group as optional and vice versa. Separatelly, same approach gives the opportunity to replace existing FIX repeating group with regular field and vice versa.
For example:
<?xml version="1.0" encoding="utf-8"?><Dialect xmlns="http://onixs.biz/fix/dialects"> <FIX version="4.0"> <Message type="D"> <!-- Field #526 does not belong to the Standard FIX 4.0. --> <Field tag="526" name="SecondaryClOrdID" isRequired="true"/> <!-- Field #21 is required in Standard FIX 4.0, but will be optional in this FIX dialect. --> <Field class=attribute>tag="21" isRequired="false" name="HandlInst"/> </Message> </FIX></Dialect>
To add a new repeating group to a FIX message or add fields into existent one just add the corresponding Group entity to the FIX dialect description file.
Note: in case of new group definition first field (subgroup) will be used as leading tag (tag which separates repeating groups entries). If current definition describes changes into existent group, original leading tag remains actual.
For example:
<?xml version="1.0" encoding="utf-8"?><Dialect xmlns="http="http://onixs.biz/fix/dialects"> <FIX version="4.0"> <Message> type="D"&g="D"> <!-- Repeating group for pre-trade allocation (does not belong to the Standard FIX 4.0). --> <Group numberOfInstancesTag="78" class=attribute>name="NoAl="NoAllocs"> <Field tag="79" class=attribute>name="Allo="AllocAccount"/> <Field> tag="661" name="Allo="AllocAcctIDSource"/> <Field tag="736" class=attribute>name="Allo="AllocSettlCurrency"/> <!-- Other group fields go here. --> </Group> </Message> </FIX></Dialect>
To define a custom (user-defined) message add the corresponding Message entity to the FIX dialect description.
For example:
<?xml version="1.0" encoding="utf-8"?><Dialect xmlns="http://onixs.biz/fix/dialects"> <FIX version="4.0"> <Message type="UserDefinedMessage_1"> <Field tag="100"/ isRequired="true"> <Field tag="101"/> </Message> </FIX></Dialect>
Such a user-defined message can be used exactly the same way as the standard FIX Message:
Message udm_1("UserDefinedMessage_1", FIX_43);udm_1.set(100, "Field 100");udm_1.set(101, "Field 101");udm_1.validate();clog << "UDM: " << udm_1 << endl;
Example of a FIX Dialect description file:
<?xml version="1.0" encoding="utf-8"?><Dialect xmlns="http://onixs.biz/fix/dialects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://onixs.biz/fix/dialects http://onixs.biz/fix/dialects/dialects-2_3.xsd"> <FIX version="4.2"> <Message type="N"> <Group numberOfInstancesTag="73" name="RefAllocID"> <!-- An additional field in the existing repeating group --> <Field tag="37" name="OrderID"/> </Group> </Message> </FIX> <FIX version="4.3"> <Message type="y"> <Group numberOfInstancesTag="146" name="NoRelatedSym"> <!-- An additional field in the existing repeating group --> <Field tag="64" isRequired="true" name="FutSettDate"/> </Group> </Message> <Message type="W"> <Group numberOfInstancesTag="268" name="NoMDEntries"> <!-- An additional field in the existing repeating group --> <Field tag="278" name="MDEntryID"/> </Group> <Field tag="64" name="FutSettDate"/> </Message> </FIX> <!-- Dialect to be used locally by single or more sessions --> <FIX version="4.3" id="ForTradeWithNewXMessage"> <Message type="X"> <!-- An additional field --> <Field tag="55" name="Symbol"/> <!-- An additional field --> <Field tag="64" name="FutSettDate"/> </Message> </FIX></Dialect>
First of all, dialects definition file must be enhanced with additional attribute id, which reduces scope of usage to session-only level:
<?xml version="1.0" encoding="utf-8"?><Dialect xmlns="http://onixs.biz/fix/dialects"> <!-- Attribute 'id' tells FIXForge Engine that dialect will be used in certain sessions only. It will not be used widely. --> <FIX version="4.0" id="Custom FIX"> <!-- Regular dialect description goes here. --> </FIX></Dialect>
Note: once defined dialect description has non-empty id attribute FIXForge Engine will not use it widely. Instead such dialect can be used for sessions only.
Afterwards, in source code, instance of FIXForge::FIX::Dialect class must be created. Its constructor accepts only one parameter which identifies the dialect you'd like to use for the session. Value of this parameter must be same as it is in XML description. Once instance of FIXForge::FIX::Dialect created, FIX FIXForge::FIX::Session can be initialized. FIXForge::FIX::Session initialization is performed in usual way with the only one difference: instead of supplying the version of FIX protocol, instance of appropriate FIXForge::FIX::Dialect class must be passed. After that created session will operate FIX messages using specified dialect.
Dialect customFIX("Custom FIX");Session sessionWithCustomFIX("Sender", "Target", customFIX, &defaultListener);
To send messages of certain dialect, the instance of FIXForge::FIX::Dialect class must be supplied during FIXForge::FIX::Message construction.
Dialect customFIX("Custom FIX");Message customOrder("D", customFIX);fillCustomFIXOrder(&customOrder);customOrder.validate();
If the sent application-level message should not be resent to the counterparty (e.g. an aged order) then the FIXForge::FIX::ISessionListener::onResendRequest() method should return false. In this case the Sequence Reset-GapFill (4) message will be sent instead.
To perform this task, inherit from the FIXForge::FIX::IEngineListener class, overwrite the FIXForge::FIX::IEngineListener::onUnknownIncomingConnection method and register your listener object with the FIXForge::FIX::Engine instance using the FIXForge::FIX::Engine::registerListener method.
An automatically created FIXForge::FIX::Session object that corresponds to the incoming FIX connection is available via the session parameter of the FIXForge::FIX::IEngineListener::onUnknownIncomingConnection callback method.
To accept the incoming connection, set the acceptConnection parameter of the FIXForge::FIX::IEngineListener::onUnknownIncomingConnection callback method to true. To listen to incoming messsages register your class inhereted from from the FIXForge::FIX::ISessionListener using the FIXForge::FIX::Session::registerListener method.
Otherwise the incoming connection will be rejected and the created FIXForge::FIX::Session object will be disposed by the FIX Engine.
To send the Logout message before closing the rejected connection set the rejectReason parameter of the FIXForge::FIX::IEngineListener::onUnknownIncomingConnection callback method to the rejection description.
For example:
class MyListener : public FIXForge::FIX::IEngineListener, public FIXForge::FIX::ISessionListener{ public: MyListener(bool acceptConnection, const string& rejectReason) : acceptConnection_(acceptConnection), rejectReason_(rejectReason), session_(NULL){;} ~MyListener() { delete session_; } virtual void onUnknownIncomingConnection(const Message& incomingLogon, Session* session, bool* acceptConnection, std::string* rejectReason) { *acceptConnection = acceptConnection_; if(acceptConnection_) { session_ = session; session_->registerListener(this); // To listen to incoming messsages. } else { *rejectReason = rejectReason_; // To send the Logout message before closing the rejected connection. } } virtual void onInboundApplicationMsg(const Message& message, Session* sn) { // ... } private: FIXForge::FIX::Session* session_; bool acceptConnection_; };// ...MyListener listener(true, "");Engine::instance()->registerListener(&listener);
For example:
ISessionListener listener; Session initiator("SenderCompIDValue", "TargetCompIDValue", FIX_42, &listener);initiator.setEncryptionMethod(Session::SSL); initiator.logonAsInitiator("localhost", 443, true);// Message exchange ... initiator.logout("SSL connection is finished.");initiator.shutdown();
To convert into this format from other format types, the openssl command-line tool could be used (http://www.openssl.org).
For example, to convert from "Personal Information Exchange - PKCS#12" (.pfx) to "Base64 Encoded" (.pem), the following command is run on the PFX file:
openssl pkcs12 -in <file_name>.pfx -out <file_name>.pem -nodes
For example:
const string targetCompID = "CNX"; const string host = "TargetHost"; { // Stream FIX Session const string streamSenderCompID = "str"; ISessionListener listener; Session streamSession(streamSenderCompID, targetCompID, FIX_42, &listener); streamSession.setEncryptionMethod(Session::SSL); const string streamSslCertificateAndPrivateKeyFile = "str.pem"; // If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File. streamSession.setSslCertificateFile(streamSslCertificateAndPrivateKeyFile); streamSession.setSslPrivateKeyFile(streamSslCertificateAndPrivateKeyFile); const int streamPort = 442; streamSession.logonAsInitiator(host, streamPort, 30, true); clog << "Stream session is established" << endl; streamSession.logout();}{ // Trading FIX Session const string tradingSenderCompID = "tr"; ISessionListener listener; Session tradingSession(tradingSenderCompID, targetCompID, FIX_42, &listener); tradingSession.setEncryptionMethod(Session::SSL); const string tradingSslCertificateAndPrivateKeyFile = "tr.pem"; // If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File. tradingSession.setSslCertificateFile(tradingSslCertificateAndPrivateKeyFile); tradingSession.setSslPrivateKeyFile(tradingSslCertificateAndPrivateKeyFile); const int tradingPort = 443; tradingSession.logonAsInitiator(host, tradingPort, 30, true); clog << "Trading session is established" << endl; tradingSession.logout();}
FAST-related classes can be found in the FIXForge::FIX::FAST_1_1 namespace.
To encode a FIX message into a FAST stream the FIXForge::FIX::FAST_1_1::Encoder class is used.
For example:
string xmlFastTemplate = readTextFile("UdpFastTemplate.xml");const bool encodeEachMessageIndependently = true;Encoder encoder(xmlFastTemplate, sourceFixMessage.getVersion(), encodeEachMessageIndependently);const int fastTemplateID = 36; const size_t bufferSize = 1024;char fastStreamChunk[bufferSize];size_t chunkSize = encoder.encode(sourceFixMessage, fastTemplateID, fastStreamChunk, bufferSize);
To decode a part of a FAST stream back into a FIX message the FIXForge::FIX::FAST_1_1::Decoder class is used.
For example:
const bool decodeEachMessageIndependently = true;Decoder decoder(xmlFastTemplate, sourceFixMessage.getVersion(), decodeEachMessageIndependently);const Message& decodedMessage = decoder.decode(fastStreamChunk, chunkSize);
A FAST Template specifies the encoding and decoding rules in accordance with the FAST specification.
For example:
<?xml version="1.0" encoding="utf-8"?><templates> <template name="Market Data - Incremental Refresh (X)" id="88"> <uInt32 name="BodyLength" id="9"/> <string name="MessageType" id="35"> <constant value="X" /> </string> <string name="SenderCompID" id="49"> <copy/> </string> <string name="TargetCompID" id="56"> <copy/> </string> <uInt64 name="MsgSeqNum" id="34"> <increment value="1"/> </uInt64> <string name="SendingTime" id="52"> <tail/> </string> <string name="PosDupFlag" id="43" presence="optional"> <default/> </string> <sequence name="MDEntries"> <length name="NoMDEntries" id="268"/> <string name="MDUpdateAction" id="279"/> <string name="Symbol" id="55"/> </sequence> <string name="CheckSum" id="10"/> </template><templates>
The optional presence attribute indicates whether the field is mandatory or optional. If the attribute is not specified, the field is mandatory.
The required name attribute identifies the corresponding field in the current FIX message type by the field name.
The optional id attribute identifies the corresponding field in the current FIX message type by the tag number.
The following field operators are supported:
|
A. You can use FIXForge::FIX::Session::setInSeqNum and FIXForge::FIX::Session::setOutSeqNum methods to set the start sequence numbers before establishing the session.
A. You need to define and use the corresponding XML-based FIX Dialect description. See: FIX Dialects.
ResetSeqNumFlag (141) field in the Logon message?
A. To send a Logon message with this field during FIX Connection establishment, use the Custom Logon Message . It is also possible to send a Logon message with the ResetSeqNumFlag set when the FIX Session is established (e.g. to maintain 24 hour connectivity). For example:
FIX Session-Initiator changes its state to RECONNECTING and tries to restore the FIX Connection pre-configured number of times in pre-configured interval (using the binary exponential back off algorithm). Please note that FIX Engine automatically handles sending of Test Request messages (when needed).
For example:
customLogonMsg.set(Tags::SenderSubID, "SenderSubID_Value");customLogonMsg.set(Tags::OnBehalfOfSubID, "OnBehalfOfSubID_Value");
"Invalid FIX Engine settings: Cannot open the persistent storage folder ('MsgStorage')" error (exception) when I try to run my FIX application as a Windows service? When I run my application as a standalone one, all work perfectly OK.A. You can use FIXForge::FIX::Session::senderSubID(const std::string &value), FIXForge::FIX::Session::targetSubID(const std::string &value), FIXForge::FIX::Session::senderLocationID(const std::string &value), FIXForge::FIX::Session::targetLocationID(const std::string &value) methods of the FIXForge::FIX::Session object.
1.5.7.1