-
Notifications
You must be signed in to change notification settings - Fork 291
/
resend_state.go
95 lines (79 loc) · 2.63 KB
/
resend_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright (c) quickfixengine.org All rights reserved.
//
// This file may be distributed under the terms of the quickfixengine.org
// license as defined by quickfixengine.org and appearing in the file
// LICENSE included in the packaging of this file.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE.
//
// See http://www.quickfixengine.org/LICENSE for licensing information.
//
// Contact ask@quickfixengine.org if any conditions of this licensing
// are not clear to you.
package quickfix
import "github.com/quickfixgo/quickfix/internal"
type resendState struct {
loggedOn
messageStash map[int]*Message
currentResendRangeEnd int
resendRangeEnd int
}
func (s resendState) String() string { return "Resend" }
func (s resendState) Timeout(session *session, event internal.Event) (nextState sessionState) {
nextState = inSession{}.Timeout(session, event)
switch nextState.(type) {
case inSession:
nextState = s
case pendingTimeout:
// Wrap pendingTimeout in resend. prevents us falling back to inSession if recovering
// from pendingTimeout.
nextState = pendingTimeout{s}
}
return
}
func (s resendState) FixMsgIn(session *session, msg *Message) (nextState sessionState) {
nextState = inSession{}.FixMsgIn(session, msg)
if !nextState.IsLoggedOn() {
return
}
if s.currentResendRangeEnd != 0 && s.currentResendRangeEnd < session.store.NextTargetMsgSeqNum() {
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd)
if err != nil {
return handleStateError(session, err)
}
nextResendState.messageStash = s.messageStash
return nextResendState
}
var gapFillFlag FIXBoolean
if msg.Body.Has(tagGapFillFlag) {
if err := msg.Body.GetField(tagGapFillFlag, &gapFillFlag); err != nil {
return handleStateError(session, err)
}
}
if bool(gapFillFlag) && s.currentResendRangeEnd != 0 && s.currentResendRangeEnd == session.store.NextTargetMsgSeqNum() {
nextResendState, err := session.sendResendRequest(session.store.NextTargetMsgSeqNum(), s.resendRangeEnd)
if err != nil {
return handleStateError(session, err)
}
nextResendState.messageStash = s.messageStash
return nextResendState
}
if s.resendRangeEnd >= session.store.NextTargetMsgSeqNum() {
return s
}
for len(s.messageStash) > 0 {
targetSeqNum := session.store.NextTargetMsgSeqNum()
msg, ok := s.messageStash[targetSeqNum]
if !ok {
break
}
delete(s.messageStash, targetSeqNum)
nextState = inSession{}.FixMsgIn(session, msg)
if !nextState.IsLoggedOn() {
return
}
}
return
}