Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ func formatCheckSum(value int) string {

// Build constructs a []byte from a Message instance.
func (m *Message) build() []byte {
m.cook()
m.cook(m.Body.length(), m.Body.total())

var b bytes.Buffer
m.Header.write(&b)
Expand All @@ -603,7 +603,7 @@ func (m *Message) build() []byte {
// This func lets us pull the Message from the Store, parse it, update the Header, and then build it back into bytes using the original Body.
// Note: The only standard non-Body group is NoHops. If that is used in the Header, this workaround may fail.
func (m *Message) buildWithBodyBytes(bodyBytes []byte) []byte {
m.cook()
m.cook(len(bodyBytes), bytesTotal(bodyBytes))

var b bytes.Buffer
m.Header.write(&b)
Expand All @@ -612,9 +612,9 @@ func (m *Message) buildWithBodyBytes(bodyBytes []byte) []byte {
return b.Bytes()
}

func (m *Message) cook() {
bodyLength := m.Header.length() + m.Body.length() + m.Trailer.length()
func (m *Message) cook(bodyLen, bodyTotal int) {
bodyLength := m.Header.length() + bodyLen + m.Trailer.length()
m.Header.SetInt(tagBodyLength, bodyLength)
checkSum := (m.Header.total() + m.Body.total() + m.Trailer.total()) % 256
checkSum := (m.Header.total() + bodyTotal + m.Trailer.total()) % 256
m.Trailer.SetString(tagCheckSum, formatCheckSum(checkSum))
}
30 changes: 30 additions & 0 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,36 @@ func (s *MessageSuite) TestReBuildWithRepeatingGroupForResend() {
s.True(bytes.Equal(expectedBytes, resendBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedBytes, resendBytes)
}

func (s *MessageSuite) TestReBuildWithRepeatingGroupMultipleEntriesInGroupForResend() {
// Given the following message with a repeating group that has 2 entries
origHeader := "8=FIXT.1.19=18435=834=349=ISLD52=20240415-03:43:17.92356=TW"
origBody := "6=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=2448=xyzzy447=D452=1448=foobar447=D452=3"
origTrailer := "10=152"
rawMsg := bytes.NewBufferString(origHeader + origBody + origTrailer)

// When I reparse the message from the store during a resend request
s.Nil(ParseMessage(s.msg, rawMsg))

// And I update the headers for resend
s.msg.Header.SetField(tagOrigSendingTime, FIXString("20240415-03:43:17.923"))
s.msg.Header.SetField(tagSendingTime, FIXString("20240415-14:41:23.456"))
s.msg.Header.SetField(tagPossDupFlag, FIXBoolean(true))

// The bodyBytes will still be correct
origBodyBytes := []byte(origBody)
s.True(bytes.Equal(origBodyBytes, s.msg.bodyBytes), "Incorrect body bytes, \n expected: %s\n but was: %s", origBodyBytes, s.msg.bodyBytes)

// So when I combine the updated header + the original bodyBytes + the as-is trailer
resendBytes := s.msg.buildWithBodyBytes(origBodyBytes)

// Then the reparsed, rebuilt message will retain the correct ordering of repeating group tags during resend
expectedResendHeader := "8=FIXT.1.19=21535=834=343=Y49=ISLD52=20240415-14:41:23.45656=TW122=20240415-03:43:17.923"
expectedResendBody := "6=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=2448=xyzzy447=D452=1448=foobar447=D452=3"
expectedResendTrailer := "10=147"
expectedResendBytes := []byte(expectedResendHeader + expectedResendBody + expectedResendTrailer)
s.True(bytes.Equal(expectedResendBytes, resendBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedResendBytes, resendBytes)
}

func (s *MessageSuite) TestReverseRoute() {
s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.29=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123")))

Expand Down
11 changes: 6 additions & 5 deletions tag_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ func (tv TagValue) String() string {
return string(tv.bytes)
}

func (tv TagValue) total() int {
total := 0

for _, b := range []byte(tv.bytes) {
func bytesTotal(bytes []byte) (total int) {
for _, b := range bytes {
total += int(b)
}
return
}

return total
func (tv TagValue) total() int {
return bytesTotal(tv.bytes)
}

func (tv TagValue) length() int {
Expand Down
1 change: 1 addition & 0 deletions tag_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ func TestTagValue_total(t *testing.T) {
var tv TagValue
require.Nil(t, tv.parse([]byte(stringField)))
assert.Equal(t, 643, tv.total(), "Total is the summation of the ascii byte values of the field string")
assert.Equal(t, 643, bytesTotal([]byte(stringField)))
}
Loading