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