Skip to content

Commit

Permalink
Merge pull request connamara#291 from martinadams/rx_intercept
Browse files Browse the repository at this point in the history
Add new Application Callback (non-breaking) for early intercept of inbou...
  • Loading branch information
mgatny committed Jun 1, 2015
2 parents ddea749 + 5820c4e commit 65eeeaf
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 2 deletions.
26 changes: 26 additions & 0 deletions QuickFIXn/IApplicationExt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;

namespace QuickFix
{
/// <summary>
/// This is the optional extension interface for processing inbound messages,
/// and facilitates early interception of such messages. 'Early', in this context,
/// means after structure, length and checksum have been validated, but before any
/// further validation has been performed.
/// This interface will not normally be required, and it should be used only with caution:
/// it allows modfications to be made to irregular inbound messages that would otherwise
/// fail validation against the Fix dictionary, an provides an alternative to dictionary
/// customisation as a means of dealing with such messages.
/// </summary>
public interface IApplicationExt : IApplication
{
/// <summary>
/// This callback provides early notification of when an administrative or application message is sent from a counterparty to your FIX engine.
/// This can be useful for doing pre-processing of an inbound message after its structure, checksum and length have been validated, but before
/// any further validation has been performed on it.
/// </summary>
/// <param name="message">received message</param>
/// <param name="sessionID">session on which message received</param>
void FromEarlyIntercept(Message message, SessionID sessionID);
}
}
3 changes: 2 additions & 1 deletion QuickFIXn/QuickFix.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<Compile Include="FileStoreFactory.cs" />
<Compile Include="FixValues.cs" />
<Compile Include="IApplication.cs" />
<Compile Include="IApplicationExt.cs" />
<Compile Include="IInitiator.cs" />
<Compile Include="ILog.cs" />
<Compile Include="ILogFactory.cs" />
Expand Down Expand Up @@ -141,4 +142,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
5 changes: 5 additions & 0 deletions QuickFIXn/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class Session : IDisposable
private SessionSchedule schedule_;
private SessionState state_;
private IMessageFactory msgFactory_;
private bool appDoesEarlyIntercept_;
private static readonly HashSet<string> AdminMsgTypes = new HashSet<string>() { "0", "A", "1", "2", "3", "4", "5" };

#endregion
Expand Down Expand Up @@ -211,6 +212,7 @@ public Session(
this.DataDictionaryProvider = new DataDictionaryProvider(dataDictProvider);
this.schedule_ = sessionSchedule;
this.msgFactory_ = msgFactory;
appDoesEarlyIntercept_ = app is IApplicationExt;

this.SenderDefaultApplVerID = senderDefaultApplVerID;

Expand Down Expand Up @@ -545,6 +547,9 @@ public void Next(Message message)
return;
}

if (appDoesEarlyIntercept_)
((IApplicationExt)Application).FromEarlyIntercept(message, this.SessionID);

if (IsNewSession)
state_.Reset("New session (detected in Next(Message))");

Expand Down
74 changes: 73 additions & 1 deletion UnitTests/SessionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,49 @@ public void OnLogout(QuickFix.SessionID sessionID)
public void OnLogon(QuickFix.SessionID sessionID)
{
}
#endregion
}

class MockApplicationExt : QuickFix.IApplicationExt
{
public HashSet<string> InterceptedMessageTypes = new HashSet<string>();

#region Application Members

public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionID)
{
}

public void FromAdmin(QuickFix.Message message, QuickFix.SessionID sessionID)
{
}

public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId)
{
}

public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionID)
{
}

public void OnCreate(QuickFix.SessionID sessionID)
{
}

public void OnLogout(QuickFix.SessionID sessionID)
{
}

public void OnLogon(QuickFix.SessionID sessionID)
{
}

public void FromEarlyIntercept(QuickFix.Message message, QuickFix.SessionID sessionID)
{
InterceptedMessageTypes.Add(message.Header.GetString(QuickFix.Fields.Tags.MsgType));
}
#endregion

}

[TestFixture]
Expand All @@ -126,6 +167,7 @@ public class SessionTest
MockApplication application = null;
QuickFix.Session session = null;
QuickFix.Session session2 = null;
QuickFix.Dictionary config = null;
int seqNum = 1;
Regex msRegex = new Regex(@"\.[\d]{1,3}$");

Expand All @@ -137,7 +179,7 @@ public void setup()
application = new MockApplication();
settings = new QuickFix.SessionSettings();

QuickFix.Dictionary config = new QuickFix.Dictionary();
config = new QuickFix.Dictionary();
config.SetBool(QuickFix.SessionSettings.PERSIST_MESSAGES, false);
config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator");
config.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00");
Expand Down Expand Up @@ -719,5 +761,35 @@ public void TestToAppResendDoNotSend()
SendResendRequest(1, 0);
Assert.False(SENT_NOS());
}


[Test]
public void TestApplicationExtension()
{
var mockApp = new MockApplicationExt();
session = new QuickFix.Session(mockApp, new QuickFix.MemoryStoreFactory(), sessionID,
new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(config), 0, new QuickFix.ScreenLogFactory(settings), new QuickFix.DefaultMessageFactory(), "blah");
session.SetResponder(responder);
session.CheckLatency = false;

Logon();
QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle(
new QuickFix.Fields.ClOrdID("1"),
new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER),
new QuickFix.Fields.Symbol("IBM"),
new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY),
new QuickFix.Fields.TransactTime(),
new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT));

order.Header.SetField(new QuickFix.Fields.TargetCompID(sessionID.SenderCompID));
order.Header.SetField(new QuickFix.Fields.SenderCompID(sessionID.TargetCompID));
order.Header.SetField(new QuickFix.Fields.MsgSeqNum(2));

session.Next(order);

Assert.That(mockApp.InterceptedMessageTypes.Count, Is.EqualTo(2));
Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.LOGON));
Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.NEWORDERSINGLE));
}
}
}

0 comments on commit 65eeeaf

Please sign in to comment.