1 // This file is under GNU General Public License 3.0
4 // DeviceGroup protocol for p≡p
6 // Copyleft (c) 2016, p≡p foundation
8 // Written by Volker Birk
12 protocol DeviceGroup {
13 // all messages have a timestamp, time out and are removed after timeout
16 broadcast sendGroupUpdate;
17 broadcast sendUpdateRequest;
18 unencrypted sendBeacon;
20 fsm DeviceState filename=sync {
21 condition deviceGrouped();
22 condition keyElectionWon(Identity partner);
23 condition sameIdentities(Identity a, Identity b);
24 condition sameKeyAndAddress(Identity a, Identity b);
43 on Beacon(Identity partner){
44 do sendHandshakeRequest(partner);
45 go SoleBeaconed(partner);
47 on HandshakeRequest(Identity partner) {
48 do sendHandshakeRequest(partner);
49 go HandshakingSole(partner);
53 // copy of sole state with a timeout to enable fast polling for a second
54 // TODO use more YSLT power here (substates ?)
55 state SoleWaiting timeout=60 {
62 on Beacon(Identity partner){
63 do sendHandshakeRequest(partner);
64 go SoleBeaconed(partner);
66 on HandshakeRequest(Identity partner) {
67 do sendHandshakeRequest(partner);
68 go HandshakingSole(partner);
73 state SoleBeaconed timeout=600 (Identity expected) {
82 on Beacon(Identity partner) {
83 do sendHandshakeRequest(partner);
84 go SoleBeaconed(partner);
86 on HandshakeRequest(Identity partner) {
87 if sameIdentities(partner, expected) {
88 // do nothing, to avoid sending handshake request twice
90 do sendHandshakeRequest(partner);
92 go HandshakingSole(partner);
97 state HandshakingSole timeout=600 (Identity expected) {
99 if keyElectionWon(expected) {
100 do notifyInitFormGroup(expected);
102 do notifyInitAddOurDevice(expected);
105 on HandshakeRejected(Identity partner) {
106 do rejectHandshake(partner);
109 on HandshakeAccepted(Identity partner) {
110 if sameIdentities(partner, expected) {
111 do acceptHandshake(partner);
112 if keyElectionWon(partner) {
114 do sendGroupKeys(partner);
116 do notifyAcceptedGroupCreated(partner);
119 go WaitForGroupKeysSole(partner);
124 on GroupKeys(Identity partner, GroupKeys groupkeys) {
125 if keyElectionWon(expected) {
126 // not supposed to receive groupkeys - ignore
128 // UUID changes in between, so we can only check for same address and fpr
129 if sameKeyAndAddress(partner, expected) {
130 go WaitForAcceptSole(partner, groupkeys);
135 do notifyTimeout(expected);
141 state WaitForGroupKeysSole timeout=600 (Identity expected) {
142 on GroupKeys(Identity partner, GroupKeys groupkeys) {
143 // UUID changes in between, so we can only check for same address and fpr
144 if sameKeyAndAddress(partner, expected) {
145 do storeGroupKeys(partner, groupkeys);
148 do notifyAcceptedDeviceAdded(partner);
153 do notifyTimeout(expected);
158 state WaitForAcceptSole timeout=600 (Identity expected, GroupKeys groupkeys) {
159 on HandshakeRejected(Identity partner) {
160 do rejectHandshake(partner);
163 on HandshakeAccepted(Identity partner) {
164 // UUID changes in between, so we can only check for same address and fpr
165 if sameKeyAndAddress(partner, expected) {
166 do acceptHandshake(partner);
167 do storeGroupKeys(partner, groupkeys);
170 do notifyAcceptedDeviceAdded(partner);
177 do notifyTimeout(expected);
182 state Grouped end=1 {
186 do sendUpdateRequest;
192 on Beacon(Identity partner){
193 do sendHandshakeRequest(partner);
194 go GroupedBeaconed(partner);
196 on HandshakeRequest(Identity partner) {
197 do sendHandshakeRequest(partner);
198 go HandshakingGrouped(partner);
200 on GroupUpdate(Identity partner, IdentityList keys)
201 do storeGroupUpdate(partner, keys);
204 // copy of grouped state, with a timeout to enable fast poling for a minut
205 state GroupWaiting timeout=60 {
209 do sendUpdateRequest;
214 on Beacon(Identity partner){
215 do sendHandshakeRequest(partner);
216 go GroupedBeaconed(partner);
218 on HandshakeRequest(Identity partner) {
219 do sendHandshakeRequest(partner);
220 go HandshakingGrouped(partner);
222 on GroupUpdate(Identity partner, IdentityList keys)
223 do storeGroupUpdate(partner, keys);
224 on Timeout go Grouped;
227 state GroupedBeaconed timeout=600 (Identity expected){
231 do sendUpdateRequest;
236 on Beacon(Identity partner){
237 do sendHandshakeRequest(partner);
238 go GroupedBeaconed(partner);
240 on HandshakeRequest(Identity partner) {
241 if sameIdentities(partner, expected) {
242 // do nothing, to avoid sending handshake request twice
244 do sendHandshakeRequest(partner);
246 go HandshakingGrouped(partner);
248 on GroupUpdate(Identity partner, IdentityList keys)
249 do storeGroupUpdate(partner, keys);
250 on Timeout go Grouped;
253 state HandshakingGrouped timeout=600 (Identity expected) {
254 // HandshakeRequest from same group are filtered in receive_sync_msg
256 if keyElectionWon(expected) {
257 do notifyInitAddOtherDevice(partner);
259 do notifyInitMoveOurDevice(partner);
262 on HandshakeRejected(Identity partner) {
263 do rejectHandshake(partner); // stores rejection of partner
267 on HandshakeAccepted(Identity partner) {
268 do acceptHandshake(partner);
270 if keyElectionWon(partner) {
271 do sendGroupKeys(partner);
272 do notifyAcceptedDeviceAdded(partner);
275 go WaitForGroupKeysGrouped(partner);
277 on Cancel go Grouped;
278 on GroupKeys(Identity partner, GroupKeys groupkeys) {
279 if keyElectionWon(expected) {
280 // not supposed to receive groupkeys - ignore
282 // UUID changes in between, so we can only check for same address and fpr
283 if sameKeyAndAddress(partner, expected) {
284 go WaitForAcceptGrouped(partner, groupkeys);
288 on GroupUpdate(Identity partner, IdentityList keys) {
289 do notifyOvertaken(partner);
290 do storeGroupUpdate(partner, keys);
294 do notifyTimeout(expected);
299 state WaitForGroupKeysGrouped timeout=600 (Identity expected) {
300 on GroupKeys(Identity partner, GroupKeys groupkeys) {
301 if sameIdentities(partner, expected) {
302 do storeGroupKeys(partner, groupkeys);
305 do notifyAcceptedDeviceMoved(partner);
309 on GroupUpdate(Identity partner, IdentityList keys) {
310 do notifyOvertaken(partner);
311 do storeGroupUpdate(partner, keys);
315 do notifyTimeout(expected);
320 state WaitForAcceptGrouped timeout=600 (Identity expected, GroupKeys groupkeys) {
321 on HandshakeRejected(Identity partner) {
322 do rejectHandshake(partner);
326 on HandshakeAccepted(Identity partner) {
327 if sameIdentities(partner, expected) {
328 do acceptHandshake(partner);
329 do storeGroupKeys(partner, groupkeys);
332 do notifyAcceptedDeviceMoved(partner);
336 on Cancel go Grouped;
337 on GroupUpdate(Identity partner, IdentityList keys) {
338 do notifyOvertaken(partner);
339 do storeGroupUpdate(partner, keys);
343 do notifyTimeout(expected);
350 tag HandshakeRequest 3;