github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/gregor/interface.go (about) 1 package gregor 2 3 import ( 4 "net" 5 "time" 6 7 "github.com/keybase/clockwork" 8 "golang.org/x/net/context" 9 ) 10 11 type InBandMsgType int 12 13 const ( 14 InBandMsgTypeNone InBandMsgType = 0 15 InBandMsgTypeUpdate InBandMsgType = 1 16 InBandMsgTypeSync InBandMsgType = 2 17 ) 18 19 type UID interface { 20 Bytes() []byte 21 String() string 22 } 23 24 type MsgID interface { 25 Bytes() []byte 26 String() string 27 } 28 29 type DeviceID interface { 30 Bytes() []byte 31 String() string 32 } 33 34 type System interface { 35 String() string 36 } 37 38 type Category interface { 39 String() string 40 } 41 42 type Body interface { 43 Bytes() []byte 44 } 45 46 type Metadata interface { 47 UID() UID 48 MsgID() MsgID 49 CTime() time.Time 50 DeviceID() DeviceID 51 InBandMsgType() InBandMsgType 52 } 53 54 type MessageWithMetadata interface { 55 Metadata() Metadata 56 } 57 58 type InBandMessage interface { 59 MessageWithMetadata 60 ToStateUpdateMessage() StateUpdateMessage 61 ToStateSyncMessage() StateSyncMessage 62 Merge(m1 InBandMessage) (InBandMessage, error) 63 } 64 65 type StateUpdateMessage interface { 66 MessageWithMetadata 67 Creation() Item 68 Dismissal() Dismissal 69 } 70 71 type StateSyncMessage interface { 72 MessageWithMetadata 73 } 74 75 type OutOfBandMessage interface { 76 System() System 77 UID() UID 78 Body() Body 79 } 80 81 type TimeOrOffset interface { 82 Time() *time.Time 83 Offset() *time.Duration 84 Before(t time.Time) bool 85 IsZero() bool 86 } 87 88 type Item interface { 89 MessageWithMetadata 90 DTime() TimeOrOffset 91 RemindTimes() []TimeOrOffset 92 Body() Body 93 Category() Category 94 } 95 96 type Reminder interface { 97 Item() Item 98 RemindTime() time.Time 99 Seqno() int 100 } 101 102 type MsgRange interface { 103 EndTime() TimeOrOffset 104 Category() Category 105 SkipMsgIDs() []MsgID 106 } 107 108 type Dismissal interface { 109 MsgIDsToDismiss() []MsgID 110 RangesToDismiss() []MsgRange 111 } 112 113 type State interface { 114 Items() ([]Item, error) 115 GetItem(msgID MsgID) (Item, bool) 116 ItemsInCategory(c Category) ([]Item, error) 117 ItemsWithCategoryPrefix(c Category) ([]Item, error) 118 Marshal() ([]byte, error) 119 Hash() ([]byte, error) 120 Export() (ProtocolState, error) 121 } 122 123 type ProtocolState interface { 124 State 125 ProtocolName() string 126 } 127 128 type Message interface { 129 ToInBandMessage() InBandMessage 130 ToOutOfBandMessage() OutOfBandMessage 131 Marshal() ([]byte, error) 132 } 133 134 type ReminderSet interface { 135 Reminders() []Reminder 136 MoreRemindersReady() bool 137 } 138 139 type ReminderID interface { 140 MsgID() MsgID 141 UID() UID 142 Seqno() int 143 } 144 145 // MessageConsumer consumes state update messages. It's half of 146 // the state machine protocol 147 type MessageConsumer interface { 148 // ConsumeMessage is called on a new incoming message to mutate the state 149 // of the state machine. Of course messages can be "inband" which actually 150 // perform state mutations, or might be "out-of-band" that just use the 151 // Gregor broadcast mechanism to make sure that all clients get the 152 // notification. It returns a version of the message to broadcast to clients. 153 ConsumeMessage(ctx context.Context, m Message) (Message, error) 154 } 155 156 // StateMachine is the central interface of the Gregor system. Various parts of the 157 // server and client infrastructure will implement various parts of this interface, 158 // to ensure that the state machine can be replicated, and that it can be queried. 159 type StateMachine interface { 160 MessageConsumer 161 162 // State returns the state for the user u on device d at time t. 163 // d can be nil, in which case the global state (across all devices) 164 // is returned. If t is nil, then use Now, otherwise, return the state 165 // at the given time. 166 State(ctx context.Context, u UID, d DeviceID, t TimeOrOffset) (State, error) 167 168 // StateByCategoryPrefix returns the IBMs in the given state that match 169 // the given category prefix. It's similar to calling State().ItemsInCategory() 170 // but results in less data transfer. 171 StateByCategoryPrefix(ctx context.Context, u UID, d DeviceID, t TimeOrOffset, cp Category) (State, error) 172 173 // IsEphemeral returns whether the backend storage needs to be saved/restored. 174 IsEphemeral() bool 175 176 // InitState iterates through the given State's Items, setting the 177 // StateMachine's storage. Note: This should only be called to 178 // initialize an ephemeral StateMachine. 179 InitState(s State) error 180 181 // LatestCTime returns the CTime of the newest item for the given user & device. 182 LatestCTime(ctx context.Context, u UID, d DeviceID) *time.Time 183 184 // Clear removes all existing state from the StateMachine. 185 Clear() error 186 187 // InBandMessagesSince returns all messages since the given time 188 // for the user u on device d. If d is nil, then we'll return 189 // all messages across all devices. If d is a device, then we'll 190 // return global messages and per-device messages for that device. 191 InBandMessagesSince(ctx context.Context, u UID, d DeviceID, t time.Time) ([]InBandMessage, error) 192 193 // Reminders returns a slice of non-dismissed items past their RemindTimes. 194 Reminders(ctx context.Context, maxReminders int) (ReminderSet, error) 195 196 // DeleteReminder deletes a reminder so it won't be in the queue any longer. 197 DeleteReminder(ctx context.Context, r ReminderID) error 198 199 // ObjFactory returns the ObjFactory used by this StateMachine. 200 ObjFactory() ObjFactory 201 202 // Clock returns the clockwork.Clock used by this StateMachine. 203 Clock() clockwork.Clock 204 205 // How long we lock access to reminders; after this time, it's open to other 206 // consumers. 207 ReminderLockDuration() time.Duration 208 209 // Local dismissals for the device this state machine runs on 210 LocalDismissals(context.Context, UID) ([]MsgID, error) 211 212 // Set local dismissals on the state machine storage to the given list 213 InitLocalDismissals(context.Context, UID, []MsgID) error 214 215 // Consume a local dismissal in state machine storage 216 ConsumeLocalDismissal(context.Context, UID, MsgID) error 217 218 // Outbox gives all of the pending messages in the outbox 219 Outbox(context.Context, UID) ([]Message, error) 220 RemoveFromOutbox(context.Context, UID, MsgID) error 221 222 // InitOutbox initializes a users outbox with the given messages 223 InitOutbox(context.Context, UID, []Message) error 224 225 // ConsumeOutboxMessage add a message to the outbox 226 ConsumeOutboxMessage(context.Context, UID, Message) error 227 } 228 229 type ObjFactory interface { 230 MakeUID(b []byte) (UID, error) 231 MakeMsgID(b []byte) (MsgID, error) 232 MakeDeviceID(b []byte) (DeviceID, error) 233 MakeBody(b []byte) (Body, error) 234 MakeCategory(s string) (Category, error) 235 MakeItem(u UID, msgid MsgID, deviceid DeviceID, ctime time.Time, c Category, dtime *time.Time, body Body) (Item, error) 236 MakeReminder(i Item, seqno int, t time.Time) (Reminder, error) 237 MakeReminderID(u UID, msgid MsgID, seqno int) (ReminderID, error) 238 MakeDismissalByRange(uid UID, msgid MsgID, devid DeviceID, ctime time.Time, c Category, d time.Time, 239 skipMsgIDs []MsgID) (InBandMessage, error) 240 MakeDismissalByIDs(uid UID, msgid MsgID, devid DeviceID, ctime time.Time, d []MsgID) (InBandMessage, error) 241 MakeStateSyncMessage(uid UID, msgid MsgID, devid DeviceID, ctime time.Time) (InBandMessage, error) 242 MakeState(i []Item) (State, error) 243 MakeStateWithLookupTable(i []Item, table map[string]Item) (State, error) 244 MakeMetadata(uid UID, msgid MsgID, devid DeviceID, ctime time.Time, i InBandMsgType) (Metadata, error) 245 MakeInBandMessageFromItem(i Item) (InBandMessage, error) 246 MakeMessageFromInBandMessage(i InBandMessage) (Message, error) 247 MakeTimeOrOffsetFromTime(t time.Time) (TimeOrOffset, error) 248 MakeTimeOrOffsetFromOffset(d time.Duration) (TimeOrOffset, error) 249 MakeReminderSetFromReminders([]Reminder, bool) (ReminderSet, error) 250 UnmarshalState([]byte) (State, error) 251 UnmarshalMessage([]byte) (Message, error) 252 } 253 254 type MainLoopServer interface { 255 ListenLoop(n net.Listener) error 256 } 257 258 func UIDFromMessage(m Message) UID { 259 ibm := m.ToInBandMessage() 260 if ibm != nil && ibm.Metadata() != nil { 261 return ibm.Metadata().UID() 262 } 263 if oobm := m.ToOutOfBandMessage(); oobm != nil { 264 return oobm.UID() 265 } 266 return nil 267 }