Skip to content

Commit e9e2c05

Browse files
authored
Merge pull request #713 from hlibman-connamara/resend_request_active
Block messages when a Resend Request is active
2 parents d52789e + 03c38dc commit e9e2c05

File tree

5 files changed

+52
-7
lines changed

5 files changed

+52
-7
lines changed

in_session.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,10 @@ func (state inSession) handleResendRequest(session *session, msg *Message) (next
208208
}
209209

210210
if err := state.resendMessages(session, int(beginSeqNo), endSeqNo, *msg); err != nil {
211+
session.isResendRequestActive = false
211212
return handleStateError(session, err)
212213
}
214+
session.isResendRequestActive = false
213215

214216
if err := session.checkTargetTooLow(msg); err != nil {
215217
return state
@@ -291,7 +293,7 @@ func (state inSession) processReject(session *session, msg *Message, rej Message
291293
nextState = currentState
292294
default:
293295
var err error
294-
if nextState, err = session.doTargetTooHigh(TypedError); err != nil {
296+
if nextState, err = session.doTargetTooHigh(TypedError, true); err != nil {
295297
return handleStateError(session, err)
296298
}
297299
}

in_session_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,26 @@ func (s *InSessionTestSuite) TestFIXMsgInResendRequestDoNotSendApp() {
373373
s.State(inSession{})
374374
}
375375

376+
func (s *InSessionTestSuite) TestIsResendRequestActive() {
377+
s.MockApp.On("FromAdmin").Return(nil)
378+
s.MockApp.On("ToApp").Return(nil)
379+
s.MockApp.On("ToAdmin")
380+
s.sendResendRequest(5, 10, false)
381+
s.True(s.isResendRequestActive)
382+
383+
nos := s.NewOrderSingle()
384+
err := s.session.send(nos)
385+
386+
s.Error(err)
387+
s.EqualError(err, "cannot send message while resend request is active")
388+
s.fixMsgIn(s.session, s.ResendRequest(5))
389+
s.False(s.isResendRequestActive)
390+
391+
err = s.session.send(nos)
392+
393+
s.NoError(err)
394+
}
395+
376396
func (s *InSessionTestSuite) TestFIXMsgInTargetTooLow() {
377397
s.IncrNextTargetMsgSeqNum()
378398

logon_state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (s logonState) FixMsgIn(session *session, msg *Message) (nextState sessionS
4646

4747
case targetTooHigh:
4848
var tooHighErr error
49-
if nextState, tooHighErr = session.doTargetTooHigh(err); tooHighErr != nil {
49+
if nextState, tooHighErr = session.doTargetTooHigh(err, false); tooHighErr != nil {
5050
return shutdownWithReason(session, msg, false, tooHighErr.Error())
5151
}
5252

resend_state.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (s resendState) FixMsgIn(session *session, msg *Message) (nextState session
4848
}
4949

5050
if s.currentResendRangeEnd != 0 && s.currentResendRangeEnd < session.store.NextTargetMsgSeqNum() {
51-
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd)
51+
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd, false)
5252
if err != nil {
5353
return handleStateError(session, err)
5454
}
@@ -64,7 +64,7 @@ func (s resendState) FixMsgIn(session *session, msg *Message) (nextState session
6464
}
6565

6666
if bool(gapFillFlag) && s.currentResendRangeEnd != 0 && s.currentResendRangeEnd == session.store.NextTargetMsgSeqNum() {
67-
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd)
67+
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd, false)
6868
if err != nil {
6969
return handleStateError(session, err)
7070
}

session.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ type session struct {
5252
sentReset bool
5353
stopOnce sync.Once
5454

55+
isResendRequestActive bool
56+
5557
targetDefaultApplVerID string
5658

5759
admin chan interface{}
@@ -295,6 +297,10 @@ func (s *session) notifyMessageOut() {
295297

296298
// send will validate, persist, queue the message. If the session is logged on, send all messages in the queue.
297299
func (s *session) send(msg *Message) error {
300+
if err := s.isResendRequestBlocking(msg); err != nil {
301+
return err
302+
}
303+
298304
return s.sendInReplyTo(msg, nil)
299305
}
300306
func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error {
@@ -316,6 +322,20 @@ func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error {
316322
return nil
317323
}
318324

325+
func (s *session) isResendRequestBlocking(msg *Message) error {
326+
msgType, err := msg.Header.GetBytes(tagMsgType)
327+
if err != nil {
328+
return err
329+
}
330+
331+
if s.isResendRequestActive && !bytes.Equal(msgType, msgTypeResendRequest) {
332+
s.log.OnEvent("Message blocked: resend request in progress")
333+
return errors.New("cannot send message while resend request is active")
334+
}
335+
336+
return nil
337+
}
338+
319339
// dropAndReset will drop the send queue and reset the message store.
320340
func (s *session) dropAndReset() error {
321341
s.sendMutex.Lock()
@@ -443,12 +463,12 @@ func (s *session) sendBytes(msg []byte, blockUntilSent bool) bool {
443463
}
444464
}
445465

446-
func (s *session) doTargetTooHigh(reject targetTooHigh) (nextState resendState, err error) {
466+
func (s *session) doTargetTooHigh(reject targetTooHigh, isReject bool) (nextState resendState, err error) {
447467
s.log.OnEventf("MsgSeqNum too high, expecting %v but received %v", reject.ExpectedTarget, reject.ReceivedTarget)
448-
return s.sendResendRequest(reject.ExpectedTarget, reject.ReceivedTarget-1)
468+
return s.sendResendRequest(reject.ExpectedTarget, reject.ReceivedTarget-1, isReject)
449469
}
450470

451-
func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState, err error) {
471+
func (s *session) sendResendRequest(beginSeq, endSeq int, isReject bool) (nextState resendState, err error) {
452472
nextState.resendRangeEnd = endSeq
453473

454474
resend := NewMessage()
@@ -477,6 +497,9 @@ func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState
477497
return
478498
}
479499
s.log.OnEventf("Sent ResendRequest FROM: %v TO: %v", beginSeq, endSeqNo)
500+
if !isReject {
501+
s.isResendRequestActive = true
502+
}
480503

481504
return
482505
}

0 commit comments

Comments
 (0)