Skip to content

Commit

Permalink
Merge pull request #18 from redjack/error-transition
Browse files Browse the repository at this point in the history
Fix error transition handling
  • Loading branch information
jhelmsen authored Aug 31, 2018
2 parents 6868f5f + 0336fbf commit 590c567
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 19 deletions.
48 changes: 33 additions & 15 deletions fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ type FSM interface {
// Returns true if State() == 'dead'
Dead() bool

// Returns true if FSM entered an error transition.
Errored() bool

// Moves to the next available state.
// Returns ErrNoTransition if there is no state to move to.
Next(ctx context.Context) error
Expand Down Expand Up @@ -91,6 +94,7 @@ type fsm struct {
doc *mar.Document // executing document
host string // bind hostname
party string // "client", "server"
errored bool // entered error transition
fteCache *fte.Cache

conn *BufferedConn // connection to remote peer
Expand Down Expand Up @@ -172,6 +176,7 @@ func (fsm *fsm) Closed() bool {
// Reset resets the state and variable set.
func (fsm *fsm) Reset() {
fsm.state = "start"
fsm.errored = false
fsm.vars = make(map[string]interface{})

for _, fn := range fsm.closeFuncs {
Expand Down Expand Up @@ -226,6 +231,9 @@ func (fsm *fsm) Port() int {
// Dead returns true when the FSM is complete.
func (fsm *fsm) Dead() bool { return fsm.state == "dead" }

// Errored returns true if FSM entered an error transition.
func (fsm *fsm) Errored() bool { return fsm.errored }

// Execute runs the the FSM to completion.
func (fsm *fsm) Execute(ctx context.Context) error {
// If no connection is passed in, create one.
Expand Down Expand Up @@ -289,28 +297,38 @@ func (fsm *fsm) next(eval bool) (nextState string, err error) {
transitions = append(transitions, errorTransitions...)

// Attempt each possible transition.
var transitionErr error
for _, transition := range transitions {
// If there's no action block then move to the next state.
if transition.ActionBlock == "NULL" {
return transition.Destination, nil
// Execute if there is an action block.
if transition.ActionBlock != "NULL" {
// Find all actions for this destination and current party.
blk := fsm.doc.ActionBlock(transition.ActionBlock)
if blk == nil {
return "", fmt.Errorf("fsm.Next(): action block not found: %q", transition.ActionBlock)
}
actions := mar.FilterActionsByParty(blk.Actions, fsm.party)

// Attempt to execute each action.
if eval {
if err := fsm.evalActions(actions); err == ErrRetryTransition {
return "", err
} else if err != nil {
if transitionErr == nil {
transitionErr = err
}
continue
}
}
}

// Find all actions for this destination and current party.
blk := fsm.doc.ActionBlock(transition.ActionBlock)
if blk == nil {
return "", fmt.Errorf("fsm.Next(): action block not found: %q", transition.ActionBlock)
// Mark FSM as errored so we don't continue looping after execution.
if transition.IsErrorTransition {
fsm.errored = true
}
actions := mar.FilterActionsByParty(blk.Actions, fsm.party)

// Attempt to execute each action.
if eval {
if err := fsm.evalActions(actions); err != nil {
return "", err
}
}
return transition.Destination, nil
}
return "", nil
return "", transitionErr
}

// init initializes the PRNG if we now have a instance id.
Expand Down
3 changes: 3 additions & 0 deletions listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ func (l *Listener) execute(fsm FSM, conn net.Conn) {
} else if err != nil {
Logger.Debug("server fsm execution error", zap.Error(err))
return
} else if fsm.Errored() {
Logger.Debug("server fsm has error transition, stopping")
return
}
fsm.Reset()
}
Expand Down
5 changes: 1 addition & 4 deletions plugins/fte/recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/redjack/marionette"
"github.com/redjack/marionette/fte"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -72,9 +71,7 @@ func recv(ctx context.Context, fsm marionette.FSM, args []interface{}, blocking
zap.Int("ciphertext", len(ciphertext)),
zap.Error(err),
)
if err == fte.ErrShortCiphertext {
return nil
} else if err != nil {
if err != nil {
logger().Error("cannot decrypt ciphertext", zap.Error(err))
return err
}
Expand Down

0 comments on commit 590c567

Please sign in to comment.