Skip to content

Commit b5d11e6

Browse files
authored
Merge pull request #166 from cloudstruct/feat/protocol-state-transition-timeout
feat: support for timeouts on protocol state transitions
2 parents b60a0cd + f597d9e commit b5d11e6

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

protocol/handshake/handshake.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package handshake
22

33
import (
4+
"time"
5+
46
"github.com/cloudstruct/go-ouroboros-network/protocol"
57
)
68

@@ -29,7 +31,8 @@ var StateMap = protocol.StateMap{
2931
},
3032
},
3133
STATE_CONFIRM: protocol.StateMapEntry{
32-
Agency: protocol.AGENCY_SERVER,
34+
Agency: protocol.AGENCY_SERVER,
35+
Timeout: 5 * time.Second,
3336
Transitions: []protocol.StateTransition{
3437
{
3538
MsgType: MESSAGE_TYPE_ACCEPT_VERSION,

protocol/protocol.go

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package protocol
33
import (
44
"bytes"
55
"fmt"
6-
"github.com/cloudstruct/go-ouroboros-network/muxer"
7-
"github.com/cloudstruct/go-ouroboros-network/utils"
8-
"github.com/fxamacker/cbor/v2"
96
"io"
107
"reflect"
118
"sync"
9+
"time"
10+
11+
"github.com/cloudstruct/go-ouroboros-network/muxer"
12+
"github.com/cloudstruct/go-ouroboros-network/utils"
13+
"github.com/fxamacker/cbor/v2"
1214
)
1315

1416
const (
@@ -17,17 +19,18 @@ const (
1719
)
1820

1921
type Protocol struct {
20-
config ProtocolConfig
21-
muxerSendChan chan *muxer.Segment
22-
muxerRecvChan chan *muxer.Segment
23-
state State
24-
stateMutex sync.Mutex
25-
recvBuffer *bytes.Buffer
26-
sendQueueChan chan Message
27-
sendStateQueueChan chan Message
28-
recvReadyChan chan bool
29-
sendReadyChan chan bool
30-
doneChan chan bool
22+
config ProtocolConfig
23+
muxerSendChan chan *muxer.Segment
24+
muxerRecvChan chan *muxer.Segment
25+
state State
26+
stateMutex sync.Mutex
27+
recvBuffer *bytes.Buffer
28+
sendQueueChan chan Message
29+
sendStateQueueChan chan Message
30+
recvReadyChan chan bool
31+
sendReadyChan chan bool
32+
doneChan chan bool
33+
stateTransitionTimer *time.Timer
3134
}
3235

3336
type ProtocolConfig struct {
@@ -316,6 +319,13 @@ func (p *Protocol) getNewState(msg Message) (State, error) {
316319
}
317320

318321
func (p *Protocol) setState(state State) {
322+
// Disable any previous state transition timer
323+
if p.stateTransitionTimer != nil {
324+
if !p.stateTransitionTimer.Stop() {
325+
<-p.stateTransitionTimer.C
326+
}
327+
p.stateTransitionTimer = nil
328+
}
319329
// Set the new state
320330
p.state = state
321331
// Mark protocol as ready to send/receive based on role and agency of the new state
@@ -335,6 +345,15 @@ func (p *Protocol) setState(state State) {
335345
p.recvReadyChan <- true
336346
}
337347
}
348+
// Set timeout for state transition
349+
if p.config.StateMap[p.state].Timeout > 0 {
350+
p.stateTransitionTimer = time.AfterFunc(
351+
p.config.StateMap[p.state].Timeout,
352+
func() {
353+
p.SendError(fmt.Errorf("%s: timeout waiting on transition from protocol state %s", p.config.Name, p.state))
354+
},
355+
)
356+
}
338357
}
339358

340359
func (p *Protocol) handleMessage(msg Message, isResponse bool) error {

protocol/state.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package protocol
22

3+
import (
4+
"time"
5+
)
6+
37
const (
48
AGENCY_NONE uint = 0
59
AGENCY_CLIENT uint = 1
@@ -33,6 +37,7 @@ type StateTransitionMatchFunc func(Message) bool
3337
type StateMapEntry struct {
3438
Agency uint
3539
Transitions []StateTransition
40+
Timeout time.Duration
3641
}
3742

3843
type StateMap map[State]StateMapEntry

0 commit comments

Comments
 (0)