55 "github.com/quickfixgo/quickfix/config"
66 "github.com/quickfixgo/quickfix/datadictionary"
77 "github.com/quickfixgo/quickfix/enum"
8+ "sync"
89 "time"
910)
1011
@@ -16,11 +17,15 @@ type session struct {
1617 sessionID SessionID
1718
1819 messageOut chan []byte
19- toSend chan Message
2020
21- sessionEvent chan event
22- application Application
23- currentState sessionState
21+ //application messages are queued up to be sent during the run loop.
22+ toSend []Message
23+ //mutex for access to toSend
24+ sendMutex sync.Mutex
25+
26+ sessionEvent chan event
27+ application Application
28+ sessionState
2429 stateTimer eventTimer
2530 peerTimer eventTimer
2631 messageStash map [int ]Message
@@ -95,12 +100,10 @@ func createSession(sessionID SessionID, storeFactory MessageStoreFactory, settin
95100 return err
96101 }
97102
98- session .toSend = make (chan Message )
99103 session .sessionEvent = make (chan event )
100104 session .application = application
101105 session .stateTimer = eventTimer {Task : func () { session .sessionEvent <- needHeartbeat }}
102106 session .peerTimer = eventTimer {Task : func () { session .sessionEvent <- peerTimeout }}
103-
104107 application .OnCreate (session .sessionID )
105108 sessions .newSession <- session
106109
@@ -109,7 +112,7 @@ func createSession(sessionID SessionID, storeFactory MessageStoreFactory, settin
109112
110113//kicks off session as an initiator
111114func (s * session ) initiate (msgIn chan fixIn , msgOut chan []byte , quit chan bool ) {
112- s .currentState = logonState {}
115+ s .sessionState = logonState {}
113116 s .messageStash = make (map [int ]Message )
114117 s .initiateLogon = true
115118
@@ -118,7 +121,7 @@ func (s *session) initiate(msgIn chan fixIn, msgOut chan []byte, quit chan bool)
118121
119122//kicks off session as an acceptor
120123func (s * session ) accept (msgIn chan fixIn , msgOut chan []byte , quit chan bool ) {
121- s .currentState = logonState {}
124+ s .sessionState = logonState {}
122125 s .messageStash = make (map [int ]Message )
123126
124127 s .run (msgIn , msgOut , quit )
@@ -161,6 +164,30 @@ func (s *session) resend(msg Message) {
161164 s .sendBytes (msg .rawMessage )
162165}
163166
167+ //queueForSend will queue up a message to be sent by the session during the next iteration of the run loop
168+ func (s * session ) queueForSend (msg Message ) {
169+ s .sendMutex .Lock ()
170+ defer s .sendMutex .Unlock ()
171+ s .toSend = append (s .toSend , msg )
172+ }
173+
174+ //sends queued messages if session is logged on
175+ func (s * session ) sendQueued () {
176+ if ! s .IsLoggedOn () {
177+ return
178+ }
179+
180+ s .sendMutex .Lock ()
181+ defer s .sendMutex .Unlock ()
182+
183+ for _ , msg := range s .toSend {
184+ s .send (msg )
185+ }
186+
187+ s .toSend = s .toSend [:0 ]
188+ }
189+
190+ //send should NOT be called outside of the run loop
164191func (s * session ) send (msg Message ) {
165192 s .fillDefaultHeader (msg )
166193
@@ -183,7 +210,6 @@ func (s *session) send(msg Message) {
183210}
184211
185212func (s * session ) sendBytes (msg []byte ) {
186-
187213 s .log .OnOutgoing (string (msg ))
188214 s .messageOut <- msg
189215 s .stateTimer .Reset (time .Duration (s .heartBeatTimeout ))
@@ -469,13 +495,13 @@ type fixIn struct {
469495
470496func (s * session ) run (msgIn chan fixIn , msgOut chan []byte , quit chan bool ) {
471497 s .messageOut = msgOut
498+
472499 defer func () {
473500 close (s .messageOut )
474501 s .onDisconnect ()
475502 }()
476503
477504 if s .initiateLogon {
478-
479505 if s .resetOnLogon {
480506 s .store .Reset ()
481507 }
@@ -500,11 +526,13 @@ func (s *session) run(msgIn chan fixIn, msgOut chan []byte, quit chan bool) {
500526
501527 for {
502528
503- switch s .currentState .(type ) {
529+ switch s .sessionState .(type ) {
504530 case latentState :
505531 return
506532 }
507533
534+ s .sendQueued ()
535+
508536 select {
509537 case fixIn , ok := <- msgIn :
510538 if ok {
@@ -513,21 +541,18 @@ func (s *session) run(msgIn chan fixIn, msgOut chan []byte, quit chan bool) {
513541 s .log .OnEventf ("Msg Parse Error: %v, %q" , err .Error (), fixIn .bytes )
514542 } else {
515543 msg .ReceiveTime = fixIn .receiveTime
516- s .currentState = s . currentState .FixMsgIn (s , msg )
544+ s .sessionState = s .FixMsgIn (s , msg )
517545 }
518546 } else {
519547 return
520548 }
521549 s .peerTimer .Reset (time .Duration (int64 (1.2 * float64 (s .heartBeatTimeout ))))
522550
523- case msg := <- s .toSend :
524- s .send (msg )
525-
526551 case <- quit :
527552 return
528553
529554 case evt := <- s .sessionEvent :
530- s .currentState = s . currentState .Timeout (s , evt )
555+ s .sessionState = s .Timeout (s , evt )
531556 }
532557 }
533558}
0 commit comments