sync/gen_message_func.ysl2
author Volker Birk <vb@pep.foundation>
Wed, 29 Aug 2018 21:49:28 +0200
branchsync
changeset 2903 33549a7c7191
parent 2864 dcbed0d35466
child 3123 2475e49c3154
permissions -rw-r--r--
safeguards
     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, 2018, 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     struct common_state_s {
    43         pEp_identity *from;
    44     } common;
    45 
    46     `` apply "fsm", mode=state
    47 };
    48 
    49 struct own_«@name»_state_s {
    50     `` for "func:distinctName(fsm/message/field[@type='TID'])" |> «func:ctype()» «@name»;
    51 };
    52 
    53 void free_«@name»_state(PEP_SESSION session);
    54 
    55 // functions for protocol «@name»
    56 
    57 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type);
    58 void free_«@name»_message(«@name»_t *msg);
    59 
    60 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
    61         «@name»_PR *fsm, int *message_type);
    62 
    63 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg);
    64 
    65 #ifdef __cplusplus
    66 }
    67 #endif
    68 
    69 ||
    70 
    71 template "fsm", mode=state
    72 ||
    73 struct _«@name»_state_s {
    74     int state;
    75 
    76     `` for "func:distinctName(message/field)" |> «func:ctype()» «@name»;
    77 } «yml:lcase(@name)»;
    78 ||
    79 
    80 template "protocol", mode=impl
    81     document "generated/{@name}_func.c", "text" {
    82 ||
    83 // This file is under GNU General Public License 3.0
    84 // see LICENSE.txt
    85 
    86 #include <assert.h>
    87 #include <stdlib.h>
    88 #include "pEp_internal.h"
    89 #include "map_asn1.h"
    90 #include "«@name»_func.h"
    91 
    92 void free_«@name»_state(PEP_SESSION session)
    93 {
    94     if (!session)
    95         return;
    96 
    97     free_identity(session->«yml:lcase(@name)»_state.common.from);
    98 
    99 ||
   100 for "fsm"
   101     for "func:distinctName(message/field[not(func:basicType())])"
   102         |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   103 for "func:distinctName(fsm/message/field[@type='TID'])"
   104     |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->own_«yml:lcase(../../../@name)»_state.«@name»);
   105 ||
   106 
   107     memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
   108 }
   109 
   110 «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type)
   111 {
   112     «@name»_t *msg = calloc(sizeof(«@name»_t), 1);
   113     assert(msg);
   114     if (!msg)
   115         return NULL;
   116 
   117     if (fsm) {
   118         msg->present = fsm;
   119         if (message_type) {
   120             switch (fsm) {
   121                 `` apply "fsm", 4, mode=impl
   122                 default:
   123                     free(msg);
   124                     return NULL;
   125             }
   126         }
   127     }
   128 
   129     return msg;
   130 }
   131 
   132 void free_«@name»_message(«@name»_t *msg)
   133 {
   134     ASN_STRUCT_FREE(asn_DEF_«@name», msg);
   135 }
   136 
   137 PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
   138         «@name»_PR *fsm, int *message_type)
   139 {
   140     int result = 0;
   141 
   142     assert(session && msg && fsm && message_type);
   143     if (!(session && msg && fsm && message_type))
   144         return PEP_ILLEGAL_VALUE;
   145 
   146     *fsm = 0;
   147     *message_type = 0;
   148 
   149     switch (msg->present) {
   150         case «@name»_PR_NOTHING:
   151             return PEP_ILLEGAL_VALUE;
   152 
   153         `` apply "fsm", 2, mode=update_state
   154         default:
   155             return PEP_ILLEGAL_VALUE;
   156     }
   157 
   158     *fsm = msg->present;
   159     return PEP_STATUS_OK;
   160 }
   161 
   162 PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg)
   163 {
   164     assert(session && msg);
   165     if (!(session && msg))
   166         return PEP_ILLEGAL_VALUE;
   167 
   168     int fsm = msg->present;
   169     switch (fsm) {
   170         case «@name»_PR_NOTHING:
   171             return PEP_ILLEGAL_VALUE;
   172 
   173         `` apply "fsm", 2, mode=update_message
   174         default:
   175             return PEP_ILLEGAL_VALUE;
   176     }
   177 
   178     return PEP_STATUS_OK;
   179 }
   180 
   181 ||
   182 }
   183 
   184 template "fsm", mode=update_message
   185 ||
   186 case «../@name»_PR_«yml:lcase(@name)»:
   187     {
   188         static long sequence = 0;
   189         msg->choice.«yml:lcase(@name)».header.sequence = ++sequence;
   190         int message_type = msg->choice.«yml:lcase(@name)».payload.present;
   191         switch (message_type) {
   192             case «@name»__payload_PR_NOTHING:
   193                 return PEP_ILLEGAL_VALUE;
   194 
   195             `` apply "message", 2, mode=update_message
   196             default:
   197                 return PEP_ILLEGAL_VALUE;
   198         }
   199         break;
   200     }
   201 ||
   202 
   203 template "message", mode=update_message {
   204     ||
   205     case «../@name»__payload_PR_«yml:mixedCase(@name)»:
   206         `` apply "auto"
   207         `` apply "field", mode=update_message
   208         break;
   209 
   210     ||
   211 }
   212 
   213 template "auto" choose {
   214     when "@type = 'Version'" {
   215         const "fsm", "ancestor::fsm";
   216         ||
   217         {
   218             long *major = (long *) malloc(sizeof(long));
   219             long *minor = (long *) malloc(sizeof(long));
   220             assert(major && minor);
   221             if (!(major && minor))
   222                 return PEP_OUT_OF_MEMORY;
   223 
   224             *major = «$fsm/version/@major»;
   225             *minor = «$fsm/version/@minor»;
   226 
   227             msg->choice.«yml:lcase($fsm/@name)».payload.choice.«yml:mixedCase(../@name)».«@name».major = major;
   228             msg->choice.«yml:lcase($fsm/@name)».payload.choice.«yml:mixedCase(../@name)».«@name».minor = minor;
   229         }
   230 
   231         ||
   232     }
   233 
   234     otherwise
   235         error "unkown type for auto in message: {@type}; allowed types: Version";
   236 }
   237 
   238 template "field", mode=update_message {
   239     const "message_name", "yml:mixedCase(../@name)";
   240     const "state" choose {
   241         when "@type='TID'"
   242             > own_«yml:lcase(ancestor::protocol/@name)»_state
   243         otherwise
   244             > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
   245     }
   246 
   247     choose {
   248         when "func:basicType()" // copyable
   249         ||
   250         msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name»
   251                  = session->«$state».«@name»;
   252 
   253         ||
   254         when "@type='IdentityList'"
   255         ||
   256         {
   257             identity_list *il = IdentityList_to_identity_list(
   258                     &session->«$state».«@name», NULL);
   259             if (!il)
   260                 return PEP_OUT_OF_MEMORY;
   261             IdentityList_t *_il = IdentityList_from_identity_list(il,
   262                     &msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name»);
   263             free_identity_list(il);
   264             if (!_il)
   265                 return PEP_OUT_OF_MEMORY;
   266         }
   267 
   268         ||
   269         otherwise // string based
   270         ||
   271         {
   272             int result = OCTET_STRING_fromBuf(
   273                     &msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name»,
   274                     (char *) session->«$state».«@name».buf,
   275                     session->«$state».«@name».size
   276                 );
   277             if (result)
   278                 return PEP_OUT_OF_MEMORY;
   279         }
   280         ||
   281     }
   282 }
   283 
   284 template "fsm", mode=update_state
   285 ||
   286 case «../@name»_PR_«yml:lcase(@name)»:
   287     switch (msg->choice.«yml:lcase(@name)».payload.present) {
   288         case «@name»__payload_PR_NOTHING:
   289             return PEP_ILLEGAL_VALUE;
   290 
   291         `` apply "message", 2, mode=update_state
   292         default:
   293             return PEP_ILLEGAL_VALUE;
   294     }
   295     *message_type = msg->choice.«yml:lcase(@name)».payload.present;
   296     break;
   297 
   298 ||
   299 
   300 template "message", mode=update_state {
   301     const "message_name", "concat(yml:lcase(substring(@name,1,1)), substring(@name,2))";
   302     ||
   303     case «../@name»__payload_PR_«$message_name»:
   304         `` apply "field", mode=update_state with "message_name", "$message_name"
   305         break;
   306 
   307     ||
   308 }
   309 
   310 template "field", mode=update_state {
   311     param "message_name";
   312     choose {
   313         when "func:basicType()" // copyable
   314         ||
   315         session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name» = msg->choice.«yml:lcase(../../@name)»
   316                 .payload.choice.«$message_name».«@name»;
   317 
   318         ||
   319         when "@type='IdentityList'"
   320         ||
   321         {
   322             identity_list *il = IdentityList_to_identity_list(
   323                     &msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name», NULL);
   324             if (!il)
   325                 return PEP_OUT_OF_MEMORY;
   326             IdentityList_t *_il = IdentityList_from_identity_list(il,
   327                     &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   328             free_identity_list(il);
   329             if (!_il)
   330                 return PEP_OUT_OF_MEMORY;
   331         }
   332 
   333         ||
   334         otherwise // string based
   335         ||
   336         result = OCTET_STRING_fromBuf(&session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»,
   337                 (char *) msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name».buf,
   338                 msg->choice.«yml:lcase(../../@name)».payload.choice.«$message_name».«@name».size);
   339         if (result)
   340             return PEP_OUT_OF_MEMORY;
   341 
   342         ||
   343     }
   344 }
   345 
   346 template "fsm", mode=impl
   347 ||
   348 case «../@name»_PR_«yml:lcase(@name)»:
   349     msg->choice.«yml:lcase(@name)».payload.present = message_type;
   350         break;
   351 
   352 ||
   353 
   354 }
   355