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@2840
|
6 |
// Copyleft (c) 2016 - 2018, 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@2838
|
24 |
#include "dynamic_api.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@3020
|
34 |
«yml:ucase(@name)»_PR fsm;
|
vb@2838
|
35 |
int event;
|
vb@3020
|
36 |
«yml:ucase(@name)» *msg;
|
vb@2838
|
37 |
} «@name»_event_t;
|
vb@2838
|
38 |
|
vb@2838
|
39 |
|
vb@2838
|
40 |
// new_«@name»_event() - allocate a new «@name»_event
|
vb@2838
|
41 |
//
|
vb@2838
|
42 |
// parameters:
|
vb@2838
|
43 |
// fsm (in) finite state machine the event is for
|
vb@2838
|
44 |
// event (in) event or None
|
vb@2838
|
45 |
// msg (in) message to compute event from
|
vb@2838
|
46 |
//
|
vb@2838
|
47 |
// return value:
|
vb@2838
|
48 |
// pointer to new event or NULL in case of failure
|
vb@2838
|
49 |
//
|
vb@2838
|
50 |
// caveat:
|
vb@2838
|
51 |
// event must be valid for fsm or None
|
vb@2838
|
52 |
// in case msg is given event will be calculated out of message
|
vb@2838
|
53 |
|
vb@3020
|
54 |
«@name»_event_t *new_«@name»_event(«yml:ucase(@name)»_PR fsm, int event, «yml:ucase(@name)» *msg);
|
vb@2838
|
55 |
|
vb@2910
|
56 |
#define «yml:ucase(@name)»_TIMEOUT_EVENT new_«@name»_event(«@name»_PR_NOTHING, 0, NULL);
|
vb@2910
|
57 |
|
vb@2838
|
58 |
|
vb@2838
|
59 |
// free_«@name»_event() - free memory occupied by event
|
vb@2838
|
60 |
//
|
vb@2838
|
61 |
// parameters:
|
vb@2838
|
62 |
// ev (in) event to free
|
vb@2838
|
63 |
|
vb@2899
|
64 |
void free_«@name»_event(«@name»_event_t *ev);
|
vb@2838
|
65 |
|
vb@2838
|
66 |
|
vb@2838
|
67 |
#ifdef __cplusplus
|
vb@2838
|
68 |
}
|
vb@2838
|
69 |
#endif
|
vb@2838
|
70 |
|
vb@2838
|
71 |
||
|
vb@2838
|
72 |
|
vb@2838
|
73 |
document "generated/{@name}_event.c", "text"
|
vb@2838
|
74 |
||
|
vb@2838
|
75 |
// This file is under GNU General Public License 3.0
|
vb@2838
|
76 |
// see LICENSE.txt
|
vb@2838
|
77 |
|
vb@3062
|
78 |
#include "platform.h"
|
vb@3062
|
79 |
|
vb@2838
|
80 |
#include "pEp_internal.h"
|
vb@2838
|
81 |
#include "«@name»_event.h"
|
vb@2838
|
82 |
#include "«@name»_func.h"
|
vb@2839
|
83 |
`` for "fsm" | #include "«@name»_fsm.h"
|
vb@2838
|
84 |
|
vb@3020
|
85 |
«@name»_event_t *new_«@name»_event(«yml:ucase(@name)»_PR fsm, int event, «@name»_t *msg)
|
vb@2838
|
86 |
{
|
vb@2838
|
87 |
«@name»_event_t *ev = («@name»_event_t *) calloc(1, sizeof(«@name»_event_t));
|
vb@2838
|
88 |
assert(ev);
|
vb@2838
|
89 |
if (!ev)
|
vb@2838
|
90 |
return NULL;
|
vb@2838
|
91 |
|
vb@2838
|
92 |
ev->fsm = fsm;
|
vb@2838
|
93 |
ev->event = event;
|
vb@2838
|
94 |
ev->msg = msg;
|
vb@2838
|
95 |
|
vb@2838
|
96 |
if (msg) {
|
vb@2838
|
97 |
switch (fsm) {
|
vb@2838
|
98 |
`` apply "fsm", 3, mode=event
|
vb@2838
|
99 |
default:
|
vb@2838
|
100 |
// unknown protocol
|
vb@2838
|
101 |
free(ev);
|
vb@2838
|
102 |
return NULL;
|
vb@2838
|
103 |
}
|
vb@2838
|
104 |
}
|
vb@2838
|
105 |
|
vb@2838
|
106 |
return ev;
|
vb@2838
|
107 |
}
|
vb@2838
|
108 |
|
vb@2899
|
109 |
void free_«@name»_event(«@name»_event_t *ev)
|
vb@2838
|
110 |
{
|
vb@2838
|
111 |
if (ev) {
|
vb@2838
|
112 |
free_«@name»_message(ev->msg);
|
vb@2838
|
113 |
free(ev);
|
vb@2838
|
114 |
}
|
vb@2838
|
115 |
}
|
vb@2838
|
116 |
|
vb@2838
|
117 |
||
|
vb@2838
|
118 |
|
vb@2829
|
119 |
document "generated/{@name}_impl.h", "text" {
|
vb@2870
|
120 |
||
|
vb@2870
|
121 |
// This file is under GNU General Public License 3.0
|
vb@2870
|
122 |
// see LICENSE.txt
|
krista@2271
|
123 |
|
vb@2870
|
124 |
#pragma once
|
krista@2271
|
125 |
|
vb@2870
|
126 |
#include "fsm_common.h"
|
vb@2889
|
127 |
#include "«@name»_event.h"
|
vb@2870
|
128 |
#include "message_api.h"
|
vb@3020
|
129 |
#include "../asn.1/«@name».h"
|
vb@2870
|
130 |
|
vb@2909
|
131 |
#define «yml:ucase(@name)»_THRESHOLD «@threshold»
|
vb@2909
|
132 |
`` for "fsm" | #define «yml:ucase(@name)»_THRESHOLD «@threshold»
|
vb@2909
|
133 |
|
vb@2870
|
134 |
#ifdef __cplusplus
|
vb@2870
|
135 |
extern "C" {
|
vb@2870
|
136 |
#endif
|
krista@2271
|
137 |
|
vb@2870
|
138 |
// conditions
|
krista@2271
|
139 |
|
vb@2870
|
140 |
||
|
vb@2870
|
141 |
for "func:distinctName(*//condition)"
|
vb@2870
|
142 |
| PEP_STATUS «@name»(PEP_SESSION session, bool *result);
|
vb@2870
|
143 |
||
|
vb@2834
|
144 |
|
vb@2870
|
145 |
// actions
|
vb@2829
|
146 |
|
vb@2870
|
147 |
||
|
vb@2870
|
148 |
for "func:distinctName(*//action)"
|
vb@2870
|
149 |
| PEP_STATUS «@name»(PEP_SESSION session);
|
vb@2870
|
150 |
||
|
vb@2829
|
151 |
|
vb@2914
|
152 |
// timeout handler
|
vb@2914
|
153 |
|
vb@2914
|
154 |
||
|
vb@2914
|
155 |
for "fsm[@threshold > 0]"
|
vb@2914
|
156 |
| PEP_STATUS «@name»TimeoutHandler(PEP_SESSION session);
|
vb@2914
|
157 |
||
|
vb@2914
|
158 |
|
vb@2870
|
159 |
// send message about an event to communication partners using state
|
vb@2829
|
160 |
|
vb@2870
|
161 |
PEP_STATUS send_«@name»_message(
|
vb@2870
|
162 |
PEP_SESSION session,
|
vb@2870
|
163 |
«@name»_PR fsm,
|
vb@2870
|
164 |
int message_type
|
vb@2870
|
165 |
);
|
vb@2829
|
166 |
|
vb@2870
|
167 |
// receive message and store it in state
|
vb@2829
|
168 |
|
vb@2870
|
169 |
PEP_STATUS recv_«@name»_event(
|
vb@2870
|
170 |
PEP_SESSION session,
|
vb@2870
|
171 |
«@name»_event_t *ev
|
vb@2870
|
172 |
);
|
vb@2870
|
173 |
|
vb@2870
|
174 |
// state machine driver
|
vb@2870
|
175 |
// if fsm or event set to 0 use fields in src if present
|
vb@2829
|
176 |
|
vb@2870
|
177 |
PEP_STATUS «@name»_driver(
|
vb@2870
|
178 |
PEP_SESSION session,
|
vb@2870
|
179 |
«@name»_PR fsm,
|
vb@2870
|
180 |
int event
|
vb@2870
|
181 |
);
|
vb@2829
|
182 |
|
vb@2888
|
183 |
// API being used by the engine internally
|
vb@2888
|
184 |
|
vb@2888
|
185 |
// call this if you need to signal an external event
|
vb@2888
|
186 |
|
vb@2880
|
187 |
PEP_STATUS signal_«@name»_event(
|
vb@2870
|
188 |
PEP_SESSION session,
|
vb@2870
|
189 |
«@name»_PR fsm,
|
vb@2870
|
190 |
int event
|
vb@2870
|
191 |
);
|
vb@2888
|
192 |
|
vb@2889
|
193 |
// call this if you are a transport and are receiving
|
vb@2889
|
194 |
// a «@name» message
|
vb@2829
|
195 |
|
vb@2888
|
196 |
PEP_STATUS signal_«@name»_message(
|
vb@2888
|
197 |
PEP_SESSION session,
|
vb@2888
|
198 |
PEP_rating rating,
|
vb@2888
|
199 |
const char *data,
|
vb@3143
|
200 |
size_t size,
|
vb@3143
|
201 |
const char *fpr
|
vb@2888
|
202 |
);
|
vb@2829
|
203 |
|
vb@2870
|
204 |
#ifdef __cplusplus
|
vb@2870
|
205 |
}
|
vb@2870
|
206 |
#endif
|
vb@2829
|
207 |
|
vb@2870
|
208 |
||
|
vb@2829
|
209 |
}
|
vb@2829
|
210 |
|
vb@2870
|
211 |
document "generated/{@name}_impl.c", "text" {
|
vb@2870
|
212 |
||
|
vb@2870
|
213 |
// This file is under GNU General Public License 3.0
|
vb@2870
|
214 |
// see LICENSE.txt
|
vb@2870
|
215 |
|
vb@2870
|
216 |
#include "«@name»_impl.h"
|
vb@2870
|
217 |
#include "pEp_internal.h"
|
vb@2870
|
218 |
#include "«@name»_event.h"
|
vb@2899
|
219 |
#include "«yml:lcase(@name)»_codec.h"
|
vb@2870
|
220 |
#include "baseprotocol.h"
|
vb@2870
|
221 |
`` for "fsm" | #include "«@name»_fsm.h"
|
vb@2829
|
222 |
|
vb@2909
|
223 |
`` apply "fsm", 0, mode=timeout
|
vb@2870
|
224 |
PEP_STATUS «@name»_driver(
|
vb@2870
|
225 |
PEP_SESSION session,
|
vb@2870
|
226 |
«@name»_PR fsm,
|
vb@2870
|
227 |
int event
|
vb@2870
|
228 |
)
|
vb@2870
|
229 |
{
|
vb@2910
|
230 |
assert(session);
|
vb@2910
|
231 |
if (!session)
|
vb@2870
|
232 |
return PEP_ILLEGAL_VALUE;
|
vb@2829
|
233 |
|
vb@2909
|
234 |
switch (fsm) {
|
vb@2910
|
235 |
case None:
|
vb@2910
|
236 |
if (!event) {
|
vb@2910
|
237 |
// timeout occured
|
vb@2910
|
238 |
`` for "fsm" |>>>> «../@name»_driver(session, «../@name»_PR_«yml:lcase(@name)», None);
|
vb@2910
|
239 |
return PEP_STATUS_OK;
|
vb@2910
|
240 |
}
|
vb@2910
|
241 |
return PEP_ILLEGAL_VALUE;
|
vb@2910
|
242 |
|
vb@2909
|
243 |
`` apply "fsm", mode=reset_state_machine;
|
vb@2909
|
244 |
default:
|
vb@2909
|
245 |
return PEP_ILLEGAL_VALUE;
|
vb@2909
|
246 |
}
|
vb@2909
|
247 |
|
vb@2870
|
248 |
int next_state = None;
|
vb@2870
|
249 |
do {
|
vb@2870
|
250 |
switch (fsm) {
|
vb@2870
|
251 |
`` apply "fsm", 3, mode=driver
|
vb@2870
|
252 |
default:
|
vb@2870
|
253 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
254 |
}
|
vb@2870
|
255 |
} while (next_state);
|
vb@2829
|
256 |
|
vb@2870
|
257 |
return PEP_STATUS_OK;
|
vb@2829
|
258 |
}
|
vb@2829
|
259 |
|
vb@2880
|
260 |
PEP_STATUS signal_«@name»_event(
|
vb@2870
|
261 |
PEP_SESSION session,
|
vb@2870
|
262 |
«@name»_PR fsm,
|
vb@2870
|
263 |
int event
|
vb@2870
|
264 |
)
|
vb@2870
|
265 |
{
|
vb@2870
|
266 |
«@name»_t *msg = NULL;
|
vb@2870
|
267 |
«@name»_event_t *ev = NULL;
|
vb@2870
|
268 |
|
vb@2870
|
269 |
assert(session && fsm > 0 && event > None);
|
vb@2870
|
270 |
if (!(session && fsm > 0 && event > None))
|
vb@2870
|
271 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
272 |
|
vb@2870
|
273 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2870
|
274 |
|
vb@2888
|
275 |
if (!session->inject_«yml:lcase(@name)»_event)
|
vb@2888
|
276 |
return PEP_«yml:ucase(@name)»_NO_INJECT_CALLBACK;
|
vb@2870
|
277 |
|
vb@2870
|
278 |
if (event < Extra) {
|
vb@2870
|
279 |
msg = new_«@name»_message(fsm, event);
|
vb@2870
|
280 |
if (!msg) {
|
vb@2870
|
281 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
282 |
goto the_end;
|
vb@2870
|
283 |
}
|
vb@2870
|
284 |
|
vb@2870
|
285 |
status = update_«@name»_message(session, msg);
|
vb@2870
|
286 |
if (status)
|
vb@2888
|
287 |
goto the_end;
|
vb@2870
|
288 |
}
|
vb@2870
|
289 |
|
vb@2888
|
290 |
ev = new_«@name»_event(fsm, event, msg);
|
vb@2870
|
291 |
if (!ev) {
|
vb@2870
|
292 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
293 |
goto the_end;
|
vb@2870
|
294 |
}
|
vb@2870
|
295 |
|
vb@2870
|
296 |
int result = session->inject_«yml:lcase(@name)»_event(ev,
|
vb@2870
|
297 |
session->«yml:lcase(@name)»_management);
|
vb@2870
|
298 |
if (result) {
|
vb@2870
|
299 |
status = PEP_STATEMACHINE_ERROR;
|
vb@2888
|
300 |
goto the_end;
|
vb@2870
|
301 |
}
|
vb@2888
|
302 |
return PEP_STATUS_OK;
|
vb@2870
|
303 |
|
vb@2870
|
304 |
the_end:
|
vb@2888
|
305 |
free_«@name»_event(ev);
|
vb@2888
|
306 |
free_«@name»_message(msg);
|
vb@2870
|
307 |
return status;
|
vb@2870
|
308 |
}
|
vb@2870
|
309 |
|
vb@2888
|
310 |
PEP_STATUS signal_«@name»_message(
|
vb@2870
|
311 |
PEP_SESSION session,
|
vb@2888
|
312 |
PEP_rating rating,
|
vb@2888
|
313 |
const char *data,
|
vb@3143
|
314 |
size_t size,
|
vb@3143
|
315 |
const char *fpr
|
vb@2870
|
316 |
)
|
vb@2870
|
317 |
{
|
vb@2888
|
318 |
assert(session && data && size);
|
vb@2888
|
319 |
if (!(session && data && size))
|
vb@2870
|
320 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
321 |
|
vb@2888
|
322 |
if (!session->inject_«yml:lcase(@name)»_event)
|
vb@2888
|
323 |
return PEP_«yml:ucase(@name)»_NO_INJECT_CALLBACK;
|
vb@2870
|
324 |
|
vb@2888
|
325 |
«@name»_t *msg = NULL;
|
vb@2888
|
326 |
PEP_STATUS status = decode_«@name»_message(data, size, &msg);
|
vb@2888
|
327 |
if (status)
|
vb@2888
|
328 |
return status;
|
vb@2888
|
329 |
|
vb@2890
|
330 |
«@name»_event_t *ev = NULL;
|
vb@2890
|
331 |
|
vb@3117
|
332 |
«@name»_PR fsm = msg->present;
|
vb@3118
|
333 |
int event = 0;
|
vb@3117
|
334 |
|
vb@3117
|
335 |
switch (fsm) {
|
vb@2890
|
336 |
`` apply "fsm", 2, mode=signal_message
|
vb@2890
|
337 |
default:
|
vb@2890
|
338 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2890
|
339 |
goto the_end;
|
vb@2890
|
340 |
}
|
vb@2890
|
341 |
|
vb@3144
|
342 |
if (fpr) {
|
vb@3144
|
343 |
if (session->«yml:lcase(@name)»_state.common.from->fpr)
|
vb@3144
|
344 |
free(session->«yml:lcase(@name)»_state.common.from->fpr);
|
vb@3144
|
345 |
session->«yml:lcase(@name)»_state.common.from->fpr = strdup(fpr);
|
vb@3144
|
346 |
assert(session->«yml:lcase(@name)»_state.common.from->fpr);
|
vb@3144
|
347 |
if (!session->«yml:lcase(@name)»_state.common.from->fpr) {
|
vb@3144
|
348 |
status = PEP_OUT_OF_MEMORY;
|
vb@3144
|
349 |
goto the_end;
|
vb@3144
|
350 |
}
|
vb@3143
|
351 |
}
|
vb@3143
|
352 |
|
vb@3117
|
353 |
ev = new_«@name»_event(fsm, event, msg);
|
vb@2888
|
354 |
if (!ev) {
|
vb@2829
|
355 |
status = PEP_OUT_OF_MEMORY;
|
vb@2888
|
356 |
goto the_end;
|
vb@2829
|
357 |
}
|
vb@2829
|
358 |
|
vb@2888
|
359 |
int result = session->inject_«yml:lcase(@name)»_event(ev,
|
vb@2888
|
360 |
session->«yml:lcase(@name)»_management);
|
vb@2888
|
361 |
if (result) {
|
vb@2888
|
362 |
status = PEP_STATEMACHINE_ERROR;
|
vb@2888
|
363 |
goto the_end;
|
vb@2888
|
364 |
}
|
vb@3143
|
365 |
|
vb@2888
|
366 |
return PEP_STATUS_OK;
|
vb@2868
|
367 |
|
vb@2870
|
368 |
the_end:
|
vb@2888
|
369 |
free_«@name»_event(ev);
|
vb@2888
|
370 |
free_«@name»_message(msg);
|
vb@2870
|
371 |
return status;
|
vb@2868
|
372 |
}
|
vb@2841
|
373 |
|
vb@2870
|
374 |
PEP_STATUS send_«@name»_message(
|
vb@2870
|
375 |
PEP_SESSION session,
|
vb@2870
|
376 |
«@name»_PR fsm,
|
vb@2870
|
377 |
int message_type
|
vb@2870
|
378 |
)
|
vb@2870
|
379 |
{
|
vb@2870
|
380 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2870
|
381 |
|
vb@2870
|
382 |
assert(session && fsm > None && message_type > None);
|
vb@2870
|
383 |
if (!(session && fsm > None && message_type > None))
|
vb@2870
|
384 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
385 |
|
vb@2870
|
386 |
«@name»_t *msg = new_«@name»_message(fsm, message_type);
|
vb@2870
|
387 |
if (!msg)
|
vb@2870
|
388 |
return PEP_OUT_OF_MEMORY;
|
vb@2870
|
389 |
|
vb@2870
|
390 |
char *data = NULL;
|
vb@2870
|
391 |
message *m = NULL;
|
vb@2870
|
392 |
identity_list *channels = NULL;
|
vb@2870
|
393 |
|
vb@2870
|
394 |
status = update_«@name»_message(session, msg);
|
vb@2870
|
395 |
if (status)
|
vb@2870
|
396 |
goto the_end;
|
vb@2870
|
397 |
|
vb@2870
|
398 |
size_t size = 0;
|
vb@2870
|
399 |
status = encode_«@name»_message(msg, &data, &size);
|
vb@2870
|
400 |
if (status)
|
vb@2870
|
401 |
goto the_end;
|
vb@2840
|
402 |
|
vb@2870
|
403 |
switch (message_type) {
|
vb@2871
|
404 |
// these messages are being broadcasted
|
vb@2877
|
405 |
`` for "fsm/message[@type='broadcast']" |>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@2871
|
406 |
status = _own_identities_retrieve(session, &channels, PEP_idf_not_for_«yml:lcase(@name)»);
|
vb@2875
|
407 |
if (status)
|
vb@2870
|
408 |
goto the_end;
|
vb@2871
|
409 |
|
vb@2871
|
410 |
if (!(channels && channels->ident)) {
|
vb@2871
|
411 |
status = PEP_«yml:ucase(@name)»_NO_CHANNEL;
|
vb@2871
|
412 |
goto the_end;
|
vb@2871
|
413 |
}
|
vb@2870
|
414 |
break;
|
vb@2829
|
415 |
|
vb@2877
|
416 |
// these go anycast; previously used address is sticky (unicast)
|
vb@2877
|
417 |
`` for "fsm/message[@type='anycast']" |>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@2870
|
418 |
if (!session->«yml:lcase(@name)»_state.common.from `> |`|
|
vb@2870
|
419 |
(session->«yml:lcase(@name)»_state.common.from->flags &
|
vb@2871
|
420 |
PEP_idf_not_for_«yml:lcase(@name)»)) {
|
vb@2870
|
421 |
|
vb@2870
|
422 |
// no address available yet, try to find one
|
vb@2871
|
423 |
status = _own_identities_retrieve(session, &channels, PEP_idf_not_for_«yml:lcase(@name)»);
|
vb@2870
|
424 |
if (!status)
|
vb@2870
|
425 |
goto the_end;
|
vb@2870
|
426 |
break;
|
vb@2829
|
427 |
|
vb@2870
|
428 |
if (channels && channels->ident) {
|
vb@2870
|
429 |
// only need the first one
|
vb@2870
|
430 |
free_identity_list(channels->next);
|
vb@2870
|
431 |
channels->next = NULL;
|
vb@2870
|
432 |
}
|
vb@2870
|
433 |
else {
|
vb@2871
|
434 |
status = PEP_«yml:ucase(@name)»_NO_CHANNEL;
|
vb@2870
|
435 |
goto the_end;
|
vb@2870
|
436 |
}
|
vb@2870
|
437 |
}
|
vb@2870
|
438 |
else {
|
vb@2870
|
439 |
pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.common.from);
|
vb@2870
|
440 |
if (!channel) {
|
vb@2870
|
441 |
status = PEP_OUT_OF_MEMORY;
|
vb@2870
|
442 |
goto the_end;
|
vb@2870
|
443 |
}
|
vb@2829
|
444 |
|
vb@2870
|
445 |
channels = new_identity_list(channel);
|
vb@2870
|
446 |
if (!channels) {
|
vb@2870
|
447 |
status = PEP_OUT_OF_MEMORY;
|
vb@2870
|
448 |
goto the_end;
|
vb@2870
|
449 |
}
|
vb@2870
|
450 |
}
|
vb@2877
|
451 |
|
vb@2877
|
452 |
default:
|
vb@2877
|
453 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2877
|
454 |
goto the_end;
|
vb@2829
|
455 |
}
|
vb@2870
|
456 |
|
vb@2870
|
457 |
for (identity_list *li = channels; li && li->ident ; li = li->next) {
|
vb@2878
|
458 |
message *_m = NULL;
|
vb@2944
|
459 |
char *_data = NULL;
|
vb@2944
|
460 |
|
vb@2944
|
461 |
_data = malloc(size);
|
vb@2944
|
462 |
assert(_data);
|
vb@2944
|
463 |
if (!_data) {
|
vb@2944
|
464 |
status = PEP_OUT_OF_MEMORY;
|
vb@2944
|
465 |
goto the_end;
|
vb@2944
|
466 |
}
|
vb@2944
|
467 |
memcpy(_data, data, size);
|
vb@2875
|
468 |
|
vb@2878
|
469 |
switch (message_type) {
|
vb@2878
|
470 |
`` for "fsm/message[@security='unencrypted']" |>>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@3129
|
471 |
status = base_prepare_message(
|
vb@3143
|
472 |
session,
|
vb@3129
|
473 |
li->ident,
|
vb@3129
|
474 |
li->ident,
|
vb@3129
|
475 |
_data,
|
vb@3129
|
476 |
size,
|
vb@3129
|
477 |
li->ident->fpr,
|
vb@3129
|
478 |
&_m
|
vb@3129
|
479 |
);
|
vb@3129
|
480 |
if (status) {
|
vb@3129
|
481 |
free(_data);
|
vb@3129
|
482 |
goto the_end;
|
vb@3129
|
483 |
}
|
Thomas@3127
|
484 |
attach_own_key(session, _m);
|
vb@2878
|
485 |
m = _m;
|
vb@2878
|
486 |
break;
|
vb@2878
|
487 |
|
vb@2878
|
488 |
default:
|
vb@3129
|
489 |
status = base_prepare_message(
|
vb@3143
|
490 |
session,
|
vb@3129
|
491 |
li->ident,
|
vb@3129
|
492 |
li->ident,
|
vb@3129
|
493 |
_data,
|
vb@3129
|
494 |
size,
|
vb@3129
|
495 |
NULL,
|
vb@3129
|
496 |
&_m
|
vb@3129
|
497 |
);
|
vb@3129
|
498 |
if (status) {
|
vb@3129
|
499 |
free(_data);
|
vb@3129
|
500 |
goto the_end;
|
vb@3129
|
501 |
}
|
vb@2878
|
502 |
status = encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
|
vb@2879
|
503 |
if (status) {
|
vb@2899
|
504 |
status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
|
vb@2878
|
505 |
goto the_end;
|
vb@2879
|
506 |
}
|
vb@2878
|
507 |
free_message(_m);
|
vb@2878
|
508 |
}
|
vb@2878
|
509 |
|
vb@2899
|
510 |
status = session->messageToSend(m);
|
vb@2870
|
511 |
m = NULL;
|
vb@2829
|
512 |
}
|
vb@2870
|
513 |
|
vb@2870
|
514 |
the_end:
|
vb@2870
|
515 |
free_identity_list(channels);
|
vb@2870
|
516 |
free_message(m);
|
vb@2870
|
517 |
free(data);
|
vb@2870
|
518 |
free_«@name»_message(msg);
|
vb@2870
|
519 |
return status;
|
vb@2829
|
520 |
}
|
vb@2829
|
521 |
|
vb@2870
|
522 |
PEP_STATUS recv_«@name»_event(
|
vb@2870
|
523 |
PEP_SESSION session,
|
vb@2870
|
524 |
«@name»_event_t *ev
|
vb@2870
|
525 |
)
|
vb@2870
|
526 |
{
|
vb@2870
|
527 |
assert(session && ev);
|
vb@2870
|
528 |
if (!(session && ev))
|
vb@2870
|
529 |
return PEP_ILLEGAL_VALUE;
|
vb@2870
|
530 |
|
vb@2870
|
531 |
PEP_STATUS status = PEP_STATUS_OK;
|
vb@2888
|
532 |
«@name»_PR fsm = (int) None;
|
vb@2888
|
533 |
int event = None;
|
vb@2870
|
534 |
|
vb@2910
|
535 |
if (ev->event > None && ev->event < Extra) {
|
vb@2870
|
536 |
status = update_«@name»_state(session, ev->msg, &fsm, &event);
|
vb@2870
|
537 |
if (status)
|
vb@2888
|
538 |
goto the_end;
|
vb@2829
|
539 |
|
vb@2870
|
540 |
if (ev->fsm) {
|
vb@2870
|
541 |
if (ev->fsm != fsm |`> |` ev->event != event) {
|
vb@2870
|
542 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2888
|
543 |
goto the_end;
|
vb@2870
|
544 |
}
|
vb@2870
|
545 |
}
|
vb@2888
|
546 |
else if (ev->event) {
|
vb@2888
|
547 |
status = PEP_«yml:ucase(@name)»_ILLEGAL_MESSAGE;
|
vb@2888
|
548 |
goto the_end;
|
vb@2870
|
549 |
}
|
vb@2870
|
550 |
}
|
vb@2888
|
551 |
else {
|
vb@2888
|
552 |
fsm = ev->fsm;
|
vb@2888
|
553 |
event = ev->event;
|
vb@2888
|
554 |
}
|
vb@2870
|
555 |
|
vb@2888
|
556 |
status = «@name»_driver(session, fsm, event);
|
vb@2870
|
557 |
|
vb@2888
|
558 |
the_end:
|
vb@2888
|
559 |
free_«@name»_event(ev);
|
vb@2870
|
560 |
return status;
|
vb@2870
|
561 |
}
|
vb@2870
|
562 |
|
vb@2870
|
563 |
||
|
vb@2829
|
564 |
}
|
vb@2829
|
565 |
|
vb@2829
|
566 |
apply "fsm", 0, mode=gen;
|
vb@2829
|
567 |
}
|
vb@2829
|
568 |
|
vb@2909
|
569 |
template "fsm", mode=timeout
|
vb@2909
|
570 |
||
|
vb@2909
|
571 |
static bool _«@name»_timeout(int state)
|
vb@2909
|
572 |
{
|
vb@2909
|
573 |
static int last_state = None;
|
vb@2909
|
574 |
static time_t switch_time = 0;
|
vb@2909
|
575 |
|
vb@2909
|
576 |
if (state > Init) {
|
vb@2909
|
577 |
if (state == last_state) {
|
vb@2909
|
578 |
if (time(NULL) - switch_time > «yml:ucase(@name)»_THRESHOLD) {
|
vb@2909
|
579 |
last_state = None;
|
vb@2909
|
580 |
switch_time = 0;
|
vb@2909
|
581 |
return true;
|
vb@2909
|
582 |
}
|
vb@2909
|
583 |
}
|
vb@2909
|
584 |
else {
|
vb@2909
|
585 |
last_state = state;
|
vb@2909
|
586 |
switch_time = time(NULL);
|
vb@2909
|
587 |
}
|
vb@2909
|
588 |
}
|
vb@2909
|
589 |
else {
|
vb@2909
|
590 |
last_state = None;
|
vb@2909
|
591 |
switch_time = 0;
|
vb@2909
|
592 |
}
|
vb@2909
|
593 |
|
vb@2909
|
594 |
return false;
|
vb@2909
|
595 |
}
|
vb@2909
|
596 |
|
vb@2909
|
597 |
||
|
vb@2909
|
598 |
|
vb@2909
|
599 |
template "fsm", mode=reset_state_machine
|
vb@2909
|
600 |
||
|
vb@2909
|
601 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@2909
|
602 |
int state = session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state;
|
vb@2909
|
603 |
switch (state) {
|
vb@2909
|
604 |
`` for "state[@name!='InitState' and @timeout != 'off']" |>>> case «@name»:
|
vb@2909
|
605 |
if (_«@name»_timeout(state)) {
|
vb@2909
|
606 |
session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state = Init;
|
vb@2909
|
607 |
event = Init;
|
vb@2914
|
608 |
`` if "@threshold > 0" |>>>>> «@name»TimeoutHandler(session);
|
vb@2909
|
609 |
}
|
vb@2909
|
610 |
break;
|
vb@2909
|
611 |
|
vb@2909
|
612 |
default:
|
vb@2909
|
613 |
_«@name»_timeout(None);
|
vb@2909
|
614 |
}
|
vb@2909
|
615 |
break;
|
vb@2909
|
616 |
}
|
vb@2909
|
617 |
|
vb@2909
|
618 |
||
|
vb@2909
|
619 |
|
vb@2890
|
620 |
template "fsm", mode=signal_message
|
vb@2890
|
621 |
{
|
vb@2890
|
622 |
||
|
vb@2890
|
623 |
case «../@name»_PR_«yml:lcase(@name)»:
|
vb@3117
|
624 |
event = msg->choice.«yml:lcase(@name)».payload.present;
|
vb@3117
|
625 |
switch (event) {
|
vb@2891
|
626 |
||
|
vb@2891
|
627 |
if "message[@security='unencrypted']" {
|
vb@3146
|
628 |
| // these messages require a detached signature
|
vb@2891
|
629 |
for "message[@security='unencrypted']"
|
vb@2891
|
630 |
|>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@2891
|
631 |
||
|
vb@3146
|
632 |
if (!fpr) {
|
vb@3146
|
633 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@3146
|
634 |
goto the_end;
|
vb@3146
|
635 |
}
|
vb@3117
|
636 |
break;
|
vb@2890
|
637 |
|
vb@2891
|
638 |
||
|
vb@2891
|
639 |
}
|
vb@2891
|
640 |
if "message[@security='untrusted']"
|
vb@2891
|
641 |
||
|
vb@2890
|
642 |
// these messages must arrive encrypted
|
vb@2890
|
643 |
`` for "message[@security='untrusted']" |>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@3146
|
644 |
if (fpr || rating < PEP_rating_reliable) {
|
vb@2890
|
645 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@2890
|
646 |
goto the_end;
|
vb@2890
|
647 |
}
|
vb@2890
|
648 |
break;
|
vb@2890
|
649 |
|
vb@2891
|
650 |
||
|
vb@2891
|
651 |
if "message[@security='trusted']"
|
vb@2891
|
652 |
||
|
vb@2890
|
653 |
// these messages must come through a trusted channel
|
vb@2890
|
654 |
`` for "message[@security='trusted']" |>> case «ancestor::fsm/@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@3146
|
655 |
if (fpr || rating < PEP_rating_trusted) {
|
vb@2890
|
656 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@2890
|
657 |
goto the_end;
|
vb@2890
|
658 |
}
|
vb@2890
|
659 |
break;
|
vb@2890
|
660 |
|
vb@2890
|
661 |
default:
|
vb@2890
|
662 |
status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
|
vb@2890
|
663 |
goto the_end;
|
vb@2890
|
664 |
}
|
vb@2890
|
665 |
break;
|
vb@2890
|
666 |
|
vb@2890
|
667 |
||
|
vb@2890
|
668 |
}
|
vb@2890
|
669 |
|
vb@2838
|
670 |
template "fsm", mode=event
|
vb@2838
|
671 |
{
|
vb@2838
|
672 |
||
|
vb@2843
|
673 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@2839
|
674 |
switch (msg->choice.«yml:lcase(@name)».payload.present) {
|
vb@2838
|
675 |
||
|
vb@2838
|
676 |
for "message"
|
vb@2838
|
677 |
||
|
vb@2838
|
678 |
case «../@name»__payload_PR_«yml:mixedCase(@name)»:
|
vb@2838
|
679 |
ev->event = «@name»;
|
vb@2838
|
680 |
break;
|
vb@2838
|
681 |
||
|
vb@2838
|
682 |
||
|
vb@2838
|
683 |
default:
|
vb@2838
|
684 |
// unknown message type
|
vb@2838
|
685 |
free(ev);
|
vb@2838
|
686 |
return NULL;
|
vb@2838
|
687 |
}
|
vb@2838
|
688 |
break;
|
vb@2838
|
689 |
}
|
vb@2838
|
690 |
|
vb@2838
|
691 |
||
|
vb@2838
|
692 |
}
|
vb@2838
|
693 |
|
vb@2829
|
694 |
template "fsm", mode=driver
|
vb@2829
|
695 |
||
|
vb@2843
|
696 |
case «../@name»_PR_«yml:lcase(@name)»: {
|
vb@2839
|
697 |
int state = session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state;
|
vb@2839
|
698 |
next_state = fsm_«@name»(session, state, event);
|
vb@2838
|
699 |
if (next_state > None) {
|
vb@2838
|
700 |
session->«yml:lcase(../@name)»_state.«yml:lcase(@name)».state = next_state;
|
vb@2838
|
701 |
event = Init;
|
vb@2838
|
702 |
}
|
vb@2838
|
703 |
else if (next_state < None) {
|
Hussein@3167
|
704 |
return PEP_STATEMACHINE_ERROR - next_state;
|
vb@2838
|
705 |
}
|
vb@2829
|
706 |
break;
|
vb@2829
|
707 |
}
|
vb@2829
|
708 |
|
vb@2829
|
709 |
||
|
vb@2829
|
710 |
|
vb@2829
|
711 |
template "fsm", mode=gen {
|
vb@2829
|
712 |
document "generated/{@name}_fsm.h", "text" {
|
vb@2829
|
713 |
||
|
vb@2829
|
714 |
// This file is under GNU General Public License 3.0
|
vb@2829
|
715 |
// see LICENSE.txt
|
vb@2829
|
716 |
|
vb@2829
|
717 |
#pragma once
|
vb@2829
|
718 |
|
vb@2829
|
719 |
#include "«../@name»_impl.h"
|
vb@2829
|
720 |
|
vb@2829
|
721 |
#ifdef __cplusplus
|
vb@2829
|
722 |
extern "C" {
|
vb@2829
|
723 |
#endif
|
vb@2829
|
724 |
|
vb@2829
|
725 |
// state machine for «@name»
|
krista@2271
|
726 |
|
krista@2271
|
727 |
// states
|
krista@2271
|
728 |
|
krista@2271
|
729 |
typedef enum _«@name»_state {
|
vb@2829
|
730 |
«@name»_state_None = None,
|
vb@2829
|
731 |
«@name»_state_Init = Init,
|
vb@2829
|
732 |
||
|
vb@2829
|
733 |
for "func:distinctName(state[not(@name='InitState')])"
|
vb@2829
|
734 |
|> «@name»`if "position()!=last()" > , `
|
vb@2829
|
735 |
||
|
krista@2271
|
736 |
} «@name»_state;
|
krista@2271
|
737 |
|
krista@2271
|
738 |
// events
|
krista@2271
|
739 |
|
krista@2271
|
740 |
typedef enum _«@name»_event {
|
vb@2829
|
741 |
«@name»_event_None = None,
|
vb@2829
|
742 |
«@name»_event_Init = Init,
|
krista@2271
|
743 |
||
|
vb@2829
|
744 |
for "func:distinctName(state/event[not(not(../../message/@name=@name))])" {
|
krista@2271
|
745 |
const "name", "@name";
|
vb@2829
|
746 |
|> «$name» = «/protocol/fsm/message[@name=$name]/@id»,
|
krista@2271
|
747 |
}
|
vb@2830
|
748 |
for "func:distinctName(state/event[not(not(../../external/@name=@name))])" {
|
vb@2830
|
749 |
const "name", "@name";
|
vb@2830
|
750 |
|> «$name» = «/protocol/fsm/external[@name=$name]/@id»,
|
vb@2830
|
751 |
}
|
vb@2829
|
752 |
|> «@name»_event_Extra = Extra,
|
vb@2830
|
753 |
for "func:distinctName(state/event[not(../../message/@name=@name or ../../external/@name=@name)])" {
|
vb@2829
|
754 |
if "@name!='Init'"
|
vb@2829
|
755 |
|> «@name»`if "position()!=last()" > , `
|
vb@2829
|
756 |
}
|
krista@2271
|
757 |
||
|
krista@2271
|
758 |
} «@name»_event;
|
krista@2271
|
759 |
|
vb@2829
|
760 |
// state machine
|
krista@2271
|
761 |
|
vb@2829
|
762 |
const char *«@name»_state_name(int state);
|
vb@2881
|
763 |
const char *«@name»_event_name(int event);
|
krista@2271
|
764 |
|
vb@2838
|
765 |
// the state machine function is returning the next state in case of a
|
vb@2838
|
766 |
// transition or None for staying
|
vb@2838
|
767 |
|
krista@2271
|
768 |
«@name»_state fsm_«@name»(
|
krista@2271
|
769 |
PEP_SESSION session,
|
krista@2271
|
770 |
«@name»_state state,
|
vb@2829
|
771 |
«@name»_event event
|
krista@2271
|
772 |
);
|
krista@2271
|
773 |
|
krista@2271
|
774 |
#ifdef __cplusplus
|
krista@2271
|
775 |
}
|
krista@2271
|
776 |
#endif
|
krista@2271
|
777 |
|
krista@2271
|
778 |
||
|
krista@2271
|
779 |
}
|
vb@2829
|
780 |
|
vb@2829
|
781 |
document "generated/{@name}_fsm.c", "text" {
|
krista@2271
|
782 |
||
|
vb@2829
|
783 |
// This file is under GNU General Public License 3.0
|
vb@2829
|
784 |
// see LICENSE.txt
|
vb@2829
|
785 |
|
vb@2829
|
786 |
#include "«@name»_fsm.h"
|
vb@2847
|
787 |
#include <stdlib.h>
|
krista@2271
|
788 |
|
vb@2829
|
789 |
const char *«@name»_state_name(int state)
|
vb@2829
|
790 |
{
|
vb@2829
|
791 |
switch (state) {
|
vb@2829
|
792 |
case End:
|
vb@2829
|
793 |
return "End";
|
vb@2829
|
794 |
case None:
|
vb@2829
|
795 |
return "None";
|
vb@2829
|
796 |
case Init:
|
vb@2829
|
797 |
return "InitState";
|
vb@2829
|
798 |
||
|
vb@2829
|
799 |
for "func:distinctName(state[not(@name='InitState')])" {
|
vb@2829
|
800 |
|>> case «@name»:
|
vb@2829
|
801 |
|>>> return "«@name»";
|
vb@2829
|
802 |
}
|
vb@2829
|
803 |
||
|
vb@2829
|
804 |
default:
|
vb@2829
|
805 |
return "unknown state";
|
vb@2829
|
806 |
}
|
vb@2829
|
807 |
}
|
vb@2829
|
808 |
|
vb@2881
|
809 |
const char *«@name»_event_name(int event)
|
vb@2881
|
810 |
{
|
vb@2881
|
811 |
switch (event) {
|
vb@2881
|
812 |
case None:
|
vb@2881
|
813 |
return "None";
|
vb@2881
|
814 |
case Init:
|
vb@2881
|
815 |
return "Init";
|
vb@2881
|
816 |
||
|
vb@2881
|
817 |
for "func:distinctName(state/event[not(@name='Init')])" {
|
vb@2881
|
818 |
|>> case «@name»:
|
vb@2881
|
819 |
|>>> return "«@name»";
|
vb@2881
|
820 |
}
|
vb@2881
|
821 |
||
|
vb@2881
|
822 |
default:
|
vb@2881
|
823 |
return "unknown event";
|
vb@2881
|
824 |
}
|
vb@2881
|
825 |
}
|
vb@2881
|
826 |
|
vb@2881
|
827 |
|
vb@2829
|
828 |
static char *_str(int n, bool hex)
|
vb@2829
|
829 |
{
|
vb@2829
|
830 |
char *buf = calloc(1, 24);
|
vb@2829
|
831 |
assert(buf);
|
vb@2829
|
832 |
if (!buf)
|
vb@2829
|
833 |
return NULL;
|
krista@2271
|
834 |
|
vb@2829
|
835 |
if (hex)
|
vb@2829
|
836 |
snprintf(buf, 24, "%.4x", n);
|
vb@2829
|
837 |
else
|
vb@2829
|
838 |
snprintf(buf, 24, "%d", n);
|
vb@2829
|
839 |
return buf;
|
vb@2829
|
840 |
}
|
krista@2271
|
841 |
|
vb@2829
|
842 |
#define «@name»_ERR_LOG(t, d) log_event(session, (t), "«@name»", (d), "error")
|
vb@2829
|
843 |
|
vb@2829
|
844 |
static PEP_STATUS _«@name»_ERR_LOG_int(PEP_SESSION session, char *t, int n, bool hex)
|
vb@2829
|
845 |
{
|
vb@2829
|
846 |
char *_buf = _str(n, hex);
|
vb@2829
|
847 |
if (!_buf)
|
vb@2829
|
848 |
return PEP_OUT_OF_MEMORY;
|
vb@2829
|
849 |
PEP_STATUS status = «@name»_ERR_LOG(t, _buf);
|
vb@2829
|
850 |
free(_buf);
|
vb@2829
|
851 |
return status;
|
vb@2829
|
852 |
}
|
vb@2829
|
853 |
|
vb@2829
|
854 |
#define «@name»_ERR_LOG_INT(t, n) _«@name»_ERR_LOG_int(session, (t), (n), false)
|
vb@2829
|
855 |
#define «@name»_ERR_LOG_HEX(t, n) _«@name»_ERR_LOG_int(session, (t), (n), true)
|
vb@2829
|
856 |
|
vb@2829
|
857 |
#ifndef SERVICE_LOG
|
vb@2829
|
858 |
// SERVICE LOG is meant to check session->service_log in runtime config;
|
vb@2829
|
859 |
// for older engines log more than needed
|
vb@2829
|
860 |
#define SERVICE_LOG(session, t, n, d) log_event((session), (t), (n), (d), "service")
|
vb@2829
|
861 |
#endif
|
vb@2829
|
862 |
|
vb@2829
|
863 |
#define «@name»_SERVICE_LOG(t, d) SERVICE_LOG(session, (t), "«@name»", (d))
|
vb@2829
|
864 |
|
vb@2829
|
865 |
«@name»_state fsm_«@name»(
|
krista@2271
|
866 |
PEP_SESSION session,
|
vb@2829
|
867 |
«@name»_state state,
|
vb@2829
|
868 |
«@name»_event event
|
krista@2271
|
869 |
)
|
krista@2271
|
870 |
{
|
krista@2271
|
871 |
assert(session);
|
krista@2271
|
872 |
if (!session)
|
vb@2829
|
873 |
return invalid_state;
|
krista@2271
|
874 |
|
krista@2271
|
875 |
switch (state) {
|
vb@2829
|
876 |
case None:
|
vb@2838
|
877 |
return «@name»_state_Init;
|
vb@2829
|
878 |
|
vb@2829
|
879 |
`` apply "state", 2, mode=fsm
|
krista@2271
|
880 |
default:
|
vb@2838
|
881 |
«@name»_ERR_LOG_INT("invalid state", state);
|
vb@2829
|
882 |
return invalid_state;
|
krista@2271
|
883 |
}
|
vb@2829
|
884 |
|
vb@2838
|
885 |
return None;
|
krista@2271
|
886 |
}
|
krista@2271
|
887 |
|
krista@2271
|
888 |
||
|
vb@2829
|
889 |
}
|
krista@2271
|
890 |
}
|
vb@2829
|
891 |
|
vb@2829
|
892 |
template "state", mode=fsm {
|
vb@2829
|
893 |
choose {
|
vb@2829
|
894 |
when "@name='InitState'" | case «../@name»_state_Init:
|
vb@2829
|
895 |
otherwise | case «@name»:
|
vb@2829
|
896 |
}
|
krista@2271
|
897 |
||
|
vb@2829
|
898 |
«../@name»_SERVICE_LOG("in state", "«@name»");
|
krista@2271
|
899 |
|
vb@2829
|
900 |
switch (event) {
|
vb@2829
|
901 |
case None:
|
vb@2829
|
902 |
«../@name»_SERVICE_LOG("received None event", "ignoring");
|
vb@2838
|
903 |
break;
|
vb@2829
|
904 |
|
vb@2838
|
905 |
||
|
vb@2838
|
906 |
if "not(event[@name='Init'])"
|
vb@2838
|
907 |
||
|
vb@2838
|
908 |
case Init:
|
vb@2838
|
909 |
// nothing to do
|
vb@2838
|
910 |
break;
|
vb@2838
|
911 |
|
vb@2838
|
912 |
||
|
vb@2838
|
913 |
||
|
vb@2829
|
914 |
`` apply "event", 2, mode=fsm
|
vb@2829
|
915 |
default:
|
vb@2885
|
916 |
// ignore events not handled here
|
vb@2885
|
917 |
«../@name»_SERVICE_LOG("ignoring event", KeySync_event_name(event));
|
vb@2885
|
918 |
break;
|
vb@2829
|
919 |
}
|
vb@2829
|
920 |
break;
|
krista@2271
|
921 |
|
krista@2271
|
922 |
||
|
vb@2829
|
923 |
}
|
vb@2829
|
924 |
|
vb@2829
|
925 |
template "event", mode=fsm {
|
vb@2829
|
926 |
| case «@name»: {
|
vb@2865
|
927 |
if "condition|action|send" |> PEP_STATUS status;
|
vb@2829
|
928 |
if "condition" |> bool result = false;
|
vb@2865
|
929 |
if "condition|action|send" |
|
vb@2829
|
930 |
||
|
vb@2829
|
931 |
«../../@name»_SERVICE_LOG("received event", "«@name»");
|
vb@2907
|
932 |
`` apply "transition|action|condition|else|send";
|
vb@2829
|
933 |
||
|
vb@2829
|
934 |
if "name(*[last()])!='transition'" {
|
vb@2829
|
935 |
|
|
vb@2843
|
936 |
|> «../../@name»_SERVICE_LOG("remaining in state", "«../@name»");
|
vb@2829
|
937 |
|> break;
|
vb@2829
|
938 |
}
|
vb@2829
|
939 |
||
|
vb@2829
|
940 |
}
|
vb@2829
|
941 |
|
vb@2829
|
942 |
||
|
vb@2829
|
943 |
}
|
vb@2829
|
944 |
|
vb@2829
|
945 |
template "transition" {
|
vb@2865
|
946 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
947 |
||
|
krista@2271
|
948 |
|
vb@2829
|
949 |
«$fsm/@name»_SERVICE_LOG("transition to state", "«@target»");
|
vb@2838
|
950 |
return «@target»;
|
krista@2271
|
951 |
||
|
vb@2829
|
952 |
}
|
vb@2829
|
953 |
|
vb@2865
|
954 |
template "send" {
|
vb@2865
|
955 |
const "fsm", "ancestor::fsm";
|
vb@2865
|
956 |
const "protocol", "ancestor::protocol";
|
vb@2865
|
957 |
||
|
krista@2271
|
958 |
|
vb@2865
|
959 |
«$fsm/@name»_SERVICE_LOG("send message", "«@name»");
|
vb@2865
|
960 |
status = send_«$protocol/@name»_message(session, «$fsm/@id», «$fsm/@name»__payload_PR_«yml:mixedCase(@name)»);
|
vb@3089
|
961 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
962 |
return out_of_memory;
|
vb@3089
|
963 |
if (status) {
|
vb@3089
|
964 |
«$fsm/@name»_ERR_LOG_HEX("sending «@name» failed", status);
|
vb@3089
|
965 |
return cannot_send;
|
vb@3089
|
966 |
}
|
vb@2865
|
967 |
||
|
vb@2865
|
968 |
}
|
krista@2271
|
969 |
|
vb@2865
|
970 |
template "action" {
|
vb@2865
|
971 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
972 |
||
|
vb@2865
|
973 |
|
vb@2865
|
974 |
«$fsm/@name»_SERVICE_LOG("do action", "«@name»");
|
vb@2865
|
975 |
status = «@name»(session);
|
vb@3089
|
976 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
977 |
return out_of_memory;
|
vb@2829
|
978 |
if (status) {
|
vb@2829
|
979 |
«$fsm/@name»_ERR_LOG_HEX("executing action «@name»() failed", status);
|
vb@2829
|
980 |
return invalid_action;
|
krista@2271
|
981 |
}
|
krista@2271
|
982 |
||
|
krista@2271
|
983 |
}
|
krista@2271
|
984 |
|
vb@2829
|
985 |
template "condition" {
|
vb@2865
|
986 |
const "fsm", "ancestor::fsm";
|
krista@2271
|
987 |
||
|
krista@2271
|
988 |
|
vb@2829
|
989 |
status = «@name»(session, &result);
|
vb@3089
|
990 |
if (status == PEP_OUT_OF_MEMORY)
|
vb@3089
|
991 |
return out_of_memory;
|
vb@2829
|
992 |
if (status) {
|
vb@2829
|
993 |
«$fsm/@name»_ERR_LOG_HEX("computing condition «@name» failed", status);
|
vb@2829
|
994 |
return invalid_condition;
|
krista@2271
|
995 |
}
|
vb@2829
|
996 |
if (result) {
|
vb@2843
|
997 |
«$fsm/@name»_SERVICE_LOG("condition applies", "«@name»");
|
vb@2829
|
998 |
||
|
vb@2907
|
999 |
apply "transition|action|condition|else|send";
|
vb@2907
|
1000 |
| }
|
vb@2907
|
1001 |
}
|
vb@2907
|
1002 |
|
vb@2907
|
1003 |
template "else" {
|
vb@2907
|
1004 |
if "not(name(preceding-sibling::*[last()]) = 'condition')"
|
vb@2907
|
1005 |
error "else without if";
|
vb@2907
|
1006 |
|
vb@2907
|
1007 |
| else {
|
vb@2907
|
1008 |
|> «ancestor::fsm/@name»_SERVICE_LOG("condition does not apply", "«preceding-sibling::*[last()]/@name»");
|
vb@2907
|
1009 |
apply "transition|action|condition|else|send";
|
krista@2271
|
1010 |
| }
|
krista@2271
|
1011 |
}
|
krista@2271
|
1012 |
}
|
krista@2271
|
1013 |
|