sync/gen_message_func.ysl2
author Neal H. Walfield <neal@pep.foundation>
Wed, 08 May 2019 12:20:37 +0200
branchemail_comparison
changeset 3649 1dd837adc30b
parent 3616 8229562ff2a1
child 3767 11a9d0f61073
permissions -rw-r--r--
Fix public key.
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 // generate message functions
     5 
     6 // Copyleft (c) 2017-2019, p≡p foundation
     7 
     8 // Written by Volker Birk
     9 
    10 include yslt.yml2
    11 
    12 tstylesheet {
    13 
    14 include standardlib.ysl2
    15 include ./functions.ysl2
    16 
    17 template "/" {
    18     apply "protocol", 0, mode=header;
    19     apply "protocol", 0, mode=impl;
    20 }
    21 
    22 template "protocol", mode=header
    23     document "generated/{@name}_func.h", "text"
    24 ||
    25 // This file is under GNU General Public License 3.0
    26 // see LICENSE.txt
    27 
    28 #pragma once
    29 
    30 #ifdef __cplusplus
    31 extern "C" {
    32 #endif
    33 
    34 #include <stdbool.h>
    35 
    36 #include "../asn.1/«@name».h"
    37 `` for "func:distinctType(fsm/message/field[not(func:basicType())])" | #include "../asn.1/«@type».h"
    38 
    39 // state
    40 
    41 struct «@name»_state_s {
    42     // common buffer for all types of «@name» messages
    43 
    44     struct common_state_s {
    45         // intermediate store own challenge
    46         TID_t challenge;
    47 
    48         // transport data
    49         pEp_identity *from;
    50         char *signature_fpr;
    51     } common;
    52     `` apply "fsm", mode=state
    53 };
    54 
    55 // own state
    56 
    57 struct own_«@name»_state_s {
    58     stringlist_t *own_keys;
    59     identity_list *own_identities;
    60 
    61     `` if "func:distinctName(fsm/message/field[@type='TID'])" |> // active TIDs
    62     `` for "func:distinctName(fsm/message/field[@type='TID'])" |> «func:ctype()» «@name»;
    63 
    64     // transport data
    65     char *signature_fpr;
    66 };
    67 
    68 void free_«@name»_state(PEP_SESSION session);
    69 
    70 // functions for protocol «@name»
    71 
    72 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type);
    73 void free_«@name»_message(«@name»_t *msg);
    74 
    75 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
    76         «@name»_PR *fsm, int *message_type);
    77 
    78 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg);
    79 
    80 #ifdef __cplusplus
    81 }
    82 #endif
    83 
    84 ||
    85 
    86 template "fsm", mode=state
    87 ||
    88 
    89 // buffer for «@name» messages
    90 
    91 struct _«@name»_state_s {
    92     int state;
    93 
    94     `` for "func:distinctName(message/field)" |> «func:ctype()» «@name»;
    95 } «yml:lcase(@name)»;
    96 ||
    97 
    98 template "protocol", mode=impl
    99     document "generated/{@name}_func.c", "text" {
   100 ||
   101 // This file is under GNU General Public License 3.0
   102 // see LICENSE.txt
   103 
   104 #include <assert.h>
   105 #include <stdlib.h>
   106 #include "pEp_internal.h"
   107 #include "map_asn1.h"
   108 #include "«@name»_func.h"
   109 `` for "fsm" | #include "«@name»_fsm.h"
   110 
   111 void free_«@name»_state(PEP_SESSION session)
   112 {
   113     if (!session)
   114         return;
   115 
   116     free_identity(session->«yml:lcase(@name)»_state.common.from);
   117     free(session->«yml:lcase(@name)»_state.common.signature_fpr);
   118     free_stringlist(session->own_«yml:lcase(@name)»_state.own_keys);
   119     free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
   120     session->own_«yml:lcase(@name)»_state.own_keys = NULL;
   121     session->own_«yml:lcase(@name)»_state.own_identities = NULL;
   122 
   123 ||
   124 for "fsm"
   125     for "func:distinctName(message/field[not(func:basicType())])"
   126         |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   127 for "func:distinctName(fsm/message/field[@type='TID'])"
   128     |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->own_«yml:lcase(../../../@name)»_state.«@name»);
   129 ||
   130 
   131     memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
   132 }
   133 
   134 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type)
   135 {
   136     «@name»_t *msg = calloc(sizeof(«@name»_t), 1);
   137     assert(msg);
   138     if (!msg)
   139         return NULL;
   140 
   141     if (fsm) {
   142         msg->present = fsm;
   143         if (message_type) {
   144             switch (fsm) {
   145                 `` apply "fsm", 4, mode=impl
   146                 default:
   147                     free(msg);
   148                     return NULL;
   149             }
   150         }
   151     }
   152 
   153     return msg;
   154 }
   155 
   156 void free_«@name»_message(«@name»_t *msg)
   157 {
   158     ASN_STRUCT_FREE(asn_DEF_«@name», msg);
   159 }
   160 
   161 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
   162         «@name»_PR *fsm, int *message_type)
   163 {
   164     int result = 0;
   165 
   166     assert(session && msg && fsm && message_type);
   167     if (!(session && msg && fsm && message_type))
   168         return PEP_ILLEGAL_VALUE;
   169 
   170     *fsm = 0;
   171     *message_type = None;
   172 
   173     switch (msg->present) {
   174         case «@name»_PR_NOTHING:
   175             return PEP_ILLEGAL_VALUE;
   176 
   177         `` apply "fsm", 2, mode=update_state
   178         default:
   179             return PEP_ILLEGAL_VALUE;
   180     }
   181 
   182     *fsm = msg->present;
   183     return PEP_STATUS_OK;
   184 }
   185 
   186 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg)
   187 {
   188     assert(session && msg);
   189     if (!(session && msg))
   190         return PEP_ILLEGAL_VALUE;
   191 
   192     int fsm = msg->present;
   193     switch (fsm) {
   194         case «@name»_PR_NOTHING:
   195             return PEP_ILLEGAL_VALUE;
   196 
   197         `` apply "fsm", 2, mode=update_message
   198         default:
   199             return PEP_ILLEGAL_VALUE;
   200     }
   201 
   202     return PEP_STATUS_OK;
   203 }
   204 
   205 ||
   206 }
   207 
   208 template "fsm", mode=update_message
   209 ||
   210 case «../@name»_PR_«yml:lcase(@name)»:
   211     {
   212         int message_type = msg->choice.«yml:lcase(@name)».present;
   213         switch (message_type) {
   214             case «@name»_PR_NOTHING:
   215                 return PEP_ILLEGAL_VALUE;
   216 
   217             `` apply "message", 2, mode=update_message
   218             default:
   219                 return PEP_ILLEGAL_VALUE;
   220         }
   221         break;
   222     }
   223 ||
   224 
   225 template "message", mode=update_message {
   226     ||
   227     case «../@name»_PR_«yml:mixedCase(@name)»:
   228         `` apply "auto"
   229         `` apply "field", mode=update_message
   230         break;
   231 
   232     ||
   233 }
   234 
   235 template "auto" choose {
   236     when "@type = 'Version'" {
   237         const "fsm", "ancestor::fsm";
   238         ||
   239         {
   240             long *major = (long *) malloc(sizeof(long));
   241             long *minor = (long *) malloc(sizeof(long));
   242             assert(major && minor);
   243             if (!(major && minor))
   244                 return PEP_OUT_OF_MEMORY;
   245 
   246             *major = «$fsm/version/@major»;
   247             *minor = «$fsm/version/@minor»;
   248 
   249             msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».major = major;
   250             msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».minor = minor;
   251         }
   252 
   253         ||
   254     }
   255 
   256     otherwise
   257         error "unkown type for auto in message: {@type}; allowed types: Version";
   258 }
   259 
   260 template "field", mode=update_message {
   261     const "message_name", "yml:mixedCase(../@name)";
   262     const "state" choose {
   263         when "@type='TID'"
   264             > own_«yml:lcase(ancestor::protocol/@name)»_state
   265         otherwise
   266             > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
   267     }
   268 
   269     choose {
   270         when "func:basicType()" // copyable
   271         ||
   272         msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»
   273                  = session->«$state».«@name»;
   274 
   275         ||
   276         when "@type='IdentityList'"
   277         ||
   278         {
   279             identity_list *il = IdentityList_to_identity_list(
   280                     &session->«$state».«@name», NULL);
   281             if (!il)
   282                 return PEP_OUT_OF_MEMORY;
   283             IdentityList_t *_il = IdentityList_from_identity_list(il,
   284                     &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
   285             free_identity_list(il);
   286             if (!_il)
   287                 return PEP_OUT_OF_MEMORY;
   288         }
   289 
   290         ||
   291         otherwise // string based
   292         ||
   293         {
   294             int result = OCTET_STRING_fromBuf(
   295                     &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»,
   296                     (char *) session->«$state».«@name».buf,
   297                     session->«$state».«@name».size
   298                 );
   299             if (result)
   300                 return PEP_OUT_OF_MEMORY;
   301         }
   302         ||
   303     }
   304 }
   305 
   306 template "fsm", mode=update_state
   307 ||
   308 case «../@name»_PR_«yml:lcase(@name)»:
   309     switch (msg->choice.«yml:lcase(@name)».present) {
   310         case «@name»_PR_NOTHING:
   311             return PEP_ILLEGAL_VALUE;
   312 
   313         `` apply "message", 2, mode=update_state
   314         default:
   315             return PEP_ILLEGAL_VALUE;
   316     }
   317     break;
   318 
   319 ||
   320 
   321 template "message", mode=update_state {
   322     const "message_name", "concat(yml:lcase(substring(@name,1,1)), substring(@name,2))";
   323     ||
   324     case «../@name»_PR_«$message_name»:
   325         `` apply "field", mode=update_state with "message_name", "$message_name"
   326         *message_type = «yml:capit($message_name)»;
   327         break;
   328 
   329     ||
   330 }
   331 
   332 template "field", mode=update_state {
   333     param "message_name";
   334     choose {
   335         when "func:basicType()" // copyable
   336         ||
   337         session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name» = msg->choice.«yml:lcase(../../@name)»
   338                 .choice.«$message_name».«@name»;
   339 
   340         ||
   341         when "@type='IdentityList'"
   342         ||
   343         {
   344             identity_list *il = IdentityList_to_identity_list(
   345                     &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
   346             if (!il)
   347                 return PEP_OUT_OF_MEMORY;
   348             IdentityList_t *_il = IdentityList_from_identity_list(il,
   349                     &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   350             free_identity_list(il);
   351             if (!_il)
   352                 return PEP_OUT_OF_MEMORY;
   353         }
   354 
   355         ||
   356         otherwise // string based
   357         ||
   358         result = OCTET_STRING_fromBuf(&session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»,
   359                 (char *) msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».buf,
   360                 msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».size);
   361         if (result)
   362             return PEP_OUT_OF_MEMORY;
   363 
   364         ||
   365     }
   366 }
   367 
   368 template "fsm", mode=impl
   369 ||
   370 case «../@name»_PR_«yml:lcase(@name)»:
   371     msg->choice.«yml:lcase(@name)».present = message_type;
   372         break;
   373 
   374 ||
   375 
   376 }
   377