75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
// Copyright 2023 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
package peer
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
pb "github.com/signalapp/svr2/proto"
|
|
)
|
|
|
|
type sequenceNumber struct {
|
|
epoch uint32
|
|
seq uint64
|
|
}
|
|
|
|
// follows returns true if this seqeunce number directly follows the provided sequence number.
|
|
// This is the case if either it's the next in the sequence, or it is from a greater epoch.
|
|
func (s sequenceNumber) follows(pred sequenceNumber) bool {
|
|
return (s.epoch > pred.epoch && s.seq == 0) || (s.epoch == pred.epoch && s.seq == pred.seq+1)
|
|
}
|
|
|
|
// next returns the sequenceNumber of the next message within an enclave peer session
|
|
func (s sequenceNumber) next() sequenceNumber {
|
|
return sequenceNumber{
|
|
epoch: s.epoch,
|
|
seq: s.seq + 1,
|
|
}
|
|
}
|
|
|
|
// nextEpoch returns the sequenceNumber of the next epoch, typically denoting the start of a new
|
|
// enclave peer session
|
|
func (s sequenceNumber) nextEpoch() sequenceNumber {
|
|
return sequenceNumber{
|
|
epoch: s.epoch + 1,
|
|
seq: 0,
|
|
}
|
|
}
|
|
|
|
// cmp compares two sequence numbers
|
|
//
|
|
// returns:
|
|
//
|
|
// < 0 if this is less than the provided sequenceNumber
|
|
// == 0 if this is equal to the provided sequenceNumber
|
|
// > 0 if this is greater than the provided sequenceNumber
|
|
func (s sequenceNumber) cmp(o sequenceNumber) int {
|
|
if ecmp := int(int32(s.epoch - o.epoch)); ecmp != 0 {
|
|
return ecmp
|
|
}
|
|
return int(s.seq - o.seq)
|
|
}
|
|
|
|
func (s sequenceNumber) proto() *pb.SequenceNumber {
|
|
return &pb.SequenceNumber{
|
|
Epoch: s.epoch,
|
|
Seq: s.seq,
|
|
}
|
|
}
|
|
|
|
func makeSeqno(p *pb.SequenceNumber) (sequenceNumber, error) {
|
|
if p == nil {
|
|
return sequenceNumber{}, errors.New("expected a sequence number present on message")
|
|
}
|
|
return sequenceNumber{
|
|
epoch: p.Epoch,
|
|
seq: p.Seq,
|
|
}, nil
|
|
}
|
|
|
|
func (s sequenceNumber) String() string {
|
|
return fmt.Sprintf("%v:%v", s.epoch, s.seq)
|
|
}
|