Browse Source

sync: documentation, moved generated code, updated .hgignore, cleaning

ENGINE-155
Edouard Tisserant 6 years ago
parent
commit
a9e235546b
12 changed files with 831 additions and 24 deletions
  1. +6
    -3
      .hgignore
  2. +1
    -1
      src/pEpEngine.h
  3. +56
    -9
      src/sync.h
  4. +11
    -5
      sync/Makefile
  5. +2
    -2
      sync/gen_actions.ysl2
  6. +4
    -4
      sync/gen_statemachine.ysl2
  7. +11
    -0
      sync/generated/README
  8. +0
    -0
      sync/generated/sync_driver.c
  9. +361
    -0
      sync/generated/sync_fsm.c
  10. +0
    -0
      sync/generated/sync_fsm.h
  11. +0
    -0
      sync/generated/sync_send_actions.c
  12. +379
    -0
      sync/skeletons/sync_actions.c

+ 6
- 3
.hgignore View File

@ -33,14 +33,17 @@ build-linux/*
msg4.asc
pep_Dokument_Titel.pdf
pEpEngine.vcxproj.user
*.skeleton
.skeletons
.statemachines
Makefile.protocols
test/msg_encrypt_for_self.asc
tags
asn.1/pEpEngineASN1/pEpEngineASN1.vcxproj.user
src/sync_fsm.c
src/sync_fsm.h
src/sync_driver.c
src/sync_send_actions.c
sync/.actions
sync/.codegen
sync/.statemachines
*.xml
*.dot
*.svg


+ 1
- 1
src/pEpEngine.h View File

@ -74,7 +74,7 @@ typedef enum {
PEP_CONTRAINTS_VIOLATED = 0x0802,
PEP_CANNOT_ENCODE = 0x0803,
PEP_SYNC_NO_NOTIFY_CALLBACK = 0x0901,
PEP_SYNC_NO_NOTIFY_CALLBACK = 0x0901,
PEP_SYNC_ILLEGAL_MESSAGE = 0x0902,
PEP_SYNC_NO_INJECT_CALLBACK = 0x0903,


+ 56
- 9
src/sync.h View File

@ -1,13 +1,60 @@
/*
====================================
Engine/adapter/app KeySync interface
====================================
In the engine, KeySync is implemented through a state machine [1]. KeySync
state machine is driven [2] by events, triggering actions [3] and transitions
to new states. Events happens on decryption of email messages, on key
generation, on user interaction through the app and in case of timeout when
staying too long in some particular states.
To use KeySync, the adapter has to create a session dedicated to handle the
protocol, register some callbacks [4] to the engine, and then call protocol's
event consumer loop [5] in a dedicated thread. KeySync actions are executed
as callback invoked from that loop : send pEp messages through app's transport
and display KeySync status and handshake to the user.
When a session is attached [6] to a KeySync session, decryption of pEp (email)
messages in that session may trigger operations in attached KeySync session. In
case of an adapter capable to serve multiple apps, each app is associated to a
different KeySync session, and sessions created for use in that app are
attached to that session.
KeySync messages [7], not to be confused with pEp (email) messages, are either
directly events to be processed by the state machine or KeySync payloads
collected from decrypted messages. They are jobs to be processed by the state
machine.
KeySync messages can be emitted by multiple session, and could naturally come
from different threads. They must be serialized in a locked queue. Attached
sessions inject [8] KeySync messages in the queue. Protocol loop retrieves [9]
them from the queue. KeySync message is received [10] by the state machine,
where event eventually deduced from payload.
A state timeout event is a particular case. It doesn't traverse the queue, and
isn't emitted by a session. It is triggered by a timeout on the retrieve
operation. Value of the timeout is determined when entering a new state, and is
passed as a parameter of the call to the blocking queue retrieve operation on
next protocol loop iteraton.
[1] sync/device_group.fsm , src/sync_fsm.c (generated)
[2] src/sync_driver.c (generated)
[3] src/sync_actions.c , src/sync_send_actions.c (generated)
[4] register_sync_callbacks()
[5] do_sync_protocol()
[6] attach_sync_session()
[7] type sync_msg_t
[8] callback inject_sync_msg
[9] callback retrieve_next_sync_msg
[10] receive_sync_msg() (src/sync_impl.c)
*/
#pragma once
#include "message.h"
#include "sync_fsm.h"
// this module is for being used WITHOUT the Transport API in transport.h
// DO NOT USE IT WHEN USING Transport API!
#ifdef __cplusplus
extern "C" {
#endif
@ -89,16 +136,16 @@ typedef struct _sync_msg_t sync_msg_t;
typedef int (*inject_sync_msg_t)(void *msg, void *management);
// retrieve_next_sync_msg - receive next sync message
// retrieve_next_sync_msg - retrieve next sync message
//
// parameters:
// management (in) application defined
// timeout (in,out) do not wait longer than timeout for message
// timeout (in,out) do not wait longer than timeout for message (seconds)
//
// return value:
// next message or :
// NULL + timeout == 0 for termination
// NULL + timeout != 0 for timeout occurence
// NULL and timeout == 0 for termination
// NULL and timeout != 0 for timeout occurence
typedef void *(*retrieve_next_sync_msg_t)(void *management, time_t *timeout);


+ 11
- 5
sync/Makefile View File

@ -1,11 +1,15 @@
include ../Makefile.conf
all: .statemachines .skeletons
all: .codegen
skeleton: .skeletons
skeleton: .actions
.skeletons: devicegroup.fsm gen_actions_skeleton.ysl2 fsm.yml2 functions.ysl2
$(YML2PROC) -y gen_actions_skeleton.ysl2 $< -o $@
.codegen: .statemachines .actions
cp -f generated/*.* ../src
touch .codegen
.actions: devicegroup.fsm gen_actions.ysl2 fsm.yml2 functions.ysl2
$(YML2PROC) -y gen_actions.ysl2 $< -o $@
.statemachines: devicegroup.fsm gen_statemachine.ysl2 fsm.yml2 functions.ysl2
$(YML2PROC) -y gen_statemachine.ysl2 $< -o $@
@ -13,7 +17,9 @@ skeleton: .skeletons
.PHONY: clean
clean:
rm -f *.xml *.xsl ../src/sync_fsm.* ../src/*.skeleton .statemachines .skeletons *.dot *.svg
rm -f *.xml *.xsl \
$(pathsub generated/%, ../src/% $(wildcard generated/*.*)) \
../generated/* ../skeletons/* .statemachines .actions *.dot *.svg
%.xml: %.fsm
yml2c $< -o $@


sync/gen_actions_skeleton.ysl2 → sync/gen_actions.ysl2 View File


+ 4
- 4
sync/gen_statemachine.ysl2 View File

@ -11,7 +11,7 @@ tstylesheet {
include ./functions.ysl2
template "/protocol" {
document "../src/Makefile.protocols", "text"
document "generated/Makefile.protocols", "text"
apply "fsm", 0, mode="make";
apply "fsm", 0, mode=gen;
}
@ -23,7 +23,7 @@ tstylesheet {
||
template "fsm", mode=gen {
document "../src/{@filename}_fsm.h", "text" {
document "generated/{@filename}_fsm.h", "text" {
||
#pragma once
@ -136,7 +136,7 @@ tstylesheet {
||
}
document "../src/{@filename}_driver.c", "text"
document "generated/{@filename}_driver.c", "text"
||
// Driver for «@name» state machine
@ -179,7 +179,7 @@ tstylesheet {
}
||
document "../src/{@filename}_fsm.c", "text"
document "generated/{@filename}_fsm.c", "text"
||
#include "«@filename»_fsm.h"
#include "pEp_internal.h"


+ 11
- 0
sync/generated/README View File

@ -0,0 +1,11 @@
Code is generated here before beeing copied to /src during build process.
This code is intended to be commited and reviewed, while the original files
in src/ aren't tracked in mercurial (.hgignore).
Generated code must be generated out of source code systematically at build,
since generation could be influenced by build environment and parameters.
Depending on build host, version control tool or unharchiving tool, generated
files timestamp may prevent re-generation. They must then be excluded from repo.

src/sync_driver.c → sync/generated/sync_driver.c View File


+ 361
- 0
sync/generated/sync_fsm.c View File

@ -0,0 +1,361 @@
#include "sync_fsm.h"
#include "pEp_internal.h"
// state machine for DeviceState
DeviceState_state fsm_DeviceState(
PEP_SESSION session,
DeviceState_state state,
DeviceState_event event,
Identity partner,
void *extra,
time_t *timeout
)
{
int cond_result;
PEP_STATUS status = PEP_STATUS_OK;
switch (state) {
case InitState:
{
*timeout = 0;
switch (event) {
case Init:
{
cond_result = storedGroupKeys(session);
if (cond_result < 0)
return cond_result;
if (cond_result) {
return Grouped;
}
return Sole;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
case Sole:
{
*timeout = 0;
switch (event) {
case Init: break;
case KeyGen:
{
status = sendBeacon(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case CannotDecrypt:
{
status = sendBeacon(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case Beacon:
{
status = sendHandshakeRequest(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case HandshakeRequest:
{
status = sendHandshakeRequest(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
session->sync_state_payload = identity_dup(partner);
return HandshakingSole;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
case HandshakingSole:
{
Identity expected = (Identity)session->sync_state_payload;
*timeout = 600;
switch (event) {
case Init:
{
status = showHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case HandshakeRejected:
{
status = rejectHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Sole;
}
case HandshakeAccepted:
{
status = acceptHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
cond_result = keyElectionWon(session, partner);
if (cond_result < 0)
return cond_result;
if (cond_result) {
status = sendGroupKeys(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
status = handshakeGroupCreated(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Grouped;
}
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
session->sync_state_payload = identity_dup(partner);
return WaitForGroupKeysSole;
}
case Cancel:
{
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Sole;
}
case Timeout:
{
status = dismissHandshake(session, state, expected, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Sole;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
case WaitForGroupKeysSole:
{
Identity expected = (Identity)session->sync_state_payload;
*timeout = 600;
switch (event) {
case Init: break;
case GroupKeys:
{
status = storeGroupKeys(session, state, partner, extra /*keys*/);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
status = handshakeSuccess(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Grouped;
}
case Timeout:
{
status = handshakeFailure(session, state, expected, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Sole;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
case Grouped:
{
*timeout = 0;
switch (event) {
case Init:
{
status = enterGroup(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case KeyGen:
{
status = sendGroupUpdate(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case CannotDecrypt:
{
status = sendUpdateRequest(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case UpdateRequest:
{
status = sendGroupUpdate(session, state, NULL, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case Beacon:
{
status = sendHandshakeRequest(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case HandshakeRequest:
{
status = sendHandshakeRequest(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
session->sync_state_payload = identity_dup(partner);
return HandshakingGrouped;
}
case GroupUpdate:
{
status = storeGroupKeys(session, state, partner, extra /*keys*/);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
case HandshakingGrouped:
{
Identity expected = (Identity)session->sync_state_payload;
*timeout = 600;
switch (event) {
case Init:
{
status = showHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
break;
}
case HandshakeRejected:
{
status = rejectHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Grouped;
}
case HandshakeAccepted:
{
status = acceptHandshake(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
status = sendGroupKeys(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
status = handshakeDeviceAdded(session, state, partner, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Grouped;
}
case Timeout:
{
status = handshakeFailure(session, state, expected, NULL);
if (status == PEP_OUT_OF_MEMORY)
return (int) invalid_out_of_memory;
if (status != PEP_STATUS_OK)
return (int) invalid_action;
if(session->sync_state_payload){
free_identity((Identity)session->sync_state_payload);
session->sync_state_payload = NULL;
}
return Grouped;
}
default:
return (DeviceState_state) invalid_event;
}
break;
}
default:
return (DeviceState_state) invalid_state;
}
return state;
}

src/sync_fsm.h → sync/generated/sync_fsm.h View File


src/sync_send_actions.c → sync/generated/sync_send_actions.c View File


+ 379
- 0
sync/skeletons/sync_actions.c View File

@ -0,0 +1,379 @@
// Actions for DeviceState state machine
#include <assert.h>
#include "pEp_internal.h"
#include "keymanagement.h"
#include "message.h"
#include "sync_fsm.h"
#include "../asn.1/DeviceGroup-Protocol.h"
// showHandshake() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS showHandshake(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// rejectHandshake() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS rejectHandshake(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// acceptHandshake() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS acceptHandshake(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// handshakeGroupCreated() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS handshakeGroupCreated(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// dismissHandshake() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS dismissHandshake(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(!partner);
if (!(session && !partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// storeGroupKeys() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS storeGroupKeys(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// handshakeSuccess() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS handshakeSuccess(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// handshakeFailure() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS handshakeFailure(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(!partner);
if (!(session && !partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// enterGroup() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) (must be NULL)
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS enterGroup(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(!partner);
if (!(session && !partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}
// handshakeDeviceAdded() -
//
// params:
// session (in) session handle
// state (in) state the state machine is in
// partner (in) partner to communicate with
//
// returns:
// PEP_STATUS_OK or any other value on error
PEP_STATUS handshakeDeviceAdded(
PEP_SESSION session,
DeviceState_state state,
Identity partner,
void *extra
)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(partner);
if (!(session && partner))
return PEP_ILLEGAL_VALUE;
// working code
// free extra
return status;
enomem:
status = PEP_OUT_OF_MEMORY;
error:
// free extra
return status;
}

Loading…
Cancel
Save