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