These chapters describe the creation of a simple application step-by step with samples.
Follow these instructions to get it to work:
- Initialize FIX engine
- Create session (initiator or acceptor)
- Send messages, process incoming messages
- Close session
- Destroy engine (release resources)
Engine initialization
Execute the following instruction to initialize FIX engine.
B2BITS_FixEngine_Init("",-1, "","");
The engine.properties file is required to read the engine configuration parameters. It must, by default, be present in the current directory. If the file is located elsewhere or has a different name specify the properties file name and path explicitly.
B2BITS_FixEngine_Init("engine.properties", -1, "", "");
If an error occurs during initialization (the properties file is not found, a required property is missing etc.) function returns B2BITS_FALSE. Use B2BITS_GetLastErrorDescription to get description.
if( B2BITS_FixEngine_Init("",-1, "","") == B2BITS_FALSE )
{
printf("ERROR: %s", B2BITS_GetLastErrorDescription());
}
Session acceptor creation
You can create a session acceptor in three steps:
- Create an application object (observer entity for session to receive events). See Processing incoming message for details)
- Create a session object
- Call the B2BITS_Session_ConnectAcceptor function
app.Process = &App_Process;
app.OnLogonEvent = &App_OnLogonEvent;
app.OnLogoutEvent = &App_OnLogoutEvent;
app.OnHeartbeatWithTestReqIDEvent = &App_OnHeartbeatWithTestReqIDEvent;
pSA = B2BITS_FixEngine_CreateSession(
&app,
&acceptorCtx,
"Sender",
"Target",
B2BITS_FIX44,
0,
B2BITS_transient_storageType,
B2BITS_FIX_TCP);
if(!pSA)
{
printf( "Error: %s\n", B2BITS_GetLastErrorDescription() );
return 1;
}
B2BITS_Session_ConnectAcceptor(pSA, B2BITS_EM_NONE);
Session initiator creation
You can create a session initiator in three steps:
- Create an application object (observer entity for session to receive events, See Processing incoming message for details)
- Create a session object
- Call the B2BITS_Session_ConnectInitiator function passing the initiator's specific parameters
app.Process = &App_Process;
app.OnLogonEvent = &App_OnLogonEvent;
app.OnLogoutEvent = &App_OnLogoutEvent;
app.OnHeartbeatWithTestReqIDEvent = &App_OnHeartbeatWithTestReqIDEvent;
pSI = B2BITS_FixEngine_CreateSession(
&app,
&initiatorCtx,
"Target",
"Sender",
B2BITS_FIX44,
0,
B2BITS_transient_storageType,
B2BITS_FIX_TCP
);
if(!pSI)
{
printf( "Error: %s\n", B2BITS_GetLastErrorDescription() );
return 1;
}
B2BITS_Session_ConnectInitiator(pSI,30, "127.0.0.1", 9105, B2BITS_EM_NONE, 0, B2BITS_AC_PRIMARY_CONNECTION);
Creating new order
FIX Antenna provides interface for FIX messages manipulations:
order = B2BITS_FIXMsgFactory_NewSkel(B2BITS_FIX44, "D", B2BITS_NA);
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_ClOrdID, "USR20000101");
Sending order
A message is sent asynchronously by calling the B2BITS_Session_Put function. Consequently the message is scheduled for sending in the internal queue and sent in a separate thread. This means that if the method returns "controld" the message is not necessarily already sent.
B2BITS_Session_Put(pSI, order, 0);
B2BITS_Session_Put(pSA, order, 0);
Processing incoming message
The Application type is responsible for:
- Processing incoming messages from the remote FIX Engine
- Processing session events
Create an instance of the B2BITS_Application type, and init the B2BITS_Application::Process function pointer to process incoming messages. If an incoming message is successfully processed, the method will return "true", if the message cannot be processed at the moment, it will return "false".
If the B2BITS_Application::Process method does not return "true", the FIX engine will try to deliver the first unprocessed message a specified number of times (DelayedProcessing.MaxDeliveryTries) in the interval, specified in the FE configuration (DelayedProcessing.DeliveryTriesInterval). If the number of unsuccessful attempts exceeds the MaxDeliveryTries, a Logout message with "Application is not available" cause indication will be sent back.
It is also necessary to init the OnLogonEvent, OnLogoutEvent, OnSequenceGapEvent, OnSessionLevelRejectEvent and other function pointers. These are the call-back methods called to notify about the corresponding session-level events.
The B2BITS_Application::Process method is called only when an incoming application-level message or a Reject message is delivered. All other session-level messages are handled inside the FE.
For example:
{
return 1;
}
void __stdcall App_OnLogonEvent(
void* context,
const B2BITS_LogonEvent* event,
B2BITS_Session sn)
{
return;
}
void __stdcall App_OnLogoutEvent(
void* context,
const B2BITS_LogoutEvent* event,
B2BITS_Session sn)
{
return;
}
{
return;
}
memset(&app, 0, sizeof(app));
app.Process = &App_Process;
app.OnLogonEvent = &App_OnLogonEvent;
app.OnLogoutEvent = &App_OnLogoutEvent;
app.OnHeartbeatWithTestReqIDEvent = &App_OnHeartbeatWithTestReqIDEvent;
Note: The B2BITS_Application::Process method must not be dead-locked or perform time-demanding operations.
Note: If a pointer to the same B2BITS_Application is transmitted to several sessions, being established, synchronize the B2BITS_Application::Process() method.
Warning: Do not delete the registered Application until you unregister it.
Closing session
Use the following method to close the session:
B2BITS_Session_Disconnect(
B2BITS_Session session, B2BITS_BOOL forcefullyMarkAsTerminated)
Sample application
The sample below illustrates all abovementioned instructions combined in one application.
#include <stdio.h>
#include <string.h>
#include "B2BITS_C_FixEngine.h"
typedef struct tagSessionContext
{
volatile int processEvent;
volatile int logoutEvent;
char const* name_;
} SessionContext;
{
int size;
const char* str;
printf( "%s: App_Process\n", ((SessionContext*)context)->name_ );
str = B2BITS_FIXMessage_ToRaw(msg, &size);
printf("%.*s", size, str);
((SessionContext*)context)->processEvent = 1;
return 0;
}
void __stdcall App_OnLogonEvent(
void* context,
const B2BITS_LogonEvent* event,
B2BITS_Session sn)
{
printf( "%s: App_OnLogonEvent\n", ((SessionContext*)context)->name_ );
return;
}
void __stdcall App_OnLogoutEvent(
void* context,
const B2BITS_LogoutEvent* event,
B2BITS_Session sn)
{
printf( "%s: App_OnLogoutEvent\n", ((SessionContext*)context)->name_ );
((SessionContext*)context)->logoutEvent = 1;
return;
}
{
printf( "App_OnHeartbeatWithTestReqIDEvent\n" );
return;
}
int main(int argc, char* argv[])
{
SessionContext acceptorCtx;
SessionContext initiatorCtx;
if( B2BITS_TRUE != B2BITS_FixEngine_Init("",-1,"","") )
{
printf( "Error: %s\n", B2BITS_GetLastErrorDescription() );
return 1;
}
memset(&app, 0, sizeof(app));
app.Process = &App_Process;
app.OnLogonEvent = &App_OnLogonEvent;
app.OnLogoutEvent = &App_OnLogoutEvent;
app.OnHeartbeatWithTestReqIDEvent = &App_OnHeartbeatWithTestReqIDEvent;
memset(&acceptorCtx, 0, sizeof(acceptorCtx));
acceptorCtx.name_ = "Acceptor";
memset(&initiatorCtx, 0, sizeof(initiatorCtx));
initiatorCtx.name_ = "Initiator";
pSA = B2BITS_FixEngine_CreateSession(
&app,
&acceptorCtx,
"Sender",
"Target",
B2BITS_FIX44,
0,
B2BITS_transient_storageType,
B2BITS_FIX_TCP);
if(!pSA)
{
printf( "Error: %s\n", B2BITS_GetLastErrorDescription() );
return 1;
}
B2BITS_Session_ConnectAcceptor(pSA, B2BITS_EM_NONE);
pSI = B2BITS_FixEngine_CreateSession(
&app,
&initiatorCtx,
"Target",
"Sender",
B2BITS_FIX44,
0,
B2BITS_transient_storageType,
B2BITS_FIX_TCP
);
if(!pSI)
{
printf( "Error: %s\n", B2BITS_GetLastErrorDescription() );
return 1;
}
B2BITS_Session_ConnectInitiator(pSI,30, "127.0.0.1", 9105, B2BITS_EM_NONE, 0, B2BITS_AC_PRIMARY_CONNECTION);
order = B2BITS_FIXMsgFactory_NewSkel(B2BITS_FIX44, "D", B2BITS_NA);
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_ClOrdID, "USR20000101");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_HandlInst, "2");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_Symbol, "IBM");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_OrderQty, "200");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_Side, "1");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_OrdType, "5");
B2BITS_FIXMessage_SetAsCString(order, B2BITS_FIXField_TimeInForce, "0");
B2BITS_Session_Put(pSI, order, 0);
while(0 == acceptorCtx.processEvent);
B2BITS_FIXMessage_Release(order);
B2BITS_Session_Disconnect(pSI, 0);
while(0 == initiatorCtx.logoutEvent);
while(0 == acceptorCtx.logoutEvent);
B2BITS_Session_RegisterApplication(pSI, NULL, NULL, 1, 0);
B2BITS_Session_Release(pSI);
B2BITS_Session_RegisterApplication(pSA, NULL, NULL, 1, 0);
B2BITS_Session_Release(pSA);
B2BITS_FixEngine_Destroy();
printf("Application shutdown.");
return 0;
}