1 // This file is under GNU General Public License 3.0
4 // generate message functions
6 // Copyleft (c) 2017-2019, p≡p foundation
8 // Written by Volker Birk
14 include standardlib.ysl2
15 include ./functions.ysl2
18 apply "protocol", 0, mode=header;
19 apply "protocol", 0, mode=impl;
22 template "protocol", mode=header
23 document "generated/{@name}_func.h", "text"
25 // This file is under GNU General Public License 3.0
36 #include "../asn.1/«@name».h"
37 `` for "func:distinctType(fsm/message/field[not(func:basicType())])" | #include "../asn.1/«@type».h"
41 struct «@name»_state_s {
44 struct own_«@name»_state_s {
46 identity_list *identities;
48 // TIDs we're using ourselves
49 `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
52 // state we learned about our communication partner
54 struct comm_partner_state_s {
55 // transport data we expect
58 // TIDs our comm partner wants to have
59 `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
62 // input buffer for actual transport data coming in
64 struct transport_data_s {
65 // transport data we got
69 `` apply "fsm", mode=state
72 void free_«@name»_state(PEP_SESSION session);
74 // functions for protocol «@name»
76 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type);
77 void free_«@name»_message(«@name»_t *msg);
79 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
80 «@name»_PR *fsm, int *message_type);
82 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg);
90 template "fsm", mode=state
93 // input/output buffer for «@name» messages
95 struct _«@name»_state_s {
98 `` for "func:distinctName(message/field)" |> «func:ctype()» «@name»;
102 template "protocol", mode=impl
103 document "generated/{@name}_func.c", "text" {
105 // This file is under GNU General Public License 3.0
110 #include "pEp_internal.h"
111 #include "map_asn1.h"
112 #include "«@name»_func.h"
113 `` for "fsm" | #include "«@name»_fsm.h"
115 void free_«@name»_state(PEP_SESSION session)
122 free_stringlist(session->«yml:lcase(@name)»_state.own.keys);
123 session->«yml:lcase(@name)»_state.own.keys = NULL;
124 free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
125 session->«yml:lcase(@name)»_state.own.identities = NULL;
127 // TIDs we're using ourselves
129 for "func:distinctName(fsm/message/field[@type='TID'])"
130 |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.own.«@name»);
133 // state we learned about our communication partner
135 free(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
136 session->«yml:lcase(@name)»_state.comm_partner.sender_fpr = NULL;
138 // TIDs our comm partner wants to have
140 for "func:distinctName(fsm/message/field[@type='TID'])"
141 |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.comm_partner.«@name»);
144 // buffer for transport data
146 free_identity(session->«yml:lcase(@name)»_state.transport.from);
147 session->«yml:lcase(@name)»_state.transport.from = NULL;
148 free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
149 session->«yml:lcase(@name)»_state.transport.sender_fpr = NULL;
155 for "func:distinctName(message/field[not(substring(@type,1,1)=yml:lcase(substring(@type,1,1)))])"
156 |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
160 memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
163 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type)
165 «@name»_t *msg = calloc(sizeof(«@name»_t), 1);
174 `` apply "fsm", 4, mode=impl
185 void free_«@name»_message(«@name»_t *msg)
187 ASN_STRUCT_FREE(asn_DEF_«@name», msg);
190 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
191 «@name»_PR *fsm, int *message_type)
195 assert(session && msg && fsm && message_type);
196 if (!(session && msg && fsm && message_type))
197 return PEP_ILLEGAL_VALUE;
200 *message_type = None;
202 switch (msg->present) {
203 case «@name»_PR_NOTHING:
204 return PEP_ILLEGAL_VALUE;
206 `` apply "fsm", 2, mode=update_state
208 return PEP_ILLEGAL_VALUE;
212 return PEP_STATUS_OK;
215 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg)
217 assert(session && msg);
218 if (!(session && msg))
219 return PEP_ILLEGAL_VALUE;
221 int fsm = msg->present;
223 case «@name»_PR_NOTHING:
224 return PEP_ILLEGAL_VALUE;
226 `` apply "fsm", 2, mode=update_message
228 return PEP_ILLEGAL_VALUE;
231 return PEP_STATUS_OK;
237 template "fsm", mode=update_message
239 case «../@name»_PR_«yml:lcase(@name)»:
241 int message_type = msg->choice.«yml:lcase(@name)».present;
242 switch (message_type) {
243 case «@name»_PR_NOTHING:
244 return PEP_ILLEGAL_VALUE;
246 `` apply "message", 2, mode=update_message
248 return PEP_ILLEGAL_VALUE;
254 template "message", mode=update_message {
256 case «../@name»_PR_«yml:mixedCase(@name)»:
258 `` apply "field", mode=update_message
264 template "auto" choose {
265 when "@type = 'Version'" {
266 const "fsm", "ancestor::fsm";
269 long *major = (long *) malloc(sizeof(long));
270 long *minor = (long *) malloc(sizeof(long));
271 assert(major && minor);
272 if (!(major && minor))
273 return PEP_OUT_OF_MEMORY;
275 *major = «$fsm/version/@major»;
276 *minor = «$fsm/version/@minor»;
278 msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».major = major;
279 msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».minor = minor;
286 error "unkown type for auto in message: {@type}; allowed types: Version";
289 template "field", mode=update_message {
290 const "message_name", "yml:mixedCase(../@name)";
291 const "state" > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
294 when "func:basicType()" // copyable
296 msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»
297 = session->«$state».«@name»;
300 when "@type='Identity'"
303 pEp_identity *ident = Identity_to_Struct(&session->«$state».«@name», NULL);
305 return PEP_OUT_OF_MEMORY;
306 Identity_t *_ident = Identity_from_Struct(ident,
307 &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
308 free_identity(ident);
310 return PEP_OUT_OF_MEMORY;
314 when "@type='IdentityList'"
317 identity_list *il = IdentityList_to_identity_list(
318 &session->«$state».«@name», NULL);
320 return PEP_OUT_OF_MEMORY;
321 IdentityList_t *_il = IdentityList_from_identity_list(il,
322 &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
323 free_identity_list(il);
325 return PEP_OUT_OF_MEMORY;
329 otherwise // string based
332 int result = OCTET_STRING_fromBuf(
333 &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»,
334 (char *) session->«$state».«@name».buf,
335 session->«$state».«@name».size
338 return PEP_OUT_OF_MEMORY;
344 template "fsm", mode=update_state
346 case «../@name»_PR_«yml:lcase(@name)»:
347 switch (msg->choice.«yml:lcase(@name)».present) {
348 case «@name»_PR_NOTHING:
349 return PEP_ILLEGAL_VALUE;
351 `` apply "message", 2, mode=update_state
353 return PEP_ILLEGAL_VALUE;
359 template "message", mode=update_state {
360 const "message_name", "concat(yml:lcase(substring(@name,1,1)), substring(@name,2))";
362 case «../@name»_PR_«$message_name»:
363 `` apply "field", mode=update_state with "message_name", "$message_name"
364 *message_type = «yml:capit($message_name)»;
370 template "field", mode=update_state {
371 param "message_name";
373 when "func:basicType()" // copyable
375 session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name» = msg->choice.«yml:lcase(../../@name)»
376 .choice.«$message_name».«@name»;
379 when "@type='Identity'"
382 pEp_identity *ident = Identity_to_Struct(
383 &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
385 return PEP_OUT_OF_MEMORY;
386 Identity_t *_ident = Identity_from_Struct(ident,
387 &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
388 free_identity(ident);
390 return PEP_OUT_OF_MEMORY;
394 when "@type='IdentityList'"
397 identity_list *il = IdentityList_to_identity_list(
398 &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
400 return PEP_OUT_OF_MEMORY;
401 IdentityList_t *_il = IdentityList_from_identity_list(il,
402 &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
403 free_identity_list(il);
405 return PEP_OUT_OF_MEMORY;
409 otherwise // string based
411 result = OCTET_STRING_fromBuf(&session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»,
412 (char *) msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».buf,
413 msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».size);
415 return PEP_OUT_OF_MEMORY;
421 template "fsm", mode=impl
423 case «../@name»_PR_«yml:lcase(@name)»:
424 msg->choice.«yml:lcase(@name)».present = message_type;