From 9628840efc2bcc0735f0d5b1b8d07569d2a1b369 Mon Sep 17 00:00:00 2001 From: Chris Busbey Date: Sun, 26 Feb 2017 14:24:44 -0600 Subject: [PATCH] use data dictionary for parsing fix messages --- in_session.go | 2 +- message.go | 42 ++++++++++++++++++++++++++++++++++++++++-- message_test.go | 23 ++++++++++++++++++++++- session.go | 3 +++ session_factory.go | 12 +++++------- session_state.go | 2 +- 6 files changed, 72 insertions(+), 12 deletions(-) diff --git a/in_session.go b/in_session.go index 8750d50a0..fe71b6d56 100644 --- a/in_session.go +++ b/in_session.go @@ -213,7 +213,7 @@ func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int nextSeqNum := seqNum msg := NewMessage() for _, msgBytes := range msgs { - _ = ParseMessage(msg, bytes.NewBuffer(msgBytes)) + _ = ParseMessageWithDataDictionary(msg, bytes.NewBuffer(msgBytes), session.transportDataDictionary, session.appDataDictionary) msgType, _ := msg.Header.GetBytes(tagMsgType) sentMessageSeqNum, _ := msg.Header.GetInt(tagMsgSeqNum) diff --git a/message.go b/message.go index 7846adf1a..767e47cc3 100644 --- a/message.go +++ b/message.go @@ -6,6 +6,7 @@ import ( "math" "time" + "github.com/quickfixgo/quickfix/datadictionary" "github.com/quickfixgo/quickfix/enum" ) @@ -116,6 +117,16 @@ func NewMessage() *Message { //ParseMessage constructs a Message from a byte slice wrapping a FIX message. func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) { + return ParseMessageWithDataDictionary(msg, rawMessage, nil, nil) +} + +//ParseMessageWithDataDictionary constructs a Message from a byte slice wrapping a FIX message using an optional session and application DataDictionary for reference. +func ParseMessageWithDataDictionary( + msg *Message, + rawMessage *bytes.Buffer, + transportDataDictionary *datadictionary.DataDictionary, + applicationDataDictionary *datadictionary.DataDictionary, +) (err error) { msg.Header.Clear() msg.Body.Clear() msg.Trailer.Clear() @@ -173,9 +184,9 @@ func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) { } switch { - case parsedFieldBytes.tag.IsHeader(): + case isHeaderField(parsedFieldBytes.tag, transportDataDictionary): msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) - case parsedFieldBytes.tag.IsTrailer(): + case isTrailerField(parsedFieldBytes.tag, transportDataDictionary): msg.Trailer.add(msg.fields[fieldIndex : fieldIndex+1]) default: foundBody = true @@ -215,6 +226,33 @@ func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) { } return + +} + +func isHeaderField(tag Tag, dataDict *datadictionary.DataDictionary) bool { + if tag.IsHeader() { + return true + } + + if dataDict == nil { + return false + } + + _, ok := dataDict.Header.Fields[int(tag)] + return ok +} + +func isTrailerField(tag Tag, dataDict *datadictionary.DataDictionary) bool { + if tag.IsTrailer() { + return true + } + + if dataDict == nil { + return false + } + + _, ok := dataDict.Trailer.Fields[int(tag)] + return ok } // MsgType returns MsgType (tag 35) field's value diff --git a/message_test.go b/message_test.go index fecd37f43..e2d2e1470 100644 --- a/message_test.go +++ b/message_test.go @@ -4,6 +4,7 @@ import ( "bytes" "testing" + "github.com/quickfixgo/quickfix/datadictionary" "github.com/quickfixgo/quickfix/enum" "github.com/stretchr/testify/suite" ) @@ -18,7 +19,7 @@ func BenchmarkParseMessage(b *testing.B) { } type MessageSuite struct { - suite.Suite + QuickFIXSuite msg *Message } @@ -53,6 +54,26 @@ func (s *MessageSuite) TestParseMessage() { s.False(s.msg.IsMsgTypeOf(enum.MsgType_LOGON)) } +func (s *MessageSuite) TestParseMessageWithDataDictionary() { + dict := new(datadictionary.DataDictionary) + dict.Header = &datadictionary.MessageDef{ + Fields: map[int]*datadictionary.FieldDef{ + 10030: nil, + }, + } + dict.Trailer = &datadictionary.MessageDef{ + Fields: map[int]*datadictionary.FieldDef{ + 5050: nil, + }, + } + rawMsg := bytes.NewBufferString("8=FIX.4.29=12635=D34=249=TW52=20140515-19:49:56.65956=ISLD10030=CUST11=10021=140=154=155=TSLA60=00010101-00:00:00.0005050=HELLO10=039") + + err := ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict) + s.Nil(err) + s.FieldEquals(Tag(10030), "CUST", s.msg.Header) + s.FieldEquals(Tag(5050), "HELLO", s.msg.Trailer) +} + func (s *MessageSuite) TestParseOutOfOrder() { //allow fields out of order, save for validation rawMsg := bytes.NewBufferString("8=FIX.4.09=8135=D11=id21=338=10040=154=155=MSFT34=249=TW52=20140521-22:07:0956=ISLD10=250") diff --git a/session.go b/session.go index 2be5d3997..21868832d 100644 --- a/session.go +++ b/session.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/quickfixgo/quickfix/datadictionary" "github.com/quickfixgo/quickfix/enum" "github.com/quickfixgo/quickfix/internal" ) @@ -40,6 +41,8 @@ type session struct { admin chan interface{} internal.SessionSettings + transportDataDictionary *datadictionary.DataDictionary + appDataDictionary *datadictionary.DataDictionary messagePool } diff --git a/session_factory.go b/session_factory.go index ea7859313..1947acae8 100644 --- a/session_factory.go +++ b/session_factory.go @@ -97,16 +97,15 @@ func (f sessionFactory) newSession( return } - var transportDataDictionary, appDataDictionary *datadictionary.DataDictionary - if transportDataDictionary, err = datadictionary.Parse(transportDataDictionaryPath); err != nil { + if s.transportDataDictionary, err = datadictionary.Parse(transportDataDictionaryPath); err != nil { return } - if appDataDictionary, err = datadictionary.Parse(appDataDictionaryPath); err != nil { + if s.appDataDictionary, err = datadictionary.Parse(appDataDictionaryPath); err != nil { return } - s.validator = &fixtValidator{transportDataDictionary, appDataDictionary, validatorSettings} + s.validator = &fixtValidator{s.transportDataDictionary, s.appDataDictionary, validatorSettings} } } else if settings.HasSetting(config.DataDictionary) { var dataDictionaryPath string @@ -114,12 +113,11 @@ func (f sessionFactory) newSession( return } - var dataDictionary *datadictionary.DataDictionary - if dataDictionary, err = datadictionary.Parse(dataDictionaryPath); err != nil { + if s.appDataDictionary, err = datadictionary.Parse(dataDictionaryPath); err != nil { return } - s.validator = &fixValidator{dataDictionary, validatorSettings} + s.validator = &fixValidator{s.appDataDictionary, validatorSettings} } if settings.HasSetting(config.ResetOnLogon) { diff --git a/session_state.go b/session_state.go index 92c30bd68..0d8263fe3 100644 --- a/session_state.go +++ b/session_state.go @@ -70,7 +70,7 @@ func (sm *stateMachine) Incoming(session *session, m fixIn) { session.log.OnIncoming(m.bytes.Bytes()) msg := session.messagePool.Get() - if err := ParseMessage(msg, m.bytes); err != nil { + if err := ParseMessageWithDataDictionary(msg, m.bytes, session.transportDataDictionary, session.appDataDictionary); err != nil { session.log.OnEventf("Msg Parse Error: %v, %q", err.Error(), m.bytes) } else { msg.ReceiveTime = m.receiveTime