1// Copyright 2017 Vector Creations Ltd
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package types provides the types that are used internally within the roomserver.
16package types
17
18import (
19	"encoding/json"
20	"sort"
21
22	"github.com/matrix-org/gomatrixserverlib"
23	"golang.org/x/crypto/blake2b"
24)
25
26// EventTypeNID is a numeric ID for an event type.
27type EventTypeNID int64
28
29// EventStateKeyNID is a numeric ID for an event state_key.
30type EventStateKeyNID int64
31
32// EventNID is a numeric ID for an event.
33type EventNID int64
34
35// RoomNID is a numeric ID for a room.
36type RoomNID int64
37
38// StateSnapshotNID is a numeric ID for the state at an event.
39type StateSnapshotNID int64
40
41// StateBlockNID is a numeric ID for a block of state data.
42// These blocks of state data are combined to form the actual state.
43type StateBlockNID int64
44
45// EventNIDs is used to sort and dedupe event NIDs.
46type EventNIDs []EventNID
47
48func (a EventNIDs) Len() int           { return len(a) }
49func (a EventNIDs) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
50func (a EventNIDs) Less(i, j int) bool { return a[i] < a[j] }
51
52func (a EventNIDs) Hash() []byte {
53	j, err := json.Marshal(a)
54	if err != nil {
55		return nil
56	}
57	h := blake2b.Sum256(j)
58	return h[:]
59}
60
61// StateBlockNIDs is used to sort and dedupe state block NIDs.
62type StateBlockNIDs []StateBlockNID
63
64func (a StateBlockNIDs) Len() int           { return len(a) }
65func (a StateBlockNIDs) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
66func (a StateBlockNIDs) Less(i, j int) bool { return a[i] < a[j] }
67
68func (a StateBlockNIDs) Hash() []byte {
69	j, err := json.Marshal(a)
70	if err != nil {
71		return nil
72	}
73	h := blake2b.Sum256(j)
74	return h[:]
75}
76
77// A StateKeyTuple is a pair of a numeric event type and a numeric state key.
78// It is used to lookup state entries.
79type StateKeyTuple struct {
80	// The numeric ID for the event type.
81	EventTypeNID EventTypeNID
82	// The numeric ID for the state key.
83	EventStateKeyNID EventStateKeyNID
84}
85
86// LessThan returns true if this state key is less than the other state key.
87// The ordering is arbitrary and is used to implement binary search and to efficiently deduplicate entries.
88func (a StateKeyTuple) LessThan(b StateKeyTuple) bool {
89	if a.EventTypeNID != b.EventTypeNID {
90		return a.EventTypeNID < b.EventTypeNID
91	}
92	return a.EventStateKeyNID < b.EventStateKeyNID
93}
94
95// A StateEntry is an entry in the room state of a matrix room.
96type StateEntry struct {
97	StateKeyTuple
98	// The numeric ID for the event.
99	EventNID EventNID
100}
101
102type StateEntries []StateEntry
103
104func (a StateEntries) Len() int           { return len(a) }
105func (a StateEntries) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
106func (a StateEntries) Less(i, j int) bool { return a[i].EventNID < a[j].EventNID }
107
108// LessThan returns true if this state entry is less than the other state entry.
109// The ordering is arbitrary and is used to implement binary search and to efficiently deduplicate entries.
110func (a StateEntry) LessThan(b StateEntry) bool {
111	if a.StateKeyTuple != b.StateKeyTuple {
112		return a.StateKeyTuple.LessThan(b.StateKeyTuple)
113	}
114	return a.EventNID < b.EventNID
115}
116
117// Deduplicate takes a set of state entries and ensures that there are no
118// duplicate (event type, state key) tuples. If there are then we dedupe
119// them, making sure that the latest/highest NIDs are always chosen.
120func DeduplicateStateEntries(a []StateEntry) []StateEntry {
121	if len(a) < 2 {
122		return a
123	}
124	sort.SliceStable(a, func(i, j int) bool {
125		return a[i].LessThan(a[j])
126	})
127	for i := 0; i < len(a)-1; i++ {
128		if a[i].StateKeyTuple == a[i+1].StateKeyTuple {
129			a = append(a[:i], a[i+1:]...)
130			i--
131		}
132	}
133	return a
134}
135
136// StateAtEvent is the state before and after a matrix event.
137type StateAtEvent struct {
138	// Should this state overwrite the latest events and memberships of the room?
139	// This might be necessary when rejoining a federated room after a period of
140	// absence, as our state and latest events will be out of date.
141	Overwrite bool
142	// The state before the event.
143	BeforeStateSnapshotNID StateSnapshotNID
144	// True if this StateEntry is rejected. State resolution should then treat this
145	// StateEntry as being a message event (not a state event).
146	IsRejected bool
147	// The state entry for the event itself, allows us to calculate the state after the event.
148	StateEntry
149}
150
151// IsStateEvent returns whether the event the state is at is a state event.
152func (s StateAtEvent) IsStateEvent() bool {
153	return s.EventStateKeyNID != 0
154}
155
156// StateAtEventAndReference is StateAtEvent and gomatrixserverlib.EventReference glued together.
157// It is used when looking up the latest events in a room in the database.
158// The gomatrixserverlib.EventReference is used to check whether a new event references the event.
159// The StateAtEvent is used to construct the current state of the room from the latest events.
160type StateAtEventAndReference struct {
161	StateAtEvent
162	gomatrixserverlib.EventReference
163}
164
165// An Event is a gomatrixserverlib.Event with the numeric event ID attached.
166// It is when performing bulk event lookup in the database.
167type Event struct {
168	EventNID EventNID
169	*gomatrixserverlib.Event
170}
171
172const (
173	// MRoomCreateNID is the numeric ID for the "m.room.create" event type.
174	MRoomCreateNID = 1
175	// MRoomPowerLevelsNID is the numeric ID for the "m.room.power_levels" event type.
176	MRoomPowerLevelsNID = 2
177	// MRoomJoinRulesNID is the numeric ID for the "m.room.join_rules" event type.
178	MRoomJoinRulesNID = 3
179	// MRoomThirdPartyInviteNID is the numeric ID for the "m.room.third_party_invite" event type.
180	MRoomThirdPartyInviteNID = 4
181	// MRoomMemberNID is the numeric ID for the "m.room.member" event type.
182	MRoomMemberNID = 5
183	// MRoomRedactionNID is the numeric ID for the "m.room.redaction" event type.
184	MRoomRedactionNID = 6
185	// MRoomHistoryVisibilityNID is the numeric ID for the "m.room.history_visibility" event type.
186	MRoomHistoryVisibilityNID = 7
187)
188
189const (
190	// EmptyStateKeyNID is the numeric ID for the empty state key.
191	EmptyStateKeyNID = 1
192)
193
194// StateBlockNIDList is used to return the result of bulk StateBlockNID lookups from the database.
195type StateBlockNIDList struct {
196	StateSnapshotNID StateSnapshotNID
197	StateBlockNIDs   []StateBlockNID
198}
199
200// StateEntryList is used to return the result of bulk state entry lookups from the database.
201type StateEntryList struct {
202	StateBlockNID StateBlockNID
203	StateEntries  []StateEntry
204}
205
206// A MissingEventError is an error that happened because the roomserver was
207// missing requested events from its database.
208type MissingEventError string
209
210func (e MissingEventError) Error() string { return string(e) }
211
212// RoomInfo contains metadata about a room
213type RoomInfo struct {
214	RoomNID          RoomNID
215	RoomVersion      gomatrixserverlib.RoomVersion
216	StateSnapshotNID StateSnapshotNID
217	IsStub           bool
218}
219