Thread: [Quickfix-users] Message with contents set through Message.setString(string) can't be cracked in .N
Brought to you by:
orenmnero
From: abaraff <ab...@ra...> - 2011-05-20 14:45:48
|
If a message is cloned using the .setString(string) method, calling crack on it fails. As you can see from my example below, crack is successful on the original message but throws an exception when called on the clone: public void fromApp(Message msg, SessionID sessionID) { try { string message = msg.ToString(); Message newMessage = new Message(); newMessage.setString(msg.ToString(), true); crack(msg, sessionID); try { crack(newMessage, sessionID); } catch (Exception e2) { System.Diagnostics.Debug.WriteLine(e2.ToString()); System.Diagnostics.Debug.WriteLine(msg.ToString() == newMessage.ToString()); System.Diagnostics.Debug.WriteLine("orig: " + msg.ToString()); System.Diagnostics.Debug.WriteLine("new: " + newMessage.ToString()); System.Diagnostics.Debug.WriteLine("orig: " + msg.ToXML()); System.Diagnostics.Debug.WriteLine("new: " + newMessage.ToXML()); System.Diagnostics.Debug.WriteLine("round trip failed"); } } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.ToString()); } } public override void onMessage(QuickFix42.NewOrderSingle message, SessionID session) { System.Diagnostics.Debug.WriteLine("New Order Single"); } Output: New Order Single A first chance exception of type 'QuickFix.UnsupportedMessageType' occurred in quickfix_net_messages.dll QuickFix.UnsupportedMessageType: Exception of type 'QuickFix.UnsupportedMessageType' was thrown. at QuickFix42.MessageCracker.onMessage(Message message, SessionID session) at QuickFix42.MessageCracker.crack(Message message, SessionID sessionID) at FIXServer.FIXServerApp.fromApp(Message msg, SessionID sessionID) in C:\Dev\Abaraff\FIXServer\FIXServer\FIXServerApp.cs:line 244 True orig: 8=FIX.4.29=18035=D34=249=SCT152=20110520-14:38:23.52356=SCTC11=SCT20110520-103823_0000818=121=138=20040=154=155=IBM58=SCT20110520-103823_0000859=060=20110520-10:38:23100=DB-SMART10=239 new: 8=FIX.4.29=18035=D34=249=SCT152=20110520-14:38:23.52356=SCTC11=SCT20110520-103823_0000818=121=138=20040=154=155=IBM58=SCT20110520-103823_0000859=060=20110520-10:38:23100=DB-SMART10=239 orig: <message> <header> <field number="8"><![CDATA[FIX.4.2]]></field> <field number="9"><![CDATA[180]]></field> <field number="35"><![CDATA[D]]></field> <field number="34"><![CDATA[2]]></field> <field number="49"><![CDATA[SCT1]]></field> <field number="52"><![CDATA[20110520-14:38:23.523]]></field> <field number="56"><![CDATA[SCTC]]></field> </header> <body> <field number="11"><![CDATA[SCT20110520-103823_00008]]></field> <field number="18"><![CDATA[1]]></field> <field number="21"><![CDATA[1]]></field> <field number="38"><![CDATA[200]]></field> <field number="40"><![CDATA[1]]></field> <field number="54"><![CDATA[1]]></field> <field number="55"><![CDATA[IBM]]></field> <field number="58"><![CDATA[SCT20110520-103823_00008]]></field> <field number="59"><![CDATA[0]]></field> <field number="60"><![CDATA[20110520-10:38:23]]></field> <field number="100"><![CDATA[DB-SMART]]></field> </body> <trailer> <field number="10"><![CDATA[239]]></field> </trailer> </message> new: <message> <header> <field number="8"><![CDATA[FIX.4.2]]></field> <field number="9"><![CDATA[180]]></field> <field number="35"><![CDATA[D]]></field> <field number="34"><![CDATA[2]]></field> <field number="49"><![CDATA[SCT1]]></field> <field number="52"><![CDATA[20110520-14:38:23.523]]></field> <field number="56"><![CDATA[SCTC]]></field> </header> <body> <field number="11"><![CDATA[SCT20110520-103823_00008]]></field> <field number="18"><![CDATA[1]]></field> <field number="21"><![CDATA[1]]></field> <field number="38"><![CDATA[200]]></field> <field number="40"><![CDATA[1]]></field> <field number="54"><![CDATA[1]]></field> <field number="55"><![CDATA[IBM]]></field> <field number="58"><![CDATA[SCT20110520-103823_00008]]></field> <field number="59"><![CDATA[0]]></field> <field number="60"><![CDATA[20110520-10:38:23]]></field> <field number="100"><![CDATA[DB-SMART]]></field> </body> <trailer> <field number="10"><![CDATA[239]]></field> </trailer> </message> round trip failed -- View this message in context: http://old.nabble.com/Message-with-contents-set-through-Message.setString%28string%29-can%27t-be-cracked-in-.Net-tp31664717p31664717.html Sent from the QuickFIX - User mailing list archive at Nabble.com. |
From: abaraff <ab...@ra...> - 2011-05-25 11:52:06
|
So I ripped off a bit of the code from the Java version of Quickfix. It's not the prettiest port--I was just trying to get it functional. It does produce correctly typed messages from strings however. I'd love to have someone post a cleaner alternative, but here is the MessageUtils class that I ported over. The parse() methods return messages that can be cracked and are correctly typed: using System; using System.Collections.Generic; using System.Text; namespace QuickFix { public class MessageUtils { private const char FIELD_SEPARATOR = '\x0001'; public const string BEGINSTRING_FIX40 = "FIX.4.0"; public const string BEGINSTRING_FIX41 = "FIX.4.1"; public const string BEGINSTRING_FIX42 = "FIX.4.2"; public const string BEGINSTRING_FIX43 = "FIX.4.3"; public const string BEGINSTRING_FIX44 = "FIX.4.4"; /** * FIX 5.0 does not have a begin string. */ public const string FIX50 = "FIX.5.0"; // FIXT.x.x support public const string FIXT_SESSION_PREFIX = "FIXT."; public const string BEGINSTRING_FIXT11 = FIXT_SESSION_PREFIX + "1.1"; private static Dictionary<string, ApplVerID> BeginStringToApplVerID = new Dictionary<String, ApplVerID>(); static MessageUtils() { // No support for earlier versions of FIX BeginStringToApplVerID.Add(BEGINSTRING_FIX40, new ApplVerID(ApplVerID.FIX40)); BeginStringToApplVerID.Add(BEGINSTRING_FIX41, new ApplVerID(ApplVerID.FIX41)); BeginStringToApplVerID.Add(BEGINSTRING_FIX42, new ApplVerID(ApplVerID.FIX42)); BeginStringToApplVerID.Add(BEGINSTRING_FIX43, new ApplVerID(ApplVerID.FIX43)); BeginStringToApplVerID.Add(BEGINSTRING_FIX44, new ApplVerID(ApplVerID.FIX44)); BeginStringToApplVerID.Add(FIX50, new ApplVerID(ApplVerID.FIX50)); } private static ApplVerID GetApplVerID(Session session, string messageString) { ApplVerID applVerID = null; string applVerIdString = GetStringField(messageString, ApplVerID.FIELD); if (applVerIdString != null) { applVerID = new ApplVerID(applVerIdString); } /* GetTargetDefaultApplicationVersionID doesn't exist in the .Net version if (applVerID == null) { applVerID = session.GetTargetDefaultApplicationVersionID(); }*/ if (applVerID == null && IsLogon(messageString)) { string defaultApplVerIdString = GetStringField(messageString, DefaultApplVerID.FIELD); if (defaultApplVerIdString != null) { applVerID = new ApplVerID(defaultApplVerIdString); } } if (applVerID == null) { throw new InvalidMessage("Can't determine ApplVerID for message"); } return applVerID; } public static string GetMessageType(String messageString) { string value = GetStringField(messageString, 35); if (value == null) { throw new InvalidMessage("Missing or garbled message type in " + messageString); } return value; } public static string GetStringField(String messageString, int tag) { string value = null; string tagString = tag.ToString(); int start = messageString.IndexOf(tagString, 0); while (start != -1 && value == null) { if ((start == 0 || messageString[start - 1] == FIELD_SEPARATOR)) { int end = start + tagString.Length; if ((end + 1) < messageString.Length && messageString[end] == '=') { // found tag, get value start = end = (end + 1); for (; end < messageString.Length && messageString[end] != FIELD_SEPARATOR; end++) { ; } if (end == messageString.Length) { return null; } else { value = messageString.Substring(start, end - start); } } } start = messageString.IndexOf(tagString, start + 1); } return value; } public static bool IsAdminMessage(string msgType) { return msgType.Length == 1 && "0A12345h".IndexOf(msgType) != -1; } public static bool IsLogon(string message) { return IsMessageType(message, MsgType.Logon); } private static bool IsMessageType(string message, string msgType) { try { return msgType == GetMessageType(message); } catch (InvalidMessage e) { return false; } } /** * Utility method for parsing a mesasge. This should only be used for parsing messages from * FIX versions 4.4 or earlier. * * @param messageFactory * @param dataDictionary * @param messageString * @return the parsed message * @throws InvalidMessage */ public static Message parse(MessageFactory messageFactory, DataDictionary dataDictionary, string messageString) { int index = messageString.IndexOf(FIELD_SEPARATOR); if (index < 0) { throw new InvalidMessage("Message does not contain any field separator"); } string beginString = messageString.Substring(2, index - 2); string messageType = GetMessageType(messageString); Message message = messageFactory.create(beginString, messageType); message.setString(messageString, dataDictionary != null, dataDictionary); return message; } /** * NOTE: This method is intended for internal use. * * @param session - the Session that will process the message * @param messageString * @return the parsed message * @throws InvalidMessage */ public static Message parse(Session session, string messageString, MessageFactory messageFactory) { BeginString beginString = new BeginString(GetStringField(messageString, BeginString.FIELD)); string msgType = GetMessageType(messageString); ApplVerID applVerID = null; //String customApplVerID = null; if (BEGINSTRING_FIXT11 == beginString.getValue()) { applVerID = GetApplVerID(session, messageString); //customApplVerID = GetStringField(messageString, CstmApplVerID.FIELD); } else { applVerID = ToApplVerID(beginString.getValue()); } //MessageFactory messageFactory = session.getMessageFactory(); DataDictionaryProvider ddProvider = session.getDataDictionaryProvider(); DataDictionary sessionDataDictionary = ddProvider == null ? null : ddProvider.getSessionDataDictionary(beginString); DataDictionary applicationDataDictionary = ddProvider == null ? null : ddProvider.getApplicationDataDictionary(applVerID); Message message = messageFactory.create(beginString.getValue(), msgType); //DataDictionary payloadDictionary = MessageUtils.IsAdminMessage(msgType) ? sessionDataDictionary : applicationDataDictionary; message.setString(messageString, sessionDataDictionary != null, sessionDataDictionary);//Closest .net version //message.parse(messageString, sessionDataDictionary, payloadDictionary, payloadDictionary != null); return message; } /** * Convert a begin string to an ApplVerID * @param beginString * @return the ApplVerID for the specified begin string. * @throws QFJException if conversion fails. * @see FixVersions */ public static ApplVerID ToApplVerID(string beginString) { ApplVerID applVerID = BeginStringToApplVerID[beginString]; if (applVerID == null) { throw new Exception("Can't convert to ApplVerID: " + beginString); } return applVerID; } } } abaraff wrote: > > If a message is cloned using the .setString(string) method, calling crack > on it fails. As you can see from my example below, crack is successful on > the original message but throws an exception when called on the clone: > > public void fromApp(Message msg, SessionID sessionID) > { > try > { > > string message = msg.ToString(); > > Message newMessage = new Message(); > newMessage.setString(msg.ToString(), true); > > crack(msg, sessionID); > try > { > crack(newMessage, sessionID); > } > catch (Exception e2) > { > System.Diagnostics.Debug.WriteLine(e2.ToString()); > System.Diagnostics.Debug.WriteLine(msg.ToString() == > newMessage.ToString()); > System.Diagnostics.Debug.WriteLine("orig: " + > msg.ToString()); > System.Diagnostics.Debug.WriteLine("new: " + > newMessage.ToString()); > System.Diagnostics.Debug.WriteLine("orig: " + > msg.ToXML()); > System.Diagnostics.Debug.WriteLine("new: " + > newMessage.ToXML()); > System.Diagnostics.Debug.WriteLine("round trip > failed"); > } > } > catch (Exception e) > { > System.Diagnostics.Debug.WriteLine(e.ToString()); > } > } > > public override void onMessage(QuickFix42.NewOrderSingle message, > SessionID session) > { > System.Diagnostics.Debug.WriteLine("New Order Single"); > } > > Output: > New Order Single > A first chance exception of type 'QuickFix.UnsupportedMessageType' > occurred in quickfix_net_messages.dll > QuickFix.UnsupportedMessageType: Exception of type > 'QuickFix.UnsupportedMessageType' was thrown. > at QuickFix42.MessageCracker.onMessage(Message message, SessionID > session) > at QuickFix42.MessageCracker.crack(Message message, SessionID > sessionID) > at FIXServer.FIXServerApp.fromApp(Message msg, SessionID sessionID) in > C:\Dev\Abaraff\FIXServer\FIXServer\FIXServerApp.cs:line 244 > True > orig: > 8=FIX.4.29=18035=D34=249=SCT152=20110520-14:38:23.52356=SCTC11=SCT20110520-103823_0000818=121=138=20040=154=155=IBM58=SCT20110520-103823_0000859=060=20110520-10:38:23100=DB-SMART10=239 > new: > 8=FIX.4.29=18035=D34=249=SCT152=20110520-14:38:23.52356=SCTC11=SCT20110520-103823_0000818=121=138=20040=154=155=IBM58=SCT20110520-103823_0000859=060=20110520-10:38:23100=DB-SMART10=239 > orig: <message> > <header> > <field number="8"><![CDATA[FIX.4.2]]></field> > <field number="9"><![CDATA[180]]></field> > <field number="35"><![CDATA[D]]></field> > <field number="34"><![CDATA[2]]></field> > <field number="49"><![CDATA[SCT1]]></field> > <field number="52"><![CDATA[20110520-14:38:23.523]]></field> > <field number="56"><![CDATA[SCTC]]></field> > </header> > <body> > <field number="11"><![CDATA[SCT20110520-103823_00008]]></field> > <field number="18"><![CDATA[1]]></field> > <field number="21"><![CDATA[1]]></field> > <field number="38"><![CDATA[200]]></field> > <field number="40"><![CDATA[1]]></field> > <field number="54"><![CDATA[1]]></field> > <field number="55"><![CDATA[IBM]]></field> > <field number="58"><![CDATA[SCT20110520-103823_00008]]></field> > <field number="59"><![CDATA[0]]></field> > <field number="60"><![CDATA[20110520-10:38:23]]></field> > <field number="100"><![CDATA[DB-SMART]]></field> > </body> > <trailer> > <field number="10"><![CDATA[239]]></field> > </trailer> > </message> > new: <message> > <header> > <field number="8"><![CDATA[FIX.4.2]]></field> > <field number="9"><![CDATA[180]]></field> > <field number="35"><![CDATA[D]]></field> > <field number="34"><![CDATA[2]]></field> > <field number="49"><![CDATA[SCT1]]></field> > <field number="52"><![CDATA[20110520-14:38:23.523]]></field> > <field number="56"><![CDATA[SCTC]]></field> > </header> > <body> > <field number="11"><![CDATA[SCT20110520-103823_00008]]></field> > <field number="18"><![CDATA[1]]></field> > <field number="21"><![CDATA[1]]></field> > <field number="38"><![CDATA[200]]></field> > <field number="40"><![CDATA[1]]></field> > <field number="54"><![CDATA[1]]></field> > <field number="55"><![CDATA[IBM]]></field> > <field number="58"><![CDATA[SCT20110520-103823_00008]]></field> > <field number="59"><![CDATA[0]]></field> > <field number="60"><![CDATA[20110520-10:38:23]]></field> > <field number="100"><![CDATA[DB-SMART]]></field> > </body> > <trailer> > <field number="10"><![CDATA[239]]></field> > </trailer> > </message> > round trip failed > -- View this message in context: http://old.nabble.com/Message-with-contents-set-through-Message.setString%28string%29-can%27t-be-cracked-in-.Net-tp31664717p31698166.html Sent from the QuickFIX - User mailing list archive at Nabble.com. |