sync/gen_statemachine.ysl2
author Edouard Tisserant <edouard@pep-project.org>
Sat, 26 Nov 2016 03:54:06 +0100
branchENGINE-133
changeset 1445 5d233bcdde76
parent 1356 ac3e66355937
child 1460 66ceb5a7f718
permissions -rw-r--r--
ENGINE-133 added timeout in sync state machine, relying on callback sync message retrieve timeout - adapters need update
     1 // generate state machine code
     2 
     3 // Copyleft (c) 2016, p≡p foundation
     4 
     5 // Written by Volker Birk
     6 
     7 include yslt.yml2
     8 
     9 tstylesheet {
    10     include ./functions.ysl2
    11 
    12     template "/protocol" {
    13         document "../src/Makefile.protocols", "text"
    14             apply "fsm", 0, mode="make";
    15         apply "fsm", 0, mode=gen;
    16     }
    17 
    18     template "fsm", mode=make
    19     ||
    20     «@filename»_fsm.c: ../sync/devicegroup.fsm
    21     \tmake -C ../«@filename»
    22     ||
    23 
    24     template "fsm", mode=gen {
    25         document "../src/{@filename}_fsm.h", "text" {
    26         ||
    27         #pragma once
    28 
    29         // state machine for «@name»
    30 
    31         #include "message_api.h"
    32         
    33         #ifdef __cplusplus
    34         extern "C" {
    35         #endif
    36 
    37         // types
    38 
    39         typedef pEp_identity * Identity;
    40         typedef stringlist_t * Stringlist;
    41         typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
    42 
    43         // error values
    44 
    45         typedef enum _fsm_error {
    46             // these error values are corresponding to
    47             // PEP_SYNC_STATEMACHINE_ERROR - value
    48             invalid_state = -2,
    49             invalid_event = -3,
    50             invalid_condition = -4,
    51             invalid_action = -5,
    52 
    53             // out of memory condition
    54             invalid_out_of_memory = -128
    55         } fsm_error;
    56 
    57         // conditions
    58 
    59         `` for "func:distinctName(condition)" | int «@name»(PEP_SESSION session`apply "parm", 0`);
    60 
    61         // states
    62 
    63         typedef enum _«@name»_state {
    64             // error values also in this namespace
    65             «@name»_state_invalid_state = (int) invalid_state,
    66             «@name»_state_invalid_event = (int) invalid_event,
    67             «@name»_state_invalid_condition = (int) invalid_condition,
    68             «@name»_state_invalid_action = (int) invalid_action,
    69             «@name»_state_invalid_out_of_memory = (int) invalid_out_of_memory,
    70 
    71             «@name»_state_NONE = 0,
    72         `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
    73         } «@name»_state;
    74 
    75         // events
    76 
    77         typedef enum _«@name»_event {
    78             «@name»_event_NONE = 0,
    79         ||
    80         for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
    81             const "name", "@name";
    82             |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
    83         }
    84         for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
    85             |> «@name»`if "position()!=last()" > , `
    86         ||
    87         } «@name»_event;
    88 
    89         // actions
    90 
    91         `` const "name", "@name"
    92         `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
    93 
    94         // event injector
    95 
    96         PEP_STATUS inject_DeviceState_event(
    97             PEP_SESSION session, 
    98             DeviceState_event event,
    99             Identity partner,
   100             void *extra);
   101 
   102         // message receiver
   103         
   104         PEP_STATUS receive_DeviceState_msg(
   105                 PEP_SESSION session, 
   106                 message *src, 
   107                 PEP_rating rating, 
   108                 stringlist_t *keylist
   109             );
   110 
   111         // state machine
   112 
   113         «@name»_state fsm_«@name»(
   114                 PEP_SESSION session,
   115                 «@name»_state state,
   116                 «@name»_event event,
   117                 Identity partner,
   118                 void *extra,
   119                 time_t *timeout
   120             );
   121 
   122         // driver
   123 
   124         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   125                 PEP_SESSION session,
   126                 «@name»_event event,
   127                 Identity partner,
   128                 void *extra,
   129                 time_t *timeout
   130             );
   131 
   132         #ifdef __cplusplus
   133         }
   134         #endif
   135 
   136         ||
   137         }
   138         document "../src/{@filename}_driver.c", "text"
   139         ||
   140         // Driver for «@name» state machine
   141 
   142         #include <assert.h>
   143         #include "pEp_internal.h"
   144 
   145 
   146         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   147                 PEP_SESSION session,
   148                 «@name»_event event,
   149                 Identity partner,
   150                 void *extra,
   151                 time_t *timeout
   152             )
   153         {
   154             assert(session);
   155             if (!session)
   156                 return PEP_ILLEGAL_VALUE;
   157 
   158             while(true)
   159             {
   160                 «@name»_state new_state = fsm_«@name»(session,
   161                     session->«@filename»_state, event, partner, extra, timeout);
   162 
   163                 if (new_state == «@name»_state_invalid_out_of_memory)
   164                     return PEP_OUT_OF_MEMORY;
   165 
   166                 if (new_state < 0)
   167                     return PEP_SYNC_STATEMACHINE_ERROR - new_state;
   168                 
   169                 if (new_state == session->«@filename»_state)
   170                     break;
   171 
   172                 event = Init;
   173                 extra = NULL;
   174                 session->«@filename»_state = new_state;
   175             } 
   176 
   177             return PEP_STATUS_OK;
   178         }
   179 
   180         ||
   181         document "../src/{@filename}_fsm.c", "text"
   182         ||
   183         #include "«@filename»_fsm.h"
   184 
   185         // state machine for «@name»
   186 
   187         «@name»_state fsm_«@name»(
   188                 PEP_SESSION session,
   189                 «@name»_state state,
   190                 «@name»_event event,
   191                 Identity partner,
   192                 void *extra,
   193                 time_t *timeout
   194             )
   195         {
   196             int cond_result;
   197             PEP_STATUS status = PEP_STATUS_OK;
   198 
   199             switch (state) {
   200             `` apply "state", 2
   201                 default:
   202                     return («@name»_state) invalid_state;
   203             }
   204 
   205             return state;
   206         }
   207 
   208         ||
   209     }
   210 
   211     template "state"
   212     ||
   213     case «@name»:
   214         *timeout = «@timeout»;
   215         switch (event) {
   216         `` if "not(event[@name='Init'])" |>> case Init: break;
   217         `` apply "event", 2
   218             default:
   219                 return («../@name»_state) invalid_event;
   220         }
   221         break;
   222 
   223     ||
   224 
   225     template "event"
   226     ||
   227     case «@name»:
   228     `` apply "action|transition|condition";
   229     `` if "name(*[position()=last()]) != 'transition'" |> break;
   230     ||
   231 
   232     template "action" {
   233         indent(0);
   234         > status = «@name»(session, state, 
   235         choose {
   236             when "parm" > «name(parm/*)»
   237             otherwise > NULL
   238         }
   239         choose {
   240             when "parm[2]" > , extra /*«name(parm[2]/*)»*/
   241             otherwise > , NULL
   242         }
   243         > );\n
   244         | if (status == PEP_OUT_OF_MEMORY)
   245         |> return (int) invalid_out_of_memory;
   246         | if (status != PEP_STATUS_OK)
   247         |> return (int) invalid_action;
   248     }
   249 
   250     template "condition" {
   251         | cond_result = «@name»(session`apply "parm", 0`);
   252         | if (cond_result < 0)
   253         |> return cond_result;
   254         | if (cond_result) {
   255         apply "action|transition|condition";
   256         | }
   257     }
   258 
   259     template "parm" choose {
   260         when "count(*) = 1"
   261             > , «name(*)»
   262         otherwise
   263             > , «name(*[1])» «name(*[2])»
   264     }
   265 
   266     template "transition" | return «@target»;
   267 }
   268