krista@2271
|
1 |
// This file is under GNU General Public License 3.0
|
krista@2271
|
2 |
// see LICENSE.txt
|
krista@2271
|
3 |
|
krista@2271
|
4 |
// generate state machine code
|
krista@2271
|
5 |
|
vb@3512
|
6 |
// Copyleft (c) 2016-2019, p≡p foundation
|
krista@2271
|
7 |
|
krista@2271
|
8 |
// Written by Volker Birk
|
krista@2271
|
9 |
|
krista@2271
|
10 |
include yslt.yml2
|
krista@2271
|
11 |
|
krista@2271
|
12 |
tstylesheet {
|
krista@2271
|
13 |
include standardlib.ysl2
|
krista@2271
|
14 |
include ./functions.ysl2
|
krista@2271
|
15 |
|
krista@2271
|
16 |
template "/protocol" {
|
vb@2838
|
17 |
document "generated/{@name}_event.h", "text"
|
vb@2838
|
18 |
||
|
vb@2838
|
19 |
// This file is under GNU General Public License 3.0
|
vb@2838
|
20 |
// see LICENSE.txt
|
vb@2838
|
21 |
|
vb@2838
|
22 |
#pragma once
|
vb@2838
|
23 |
|
vb@3534
|
24 |
#include "pEpEngine.h"
|
vb@2838
|
25 |
|
vb@2838
|
26 |
#ifdef __cplusplus
|
vb@2838
|
27 |
extern "C" {
|
vb@2838
|
28 |
#endif
|
vb@2838
|
29 |
|
vb@3020
|
30 |
typedef struct «@name» «yml:ucase(@name)»;
|
vb@3020
|
31 |
typedef int «yml:ucase(@name)»_PR;
|
vb@2838
|
32 |
|
vb@2847
|
33 |
typedef struct «@name»_event {
|
vb@3534
|
34 |
// state machine data
|
vb@3020
|
35 |
«yml:ucase(@name)»_PR fsm;
|
vb@2838
|
36 |
int event;
|
vb@3020
|
37 |
«yml:ucase(@name)» *msg;
|
vb@3534
|
38 |
|
vb@3534
|
39 |
// transport data
|
vb@3534
|
40 |
pEp_identity *from;
|
vb@3534
|
41 |
char *signature_fpr;
|
vb@3540
|
42 |
|
vb@3540
|
43 |
identity_list *own_identities;
|
vb@2838
|
44 |
} «@name»_event_t;
|
vb@2838
|
45 |
|
vb@2838
|
46 |
|
vb@2838
|
47 |
// new_«@name»_event() - allocate a new «@name»_event
|
vb@2838
|
48 |
//
|
vb@2838
|
49 |
// parameters:
|
vb@2838
|
50 |
// fsm (in) finite state machine the event is for
|
vb@2838
|
51 |
// event (in) event or None
|
vb@2838
|
52 |
// msg (in) message to compute event from
|
vb@2838
|
53 |
//
|
vb@2838
|
54 |
// return value:
|
vb@2838
|
55 |
// pointer to new event or NULL in case of failure
|
vb@2838
|
56 |
//
|
vb@2838
|
57 |
// caveat:
|
vb@2838
|
58 |
// event must be valid for fsm or None
|
vb@2838
|
59 |
// in case msg is given event will be calculated out of message
|
vb@2838
|
60 |
|
vb@3020
|
61 |
«@name»_event_t *new_«@name»_event(«yml:ucase(@name)»_PR fsm, int event, «yml:ucase(@name)» *msg);
|
vb@2838
|
62 |
|
vb@2910
|
63 |
#define «yml:ucase(@name)»_TIMEOUT_EVENT new_«@name»_event(«@name»_PR_NOTHING, 0, NULL);
|
vb@2910
|
64 |
|
vb@3338
|
65 |
|
vb@2838
|
66 |
// free_«@name»_event() - free memory occupied by event
|
vb@2838
|
67 |
//
|
vb@2838
|
68 |
// parameters:
|
vb@2838
|
69 |
// ev (in) event to free
|
vb@2838
|
70 |
|
vb@2899
|
71 |
void free_«@name»_event(«@name»_event_t *ev);
|
vb@2838
|
72 |
|
vb@2838
|
73 |
|
vb@2838
|
74 |
#ifdef __cplusplus
|
vb@2838
|
75 |
}
|
vb@2838
|
76 |
#endif
|
vb@2838
|
77 |
|
vb@2838
|
78 |
||
|
vb@2838
|
79 |
|
vb@2838
|
80 |
document "generated/{@name}_event.c", "text"
|
vb@2838
|
81 |
||
|
vb@2838
|
82 |
// This file is under GNU General Public License 3.0
|
vb@2838
|
83 |
// see LICENSE.txt
|
vb@2838
|
84 |
|
vb@3062
|
85 |
#include "platform.h"
|
vb@3062
|
86 |
|
vb@2838
|
87 |
#include "pEp_internal.h"
|
vb@2838
|
88 |
#include "«@name»_event.h"
|
vb@2838
|
89 |
#include "«@name»_func.h"
|
vb@2839
|
90 |
`` for "fsm" | #include "«@name»_fsm.h"
|
vb@2838
|
91 |
|
vb@3020
|
92 |
«@name»_event_t *new_«@name»_event(«yml:ucase(@name)»_PR fsm, int event, «@name»_t *msg)
|
vb@2838
|
93 |
{
|
vb@2838
|
94 |
«@name»_event_t *ev = («@name»_event_t *) calloc(1, sizeof(«@name»_event_t));
|
vb@2838
|
95 |
assert(ev);
|
vb@2838
|
96 |
if (!ev)
|
vb@2838
|
97 |
return NULL;
|
vb@2838
|
98 |
|
vb@2838
|
99 |
ev->fsm = fsm;
|
vb@2838
|
100 |
ev->event = event;
|
vb@2838
|
101 |
ev->msg = msg;
|
vb@2838
|
102 |
|
vb@2838
|
103 |
if (msg) {
|
vb@2838
|
104 |
switch (fsm) {
|
vb@2838
|
105 |
`` apply "fsm", 3, mode=event
|
vb@2838
|
106 |
default:
|
vb@2838
|
107 |
// unknown protocol
|
vb@2838
|
108 |
free(ev);
|
vb@2838
|
109 |
return NULL;
|
vb@2838
|
110 |
}
|
vb@2838
|
111 |
}
|
vb@2838
|
112 |
|
vb@2838
|
113 |
return ev;
|
vb@2838
|
114 |
}
|
vb@2838
|
115 |
|
vb@2899
|
116 |
void free_«@name»_event(«@name»_event_t *ev)
|
vb@2838
|
117 |
{
|
vb@2838
|
118 |
if (ev) {
|
vb@3540
|
119 |
free_identity_list(ev->own_identities);
|
vb@2838
|
120 |
free_«@name»_message(ev->msg);
|
vb@3534
|
121 |
free_identity(ev->from);
|
vb@3534
|
122 |
free(ev->signature_fpr);
|
vb@2838
|
123 |
free(ev);
|
vb@2838
|
124 |
}
|
vb@2838
|
125 |
}
|
vb@2838
|
126 |
|
vb@2838
|
127 |
||
|
vb@2838
|
128 |
|
vb@2829
|
129 |
document "generated/{@name}_impl.h", "text" {
|
vb@2870
|
130 |
||
|
vb@2870
|
131 |
// This file is under GNU General Public License 3.0
|
vb@2870
|
132 |
// see LICENSE.txt
|
krista@2271
|
133 |
|
vb@2870
|
134 |
#pragma once
|
krista@2271
|
135 |
|
vb@2870
|
136 |
#include "fsm_common.h"
|
vb@2889
|
137 |
#include "«@name»_event.h"
|
vb@2870
|
138 |
#include "message_api.h"
|
vb@3020
|
139 |
#include "../asn.1/«@name».h"
|
vb@2870
|
140 |
|
vb@2909
|
141 |
#define «yml:ucase(@name)»_THRESHOLD «@threshold»
|
vb@2909
|
142 |
`` for "fsm" | #define «yml:ucase(@name)»_THRESHOLD «@threshold»
|
vb@2909
|
143 |
|
vb@2870
|
144 |
#ifdef __cplusplus
|
vb@2870
|
145 |
extern "C" {
|
vb@2870
|
146 |
#endif
|
krista@2271
|
147 |
|
vb@2870
|
148 |
// conditions
|
krista@2271
|
149 |
|
vb@2870
|
150 |
||
|
vb@2870
|
151 |
for "func:distinctName(*//condition)"
|
vb@2870
|
152 |
| PEP_STATUS «@name»(PEP_SESSION session, bool *result);
|
vb@2870
|
153 |
||
|
vb@2834
|
154 |
|
vb@2870
|
155 |
// actions
|
vb@2829
|
156 |
|
vb@2870
|
157 |
||
|
vb@2870
|
158 |
for "func:distinctName(*//action)"
|
vb@2870
|
159 |
| PEP_STATUS «@name»(PEP_SESSION session);
|
vb@2870
|
160 |
||
|
vb@2829
|
161 |
|
vb@2914
|
162 |
// timeout handler
|
vb@2914
|
163 |
|
vb@2914
|
164 |
||
|
vb@2914
|
165 |
for "fsm[@threshold > 0]"
|
vb@2914
|
166 |
| PEP_STATUS «@name»TimeoutHandler(PEP_SESSION session);
|
vb@2914
|
167 |
||
|
vb@2914
|
168 |
|
vb@2870
|
169 |
// send message about an event to communication partners using state
|
vb@2829
|
170 |
|
vb@2870
|
171 |
PEP_STATUS send_«@name»_message(
|
vb@2870
|
172 |
PEP_SESSION session,
|
vb@2870
|
173 |
«@name»_PR fsm,
|
vb@2870
|
174 |
int message_type
|
vb@2870
|
175 |
);
|
vb@2829
|
176 |
|
vb@2870
|
177 |
// receive message and store it in state
|
vb@2829
|
178 |
|
vb@2870
|
179 |
PEP_STATUS recv_«@name»_event(
|
vb@2870
|
180 |
PEP_SESSION session,
|
vb@2870
|
181 |
«@name»_event_t *ev
|
vb@2870
|
182 |
);
|
vb@2870
|
183 |
|
vb@2870
|
184 |
// state machine driver
|
vb@2870
|
185 |
// if fsm or event set to 0 use fields in src if present
|
vb@2829
|
186 |
|
vb@2870
|
187 |
PEP_STATUS «@name»_driver(
|
vb@2870
|
188 |
PEP_SESSION session,
|
vb@2870
|
189 |
«@name»_PR fsm,
|
vb@2870
|
190 |
int event
|
vb@2870
|
191 |
);
|
vb@2829
|
192 |
|
vb@2888
|
193 |
// API being used by the engine internally
|
vb@2888
|
194 |
|
vb@2888
|
195 |
// call this if you need to signal an external event
|
vb@3540
|
196 |
// caveat: the ownership of own_identities goes to the callee
|
vb@2888
|
197 |
|
vb@2880
|
198 |
PEP_STATUS signal_«@name»_event(
|
vb@2870
|
199 |
PEP_SESSION session,
|
vb@2870
|
200 |
«@name»_PR fsm,
|
vb@3540
|
201 |
int event,
|
vb@3540
|
202 |
identity_list *own_identities
|
vb@2870
|
203 |
);
|
vb@2888
|
204 |
|
vb@2889
|
205 |
// call this if you are a transport and are receiving
|
vb@2889
|
206 |
// a «@name» message
|
vb@2829
|
207 |
|
vb@2888
|
208 |
PEP_STATUS signal_«@name»_message(
|
vb@2888
|
209 |
PEP_SESSION session,
|
vb@2888
|
210 |
PEP_rating rating,
|
vb@2888
|
211 |
const char *data,
|
vb@3143
|
212 |
size_t size,
|
vb@3363
|
213 |
const pEp_identity *from,
|
vb@3363
|
214 |
const char *signature_fpr
|
vb@2888
|
215 |
);
|
vb@2829
|
216 |
|
vb@2870
|
217 |
#ifdef __cplusplus
|
vb@2870
|
218 |
}
|
vb@2870
|
219 |
#endif
|
vb@2829
|
220 |
|
vb@2870
|
221 |
||
|
vb@2829
|
222 |
}
|
vb@2829
|
223 |
|
vb@2870
|
224 |
document "generated/{@name}_impl.c", "text" {
|
vb@2870
|
225 |
||
|
vb@2870
|
226 |
// This file is under GNU General Public License 3.0
|
vb@2870
|
227 |
// see LICENSE.txt
|
vb@2870
|
228 |
|
vb@2870
|
229 |
#include "«@name»_impl.h"
|
vb@2870
|
230 |
#include "pEp_internal.h"
|
vb@2870
|
231 |
#include "«@name»_event.h"
|
vb@2899
|
232 |
#include "«yml:lcase(@name)»_codec.h"
|
vb@2870
|
233 |
#include "baseprotocol.h"
|
vb@2870
|
234 |
`` for "fsm" | #include "«@name»_fsm.h"
|
vb@2829
|
235 |
|
vb@2909
|
236 |
`` apply "fsm", 0, mode=timeout
|
vb@2870
|
237 |
PEP_STATUS «@name»_driver(
|
vb@2870
|
238 |
PEP_SESSION session,
|
vb@2870
|
239 |
«@name»_PR fsm,
|
vb@2870
|
240 |
int event
|
vb@2870
|
241 |
)
|
vb@2870
|
242 |
{
|
vb@2910
|
243 |
assert(session);
|
vb@2910
|
244 |
if (!session)
|
vb@2870
|
245 |
return PEP_ILLEGAL_VALUE;
|
vb@2829
|
246 |
|
vb@2909
|
247 |
switch (fsm) {
|
vb@2910
|
248 |
case None:
|
vb@2910
|
249 |
if (!event) {
|
vb@2910
|
250 |
// timeout occured
|
vb@2910
|
251 |
`` for "fsm" |>>>> «../@name»_driver(session, «../@name»_PR_«yml:lcase(@name)», None);
|
vb@2910
|
252 |
return PEP_STATUS_OK;
|
vb@2910
|
253 |
}
|
vb@2910
|
254 |
return PEP_ILLEGAL_VALUE;
|
vb@2910
|
255 |
|
vb@2909
|
256 |
`` apply "fsm", mode=reset_state_machine;
|
vb@2909
|
257 |
default:
|
vb@2909
|
258 |
return PEP_ILLEGAL_VALUE;
|
vb@2909
|
259 |
}
|
vb@2909
|
260 |
|
vb@2870
|
261 |
int next_state = None;
|
vb@2870
|
262 |
do {
|
vb@2870
|
263 |
switch (fsm) {
|
vb@2870
|
264 |
`` apply "fsm", 3, mode=driver
|
vb@2870
|
265 |
default:
|
vb@2870
|
266 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
267 |
}
|
vb@2870
|
268 |
} while (next_state);
|
vb@2829
|
269 |
|
vb@2870
|
270 |
return PEP_STATUS_OK;
|
vb@2829
|
271 |
}
|
vb@2829
|
272 |
|
vb@2880
|
273 |
PEP_STATUS signal_«@name»_event(
|
vb@2870
|
274 |
PEP_SESSION session,
|
vb@2870
|
275 |
«@name»_PR fsm,
|
vb@3540
|
276 |
int event,
|
vb@3540
|
277 |
identity_list *own_identities
|
vb@2870
|
278 |
)
|
vb@2870
|
279 |
{
|
vb@2870
|
280 |
«@name»_t *msg = NULL;
|
vb@2870
|
281 |
«@name»_event_t *ev = NULL;
|
vb@2870
|
282 |
|
vb@2870
|
283 |
assert(session && fsm > 0 && event > None);
|
vb@2870
|
284 |
if (!(session && fsm > 0 && event > None))
|
vb@2870
|
285 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
286 |
|
vb@2870
|
287 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2870
|
288 |
|
vb@2888
|
289 |
if (!session->inject_«yml:lcase(@name)»_event)
|
vb@2888
|
290 |
return PEP_«yml:ucase(@name)»_NO_INJECT_CALLBACK;
|
vb@2870
|
291 |
|
vb@2870
|
292 |
if (event < Extra) {
|
vb@2870
|
293 |
msg = new_«@name»_message(fsm, event);
|
vb@2870
|
294 |
if (!msg) {
|
vb@2870
|
295 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
296 |
goto the_end;
|
vb@2870
|
297 |
}
|
vb@2870
|
298 |
|
vb@2870
|
299 |
status = update_«@name»_message(session, msg);
|
vb@2870
|
300 |
if (status)
|
vb@2888
|
301 |
goto the_end;
|
vb@2870
|
302 |
}
|
vb@2870
|
303 |
|
vb@2888
|
304 |
ev = new_«@name»_event(fsm, event, msg);
|
vb@2870
|
305 |
if (!ev) {
|
vb@2870
|
306 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
307 |
goto the_end;
|
vb@2870
|
308 |
}
|
vb@2870
|
309 |
|
vb@3540
|
310 |
ev->own_identities = own_identities;
|
vb@3540
|
311 |
|
vb@2870
|
312 |
int result = session->inject_«yml:lcase(@name)»_event(ev,
|
vb@2870
|
313 |
session->«yml:lcase(@name)»_management);
|
vb@2870
|
314 |
if (result) {
|
vb@2870
|
315 |
status = PEP_STATEMACHINE_ERROR;
|
vb@2888
|
316 |
goto the_end;
|
vb@2870
|
317 |
}
|
vb@2888
|
318 |
return PEP_STATUS_OK;
|
vb@2870
|
319 |
|
vb@2870
|
320 |
the_end:
|
krista@3331
|
321 |
free_«@name»_event(ev); // msg gets freed here
|
vb@2870
|
322 |
return status;
|
vb@2870
|
323 |
}
|
vb@2870
|
324 |
|
vb@2888
|
325 |
PEP_STATUS signal_«@name»_message(
|
vb@2870
|
326 |
PEP_SESSION session,
|
vb@2888
|
327 |
PEP_rating rating,
|
vb@2888
|
328 |
const char *data,
|
vb@3143
|
329 |
size_t size,
|
vb@3363
|
330 |
const pEp_identity *from,
|
vb@3363
|
331 |
const char *signature_fpr
|
vb@2870
|
332 |
)
|
vb@2870
|
333 |
{
|
vb@2888
|
334 |
assert(session && data && size);
|
vb@2888
|
335 |
if (!(session && data && size))
|
vb@2870
|
336 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
337 |
|
vb@2888
|
338 |
if (!session->inject_«yml:lcase(@name)»_event)
|
vb@2888
|
339 |
return PEP_«yml:ucase(@name)»_NO_INJECT_CALLBACK;
|
vb@2870
|
340 |
|
vb@3341
|
341 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2890
|
342 |
«@name»_event_t *ev = NULL;
|
vb@2890
|
343 |
|
vb@3341
|
344 |
«@name»_t *msg = NULL;
|
vb@3341
|
345 |
status = decode_«@name»_message(data, size, &msg);
|
vb@3341
|
346 |
if (status)
|
vb@3341
|
347 |
return status;
|
vb@3341
|
348 |
|
vb@3341
|
349 |
«@name»_PR fsm = msg->present;
|
vb@3341
|
350 |
int event = 0;
|
vb@3593
|
351 |
bool is_own_key = false;
|
vb@3341
|
352 |
|
vb@3341
|
353 |
switch (fsm) {
|
vb@3341
|
354 |
`` apply "fsm", 2, mode=signal_message
|
vb@3341
|
355 |
default:
|
vb@3341
|
356 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@3341
|
357 |
goto the_end;
|
vb@3341
|
358 |
}
|
vb@3341
|
359 |
|
vb@3117
|
360 |
ev = new_«@name»_event(fsm, event, msg);
|
vb@2888
|
361 |
if (!ev) {
|
vb@2829
|
362 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
363 |
goto the_end;
|
vb@2829
|
364 |
}
|
vb@2829
|
365 |
|
vb@3534
|
366 |
// add transport data
|
vb@3534
|
367 |
|
vb@3534
|
368 |
if (from) {
|
vb@3534
|
369 |
ev->from = identity_dup(from);
|
vb@3534
|
370 |
if (!ev->from) {
|
vb@3534
|
371 |
status = PEP_OUT_OF_MEMORY;
|
vb@3534
|
372 |
goto the_end;
|
vb@3534
|
373 |
}
|
vb@3534
|
374 |
}
|
vb@3534
|
375 |
|
vb@3534
|
376 |
if (signature_fpr) {
|
vb@3534
|
377 |
ev->signature_fpr = strdup(signature_fpr);
|
vb@3534
|
378 |
assert(ev->signature_fpr);
|
vb@3534
|
379 |
if (!ev->signature_fpr) {
|
vb@3534
|
380 |
status = PEP_OUT_OF_MEMORY;
|
vb@3534
|
381 |
goto the_end;
|
vb@3534
|
382 |
}
|
vb@3534
|
383 |
}
|
vb@3534
|
384 |
|
vb@2888
|
385 |
int result = session->inject_«yml:lcase(@name)»_event(ev,
|
vb@2888
|
386 |
session->«yml:lcase(@name)»_management);
|
vb@2888
|
387 |
if (result) {
|
vb@2888
|
388 |
status = PEP_STATEMACHINE_ERROR;
|
vb@2888
|
389 |
goto the_end;
|
vb@2888
|
390 |
}
|
vb@3143
|
391 |
|
vb@2888
|
392 |
return PEP_STATUS_OK;
|
vb@2868
|
393 |
|
vb@2870
|
394 |
the_end:
|
krista@3331
|
395 |
free_«@name»_event(ev); // msg gets freed here
|
vb@2870
|
396 |
return status;
|
vb@2868
|
397 |
}
|
vb@2841
|
398 |
|
vb@2870
|
399 |
PEP_STATUS send_«@name»_message(
|
vb@2870
|
400 |
PEP_SESSION session,
|
vb@2870
|
401 |
«@name»_PR fsm,
|
vb@2870
|
402 |
int message_type
|
vb@2870
|
403 |
)
|
vb@2870
|
404 |
{
|
vb@2870
|
405 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2870
|
406 |
|
vb@2870
|
407 |
assert(session && fsm > None && message_type > None);
|
vb@2870
|
408 |
if (!(session && fsm > None && message_type > None))
|
vb@2870
|
409 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
410 |
|
vb@2870
|
411 |
«@name»_t *msg = new_«@name»_message(fsm, message_type);
|
vb@2870
|
412 |
if (!msg)
|
vb@2870
|
413 |
return PEP_OUT_OF_MEMORY;
|
vb@2870
|
414 |
|
vb@2870
|
415 |
char *data = NULL;
|
vb@2870
|
416 |
message *m = NULL;
|
vb@2870
|
417 |
identity_list *channels = NULL;
|
vb@3545
|
418 |
char *key_data = NULL;
|
vb@3545
|
419 |
size_t key_data_size = 0;
|
vb@3594
|
420 |
stringlist_t *extra = NULL;
|
vb@3594
|
421 |
bool transaction;
|
vb@2870
|
422 |
|
vb@2870
|
423 |
status = update_«@name»_message(session, msg);
|
vb@2870
|
424 |
if (status)
|
vb@2870
|
425 |
goto the_end;
|
vb@2870
|
426 |
|
vb@2870
|
427 |
size_t size = 0;
|
vb@2870
|
428 |
status = encode_«@name»_message(msg, &data, &size);
|
vb@2870
|
429 |
if (status)
|
vb@2870
|
430 |
goto the_end;
|
vb@2840
|
431 |
|
vb@2870
|
432 |
switch (message_type) {
|
vb@2871
|
433 |
// these messages are being broadcasted
|
vb@3509
|
434 |
`` for "fsm/message[@type='broadcast']" |>> case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@2871
|
435 |
status = _own_identities_retrieve(session, &channels, PEP_idf_not_for_«yml:lcase(@name)»);
|
vb@2875
|
436 |
if (status)
|
vb@2870
|
437 |
goto the_end;
|
vb@2871
|
438 |
|
vb@2871
|
439 |
if (!(channels && channels->ident)) {
|
vb@3240
|
440 |
// status = PEP_«yml:ucase(@name)»_NO_CHANNEL;
|
vb@3240
|
441 |
// we don't check for having a channel, because if
|
vb@3240
|
442 |
// this is initial setup before having an own
|
vb@3240
|
443 |
// identity we're fine
|
vb@2871
|
444 |
goto the_end;
|
vb@2871
|
445 |
}
|
vb@2870
|
446 |
break;
|
vb@2829
|
447 |
|
vb@2877
|
448 |
// these go anycast; previously used address is sticky (unicast)
|
vb@3509
|
449 |
`` for "fsm/message[@type='anycast']" |>> case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@2870
|
450 |
if (!session->«yml:lcase(@name)»_state.common.from `> |`|
|
vb@2870
|
451 |
(session->«yml:lcase(@name)»_state.common.from->flags &
|
vb@2871
|
452 |
PEP_idf_not_for_«yml:lcase(@name)»)) {
|
vb@2870
|
453 |
|
vb@2870
|
454 |
// no address available yet, try to find one
|
vb@2871
|
455 |
status = _own_identities_retrieve(session, &channels, PEP_idf_not_for_«yml:lcase(@name)»);
|
krista@3626
|
456 |
if (status)
|
vb@2870
|
457 |
goto the_end;
|
vb@2870
|
458 |
break;
|
vb@2829
|
459 |
|
vb@2870
|
460 |
if (channels && channels->ident) {
|
vb@2870
|
461 |
// only need the first one
|
vb@2870
|
462 |
free_identity_list(channels->next);
|
vb@2870
|
463 |
channels->next = NULL;
|
vb@2870
|
464 |
}
|
vb@2870
|
465 |
else {
|
vb@2871
|
466 |
status = PEP_«yml:ucase(@name)»_NO_CHANNEL;
|
vb@2870
|
467 |
goto the_end;
|
vb@2870
|
468 |
}
|
vb@2870
|
469 |
}
|
vb@2870
|
470 |
else {
|
vb@2870
|
471 |
pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.common.from);
|
vb@2870
|
472 |
if (!channel) {
|
vb@2870
|
473 |
status = PEP_OUT_OF_MEMORY;
|
vb@2870
|
474 |
goto the_end;
|
vb@2870
|
475 |
}
|
vb@2829
|
476 |
|
vb@2870
|
477 |
channels = new_identity_list(channel);
|
vb@2870
|
478 |
if (!channels) {
|
vb@2870
|
479 |
status = PEP_OUT_OF_MEMORY;
|
vb@2870
|
480 |
goto the_end;
|
vb@2870
|
481 |
}
|
vb@2870
|
482 |
}
|
vb@3340
|
483 |
break;
|
vb@2877
|
484 |
|
vb@2877
|
485 |
default:
|
vb@2877
|
486 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2877
|
487 |
goto the_end;
|
vb@2829
|
488 |
}
|
vb@2870
|
489 |
|
vb@2870
|
490 |
for (identity_list *li = channels; li && li->ident ; li = li->next) {
|
vb@2878
|
491 |
message *_m = NULL;
|
vb@2944
|
492 |
char *_data = NULL;
|
vb@2944
|
493 |
|
vb@2944
|
494 |
_data = malloc(size);
|
vb@2944
|
495 |
assert(_data);
|
vb@2944
|
496 |
if (!_data) {
|
vb@2944
|
497 |
status = PEP_OUT_OF_MEMORY;
|
vb@2944
|
498 |
goto the_end;
|
vb@2944
|
499 |
}
|
vb@2944
|
500 |
memcpy(_data, data, size);
|
vb@2875
|
501 |
|
vb@2878
|
502 |
switch (message_type) {
|
vb@3509
|
503 |
`` for "fsm/message[@security='unencrypted']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3129
|
504 |
status = base_prepare_message(
|
vb@3143
|
505 |
session,
|
vb@3129
|
506 |
li->ident,
|
vb@3129
|
507 |
li->ident,
|
vb@3129
|
508 |
_data,
|
vb@3129
|
509 |
size,
|
vb@3129
|
510 |
li->ident->fpr,
|
vb@3129
|
511 |
&_m
|
vb@3129
|
512 |
);
|
vb@3129
|
513 |
if (status) {
|
vb@3129
|
514 |
free(_data);
|
vb@3129
|
515 |
goto the_end;
|
vb@3129
|
516 |
}
|
Thomas@3127
|
517 |
attach_own_key(session, _m);
|
vb@2878
|
518 |
m = _m;
|
vb@2878
|
519 |
break;
|
vb@2878
|
520 |
|
vb@3594
|
521 |
`` for "fsm/message[@security='untrusted']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3594
|
522 |
// add fpr of key of comm partner
|
vb@3594
|
523 |
|
vb@3594
|
524 |
assert(session->«yml:lcase(@name)»_state.common.signature_fpr);
|
vb@3594
|
525 |
if (!session->«yml:lcase(@name)»_state.common.signature_fpr) {
|
vb@3594
|
526 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3594
|
527 |
goto the_end;
|
vb@3594
|
528 |
}
|
vb@3594
|
529 |
|
vb@3594
|
530 |
extra = new_stringlist(session->«yml:lcase(@name)»_state.common.signature_fpr);
|
vb@3594
|
531 |
if (!extra) {
|
vb@3594
|
532 |
status = PEP_OUT_OF_MEMORY;
|
vb@3594
|
533 |
goto the_end;
|
vb@3594
|
534 |
}
|
vb@3594
|
535 |
|
vb@3594
|
536 |
status = base_prepare_message(
|
vb@3594
|
537 |
session,
|
vb@3594
|
538 |
li->ident,
|
vb@3594
|
539 |
li->ident,
|
vb@3594
|
540 |
_data,
|
vb@3594
|
541 |
size,
|
vb@3594
|
542 |
NULL,
|
vb@3594
|
543 |
&_m
|
vb@3594
|
544 |
);
|
vb@3594
|
545 |
if (status) {
|
vb@3594
|
546 |
free(_data);
|
vb@3594
|
547 |
goto the_end;
|
vb@3594
|
548 |
}
|
vb@3594
|
549 |
|
vb@3594
|
550 |
status = encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
|
vb@3594
|
551 |
if (status) {
|
vb@3519
|
552 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3519
|
553 |
goto the_end;
|
vb@3519
|
554 |
}
|
vb@3594
|
555 |
free_message(_m);
|
vb@3594
|
556 |
break;
|
vb@3594
|
557 |
|
vb@3594
|
558 |
`` for "fsm/message[@security='attach_own_keys']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3594
|
559 |
// check if this is the key of a former negotiation
|
vb@3594
|
560 |
|
vb@3594
|
561 |
transaction = false;
|
vb@3594
|
562 |
for (int i=0; i < session->own_«yml:lcase(@name)»_state.negotiation.size; i++) {
|
vb@3594
|
563 |
if (session->own_«yml:lcase(@name)»_state.negotiation.buf[i]) {
|
vb@3594
|
564 |
transaction = true;
|
vb@3594
|
565 |
break;
|
vb@3594
|
566 |
}
|
vb@3594
|
567 |
}
|
vb@3594
|
568 |
|
vb@3594
|
569 |
// if it is a former negotiation check if the key
|
vb@3594
|
570 |
// is fully trusted and the sender key of this
|
vb@3594
|
571 |
// transaction; if so add the sender key to extra
|
vb@3594
|
572 |
// keys allowing this new partner to read the
|
vb@3594
|
573 |
// secret keys
|
vb@3594
|
574 |
|
vb@3594
|
575 |
if (transaction) {
|
vb@3594
|
576 |
assert(session->own_«yml:lcase(@name)»_state.signature_fpr &&
|
vb@3594
|
577 |
session->«yml:lcase(@name)»_state.common.from &&
|
vb@3594
|
578 |
session->«yml:lcase(@name)»_state.common.from->user_id);
|
vb@3594
|
579 |
if (!(session->own_«yml:lcase(@name)»_state.signature_fpr &&
|
vb@3594
|
580 |
session->«yml:lcase(@name)»_state.common.from &&
|
vb@3594
|
581 |
session->«yml:lcase(@name)»_state.common.from->user_id))
|
vb@3594
|
582 |
{
|
vb@3594
|
583 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3594
|
584 |
goto the_end;
|
vb@3594
|
585 |
}
|
vb@3519
|
586 |
|
vb@3594
|
587 |
// test if this is a green channel
|
vb@3594
|
588 |
|
vb@3519
|
589 |
pEp_identity *ident = new_identity(NULL,
|
vb@3594
|
590 |
session->own_«yml:lcase(@name)»_state.signature_fpr,
|
vb@3519
|
591 |
session->«yml:lcase(@name)»_state.common.from->user_id,
|
vb@3519
|
592 |
NULL
|
vb@3519
|
593 |
);
|
vb@3519
|
594 |
if (!ident) {
|
vb@3519
|
595 |
status = PEP_OUT_OF_MEMORY;
|
vb@3519
|
596 |
goto the_end;
|
vb@3519
|
597 |
}
|
vb@3519
|
598 |
status = get_trust(session, ident);
|
vb@3519
|
599 |
if (status) {
|
vb@3519
|
600 |
free_identity(ident);
|
vb@3519
|
601 |
goto the_end;
|
vb@3519
|
602 |
}
|
vb@3519
|
603 |
assert(ident->comm_type == PEP_ct_pEp); // we don't deliver otherwise
|
vb@3519
|
604 |
if (ident->comm_type != PEP_ct_pEp) {
|
vb@3519
|
605 |
free_identity(ident);
|
vb@3519
|
606 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3519
|
607 |
goto the_end;
|
vb@3519
|
608 |
}
|
vb@3519
|
609 |
free_identity(ident);
|
vb@3594
|
610 |
|
vb@3594
|
611 |
// test if we accepted this as own key already
|
vb@3594
|
612 |
|
vb@3594
|
613 |
bool is_own_key = false;
|
vb@3594
|
614 |
status = own_key_is_listed(session,
|
vb@3594
|
615 |
session->own_«yml:lcase(@name)»_state.signature_fpr,
|
vb@3594
|
616 |
&is_own_key);
|
vb@3594
|
617 |
assert(!status);
|
vb@3594
|
618 |
if (status)
|
vb@3594
|
619 |
goto the_end;
|
vb@3594
|
620 |
assert(is_own_key);
|
vb@3594
|
621 |
if (!is_own_key) {
|
vb@3594
|
622 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3594
|
623 |
goto the_end;
|
vb@3594
|
624 |
}
|
vb@3594
|
625 |
|
vb@3594
|
626 |
// if so add key of comm partner to extra keys
|
vb@3594
|
627 |
|
vb@3594
|
628 |
extra = new_stringlist(session->own_«yml:lcase(@name)»_state.signature_fpr);
|
vb@3594
|
629 |
if (!extra) {
|
vb@3594
|
630 |
status = PEP_OUT_OF_MEMORY;
|
vb@3594
|
631 |
goto the_end;
|
vb@3594
|
632 |
}
|
vb@3519
|
633 |
}
|
vb@3593
|
634 |
|
vb@3393
|
635 |
status = base_prepare_message(
|
vb@3393
|
636 |
session,
|
vb@3393
|
637 |
li->ident,
|
vb@3393
|
638 |
li->ident,
|
vb@3393
|
639 |
_data,
|
vb@3393
|
640 |
size,
|
vb@3393
|
641 |
NULL,
|
vb@3393
|
642 |
&_m
|
vb@3393
|
643 |
);
|
vb@3393
|
644 |
if (status) {
|
vb@3393
|
645 |
free(_data);
|
vb@3393
|
646 |
goto the_end;
|
vb@3393
|
647 |
}
|
vb@3509
|
648 |
|
vb@3545
|
649 |
// export secret keys into memory
|
vb@3545
|
650 |
|
vb@3545
|
651 |
key_data = strdup("");
|
vb@3545
|
652 |
assert(key_data);
|
vb@3545
|
653 |
if (!key_data) {
|
vb@3545
|
654 |
free(_data);
|
vb@3567
|
655 |
free_message(_m);
|
vb@3545
|
656 |
status = PEP_OUT_OF_MEMORY;
|
vb@3545
|
657 |
goto the_end;
|
vb@3545
|
658 |
}
|
vb@3545
|
659 |
key_data_size = 1;
|
vb@3545
|
660 |
|
vb@3594
|
661 |
for (stringlist_t *sl = session->own_«yml:lcase(@name)»_state.own_keys;
|
vb@3545
|
662 |
sl && sl->value ; sl = sl->next)
|
vb@3545
|
663 |
{
|
vb@3545
|
664 |
char *_key_data = NULL;
|
vb@3545
|
665 |
size_t _size = 0;
|
vb@3545
|
666 |
status = export_secret_key(session, sl->value, &_key_data, &_size);
|
vb@3545
|
667 |
if (status && status != PEP_KEY_NOT_FOUND) {
|
vb@3545
|
668 |
free(_data);
|
vb@3567
|
669 |
free_message(_m);
|
vb@3545
|
670 |
goto the_end;
|
vb@3545
|
671 |
}
|
vb@3545
|
672 |
|
vb@3545
|
673 |
if (status != PEP_KEY_NOT_FOUND) {
|
vb@3545
|
674 |
assert(_key_data && _size);
|
vb@3545
|
675 |
char *n = realloc(key_data, key_data_size + _size);
|
vb@3545
|
676 |
if (!n) {
|
vb@3545
|
677 |
free(_data);
|
vb@3567
|
678 |
free_message(_m);
|
vb@3545
|
679 |
status = PEP_OUT_OF_MEMORY;
|
vb@3545
|
680 |
goto the_end;
|
vb@3545
|
681 |
}
|
vb@3545
|
682 |
key_data = n;
|
vb@3545
|
683 |
key_data_size += _size;
|
vb@3545
|
684 |
strlcat(key_data, _key_data, key_data_size);
|
vb@3545
|
685 |
free(_key_data);
|
vb@3545
|
686 |
_key_data = NULL;
|
vb@3545
|
687 |
}
|
vb@3545
|
688 |
status = export_key(session, sl->value, &_key_data, &_size);
|
vb@3545
|
689 |
if (status && status != PEP_KEY_NOT_FOUND) {
|
vb@3545
|
690 |
free(_data);
|
vb@3567
|
691 |
free_message(_m);
|
vb@3545
|
692 |
goto the_end;
|
vb@3545
|
693 |
}
|
vb@3545
|
694 |
|
vb@3545
|
695 |
if (status != PEP_KEY_NOT_FOUND) {
|
vb@3545
|
696 |
assert(_key_data && _size);
|
vb@3545
|
697 |
char *n = realloc(key_data, key_data_size + _size);
|
vb@3545
|
698 |
if (!n) {
|
vb@3545
|
699 |
free(_data);
|
vb@3567
|
700 |
free_message(_m);
|
vb@3545
|
701 |
status = PEP_OUT_OF_MEMORY;
|
vb@3545
|
702 |
goto the_end;
|
vb@3545
|
703 |
}
|
vb@3545
|
704 |
key_data = n;
|
vb@3545
|
705 |
key_data_size += _size;
|
vb@3545
|
706 |
strlcat(key_data, _key_data, key_data_size);
|
vb@3545
|
707 |
free(_key_data);
|
vb@3545
|
708 |
_key_data = NULL;
|
vb@3545
|
709 |
}
|
vb@3545
|
710 |
}
|
vb@3545
|
711 |
|
vb@3545
|
712 |
// add secret key data as attachment
|
vb@3545
|
713 |
|
vb@3545
|
714 |
bloblist_t *bl = bloblist_add(_m->attachments, key_data, key_data_size,
|
vb@3545
|
715 |
"application/octet-stream", "file://own.key");
|
vb@3545
|
716 |
if (!bl) {
|
vb@3545
|
717 |
free(_data);
|
vb@3567
|
718 |
free_message(_m);
|
vb@3545
|
719 |
status = PEP_OUT_OF_MEMORY;
|
vb@3545
|
720 |
goto the_end;
|
vb@3545
|
721 |
}
|
vb@3545
|
722 |
key_data = NULL;
|
vb@3545
|
723 |
|
vb@3594
|
724 |
status = encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
|
vb@3393
|
725 |
if (status) {
|
vb@3393
|
726 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@3393
|
727 |
goto the_end;
|
vb@3393
|
728 |
}
|
vb@3393
|
729 |
free_message(_m);
|
vb@3393
|
730 |
break;
|
vb@3393
|
731 |
|
vb@3594
|
732 |
default: // security=trusted only
|
vb@3129
|
733 |
status = base_prepare_message(
|
vb@3143
|
734 |
session,
|
vb@3129
|
735 |
li->ident,
|
vb@3129
|
736 |
li->ident,
|
vb@3129
|
737 |
_data,
|
vb@3129
|
738 |
size,
|
vb@3129
|
739 |
NULL,
|
vb@3129
|
740 |
&_m
|
vb@3129
|
741 |
);
|
vb@3129
|
742 |
if (status) {
|
vb@3129
|
743 |
free(_data);
|
vb@3129
|
744 |
goto the_end;
|
vb@3129
|
745 |
}
|
vb@3509
|
746 |
|
vb@3594
|
747 |
status = encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
|
vb@2879
|
748 |
if (status) {
|
vb@2899
|
749 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@2878
|
750 |
goto the_end;
|
vb@2879
|
751 |
}
|
vb@2878
|
752 |
free_message(_m);
|
vb@2878
|
753 |
}
|
vb@2878
|
754 |
|
vb@2899
|
755 |
status = session->messageToSend(m);
|
vb@2870
|
756 |
m = NULL;
|
vb@2829
|
757 |
}
|
vb@2870
|
758 |
|
vb@2870
|
759 |
the_end:
|
vb@3594
|
760 |
free_stringlist(extra);
|
vb@2870
|
761 |
free_identity_list(channels);
|
vb@2870
|
762 |
free_message(m);
|
vb@2870
|
763 |
free(data);
|
vb@3545
|
764 |
free(key_data);
|
vb@2870
|
765 |
free_«@name»_message(msg);
|
vb@2870
|
766 |
return status;
|
vb@2829
|
767 |
}
|
vb@2829
|
768 |
|
vb@2870
|
769 |
PEP_STATUS recv_«@name»_event(
|
vb@2870
|
770 |
PEP_SESSION session,
|
vb@2870
|
771 |
«@name»_event_t *ev
|
vb@2870
|
772 |
)
|
vb@2870
|
773 |
{
|
vb@2870
|
774 |
assert(session && ev);
|
vb@2870
|
775 |
if (!(session && ev))
|
vb@2870
|
776 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
777 |
|
vb@2870
|
778 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2888
|
779 |
«@name»_PR fsm = (int) None;
|
vb@2888
|
780 |
int event = None;
|
vb@2870
|
781 |
|
vb@2910
|
782 |
if (ev->event > None && ev->event < Extra) {
|
vb@2870
|
783 |
status = update_«@name»_state(session, ev->msg, &fsm, &event);
|
vb@2870
|
784 |
if (status)
|
vb@2888
|
785 |
goto the_end;
|
vb@2829
|
786 |
|
vb@2870
|
787 |
if (ev->fsm) {
|
vb@2870
|
788 |
if (ev->fsm != fsm |`> |` ev->event != event) {
|
vb@2870
|
789 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2888
|
790 |
goto the_end;
|
vb@2870
|
791 |
}
|
vb@2870
|
792 |
}
|
vb@2888
|
793 |
else if (ev->event) {
|
vb@2888
|
794 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2888
|
795 |
goto the_end;
|
vb@2870
|
796 |
}
|
vb@2870
|
797 |
}
|
vb@2888
|
798 |
else {
|
vb@2888
|
799 |
fsm = ev->fsm;
|
vb@2888
|
800 |
event = ev->event;
|
vb@2888
|
801 |
}
|
vb@2870
|
802 |
|
vb@3534
|
803 |
// update transport data
|
vb@3534
|
804 |
|
vb@3534
|
805 |
if (ev->from) {
|
vb@3540
|
806 |
free_identity(session->«yml:lcase(@name)»_state.common.from);
|
vb@3540
|
807 |
session->«yml:lcase(@name)»_state.common.from = ev->from;
|
vb@3540
|
808 |
ev->from = NULL;
|
vb@3534
|
809 |
}
|
vb@3534
|
810 |
|
vb@3534
|
811 |
if (ev->signature_fpr) {
|
vb@3540
|
812 |
free(session->«yml:lcase(@name)»_state.common.signature_fpr);
|
vb@3540
|
813 |
session->«yml:lcase(@name)»_state.common.signature_fpr = ev->signature_fpr;
|
vb@3540
|
814 |
ev->signature_fpr = NULL;
|
vb@3540
|
815 |
}
|
vb@3540
|
816 |
|
vb@3540
|
817 |
// update own identities
|
vb@3540
|
818 |
|
vb@3540
|
819 |
if (ev->own_identities && ev->own_identities->ident) {
|
vb@3594
|
820 |
free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
|
vb@3594
|
821 |
session->own_«yml:lcase(@name)»_state.own_identities = ev->own_identities;
|
vb@3540
|
822 |
ev->own_identities = NULL;
|
vb@3534
|
823 |
}
|
vb@3534
|
824 |
|
vb@2888
|
825 |
status = «@name»_driver(session, fsm, event);
|
vb@2870
|
826 |
|
vb@2888
|
827 |
the_end:
|
krista@3331
|
828 |
//free_«@name»_event(ev); // FIXME: We don't own this pointer. Are we sure it gets freed externally?
|
vb@2870
|
829 |
return status;
|
vb@2870
|
830 |
}
|
vb@2870
|
831 |
|
vb@2870
|
832 |
||
|
vb@2829
|
833 |
}
|
vb@2829
|
834 |
|
vb@2829
|
835 |
apply "fsm", 0, mode=gen;
|
vb@2829
|
836 |
}
|
vb@2829
|
837 |
|
vb@2909
|
838 |
template "fsm", mode=timeout
|
vb@2909
|
839 |
||
|
vb@2909
|
840 |
static bool _«@name»_timeout(int state)
|
vb@2909
|
841 |
{
|
vb@2909
|
842 |
static int last_state = None;
|
vb@2909
|
843 |
static time_t switch_time = 0;
|
vb@2909
|
844 |
|
vb@2909
|
845 |
if (state > Init) {
|
vb@2909
|
846 |
if (state == last_state) {
|
vb@2909
|
847 |
if (time(NULL) - switch_time > «yml:ucase(@name)»_THRESHOLD) {
|
vb@2909
|
848 |
last_state = None;
|
vb@2909
|
849 |
switch_time = 0;
|
vb@2909
|
850 |
return true;
|
vb@2909
|
851 |
}
|
vb@2909
|
852 |
}
|
vb@2909
|
853 |
else {
|
vb@2909
|
854 |
last_state = state;
|
vb@2909
|
855 |
switch_time = time(NULL);
|
vb@2909
|
856 |
}
|
vb@2909
|
857 |
}
|
vb@2909
|
858 |
else {
|
vb@2909
|
859 |
last_state = None;
|
vb@2909
|
860 |
switch_time = 0;
|
vb@2909
|
861 |
}
|
vb@2909
|
862 |
|
vb@2909
|
863 |
return false;
|
vb@2909
|
864 |
}
|
vb@2909
|
865 |
|
vb@2909
|
866 |
||
|
vb@2909
|
867 |
|
vb@2909
|
868 |
template "fsm", mode=reset_state_machine
|
vb@2909
|
869 |
||
|
vb@2909
|
870 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@2909
|
871 |
int state = session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state;
|
vb@2909
|
872 |
switch (state) {
|
vb@2909
|
873 |
`` for "state[@name!='InitState' and @timeout != 'off']" |>>> case «@name»:
|
vb@2909
|
874 |
if (_«@name»_timeout(state)) {
|
vb@2909
|
875 |
session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state = Init;
|
vb@2909
|
876 |
event = Init;
|
vb@2914
|
877 |
`` if "@threshold > 0" |>>>>> «@name»TimeoutHandler(session);
|
vb@2909
|
878 |
}
|
vb@2909
|
879 |
break;
|
vb@2909
|
880 |
|
vb@2909
|
881 |
default:
|
vb@2909
|
882 |
_«@name»_timeout(None);
|
vb@2909
|
883 |
}
|
vb@2909
|
884 |
break;
|
vb@2909
|
885 |
}
|
vb@2909
|
886 |
|
vb@2909
|
887 |
||
|
vb@2909
|
888 |
|
vb@2890
|
889 |
template "fsm", mode=signal_message
|
vb@2890
|
890 |
{
|
vb@2890
|
891 |
||
|
vb@2890
|
892 |
case «../@name»_PR_«yml:lcase(@name)»:
|
vb@3509
|
893 |
switch (msg->choice.«yml:lcase(@name)».present) {
|
vb@2891
|
894 |
||
|
vb@3518
|
895 |
for "message[@security='unencrypted']" {
|
vb@3518
|
896 |
if "position()=1" |>> // these messages require a detached signature
|
vb@3518
|
897 |
||
|
vb@3518
|
898 |
case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3518
|
899 |
if (!signature_fpr) {
|
vb@3518
|
900 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@3518
|
901 |
goto the_end;
|
vb@3518
|
902 |
}
|
vb@3518
|
903 |
event = «@name»;
|
vb@3518
|
904 |
break;
|
vb@3338
|
905 |
|
vb@3518
|
906 |
||
|
vb@3338
|
907 |
}
|
vb@3518
|
908 |
for "message[@security='untrusted']" {
|
vb@3518
|
909 |
if "position()=1" |>> // these messages must arrive encrypted
|
vb@3518
|
910 |
||
|
vb@3518
|
911 |
case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3518
|
912 |
if (rating < PEP_rating_reliable) {
|
vb@3518
|
913 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@3518
|
914 |
goto the_end;
|
vb@3518
|
915 |
}
|
vb@3518
|
916 |
event = «@name»;
|
vb@3518
|
917 |
break;
|
vb@2890
|
918 |
|
vb@3518
|
919 |
||
|
vb@2891
|
920 |
}
|
vb@3518
|
921 |
for "message[@security!='unencrypted' and @security!='untrusted']" {
|
vb@3518
|
922 |
if "position()=1" |>> // these messages must come through a trusted channel
|
vb@3518
|
923 |
||
|
vb@3518
|
924 |
case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@3518
|
925 |
if (rating < PEP_rating_trusted) {
|
vb@3518
|
926 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@3518
|
927 |
goto the_end;
|
vb@3518
|
928 |
}
|
vb@3593
|
929 |
status = own_key_is_listed(session, signature_fpr, &is_own_key);
|
vb@3593
|
930 |
if (status)
|
vb@3593
|
931 |
goto the_end;
|
vb@3593
|
932 |
if (!is_own_key) {
|
vb@3593
|
933 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@3593
|
934 |
goto the_end;
|
vb@3593
|
935 |
}
|
vb@3518
|
936 |
event = «@name»;
|
vb@3518
|
937 |
break;
|
vb@2890
|
938 |
|
vb@3518
|
939 |
||
|
vb@3338
|
940 |
}
|
vb@2891
|
941 |
||
|
vb@2890
|
942 |
default:
|
vb@2890
|
943 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@2890
|
944 |
goto the_end;
|
vb@2890
|
945 |
}
|
vb@2890
|
946 |
break;
|
vb@2890
|
947 |
|
vb@2890
|
948 |
||
|
vb@2890
|
949 |
}
|
vb@2890
|
950 |
|
vb@2838
|
951 |
template "fsm", mode=event
|
vb@2838
|
952 |
{
|
vb@2838
|
953 |
||
|
vb@2843
|
954 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@3509
|
955 |
switch (msg->choice.«yml:lcase(@name)».present) {
|
vb@2838
|
956 |
||
|
vb@2838
|
957 |
for "message"
|
vb@2838
|
958 |
||
|
vb@3509
|
959 |
case «../@name»_PR_«yml:mixedCase(@name)»:
|
vb@2838
|
960 |
ev->event = «@name»;
|
vb@2838
|
961 |
break;
|
vb@2838
|
962 |
||
|
vb@2838
|
963 |
||
|
vb@2838
|
964 |
default:
|
vb@2838
|
965 |
// unknown message type
|
vb@2838
|
966 |
free(ev);
|
vb@2838
|
967 |
return NULL;
|
vb@2838
|
968 |
}
|
vb@2838
|
969 |
break;
|
vb@2838
|
970 |
}
|
vb@2838
|
971 |
|
vb@2838
|
972 |
||
|
vb@2838
|
973 |
}
|
vb@2838
|
974 |
|
vb@2829
|
975 |
template "fsm", mode=driver
|
vb@2829
|
976 |
||
|
vb@2843
|
977 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@2839
|
978 |
int state = session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state;
|
vb@2839
|
979 |
next_state = fsm_«@name»(session, state, event);
|
vb@2838
|
980 |
if (next_state > None) {
|
vb@2838
|
981 |
session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state = next_state;
|
vb@2838
|
982 |
event = Init;
|
vb@2838
|
983 |
}
|
vb@2838
|
984 |
else if (next_state < None) {
|
Hussein@3167
|
985 |
return PEP_STATEMACHINE_ERROR - next_state;
|
vb@2838
|
986 |
}
|
vb@2829
|
987 |
break;
|
vb@2829
|
988 |
}
|
vb@2829
|
989 |
|
vb@2829
|
990 |
||
|
vb@2829
|
991 |
|
vb@2829
|
992 |
template "fsm", mode=gen {
|
vb@2829
|
993 |
document "generated/{@name}_fsm.h", "text" {
|
vb@2829
|
994 |
||
|
vb@2829
|
995 |
// This file is under GNU General Public License 3.0
|
vb@2829
|
996 |
// see LICENSE.txt
|
vb@2829
|
997 |
|
vb@2829
|
998 |
#pragma once
|
vb@2829
|
999 |
|
vb@2829
|
1000 |
#include "«../@name»_impl.h"
|
vb@2829
|
1001 |
|
vb@2829
|
1002 |
#ifdef __cplusplus
|
vb@2829
|
1003 |
extern "C" {
|
vb@2829
|
1004 |
#endif
|
vb@2829
|
1005 |
|
vb@2829
|
1006 |
// state machine for «@name»
|
krista@2271
|
1007 |
|
krista@2271
|
1008 |
// states
|
krista@2271
|
1009 |
|
krista@2271
|
1010 |
typedef enum _«@name»_state {
|
vb@2829
|
1011 |
«@name»_state_None = None,
|
vb@2829
|
1012 |
«@name»_state_Init = Init,
|
vb@2829
|
1013 |
||
|
vb@2829
|
1014 |
for "func:distinctName(state[not(@name='InitState')])"
|
vb@2829
|
1015 |
|> «@name»`if "position()!=last()" > , `
|
vb@2829
|
1016 |
||
|
krista@2271
|
1017 |
} «@name»_state;
|
krista@2271
|
1018 |
|
krista@2271
|
1019 |
// events
|
krista@2271
|
1020 |
|
krista@2271
|
1021 |
typedef enum _«@name»_event {
|
vb@2829
|
1022 |
«@name»_event_None = None,
|
vb@2829
|
1023 |
«@name»_event_Init = Init,
|
krista@2271
|
1024 |
||
|
vb@3388
|
1025 |
for "message" {
|
krista@2271
|
1026 |
const "name", "@name";
|
vb@2829
|
1027 |
|> «$name» = «/protocol/fsm/message[@name=$name]/@id»,
|
krista@2271
|
1028 |
}
|
vb@2829
|
1029 |
|> «@name»_event_Extra = Extra,
|
vb@3387
|
1030 |
for "external" {
|
vb@3385
|
1031 |
if "@id < 128"
|
vb@3385
|
1032 |
error > external «@name» must have ID >= 128 but it's «@id»
|
vb@3384
|
1033 |
|> «@name» = «@id»,
|
vb@3385
|
1034 |
}
|
vb@2830
|
1035 |
for "func:distinctName(state/event[not(../../message/@name=@name or ../../external/@name=@name)])" {
|
vb@2829
|
1036 |
if "@name!='Init'"
|
vb@2829
|
1037 |
|> «@name»`if "position()!=last()" > , `
|
vb@2829
|
1038 |
}
|
krista@2271
|
1039 |
||
|
krista@2271
|
1040 |
} «@name»_event;
|
krista@2271
|
1041 |
|
vb@2829
|
1042 |
// state machine
|
krista@2271
|
1043 |
|
vb@2829
|
1044 |
const char *«@name»_state_name(int state);
|
vb@2881
|
1045 |
const char *«@name»_event_name(int event);
|
krista@2271
|
1046 |
|
vb@2838
|
1047 |
// the state machine function is returning the next state in case of a
|
vb@2838
|
1048 |
// transition or None for staying
|
vb@2838
|
1049 |
|
krista@2271
|
1050 |
«@name»_state fsm_«@name»(
|
krista@2271
|
1051 |
PEP_SESSION session,
|
krista@2271
|
1052 |
«@name»_state state,
|
vb@2829
|
1053 |
«@name»_event event
|
krista@2271
|
1054 |
);
|
krista@2271
|
1055 |
|
krista@2271
|
1056 |
#ifdef __cplusplus
|
krista@2271
|
1057 |
}
|
krista@2271
|
1058 |
#endif
|
krista@2271
|
1059 |
|
krista@2271
|
1060 |
||
|
krista@2271
|
1061 |
}
|
vb@2829
|
1062 |
|
vb@2829
|
1063 |
document "generated/{@name}_fsm.c", "text" {
|
krista@2271
|
1064 |
||
|
vb@2829
|
1065 |
// This file is under GNU General Public License 3.0
|
vb@2829
|
1066 |
// see LICENSE.txt
|
vb@2829
|
1067 |
|
vb@2829
|
1068 |
#include "«@name»_fsm.h"
|
vb@2847
|
1069 |
#include <stdlib.h>
|
krista@2271
|
1070 |
|
vb@2829
|
1071 |
const char *«@name»_state_name(int state)
|
vb@2829
|
1072 |
{
|
vb@2829
|
1073 |
switch (state) {
|
vb@2829
|
1074 |
case End:
|
vb@2829
|
1075 |
return "End";
|
vb@2829
|
1076 |
case None:
|
vb@2829
|
1077 |
return "None";
|
vb@2829
|
1078 |
case Init:
|
vb@2829
|
1079 |
return "InitState";
|
vb@2829
|
1080 |
||
|
vb@2829
|
1081 |
for "func:distinctName(state[not(@name='InitState')])" {
|
vb@2829
|
1082 |
|>> case «@name»:
|
vb@2829
|
1083 |
|>>> return "«@name»";
|
vb@2829
|
1084 |
}
|
vb@2829
|
1085 |
||
|
vb@2829
|
1086 |
default:
|
vb@2829
|
1087 |
return "unknown state";
|
vb@2829
|
1088 |
}
|
vb@2829
|
1089 |
}
|
vb@2829
|
1090 |
|
vb@2881
|
1091 |
const char *«@name»_event_name(int event)
|
vb@2881
|
1092 |
{
|
vb@2881
|
1093 |
switch (event) {
|
vb@2881
|
1094 |
case None:
|
vb@2881
|
1095 |
return "None";
|
vb@2881
|
1096 |
case Init:
|
vb@2881
|
1097 |
return "Init";
|
vb@2881
|
1098 |
||
|
vb@2881
|
1099 |
for "func:distinctName(state/event[not(@name='Init')])" {
|
vb@2881
|
1100 |
|>> case «@name»:
|
vb@2881
|
1101 |
|>>> return "«@name»";
|
vb@2881
|
1102 |
}
|
vb@2881
|
1103 |
||
|
vb@2881
|
1104 |
default:
|
vb@2881
|
1105 |
return "unknown event";
|
vb@2881
|
1106 |
}
|
vb@2881
|
1107 |
}
|
vb@2881
|
1108 |
|
vb@2881
|
1109 |
|
vb@2829
|
1110 |
static char *_str(int n, bool hex)
|
vb@2829
|
1111 |
{
|
vb@2829
|
1112 |
char *buf = calloc(1, 24);
|
vb@2829
|
1113 |
assert(buf);
|
vb@2829
|
1114 |
if (!buf)
|
vb@2829
|
1115 |
return NULL;
|
krista@2271
|
1116 |
|
vb@2829
|
1117 |
if (hex)
|
vb@2829
|
1118 |
snprintf(buf, 24, "%.4x", n);
|
vb@2829
|
1119 |
else
|
vb@2829
|
1120 |
snprintf(buf, 24, "%d", n);
|
vb@2829
|
1121 |
return buf;
|
vb@2829
|
1122 |
}
|
krista@2271
|
1123 |
|
vb@2829
|
1124 |
#define «@name»_ERR_LOG(t, d) log_event(session, (t), "«@name»", (d), "error")
|
vb@2829
|
1125 |
|
vb@2829
|
1126 |
static PEP_STATUS _«@name»_ERR_LOG_int(PEP_SESSION session, char *t, int n, bool hex)
|
vb@2829
|
1127 |
{
|
vb@2829
|
1128 |
char *_buf = _str(n, hex);
|
vb@2829
|
1129 |
if (!_buf)
|
vb@2829
|
1130 |
return PEP_OUT_OF_MEMORY;
|
vb@2829
|
1131 |
PEP_STATUS status = «@name»_ERR_LOG(t, _buf);
|
vb@2829
|
1132 |
free(_buf);
|
vb@2829
|
1133 |
return status;
|
vb@2829
|
1134 |
}
|
vb@2829
|
1135 |
|
vb@2829
|
1136 |
#define «@name»_ERR_LOG_INT(t, n) _«@name»_ERR_LOG_int(session, (t), (n), false)
|
vb@2829
|
1137 |
#define «@name»_ERR_LOG_HEX(t, n) _«@name»_ERR_LOG_int(session, (t), (n), true)
|
vb@2829
|
1138 |
#define «@name»_SERVICE_LOG(t, d) SERVICE_LOG(session, (t), "«@name»", (d))
|
vb@2829
|
1139 |
|
vb@2829
|
1140 |
«@name»_state fsm_«@name»(
|
krista@2271
|
1141 |
PEP_SESSION session,
|
vb@2829
|
1142 |
«@name»_state state,
|
vb@2829
|
1143 |
«@name»_event event
|
krista@2271
|
1144 |
)
|
krista@2271
|
1145 |
{
|
krista@2271
|
1146 |
assert(session);
|
krista@2271
|
1147 |
if (!session)
|
vb@2829
|
1148 |
return invalid_state;
|
krista@2271
|
1149 |
|
vb@3365
|
1150 |
if (state == None)
|
vb@3365
|
1151 |
state = «@name»_state_Init;
|
vb@3365
|
1152 |
|
krista@2271
|
1153 |
switch (state) {
|
vb@2829
|
1154 |
`` apply "state", 2, mode=fsm
|
krista@2271
|
1155 |
default:
|
vb@2838
|
1156 |
«@name»_ERR_LOG_INT("invalid state", state);
|
vb@2829
|
1157 |
return invalid_state;
|
krista@2271
|
1158 |
}
|
vb@2829
|
1159 |
|
vb@2838
|
1160 |
return None;
|
krista@2271
|
1161 |
}
|
krista@2271
|
1162 |
|
krista@2271
|
1163 |
||
|
vb@2829
|
1164 |
}
|
krista@2271
|
1165 |
}
|
vb@2829
|
1166 |
|
vb@2829
|
1167 |
template "state", mode=fsm {
|
vb@2829
|
1168 |
choose {
|
vb@2829
|
1169 |
when "@name='InitState'" | case «../@name»_state_Init:
|
vb@2829
|
1170 |
otherwise | case «@name»:
|
vb@2829
|
1171 |
}
|
krista@2271
|
1172 |
||
|
vb@2829
|
1173 |
«../@name»_SERVICE_LOG("in state", "«@name»");
|
krista@2271
|
1174 |
|
vb@2829
|
1175 |
switch (event) {
|
vb@3366
|
1176 |
case None:
|
vb@3366
|
1177 |
«../@name»_SERVICE_LOG("received None event", "ignoring");
|
vb@3366
|
1178 |
break;
|
vb@3366
|
1179 |
|
vb@2838
|
1180 |
||
|
vb@2838
|
1181 |
if "not(event[@name='Init'])"
|
vb@2838
|
1182 |
||
|
vb@2838
|
1183 |
case Init:
|
vb@3379
|
1184 |
«../@name»_SERVICE_LOG("received Init but nothing to do", "Init");
|
vb@2838
|
1185 |
break;
|
vb@2838
|
1186 |
|
vb@2838
|
1187 |
||
|
vb@2838
|
1188 |
||
|
vb@2829
|
1189 |
`` apply "event", 2, mode=fsm
|
vb@2829
|
1190 |
default:
|
vb@2885
|
1191 |
// ignore events not handled here
|
vb@3594
|
1192 |
«../@name»_SERVICE_LOG("ignoring event", «../@name»_event_name(event));
|
vb@3362
|
1193 |
return invalid_event;
|
vb@2829
|
1194 |
}
|
vb@2829
|
1195 |
break;
|
krista@2271
|
1196 |
|
krista@2271
|
1197 |
||
|
vb@2829
|
1198 |
}
|
vb@2829
|
1199 |
|
vb@2829
|
1200 |
template "event", mode=fsm {
|
vb@2829
|
1201 |
| case «@name»: {
|
vb@2865
|
1202 |
if "condition|action|send" |> PEP_STATUS status;
|
vb@2829
|
1203 |
if "condition" |> bool result = false;
|
vb@2865
|
1204 |
if "condition|action|send" |
|
vb@2829
|
1205 |
||
|
vb@2829
|
1206 |
«../../@name»_SERVICE_LOG("received event", "«@name»");
|
vb@2907
|
1207 |
`` apply "transition|action|condition|else|send";
|
vb@2829
|
1208 |
||
|
vb@2829
|
1209 |
if "name(*[last()])!='transition'" {
|
vb@2829
|
1210 |
|
|
vb@2843
|
1211 |
|> «../../@name»_SERVICE_LOG("remaining in state", "«../@name»");
|
vb@2829
|
1212 |
|> break;
|
vb@2829
|
1213 |
}
|
vb@2829
|
1214 |
||
|
vb@2829
|
1215 |
}
|
vb@2829
|
1216 |
|
vb@2829
|
1217 |
||
|
vb@2829
|
1218 |
}
|
vb@2829
|
1219 |
|
vb@2829
|
1220 |
template "transition" {
|
vb@2865
|
1221 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
1222 |
||
|
krista@2271
|
1223 |
|
vb@2829
|
1224 |
«$fsm/@name»_SERVICE_LOG("transition to state", "«@target»");
|
vb@2838
|
1225 |
return «@target»;
|
krista@2271
|
1226 |
||
|
vb@2829
|
1227 |
}
|
vb@2829
|
1228 |
|
vb@2865
|
1229 |
template "send" {
|
vb@2865
|
1230 |
const "fsm", "ancestor::fsm";
|
vb@2865
|
1231 |
const "protocol", "ancestor::protocol";
|
vb@2865
|
1232 |
||
|
krista@2271
|
1233 |
|
vb@2865
|
1234 |
«$fsm/@name»_SERVICE_LOG("send message", "«@name»");
|
vb@3509
|
1235 |
status = send_«$protocol/@name»_message(session, «$fsm/@id», «$fsm/@name»_PR_«yml:mixedCase(@name)»);
|
vb@3089
|
1236 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
1237 |
return out_of_memory;
|
vb@3089
|
1238 |
if (status) {
|
vb@3089
|
1239 |
«$fsm/@name»_ERR_LOG_HEX("sending «@name» failed", status);
|
vb@3089
|
1240 |
return cannot_send;
|
vb@3089
|
1241 |
}
|
vb@2865
|
1242 |
||
|
vb@2865
|
1243 |
}
|
krista@2271
|
1244 |
|
vb@2865
|
1245 |
template "action" {
|
vb@2865
|
1246 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
1247 |
||
|
vb@2865
|
1248 |
|
vb@2865
|
1249 |
«$fsm/@name»_SERVICE_LOG("do action", "«@name»");
|
vb@2865
|
1250 |
status = «@name»(session);
|
vb@3089
|
1251 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
1252 |
return out_of_memory;
|
vb@2829
|
1253 |
if (status) {
|
vb@2829
|
1254 |
«$fsm/@name»_ERR_LOG_HEX("executing action «@name»() failed", status);
|
vb@2829
|
1255 |
return invalid_action;
|
krista@2271
|
1256 |
}
|
krista@2271
|
1257 |
||
|
krista@2271
|
1258 |
}
|
krista@2271
|
1259 |
|
vb@2829
|
1260 |
template "condition" {
|
vb@2865
|
1261 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
1262 |
||
|
krista@2271
|
1263 |
|
vb@2829
|
1264 |
status = «@name»(session, &result);
|
vb@3089
|
1265 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
1266 |
return out_of_memory;
|
vb@2829
|
1267 |
if (status) {
|
vb@2829
|
1268 |
«$fsm/@name»_ERR_LOG_HEX("computing condition «@name» failed", status);
|
vb@2829
|
1269 |
return invalid_condition;
|
krista@2271
|
1270 |
}
|
vb@2829
|
1271 |
if (result) {
|
vb@2843
|
1272 |
«$fsm/@name»_SERVICE_LOG("condition applies", "«@name»");
|
vb@2829
|
1273 |
||
|
vb@2907
|
1274 |
apply "transition|action|condition|else|send";
|
vb@2907
|
1275 |
| }
|
vb@2907
|
1276 |
}
|
vb@2907
|
1277 |
|
vb@2907
|
1278 |
template "else" {
|
vb@3520
|
1279 |
if "not(name(preceding-sibling::*[1]) = 'condition')"
|
vb@2907
|
1280 |
error "else without if";
|
vb@2907
|
1281 |
|
vb@2907
|
1282 |
| else {
|
vb@2907
|
1283 |
|> «ancestor::fsm/@name»_SERVICE_LOG("condition does not apply", "«preceding-sibling::*[last()]/@name»");
|
vb@2907
|
1284 |
apply "transition|action|condition|else|send";
|
krista@2271
|
1285 |
| }
|
krista@2271
|
1286 |
}
|
krista@2271
|
1287 |
}
|