SYNC HAS RETURNED. Keysync still removed from Engine.
authorKrista Bennett <krista@pep-project.org>
Fri, 03 Nov 2017 13:32:38 +0100
changeset 227125bfd109320c
parent 2265 73c0738de68c
child 2272 71ca25a5bb4a
SYNC HAS RETURNED. Keysync still removed from Engine.
Makefile
src/Makefile
src/pEp_internal.h
src/sync.c
src/sync.h
src/sync_actions.c
src/sync_app.h
src/sync_impl.c
src/sync_impl.h
sync/Makefile
sync/devicegroup.fsm
sync/fsm.yml2
sync/functions.ysl2
sync/gen_actions.ysl2
sync/gen_dot.ysl2
sync/gen_statemachine.ysl2
sync/generated/README
sync/generated/sync_driver.c
sync/generated/sync_fsm.c
sync/generated/sync_fsm.h
sync/generated/sync_send_actions.c
sync/skeletons/sync_actions.c
     1.1 --- a/Makefile	Thu Nov 02 17:30:01 2017 +0100
     1.2 +++ b/Makefile	Fri Nov 03 13:32:38 2017 +0100
     1.3 @@ -23,6 +23,7 @@
     1.4  all:
     1.5  	$(MAKE) -C asn.1 generate
     1.6  	$(MAKE) -C asn.1
     1.7 +	$(MAKE) -C sync
     1.8  	$(MAKE) -C src all
     1.9  
    1.10  .PHONY: install
    1.11 @@ -40,6 +41,7 @@
    1.12  	$(MAKE) -C src clean
    1.13  	$(MAKE) -C test clean
    1.14  	$(MAKE) -C db clean
    1.15 +	$(MAKE) -C sync clean
    1.16  	$(MAKE) -C asn.1 clean
    1.17  	rm -rf test_home
    1.18  
     2.1 --- a/src/Makefile	Thu Nov 02 17:30:01 2017 +0100
     2.2 +++ b/src/Makefile	Fri Nov 03 13:32:38 2017 +0100
     2.3 @@ -86,7 +86,7 @@
     2.4  	mkdir -p "$(PREFIX)/lib/"
     2.5  	cp $< $(PREFIX)/lib/
     2.6  	mkdir -p $(PREFIX)/include/pEp
     2.7 -	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h cryptotech.h blacklist.h openpgp_compat.h $(PREFIX)/include/pEp/
     2.8 +	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h cryptotech.h sync.h sync_fsm.h sync_app.h blacklist.h openpgp_compat.h $(PREFIX)/include/pEp/
     2.9  
    2.10  .PHONY: uninstall
    2.11  uninstall:
     3.1 --- a/src/pEp_internal.h	Thu Nov 02 17:30:01 2017 +0100
     3.2 +++ b/src/pEp_internal.h	Fri Nov 03 13:32:38 2017 +0100
     3.3 @@ -101,6 +101,7 @@
     3.4  #include "keymanagement.h"
     3.5  #include "cryptotech.h"
     3.6  #include "transport.h"
     3.7 +#include "sync.h"
     3.8  
     3.9  #define NOT_IMPLEMENTED assert(0); return PEP_UNKNOWN_ERROR;
    3.10  
    3.11 @@ -167,9 +168,14 @@
    3.12      void *examine_management;
    3.13      void *sync_management;
    3.14      void *sync_obj;
    3.15 +    messageToSend_t messageToSend;
    3.16 +    notifyHandshake_t notifyHandshake;
    3.17 +    inject_sync_msg_t inject_sync_msg;
    3.18 +    retrieve_next_sync_msg_t retrieve_next_sync_msg;
    3.19  
    3.20      // key sync
    3.21      pEpSession* sync_session;
    3.22 +    DeviceState_state sync_state;
    3.23      void* sync_state_payload;
    3.24      char sync_uuid[37];
    3.25      time_t LastCannotDecrypt;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/sync.c	Fri Nov 03 13:32:38 2017 +0100
     4.3 @@ -0,0 +1,288 @@
     4.4 +// This file is under GNU General Public License 3.0
     4.5 +// see LICENSE.txt
     4.6 +
     4.7 +#include "pEp_internal.h"
     4.8 +
     4.9 +#include <memory.h>
    4.10 +#include <assert.h>
    4.11 +
    4.12 +#include "asn1_helper.h"
    4.13 +#include "../asn.1/DeviceGroup-Protocol.h"
    4.14 +
    4.15 +// receive_sync_msg is defined in the sync_impl
    4.16 +
    4.17 +PEP_STATUS receive_sync_msg(
    4.18 +        PEP_SESSION session,
    4.19 +        sync_msg_t *sync_msg,
    4.20 +        time_t *timeout
    4.21 +    );
    4.22 +
    4.23 +DYNAMIC_API PEP_STATUS register_sync_callbacks(
    4.24 +        PEP_SESSION session,
    4.25 +        void *management,
    4.26 +        messageToSend_t messageToSend,
    4.27 +        notifyHandshake_t notifyHandshake,
    4.28 +        inject_sync_msg_t inject_sync_msg,
    4.29 +        retrieve_next_sync_msg_t retrieve_next_sync_msg
    4.30 +    )
    4.31 +{
    4.32 +    assert(session && management && messageToSend && notifyHandshake && inject_sync_msg && retrieve_next_sync_msg);
    4.33 +    if (!(session && management && messageToSend && notifyHandshake && inject_sync_msg && retrieve_next_sync_msg))
    4.34 +        return PEP_ILLEGAL_VALUE;
    4.35 +
    4.36 +    pEpUUID uuid;
    4.37 +    uuid_generate_random(uuid);
    4.38 +    uuid_unparse_upper(uuid, session->sync_uuid);
    4.39 +
    4.40 +    session->sync_management = management;
    4.41 +    session->messageToSend = messageToSend;
    4.42 +    session->notifyHandshake = notifyHandshake;
    4.43 +    session->inject_sync_msg = inject_sync_msg;
    4.44 +    session->retrieve_next_sync_msg = retrieve_next_sync_msg;
    4.45 +
    4.46 +    // start state machine
    4.47 +    session->sync_state = InitState;
    4.48 +    time_t unused = 0;
    4.49 +    PEP_STATUS status = fsm_DeviceState_inject(session, Init, NULL, NULL, &unused);
    4.50 +    if (status != PEP_STATUS_OK)
    4.51 +        unregister_sync_callbacks(session);
    4.52 +
    4.53 +    return status;
    4.54 +}
    4.55 +
    4.56 +DYNAMIC_API PEP_STATUS attach_sync_session(
    4.57 +        PEP_SESSION session,
    4.58 +        PEP_SESSION sync_session
    4.59 +    )
    4.60 +{
    4.61 +    assert(session && sync_session && sync_session->sync_management && sync_session->inject_sync_msg );
    4.62 +    if (!(session && sync_session && sync_session->sync_management && sync_session->inject_sync_msg ))
    4.63 +        return PEP_ILLEGAL_VALUE;
    4.64 +
    4.65 +    session->sync_session = sync_session;
    4.66 +    // memcpy(session->sync_uuid, sync_session->sync_uuid, 37);
    4.67 +
    4.68 +    // session->sync_management = sync_session->sync_management;
    4.69 +    // session->inject_sync_msg = sync_session->inject_sync_msg;
    4.70 +
    4.71 +    return PEP_STATUS_OK;
    4.72 +}
    4.73 +
    4.74 +DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session)
    4.75 +{
    4.76 +    assert(session);
    4.77 +    if (!(session))
    4.78 +        return PEP_ILLEGAL_VALUE;
    4.79 +
    4.80 +    session->sync_session = session;
    4.81 +    // memset(session->sync_uuid, 0, 37);
    4.82 +
    4.83 +    // session->sync_management = NULL;
    4.84 +    // session->inject_sync_msg = NULL;
    4.85 +
    4.86 +    return PEP_STATUS_OK;
    4.87 +}
    4.88 +
    4.89 +int call_inject_sync_msg(PEP_SESSION session, void *msg)
    4.90 +{
    4.91 +    if(session->sync_session->inject_sync_msg &&
    4.92 +       session->sync_session->sync_management)
    4.93 +        return session->sync_session->inject_sync_msg(msg, 
    4.94 +            session->sync_session->sync_management);
    4.95 +    else
    4.96 +       return PEP_SYNC_NO_INJECT_CALLBACK;
    4.97 +}
    4.98 +
    4.99 +DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session) {
   4.100 +    // stop state machine
   4.101 +    session->sync_state = DeviceState_state_NONE;
   4.102 +
   4.103 +    // unregister
   4.104 +    session->sync_management = NULL;
   4.105 +    session->messageToSend = NULL;
   4.106 +    session->notifyHandshake = NULL;
   4.107 +    session->inject_sync_msg = NULL;
   4.108 +    session->retrieve_next_sync_msg = NULL;
   4.109 +}
   4.110 +
   4.111 +DYNAMIC_API PEP_STATUS deliverHandshakeResult(
   4.112 +        PEP_SESSION session,
   4.113 +        Identity partner,
   4.114 +        sync_handshake_result result
   4.115 +    )
   4.116 +{
   4.117 +    assert(session);
   4.118 +    if (!session)
   4.119 +        return PEP_ILLEGAL_VALUE;
   4.120 +
   4.121 +    PEP_STATUS status = PEP_STATUS_OK;
   4.122 +
   4.123 +    DeviceState_event event;
   4.124 +    bool need_partner = false;
   4.125 +
   4.126 +    switch (result) {
   4.127 +        case SYNC_HANDSHAKE_CANCEL:
   4.128 +            event = Cancel;
   4.129 +            break;
   4.130 +        case SYNC_HANDSHAKE_ACCEPTED:
   4.131 +        {
   4.132 +            event = HandshakeAccepted;
   4.133 +            need_partner = true;
   4.134 +            break;
   4.135 +        }
   4.136 +        case SYNC_HANDSHAKE_REJECTED:
   4.137 +        {
   4.138 +            event = HandshakeRejected;
   4.139 +            need_partner = true;
   4.140 +            break;
   4.141 +        }
   4.142 +        default:
   4.143 +            return PEP_ILLEGAL_VALUE;
   4.144 +    }
   4.145 +
   4.146 +    pEp_identity *_partner = NULL;
   4.147 +    if(need_partner){
   4.148 +        _partner = identity_dup(partner);
   4.149 +        if (_partner == NULL)
   4.150 +            return PEP_OUT_OF_MEMORY;
   4.151 +    }
   4.152 +    status = inject_DeviceState_event(session, event, _partner, NULL);
   4.153 +
   4.154 +    return status;
   4.155 +}
   4.156 +
   4.157 +DYNAMIC_API PEP_STATUS do_sync_protocol(
   4.158 +        PEP_SESSION session,
   4.159 +        void *obj
   4.160 +    )
   4.161 +{
   4.162 +    sync_msg_t *msg = NULL;
   4.163 +    PEP_STATUS status = PEP_STATUS_OK;
   4.164 +    time_t timeout = 0;
   4.165 +
   4.166 +    assert(session && session->retrieve_next_sync_msg);
   4.167 +    assert(obj);
   4.168 +
   4.169 +    if (!(session && session->retrieve_next_sync_msg) || !obj)
   4.170 +        return PEP_ILLEGAL_VALUE;
   4.171 +
   4.172 +    log_event(session, "sync_protocol thread started", "pEp sync protocol", NULL, NULL);
   4.173 +
   4.174 +    session->sync_obj = obj;
   4.175 +
   4.176 +    while (true) 
   4.177 +    {
   4.178 +        msg = (sync_msg_t *) session->retrieve_next_sync_msg(session->sync_management, &timeout);
   4.179 +        if(msg == NULL && timeout == 0)
   4.180 +            break;
   4.181 +        else if(msg == NULL && timeout != 0){
   4.182 +            status = fsm_DeviceState_inject(session, Timeout, NULL, NULL, &timeout);
   4.183 +#ifndef NDEBUG
   4.184 +            char buffer[MAX_LINELENGTH];
   4.185 +            memset(buffer, 0, MAX_LINELENGTH);
   4.186 +            snprintf(buffer, MAX_LINELENGTH, "problem with timeout event : %d\n", (int) status);
   4.187 +            log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   4.188 +            continue;
   4.189 +#endif
   4.190 +        }
   4.191 +        else {
   4.192 +            status = receive_sync_msg(session, msg, &timeout);
   4.193 +            if (status != PEP_STATUS_OK && status != PEP_MESSAGE_IGNORE) {
   4.194 +#ifndef NDEBUG
   4.195 +                char buffer[MAX_LINELENGTH];
   4.196 +                memset(buffer, 0, MAX_LINELENGTH);
   4.197 +                snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
   4.198 +                log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   4.199 +#endif
   4.200 +            }
   4.201 +        }
   4.202 +    }
   4.203 +
   4.204 +    log_event(session, "sync_protocol thread shutdown", "pEp sync protocol", NULL, NULL);
   4.205 +
   4.206 +    session->sync_obj = NULL;
   4.207 +
   4.208 +    return PEP_STATUS_OK;
   4.209 +}
   4.210 +
   4.211 +DYNAMIC_API PEP_STATUS decode_sync_msg(
   4.212 +        const char *data,
   4.213 +        size_t size,
   4.214 +        char **text
   4.215 +    )
   4.216 +{
   4.217 +    PEP_STATUS status = PEP_STATUS_OK;
   4.218 +
   4.219 +    assert(data && text);
   4.220 +    if (!(data && text))
   4.221 +        return PEP_ILLEGAL_VALUE;
   4.222 +
   4.223 +    *text = NULL;
   4.224 +
   4.225 +    DeviceGroup_Protocol_t *msg = NULL;
   4.226 +    uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **) &msg,
   4.227 +            data, size);
   4.228 +    if (!msg)
   4.229 +        return PEP_SYNC_ILLEGAL_MESSAGE;
   4.230 +
   4.231 +    growing_buf_t *dst = new_growing_buf();
   4.232 +    if (!dst) {
   4.233 +        status = PEP_OUT_OF_MEMORY;
   4.234 +        goto the_end;
   4.235 +    }
   4.236 +
   4.237 +    asn_enc_rval_t er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg,
   4.238 +            XER_F_BASIC, (asn_app_consume_bytes_f *) consume_bytes, (void *) dst);
   4.239 +    if (er.encoded == -1) {
   4.240 +        status = PEP_CANNOT_ENCODE;
   4.241 +        goto the_end;
   4.242 +    }
   4.243 +
   4.244 +    *text = dst->data;
   4.245 +    dst->data = NULL;
   4.246 +
   4.247 +the_end:
   4.248 +    free_growing_buf(dst);
   4.249 +    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   4.250 +    return status;
   4.251 +}
   4.252 +
   4.253 +DYNAMIC_API PEP_STATUS encode_sync_msg(
   4.254 +        const char *text,
   4.255 +        char **data,
   4.256 +        size_t *size
   4.257 +    )
   4.258 +{
   4.259 +    PEP_STATUS status = PEP_STATUS_OK;
   4.260 +
   4.261 +    assert(text && data && size);
   4.262 +    if (!(text && data && size))
   4.263 +        return PEP_ILLEGAL_VALUE;
   4.264 +
   4.265 +    *data = NULL;
   4.266 +    *size = 0;
   4.267 +
   4.268 +    DeviceGroup_Protocol_t *msg = NULL;
   4.269 +    asn_dec_rval_t dr = xer_decode(NULL, &asn_DEF_DeviceGroup_Protocol,
   4.270 +            (void **) &msg, (const void *) text, strlen(text));
   4.271 +    if (dr.code != RC_OK) {
   4.272 +        status = PEP_SYNC_ILLEGAL_MESSAGE;
   4.273 +        goto the_end;
   4.274 +    }
   4.275 +
   4.276 +    char *payload = NULL;
   4.277 +    ssize_t _size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   4.278 +            NULL, msg, (void **) &payload);
   4.279 +    if (_size == -1) {
   4.280 +        status = PEP_CANNOT_ENCODE;
   4.281 +        goto the_end;
   4.282 +    }
   4.283 +
   4.284 +    *data = payload;
   4.285 +    *size = (size_t) _size;
   4.286 +
   4.287 +the_end:
   4.288 +    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   4.289 +    return status;
   4.290 +}
   4.291 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/sync.h	Fri Nov 03 13:32:38 2017 +0100
     5.3 @@ -0,0 +1,417 @@
     5.4 +// This file is under GNU General Public License 3.0
     5.5 +// see LICENSE.txt
     5.6 +
     5.7 +/*
     5.8 +====================================
     5.9 +Engine/adapter/app KeySync interface 
    5.10 +====================================
    5.11 +
    5.12 +
    5.13 +         Engine         |          Adapter            |          App
    5.14 +                        |                             |
    5.15 + . . . . . . . . . . . .|. . . . . . . . . . . . . . .|. . Attached session .  
    5.16 +     ,---------,        |                             |
    5.17 +   ,-| decrypt |<--------------------------------------- Incomming message 
    5.18 +   | | message |        |                             |
    5.19 +   | '---------'        |                             |
    5.20 +   | ,----------,       |                             |
    5.21 +   |-| myself   |<-------------------------------------- Create new account
    5.22 +   | | (keygen) |       |                             |
    5.23 +   | '----------'       |                             |
    5.24 +   | ,-----------,      |                             |
    5.25 +   |-| deliver   |<------------------------------------------- Accept/reject
    5.26 +   | | handshake |      |                     KeySync |            handshake
    5.27 +   | | result    |      |                     Message |
    5.28 +   | '-----------'      |                      Queue  |
    5.29 +   |                    |                      ,---,  |
    5.30 +   '-----------------------inject_sync_msg---->|   |  |
    5.31 + . . . . . . . . . . . .|. . . . . . . . . . . |---| .|. . . . Sync session .  
    5.32 + *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *|   |* | 
    5.33 +                        |                      |---|  | 
    5.34 + *   ,------------------retrieve_next_sync_msg-|   |* | 
    5.35 +   ,-v--------,         |                      '---'  | 
    5.36 + * | Driver   |         |                           * |
    5.37 +   '----------'         |                             |
    5.38 + *  ||'-event-----,     |                           * |
    5.39 +    |'--partner--,|     |                             |
    5.40 + *  '---extra---,||     |           SYNC THREAD     *<-------------- Start Sync
    5.41 +            ,---vvv---, |                             |
    5.42 + *     ,----|   FSM   | |                           * |
    5.43 +       |    '---------' |                             |
    5.44 + *     |  ,-------,     |                           * |
    5.45 +       '->|actions|---------messageToSend-------------------> Send mail to self
    5.46 + *        '-------'     |                           * |
    5.47 +              '-------------notifyHandshake-----------------> Ask for handshake
    5.48 + *                      |                           * |    display group status
    5.49 +                        |                             |
    5.50 + *  *  *  *  *  *  *  * |*  *  *  *  *  *  *  *  *  * |
    5.51 +                        |                             |
    5.52 +
    5.53 +Emails to self
    5.54 +--------------
    5.55 +
    5.56 +With e-mail as a transport KeySync message handling is done when an incoming 
    5.57 +email to self is passed to decrypt_message(), assuming that all incoming email
    5.58 +messages are passed to decrypt_massage(). 
    5.59 +
    5.60 +In case of an email containing a KeySync paload, KeySync may consume or ignore
    5.61 +the message. decrypt_message() signals this to the app with decrypt flags
    5.62 +PEP_decrypt_flag_consume and PEP_decrypt_flag_ignore.
    5.63 +
    5.64 +In case of PEP_decrypt_flag_consume, app should delete the message.
    5.65 +In case of PEP_decrypt_flag_ignore, app should ignore message.
    5.66 +In both cases, message should be hidden.
    5.67 +
    5.68 +States, events, actions
    5.69 +-----------------------
    5.70 +
    5.71 +In the engine, KeySync is implemented through a finite state machine (FSM) [1].
    5.72 +KeySync state machine is driven [2] by events, triggering actions [3] and
    5.73 +transitions to new states.
    5.74 +
    5.75 +Events happen on :
    5.76 +
    5.77 + - decryption of email messages
    5.78 +
    5.79 + - key generation
    5.80 +
    5.81 + - user interaction through the app 
    5.82 +
    5.83 + - timeout when staying too long in some particular states.
    5.84 +
    5.85 +[1] sync/devicegroup.fsm , src/sync_fsm.c (generated)
    5.86 +[2] src/sync_driver.c (generated)
    5.87 +[3] src/sync_actions.c , src/sync_send_actions.c (generated)
    5.88 +
    5.89 +Sync session, attached sessions
    5.90 +-------------------------------
    5.91 +
    5.92 +To use KeySync, the adapter has to create a session dedicated to handle the
    5.93 +protocol, register some callbacks [4] to the engine, and then call protocol's
    5.94 +event consumer loop [5] in a dedicated thread. KeySync actions are executed as
    5.95 +callback invoked from that thread.
    5.96 +
    5.97 +When a session is attached [6] to a KeySync session, decryption of pEp email
    5.98 +messages in the attached session may trigger operations in KeySync session. In
    5.99 +case of an adapter capable to serve multiple apps, each app is associated to a
   5.100 +different KeySync session, and sessions created for use in that app are
   5.101 +attached to that session.
   5.102 +
   5.103 +Adapters present different approaches regarding session and client abstraction,
   5.104 +and may not propose to explicitely create or attach session or sync session.
   5.105 +
   5.106 +[4] register_sync_callbacks()
   5.107 +[5] do_sync_protocol()
   5.108 +[6] attach_sync_session()
   5.109 +
   5.110 +KeySync Messages and queue
   5.111 +--------------------------
   5.112 +
   5.113 +KeySync messages [7], not to be confused with pEp (email) messages, are either
   5.114 +directly events to be processed by the state machine, or KeySync payloads
   5.115 +collected from decrypted messages. 
   5.116 +
   5.117 +KeySync messages can be emitted by different sessions, and could naturally come
   5.118 +from different threads. They must be serialized in a locked queue. 
   5.119 +KeySync messages queue is implemented by adapter, along with thread handling
   5.120 +KeySync protocol. 
   5.121 +
   5.122 +Attached sessions inject [8] KeySync messages in the queue. Protocol loop
   5.123 +retrieves [9] them from the queue. KeySync message is received [10] by the
   5.124 +state machine, where event, partner and extra parameters are eventually deduced
   5.125 +from payload.
   5.126 +
   5.127 +A state timeout event is a particular case. It doesn't traverse the queue, and
   5.128 +isn't emitted by a session. It is triggered by a timeout on the retrieve
   5.129 +operation. Value of the timeout is determined when entering a new state, and is
   5.130 +passed as a parameter of the call to the blocking queue retrieve operation on 
   5.131 +next protocol loop iteraton.
   5.132 +
   5.133 +[7] type sync_msg_t
   5.134 +[8] callback inject_sync_msg
   5.135 +[9] callback retrieve_next_sync_msg
   5.136 +[10] receive_sync_msg() (src/sync_impl.c)
   5.137 +
   5.138 +Application callbacks
   5.139 +---------------------
   5.140 +
   5.141 +Some Keysync actions require the application to act, through callbacks :
   5.142 +
   5.143 + - messageToSend : send pEp messages through app's transport. 
   5.144 +   Messages are already encrypted and just need to be passed as-is to
   5.145 +   transport for transmission, as for messages returned by encrypt_message().
   5.146 +
   5.147 + - notifyHandshake : display KeySync status and handshake to the user.
   5.148 +   notifyHandshake callback receives 2 identities, 'me' and 'partner', together
   5.149 +   with a sync_handshake_signal enum :
   5.150 +
   5.151 +    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE :
   5.152 +        Device (me) is sole, about to enter a group (partner).
   5.153 +        App displays trustwords, and requests user accept or reject
   5.154 +        App calls deliverHandshakeResult with user's answer
   5.155 +
   5.156 +    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE :
   5.157 +        Device (me) is grouped, another device (partner) wants to join group.
   5.158 +        App displays trustwords, and requests user accept or reject
   5.159 +        App calls deliverHandshakeResult with user's answer
   5.160 +
   5.161 +    SYNC_NOTIFY_INIT_FORM_GROUP :
   5.162 +        Device (me) is forming a group, including another device (partner)
   5.163 +        App displays trustwords, and requests user accept or reject
   5.164 +        App calls deliverHandshakeResult with user's answer
   5.165 +
   5.166 +    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE
   5.167 +        Device (me) is grouped and will leave current group to join another
   5.168 +        device's (partner) group.
   5.169 +        App displays trustwords, and requests user accept or reject
   5.170 +        App calls deliverHandshakeResult with user's answer
   5.171 +
   5.172 +
   5.173 +    SYNC_NOTIFY_TIMEOUT :
   5.174 +        KeySync operation timed out.
   5.175 +        Identities are set reflecting peers involved in aborted operation.
   5.176 +        App displays error message. No feedback to engine.
   5.177 +
   5.178 +    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
   5.179 +        New device was added to group.
   5.180 +        App displays message. No feedback to engine.
   5.181 +
   5.182 +    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   5.183 +        New group created.
   5.184 +        App displays message. No feedback to engine.
   5.185 +
   5.186 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED
   5.187 +        New device was moved from one group to another.
   5.188 +        App displays message. No feedback to engine.
   5.189 +
   5.190 +   To deliver handshake result back to engine once user reacted,
   5.191 +   deliver_handshake_result is used. Result can be :
   5.192 +
   5.193 +    SYNC_HANDSHAKE_CANCEL
   5.194 +        Gives no answer. User doesn't know id TrustWord are good or bad.
   5.195 +        For example in case peering device is away.
   5.196 +        Handshake will re-appear later.
   5.197 +
   5.198 +    SYNC_HANDSHAKE_ACCEPTED
   5.199 +        Trustwords match with other device and user accepts handshake.
   5.200 +
   5.201 +    SYNC_HANDSHAKE_REJECTED
   5.202 +        Trustwords do not match with any device and user rejects handshake.
   5.203 +*/
   5.204 +
   5.205 +#pragma once
   5.206 +
   5.207 +#include "message.h"
   5.208 +#include "sync_fsm.h"
   5.209 +#include "sync_app.h"
   5.210 +
   5.211 +// this module is for being used WITHOUT the Transport API in transport.h
   5.212 +// DO NOT USE IT WHEN USING Transport API!
   5.213 +
   5.214 +
   5.215 +#ifdef __cplusplus
   5.216 +extern "C" {
   5.217 +#endif
   5.218 +
   5.219 +// messageToSend() - send a message
   5.220 +//
   5.221 +//  parameters:
   5.222 +//      obj (in)        object handle (implementation defined)
   5.223 +//      msg (in)        message struct with message to send
   5.224 +//
   5.225 +//  return value:
   5.226 +//      PEP_STATUS_OK or any other value on error
   5.227 +//
   5.228 +//  caveat:
   5.229 +//      the ownership of msg goes to the callee
   5.230 +
   5.231 +typedef PEP_STATUS (*messageToSend_t)(void *obj, message *msg);
   5.232 +
   5.233 +// notifyHandshake() - notify UI about sync handshaking process
   5.234 +//
   5.235 +//  parameters:
   5.236 +//      obj (in)        object handle (implementation defined)
   5.237 +//      me (in)         own identity
   5.238 +//      partner (in)    identity of partner
   5.239 +//      signal (in)     reason of the notification
   5.240 +//
   5.241 +//  return value:
   5.242 +//      PEP_STATUS_OK or any other value on error
   5.243 +//
   5.244 +//  caveat:
   5.245 +//      ownership of self and partner go to the callee
   5.246 +
   5.247 +typedef PEP_STATUS (*notifyHandshake_t)(
   5.248 +        void *obj,
   5.249 +        pEp_identity *me,
   5.250 +        pEp_identity *partner,
   5.251 +        sync_handshake_signal signal
   5.252 +    );
   5.253 +
   5.254 +typedef enum _sync_handshake_result {
   5.255 +    SYNC_HANDSHAKE_CANCEL = -1,
   5.256 +    SYNC_HANDSHAKE_ACCEPTED = 0,
   5.257 +    SYNC_HANDSHAKE_REJECTED = 1
   5.258 +} sync_handshake_result;
   5.259 +
   5.260 +// deliverHandshakeResult() - give the result of the handshake dialog
   5.261 +//
   5.262 +//  parameters:
   5.263 +//      session (in)        session handle
   5.264 +//      result (in)         handshake result
   5.265 +
   5.266 +DYNAMIC_API PEP_STATUS deliverHandshakeResult(
   5.267 +        PEP_SESSION session,
   5.268 +        Identity partner,
   5.269 +        sync_handshake_result result
   5.270 +    );
   5.271 +
   5.272 +// sync_msg_t - items queued for serialized handling by protocol engine
   5.273 +typedef struct _sync_msg_t sync_msg_t;
   5.274 +
   5.275 +// inject_sync_msg - inject sync protocol message
   5.276 +//
   5.277 +//  parameters:
   5.278 +//      msg (in)            message to inject
   5.279 +//      management (in)     application defined
   5.280 +//
   5.281 +//  *** BEWARE: msg is 1st parameter, obj is second!!! ***
   5.282 +//  return value:
   5.283 +//      0 if msg could be stored successfully or nonzero otherwise
   5.284 +
   5.285 +typedef int (*inject_sync_msg_t)(void *msg, void *management);
   5.286 +
   5.287 +
   5.288 +// retrieve_next_sync_msg - receive next sync message
   5.289 +//
   5.290 +//  parameters:
   5.291 +//      management (in)     application defined
   5.292 +//      timeout (in,out)    do not wait longer than timeout for message
   5.293 +//                          timeout == NULL or *timeout == 0 is blocking
   5.294 +//
   5.295 +//  return value:
   5.296 +//      next message, then timeout[out] == remaining time
   5.297 +//      NULL and timeout[out] != 0 for timeout occurence
   5.298 +//      NULL and timeout[out] == 0 for termination
   5.299 +
   5.300 +typedef void *(*retrieve_next_sync_msg_t)(void *management, time_t *timeout);
   5.301 +
   5.302 +
   5.303 +// register_sync_callbacks() - register adapter's callbacks
   5.304 +//
   5.305 +//  parameters:
   5.306 +//      session (in)                session where to store obj handle
   5.307 +//      management (in)             application defined
   5.308 +//      messageToSend (in)          callback for sending message
   5.309 +//      notifyHandshake (in)        callback for doing the handshake
   5.310 +//      retrieve_next_sync_msg (in) callback for receiving sync messages
   5.311 +//
   5.312 +//  return value:
   5.313 +//      PEP_STATUS_OK or any other value on errror
   5.314 +//
   5.315 +//  caveat:
   5.316 +//      call that BEFORE you're using any other part of the engine
   5.317 +
   5.318 +DYNAMIC_API PEP_STATUS register_sync_callbacks(
   5.319 +        PEP_SESSION session,
   5.320 +        void *management,
   5.321 +        messageToSend_t messageToSend,
   5.322 +        notifyHandshake_t notifyHandshake,
   5.323 +        inject_sync_msg_t inject_sync_msg,
   5.324 +        retrieve_next_sync_msg_t retrieve_next_sync_msg
   5.325 +    );
   5.326 +
   5.327 +// attach_sync_session() - attach session to a session running keysync state machine 
   5.328 +//
   5.329 +//  parameters:
   5.330 +//      session (in)                session to attach
   5.331 +//      sync_session (in)           session running keysync
   5.332 +//
   5.333 +//  return value:
   5.334 +//      PEP_STATUS_OK or any other value on errror
   5.335 +//
   5.336 +//  caveat:
   5.337 +//      register_sync_callbacks must have been called on sync_session
   5.338 +//      call that BEFORE you're using that session in any other part of the engine
   5.339 +
   5.340 +DYNAMIC_API PEP_STATUS attach_sync_session(
   5.341 +        PEP_SESSION session,
   5.342 +        PEP_SESSION sync_session
   5.343 +    );
   5.344 +
   5.345 +// detach_sync_session() - detach previously attached sync session
   5.346 +//
   5.347 +//  parameters:
   5.348 +//      session (in)                session to detach 
   5.349 +
   5.350 +DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session);
   5.351 +
   5.352 +// unregister_sync_callbacks() - unregister adapter's callbacks
   5.353 +//
   5.354 +//  parameters:
   5.355 +//      session (in)                session to unregister
   5.356 +
   5.357 +DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session);
   5.358 +
   5.359 +// do_sync_protocol() - function to be run on an extra thread
   5.360 +//
   5.361 +//  parameters:
   5.362 +//      session                 pEp session to use
   5.363 +//      retrieve_next_sync_msg  pointer to retrieve_next_identity() callback
   5.364 +//                              which returns at least a valid address field in
   5.365 +//                              the identity struct
   5.366 +//      obj                     application defined sync object
   5.367 +//
   5.368 +//  return value:
   5.369 +//      PEP_STATUS_OK if thread has to terminate successfully or any other
   5.370 +//      value on failure
   5.371 +//
   5.372 +//  caveat:
   5.373 +//      to ensure proper working of this library, a thread has to be started
   5.374 +//      with this function immediately after initialization
   5.375 +
   5.376 +DYNAMIC_API PEP_STATUS do_sync_protocol(
   5.377 +        PEP_SESSION session,
   5.378 +        void *obj
   5.379 +    );
   5.380 +
   5.381 +// free_sync_msg() - free sync_msg_t struct when not passed to do_sync_protocol  
   5.382 +//
   5.383 +//  parameters:
   5.384 +//      sync_msg (in)            pointer to sync_msg_t struct to free.
   5.385 +//                               pointer can be NULL.
   5.386 +
   5.387 +DYNAMIC_API void free_sync_msg(sync_msg_t *sync_msg);
   5.388 +
   5.389 +// decode_sync_msg() - decode sync message from PER into XER
   5.390 +//
   5.391 +//  parameters:
   5.392 +//      data (in)               PER encoded data
   5.393 +//      size (in)               size of PER encoded data
   5.394 +//      text (out)              XER text of the same sync message
   5.395 +
   5.396 +DYNAMIC_API PEP_STATUS decode_sync_msg(
   5.397 +        const char *data,
   5.398 +        size_t size,
   5.399 +        char **text
   5.400 +    );
   5.401 +
   5.402 +
   5.403 +// encode_sync_msg() - encode sync message from XER into PER
   5.404 +//
   5.405 +//  parameters:
   5.406 +//      text (in)               string with XER text of the sync message
   5.407 +//      data (out)              PER encoded data
   5.408 +//      size (out)              size of PER encoded data
   5.409 +
   5.410 +DYNAMIC_API PEP_STATUS encode_sync_msg(
   5.411 +        const char *text,
   5.412 +        char **data,
   5.413 +        size_t *size
   5.414 +    );
   5.415 +
   5.416 +
   5.417 +#ifdef __cplusplus
   5.418 +}
   5.419 +#endif
   5.420 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/sync_actions.c	Fri Nov 03 13:32:38 2017 +0100
     6.3 @@ -0,0 +1,434 @@
     6.4 +// This file is under GNU General Public License 3.0
     6.5 +// see LICENSE.txt
     6.6 +
     6.7 +// Actions for DeviceState state machine
     6.8 +
     6.9 +#include <assert.h>
    6.10 +#include "pEp_internal.h"
    6.11 +#include "message.h"
    6.12 +#include "sync_fsm.h"
    6.13 +#include "sync_impl.h"
    6.14 +#include "map_asn1.h"
    6.15 +#include "baseprotocol.h"
    6.16 +
    6.17 +// conditions
    6.18 +
    6.19 +int deviceGrouped(PEP_SESSION session)
    6.20 +{
    6.21 +    assert(session);
    6.22 +    if (!session)
    6.23 +        return invalid_condition; // error
    6.24 +
    6.25 +    char *devgrp = NULL;
    6.26 +    int res = 0;
    6.27 +    PEP_STATUS status;
    6.28 +
    6.29 +    status = get_device_group(session, &devgrp);
    6.30 +
    6.31 +    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
    6.32 +        res = 1;
    6.33 +
    6.34 +    free(devgrp);
    6.35 +
    6.36 +    return res;
    6.37 +}
    6.38 +
    6.39 +int keyElectionWon(PEP_SESSION session, Identity partner)
    6.40 +{
    6.41 +    assert(session);
    6.42 +    assert(partner);
    6.43 +    if (!(session && partner))
    6.44 +        return invalid_condition; // error
    6.45 +
    6.46 +    int partner_is_group = partner->flags & PEP_idf_devicegroup;
    6.47 +
    6.48 +    if (deviceGrouped(session)){
    6.49 +        // existing group always wins against sole device
    6.50 +        if(!partner_is_group)
    6.51 +            return 1;
    6.52 +    } else {
    6.53 +        // sole device always loses against group
    6.54 +        if(partner_is_group)
    6.55 +            return 0;
    6.56 +    }
    6.57 +
    6.58 +    // two groups or two sole are elected based on key age
    6.59 +    // key created first wins
    6.60 +
    6.61 +    Identity me = NULL;
    6.62 +    PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
    6.63 +            &me);
    6.64 +    if (status == PEP_OUT_OF_MEMORY)
    6.65 +        return invalid_out_of_memory;
    6.66 +    if (status != PEP_STATUS_OK)
    6.67 +        return invalid_condition; // error
    6.68 +
    6.69 +    int result = invalid_condition; // error state has to be overwritten
    6.70 +
    6.71 +    time_t own_created;
    6.72 +    time_t partners_created;
    6.73 +
    6.74 +    status = key_created(session, me->fpr, &own_created);
    6.75 +    if (status != PEP_STATUS_OK)
    6.76 +        goto the_end;
    6.77 +
    6.78 +    status = key_created(session, partner->fpr, &partners_created);
    6.79 +    if (status != PEP_STATUS_OK)
    6.80 +        goto the_end;
    6.81 +
    6.82 +    if (own_created > partners_created)
    6.83 +        result = 0;
    6.84 +    else
    6.85 +        result = 1;
    6.86 +
    6.87 +the_end:
    6.88 +    free_identity(me);
    6.89 +    return result;
    6.90 +}
    6.91 +
    6.92 +int sameIdentities(PEP_SESSION session, Identity a, Identity b)
    6.93 +{
    6.94 +    assert(session);
    6.95 +    assert(a);
    6.96 +    assert(b);
    6.97 +
    6.98 +    if (!(session && a && b))
    6.99 +        return invalid_condition; // error
   6.100 +
   6.101 +    if (a->fpr == NULL || b->fpr == NULL ||
   6.102 +        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
   6.103 +        a->address == NULL || b->address == NULL ||
   6.104 +        strcmp(a->address, b->address) != 0 ||
   6.105 +        a->user_id == NULL || b->user_id == NULL ||
   6.106 +        strcmp(a->user_id, b->user_id) != 0)
   6.107 +            return 0;
   6.108 +    return 1;
   6.109 +}
   6.110 +
   6.111 +int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b)
   6.112 +{
   6.113 +    assert(session);
   6.114 +    assert(a);
   6.115 +    assert(b);
   6.116 +
   6.117 +    if (!(session && a && b))
   6.118 +        return invalid_condition; // error
   6.119 +
   6.120 +    if (a->fpr == NULL || b->fpr == NULL ||
   6.121 +        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
   6.122 +        a->address == NULL || b->address == NULL ||
   6.123 +        strcmp(a->address, b->address) != 0)
   6.124 +            return 0;
   6.125 +    return 1;
   6.126 +}
   6.127 +
   6.128 +// actions
   6.129 +
   6.130 +PEP_STATUS _notifyHandshake(
   6.131 +        PEP_SESSION session,
   6.132 +        Identity partner,
   6.133 +        sync_handshake_signal signal
   6.134 +    )
   6.135 +{
   6.136 +    PEP_STATUS status = PEP_STATUS_OK;
   6.137 +
   6.138 +    assert(session);
   6.139 +    assert(partner);
   6.140 +
   6.141 +    if (!(session && partner))
   6.142 +        return PEP_ILLEGAL_VALUE;
   6.143 +
   6.144 +    assert(session->notifyHandshake);
   6.145 +    if (!session->notifyHandshake)
   6.146 +        return PEP_SYNC_NO_NOTIFY_CALLBACK;
   6.147 +
   6.148 +    // notifyHandshake take ownership of given identities
   6.149 +    pEp_identity *me = NULL;
   6.150 +    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
   6.151 +    if (status != PEP_STATUS_OK)
   6.152 +        goto error;
   6.153 +    
   6.154 +    pEp_identity *_partner = NULL;
   6.155 +    _partner = identity_dup(partner);
   6.156 +    if (_partner == NULL){
   6.157 +        status = PEP_OUT_OF_MEMORY;
   6.158 +        goto error;
   6.159 +    }
   6.160 +
   6.161 +    status = session->notifyHandshake(session->sync_obj, me, _partner, signal);
   6.162 +    if (status != PEP_STATUS_OK)
   6.163 +        goto error;
   6.164 +
   6.165 +    return status;
   6.166 +
   6.167 +error:
   6.168 +    free_identity(me);
   6.169 +    return status;
   6.170 +}
   6.171 +
   6.172 +// acceptHandshake() - stores acception of partner
   6.173 +//
   6.174 +//  params:
   6.175 +//      session (in)        session handle
   6.176 +//      state (in)          state the state machine is in
   6.177 +//      partner (in)        partner to communicate with
   6.178 +//
   6.179 +//  returns:
   6.180 +//      PEP_STATUS_OK or any other value on error
   6.181 +
   6.182 +PEP_STATUS acceptHandshake(
   6.183 +        PEP_SESSION session,
   6.184 +        DeviceState_state state,
   6.185 +        Identity partner,
   6.186 +        void *extra
   6.187 +    )
   6.188 +{
   6.189 +    PEP_STATUS status = PEP_STATUS_OK;
   6.190 +
   6.191 +    assert(session);
   6.192 +    assert(partner);
   6.193 +    assert(extra == NULL);
   6.194 +    if (!(session && partner))
   6.195 +        return PEP_ILLEGAL_VALUE;
   6.196 +
   6.197 +    status = trust_personal_key(session, partner);
   6.198 +
   6.199 +    return status;
   6.200 +}
   6.201 +
   6.202 +
   6.203 +// rejectHandshake() - stores rejection of partner
   6.204 +//
   6.205 +//  params:
   6.206 +//      session (in)        session handle
   6.207 +//      state (in)          state the state machine is in
   6.208 +//      partner (in)        partner to communicate with
   6.209 +//
   6.210 +//  returns:
   6.211 +//      PEP_STATUS_OK or any other value on error
   6.212 +
   6.213 +PEP_STATUS rejectHandshake(
   6.214 +        PEP_SESSION session,
   6.215 +        DeviceState_state state,
   6.216 +        Identity partner,
   6.217 +        void *extra
   6.218 +    )
   6.219 +{
   6.220 +    PEP_STATUS status = PEP_STATUS_OK;
   6.221 +
   6.222 +    assert(session);
   6.223 +    assert(partner);
   6.224 +    assert(extra == NULL);
   6.225 +    if (!(session && partner))
   6.226 +        return PEP_ILLEGAL_VALUE;
   6.227 +
   6.228 +    // TODO : disable sync globally if not in a group
   6.229 +    status = set_identity_flags(session, partner,
   6.230 +            partner->flags | PEP_idf_not_for_sync);
   6.231 +
   6.232 +    return status;
   6.233 +}
   6.234 +
   6.235 +PEP_STATUS _storeGroupKeys(
   6.236 +        PEP_SESSION session,
   6.237 +        identity_list *group_keys
   6.238 +    )
   6.239 +{
   6.240 +    PEP_STATUS status = PEP_STATUS_OK;
   6.241 +
   6.242 +    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
   6.243 +
   6.244 +        if (strcmp(il->ident->user_id, PEP_OWN_USERID)!=0) {
   6.245 +            assert(0);
   6.246 +            continue;
   6.247 +        }
   6.248 +        // Check that identity isn't excluded from sync.
   6.249 +        pEp_identity *stored_identity = NULL;
   6.250 +        status = get_identity(session, il->ident->address, PEP_OWN_USERID,
   6.251 +                &stored_identity);
   6.252 +        if (status == PEP_STATUS_OK) {
   6.253 +            if(stored_identity->flags & PEP_idf_not_for_sync){
   6.254 +                free_identity(stored_identity);
   6.255 +                continue;
   6.256 +            }
   6.257 +            free_identity(stored_identity);
   6.258 +        }
   6.259 +
   6.260 +        status = set_identity(session, il->ident);
   6.261 +        if (status != PEP_STATUS_OK)
   6.262 +            break;
   6.263 +    }
   6.264 +
   6.265 +    return status;
   6.266 +}
   6.267 +    
   6.268 +
   6.269 +// storeGroupKeys() - 
   6.270 +//
   6.271 +//  params:
   6.272 +//      session (in)        session handle
   6.273 +//      state (in)          state the state machine is in
   6.274 +//      partner (in)        partner to communicate with
   6.275 +//      _group_keys (in)    group keys received from partner
   6.276 +//
   6.277 +//  returns:
   6.278 +//      PEP_STATUS_OK or any other value on error
   6.279 +
   6.280 +PEP_STATUS storeGroupKeys(
   6.281 +        PEP_SESSION session,
   6.282 +        DeviceState_state state,
   6.283 +        Identity partner,
   6.284 +        void *group_keys_extra_
   6.285 +    )
   6.286 +{
   6.287 +    PEP_STATUS status = PEP_STATUS_OK;
   6.288 +
   6.289 +    assert(session);
   6.290 +    assert(partner);
   6.291 +    assert(group_keys_extra_);
   6.292 +    if (!(session && partner && group_keys_extra_))
   6.293 +        return PEP_ILLEGAL_VALUE;
   6.294 +
   6.295 +    group_keys_extra_t *group_keys_extra = 
   6.296 +        (group_keys_extra_t*) group_keys_extra_;
   6.297 +    identity_list *group_keys = group_keys_extra->group_keys;
   6.298 +    char *group_id = group_keys_extra->group_id;
   6.299 +
   6.300 +    status = _storeGroupKeys(session, group_keys);
   6.301 +    if (status != PEP_STATUS_OK)
   6.302 +        return status;
   6.303 +
   6.304 +    // set group id according to given group-id
   6.305 +    status = set_device_group(session, group_id);
   6.306 +    if (status != PEP_STATUS_OK)
   6.307 +        return status;
   6.308 +    
   6.309 +    return status;
   6.310 +}
   6.311 +
   6.312 +// storeGroupUpdate() - 
   6.313 +//
   6.314 +//  params:
   6.315 +//      session (in)        session handle
   6.316 +//      state (in)          state the state machine is in
   6.317 +//      partner (in)        partner to communicate with
   6.318 +//      _group_keys (in)    group keys received from partner
   6.319 +//
   6.320 +//  returns:
   6.321 +//      PEP_STATUS_OK or any other value on error
   6.322 +
   6.323 +PEP_STATUS storeGroupUpdate(
   6.324 +        PEP_SESSION session,
   6.325 +        DeviceState_state state,
   6.326 +        Identity partner,
   6.327 +        void *group_keys_
   6.328 +    )
   6.329 +{
   6.330 +    PEP_STATUS status = PEP_STATUS_OK;
   6.331 +
   6.332 +    assert(session);
   6.333 +    assert(partner);
   6.334 +    assert(group_keys_);
   6.335 +    if (!(session && partner && group_keys_))
   6.336 +        return PEP_ILLEGAL_VALUE;
   6.337 +
   6.338 +    identity_list *group_keys = (identity_list*) group_keys_;
   6.339 +
   6.340 +    status = _storeGroupKeys(session, group_keys);
   6.341 +
   6.342 +
   6.343 +    return status;
   6.344 +}
   6.345 +
   6.346 +// makeGroup() - 
   6.347 +//
   6.348 +//  params:
   6.349 +//      session (in)        session handle
   6.350 +//      state (in)          state the state machine is in
   6.351 +//      partner (in)        ignored
   6.352 +//      extra (in)          ignored
   6.353 +//
   6.354 +//  returns:
   6.355 +//      PEP_STATUS_OK or any other value on error
   6.356 +
   6.357 +PEP_STATUS makeGroup(
   6.358 +        PEP_SESSION session,
   6.359 +        DeviceState_state state,
   6.360 +        Identity partner,
   6.361 +        void *extra
   6.362 +    )
   6.363 +{
   6.364 +    PEP_STATUS status = PEP_STATUS_OK;
   6.365 +
   6.366 +    assert(session);
   6.367 +   
   6.368 +    // make a new uuid 
   6.369 +    char new_uuid[37];
   6.370 +    pEpUUID uuid;
   6.371 +    uuid_generate_random(uuid);
   6.372 +    uuid_unparse_upper(uuid, new_uuid);
   6.373 +
   6.374 +    // take that new uuid as group-id
   6.375 +    status = set_device_group(session, new_uuid);
   6.376 +
   6.377 +    return status;
   6.378 +}
   6.379 +
   6.380 +// renewUUID() - 
   6.381 +//
   6.382 +//  params:
   6.383 +//      session (in)        session handle
   6.384 +//      state (in)          state the state machine is in
   6.385 +//      partner (in)        ignored
   6.386 +//      extra (in)          ignored
   6.387 +//
   6.388 +//  returns:
   6.389 +//      PEP_STATUS_OK or any other value on error
   6.390 +
   6.391 +PEP_STATUS renewUUID(
   6.392 +        PEP_SESSION session,
   6.393 +        DeviceState_state state,
   6.394 +        Identity partner,
   6.395 +        void *extra
   6.396 +    )
   6.397 +{
   6.398 +    PEP_STATUS status = PEP_STATUS_OK;
   6.399 +
   6.400 +    assert(session);
   6.401 +
   6.402 +    // change sync_uuid when entering group 
   6.403 +    // thus ignoring unprocessed handshakes
   6.404 +    // addressed to previous self (sole) once in.
   6.405 +    pEpUUID uuid;
   6.406 +    uuid_generate_random(uuid);
   6.407 +    uuid_unparse_upper(uuid, session->sync_uuid);
   6.408 +    
   6.409 +    return status;
   6.410 +}
   6.411 +
   6.412 +// leaveGroup() - 
   6.413 +//
   6.414 +//  params:
   6.415 +//      session (in)        session handle
   6.416 +//      state (in)          state the state machine is in
   6.417 +//      partner (in)        ignored
   6.418 +//      extra (in)          ignored
   6.419 +//
   6.420 +//  returns:
   6.421 +//      PEP_STATUS_OK or any other value on error
   6.422 +
   6.423 +PEP_STATUS leaveGroup(
   6.424 +        PEP_SESSION session,
   6.425 +        DeviceState_state state,
   6.426 +        Identity partner,
   6.427 +        void *extra
   6.428 +    )
   6.429 +{
   6.430 +    PEP_STATUS status = PEP_STATUS_OK;
   6.431 +
   6.432 +    assert(session);
   6.433 +
   6.434 +    status = set_device_group(session, NULL);
   6.435 +    
   6.436 +    return status;
   6.437 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/sync_app.h	Fri Nov 03 13:32:38 2017 +0100
     7.3 @@ -0,0 +1,34 @@
     7.4 +//
     7.5 +//  sync_app.h
     7.6 +//  pEpEngine
     7.7 +//
     7.8 +//  Created by Dirk Zimmermann on 16.05.17.
     7.9 +//  Copyright © 2017 Edouard Tisserant. All rights reserved.
    7.10 +//
    7.11 +
    7.12 +#ifndef sync_app_h
    7.13 +#define sync_app_h
    7.14 +
    7.15 +// TODO add this to generated code.
    7.16 +typedef enum _sync_handshake_signal {
    7.17 +    SYNC_NOTIFY_UNDEFINED = 0,
    7.18 +
    7.19 +    // request show handshake dialog
    7.20 +    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
    7.21 +    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
    7.22 +    SYNC_NOTIFY_INIT_FORM_GROUP,
    7.23 +    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE,
    7.24 +
    7.25 +    // handshake process timed out
    7.26 +    SYNC_NOTIFY_TIMEOUT,
    7.27 +
    7.28 +    // handshake accepted by user
    7.29 +    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
    7.30 +    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED,
    7.31 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED,
    7.32 +
    7.33 +    // handshake dialog must be closed
    7.34 +    SYNC_NOTIFY_OVERTAKEN
    7.35 +} sync_handshake_signal;
    7.36 +
    7.37 +#endif /* sync_app_h */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/sync_impl.c	Fri Nov 03 13:32:38 2017 +0100
     8.3 @@ -0,0 +1,971 @@
     8.4 +// This file is under GNU General Public License 3.0
     8.5 +// see LICENSE.txt
     8.6 +
     8.7 +#include "platform.h"
     8.8 +
     8.9 +// it seems pEp_internal.h needs to be the first pEp include due to the 
    8.10 +// #define for the dllimport / dllexport DYNAMIC_API stuff.
    8.11 +#include "pEp_internal.h"
    8.12 +
    8.13 +#include "sync_impl.h"
    8.14 +#include "keymanagement.h"
    8.15 +#include "message_api.h"
    8.16 +#include "map_asn1.h"
    8.17 +#include "baseprotocol.h"
    8.18 +
    8.19 +#define SYNC_VERSION_MAJOR 1
    8.20 +#define SYNC_VERSION_MINOR 0
    8.21 +
    8.22 +#define SYNC_INHIBIT_TIME (60*10)
    8.23 +#define SYNC_MSG_EXPIRE_TIME (60 * 10)
    8.24 +
    8.25 +struct _sync_msg_t {
    8.26 +    bool is_a_message;
    8.27 +    union {
    8.28 +        DeviceGroup_Protocol_t *message;
    8.29 +        struct {
    8.30 +            DeviceState_event event;
    8.31 +            Identity partner;
    8.32 +            void *extra;
    8.33 +        } event;
    8.34 +    } u;
    8.35 +};
    8.36 +
    8.37 +static bool _is_own_uuid( PEP_SESSION session, UTF8String_t *uuid)
    8.38 +{
    8.39 +    return strncmp(session->sync_session->sync_uuid,
    8.40 +                   (const char*)uuid->buf, uuid->size) == 0;
    8.41 +}
    8.42 +
    8.43 +static bool _is_own_group_uuid( PEP_SESSION session, UTF8String_t *uuid, char** our_group)
    8.44 +{
    8.45 +    PEP_STATUS status = PEP_STATUS_OK;
    8.46 +    char *devgrp = NULL;
    8.47 +
    8.48 +    if(our_group == NULL || *our_group == NULL)
    8.49 +        status = get_device_group(session, &devgrp);
    8.50 +    else
    8.51 +        devgrp = *our_group;
    8.52 +
    8.53 +    bool res = (status == PEP_STATUS_OK && devgrp && devgrp[0] &&
    8.54 +        strncmp(devgrp,(const char*)uuid->buf, uuid->size) == 0);
    8.55 +
    8.56 +    if(our_group == NULL)
    8.57 +        free(devgrp);
    8.58 +    else if(*our_group == NULL)
    8.59 +        *our_group = devgrp;
    8.60 +
    8.61 +    return res;
    8.62 +}
    8.63 +
    8.64 +PEP_STATUS receive_sync_msg(
    8.65 +        PEP_SESSION session,
    8.66 +        sync_msg_t *sync_msg,
    8.67 +        time_t *timeout
    8.68 +    )
    8.69 +{
    8.70 +    PEP_STATUS status;
    8.71 +    void *extra = NULL;
    8.72 +    Identity partner = NULL;
    8.73 +    DeviceState_event event = DeviceState_event_NONE;
    8.74 +    assert(session && sync_msg);
    8.75 +    if (!(session && sync_msg))
    8.76 +        return PEP_ILLEGAL_VALUE;
    8.77 +
    8.78 +    bool msgIsFromGroup = false;
    8.79 +    if(sync_msg->is_a_message){
    8.80 +        DeviceGroup_Protocol_t *msg = sync_msg->u.message;
    8.81 +        assert(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING);
    8.82 +        if (!(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING)){
    8.83 +            status = PEP_OUT_OF_MEMORY;
    8.84 +            goto error;
    8.85 +        }
    8.86 +
    8.87 +        partner = Identity_to_Struct(&msg->header.me, NULL);
    8.88 +        if (!partner){
    8.89 +            status = PEP_OUT_OF_MEMORY;
    8.90 +            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    8.91 +            goto error;
    8.92 +        }
    8.93 +
    8.94 +        msgIsFromGroup = msg->header.devicegroup;
    8.95 +
    8.96 +        switch (msg->payload.present) {
    8.97 +            case DeviceGroup_Protocol__payload_PR_beacon:
    8.98 +                event = Beacon;
    8.99 +                break;
   8.100 +
   8.101 +            case DeviceGroup_Protocol__payload_PR_handshakeRequest:
   8.102 +            {
   8.103 +                // re-check uuid in case sync_uuid or group changed while in the queue
   8.104 +                char *own_group_id = NULL;
   8.105 +                bool is_for_me = _is_own_uuid(session, 
   8.106 +                    msg->payload.choice.handshakeRequest.partner_id);
   8.107 +                bool is_for_group = !is_for_me && _is_own_group_uuid(session, 
   8.108 +                    msg->payload.choice.handshakeRequest.partner_id, &own_group_id);
   8.109 +                if (!(is_for_me || is_for_group)){
   8.110 +                    status = PEP_MESSAGE_IGNORE;
   8.111 +                    goto error;
   8.112 +                }
   8.113 +
   8.114 +                UTF8String_t *guuid = msg->payload.choice.handshakeRequest.group_id;
   8.115 +                if(msgIsFromGroup && guuid && guuid->buf && guuid->size) {
   8.116 +                    bool is_from_own_group = _is_own_group_uuid(session, 
   8.117 +                                                                guuid, &own_group_id);
   8.118 +
   8.119 +                    // Filter handshake requests from own group
   8.120 +                    if(is_from_own_group) {
   8.121 +                        status = PEP_MESSAGE_IGNORE;
   8.122 +                        goto error;
   8.123 +                    }
   8.124 +
   8.125 +                    // if it comes from another group, 
   8.126 +                    // we want to communicate with that group
   8.127 +                    // insert group_id given in handshake request 
   8.128 +                    // into partner's id
   8.129 +
   8.130 +                    free(partner->user_id);
   8.131 +                    partner->user_id = strndup((const char*)guuid->buf, guuid->size);
   8.132 +                    if(partner->user_id == NULL){
   8.133 +                        status = PEP_OUT_OF_MEMORY;
   8.134 +                        goto error;
   8.135 +                    }
   8.136 +
   8.137 +                    // if it comes from another group, and we are grouped,
   8.138 +                    // then this is groupmerge
   8.139 +                }
   8.140 +
   8.141 +                event = HandshakeRequest;
   8.142 +                break;
   8.143 +
   8.144 +            }
   8.145 +            case DeviceGroup_Protocol__payload_PR_updateRequest:
   8.146 +                event = UpdateRequest;
   8.147 +                break;
   8.148 +
   8.149 +            case DeviceGroup_Protocol__payload_PR_groupKeys:
   8.150 +            {
   8.151 +                // re-check uuid in case sync_uuid or group_uuid changed while in the queue
   8.152 +                char *own_group_id = NULL;
   8.153 +                UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
   8.154 +                bool is_for_me = _is_own_uuid(session, puuid);
   8.155 +                bool is_for_group = !is_for_me &&
   8.156 +                                    _is_own_group_uuid(session, 
   8.157 +                                        puuid, &own_group_id);
   8.158 +                if (!(is_for_me || is_for_group)){
   8.159 +                    status = PEP_MESSAGE_IGNORE;
   8.160 +                    goto error;
   8.161 +                }
   8.162 +
   8.163 +                UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
   8.164 +
   8.165 +                // GroupKeys come from groups, no choice
   8.166 +                if(!(msgIsFromGroup && guuid && guuid->buf && guuid->size)) {
   8.167 +                    status = PEP_SYNC_ILLEGAL_MESSAGE;
   8.168 +                    goto error;
   8.169 +                }
   8.170 +
   8.171 +                // Filter groupKeys from own group
   8.172 +                bool is_from_own_group = _is_own_group_uuid(session, 
   8.173 +                                                            guuid, 
   8.174 +                                                            &own_group_id);
   8.175 +                if(is_from_own_group) {
   8.176 +                    // FixMe : protocol shouldn't allow this
   8.177 +                    status = PEP_SYNC_ILLEGAL_MESSAGE;
   8.178 +                    goto error;
   8.179 +                }
   8.180 +
   8.181 +                // insert group_id given in groupKeys into partner's id
   8.182 +                free(partner->user_id);
   8.183 +                partner->user_id = strndup((const char*)guuid->buf, guuid->size);
   8.184 +                if(partner->user_id == NULL){
   8.185 +                    status = PEP_OUT_OF_MEMORY;
   8.186 +                    goto error;
   8.187 +                }
   8.188 +
   8.189 +                // if it comes from another group, and we are grouped,
   8.190 +                // then this is groupmerge's groupKeys
   8.191 +
   8.192 +                group_keys_extra_t *group_keys_extra;
   8.193 +                group_keys_extra = malloc(sizeof(group_keys_extra_t));
   8.194 +                if(group_keys_extra == NULL){
   8.195 +                    status = PEP_OUT_OF_MEMORY;
   8.196 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.197 +                    goto error;
   8.198 +                }
   8.199 +
   8.200 +                char *group_id = strndup((char*)guuid->buf, guuid->size);
   8.201 +
   8.202 +                if (!group_id){
   8.203 +                    status = PEP_OUT_OF_MEMORY;
   8.204 +                    free(group_keys_extra);
   8.205 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.206 +                    goto error;
   8.207 +                }
   8.208 +                group_keys_extra->group_id = group_id;
   8.209 +
   8.210 +                identity_list *group_keys = IdentityList_to_identity_list(
   8.211 +                        &msg->payload.choice.groupKeys.ownIdentities,
   8.212 +                        NULL);
   8.213 +                if (!group_keys) {
   8.214 +                    status = PEP_OUT_OF_MEMORY;
   8.215 +                    free(group_id);
   8.216 +                    free(group_keys_extra);
   8.217 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.218 +                    goto error;
   8.219 +                }
   8.220 +                group_keys_extra->group_keys = group_keys;
   8.221 +
   8.222 +                extra = (void *) group_keys_extra;
   8.223 +                event = GroupKeys;
   8.224 +
   8.225 +                break;
   8.226 +            }
   8.227 +            case DeviceGroup_Protocol__payload_PR_groupUpdate:
   8.228 +            {
   8.229 +                identity_list *group_keys = IdentityList_to_identity_list(
   8.230 +                        &msg->payload.choice.groupUpdate.ownIdentities, NULL);
   8.231 +                if (!group_keys) {
   8.232 +                    status = PEP_OUT_OF_MEMORY;
   8.233 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.234 +                    goto error;
   8.235 +                }
   8.236 +                extra = (void *) group_keys;
   8.237 +                event = GroupUpdate;
   8.238 +                break;
   8.239 +            }
   8.240 +
   8.241 +            default:
   8.242 +                status = PEP_SYNC_ILLEGAL_MESSAGE;
   8.243 +                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.244 +                goto error;
   8.245 +        }
   8.246 +
   8.247 +    }
   8.248 +    else{
   8.249 +        partner = sync_msg->u.event.partner;
   8.250 +        extra = sync_msg->u.event.extra;
   8.251 +        event = sync_msg->u.event.event;
   8.252 +    }
   8.253 +
   8.254 +    // Event inhibition, to limit mailbox and prevent cycles
   8.255 +    time_t *last = NULL;
   8.256 +    switch(event){
   8.257 +        case CannotDecrypt:
   8.258 +            last = &session->LastCannotDecrypt;
   8.259 +            break;
   8.260 +
   8.261 +        case UpdateRequest:
   8.262 +            last = &session->LastUpdateRequest;
   8.263 +            break;
   8.264 +
   8.265 +        default:
   8.266 +            break;
   8.267 +    }
   8.268 +
   8.269 +    if(last != NULL){
   8.270 +        time_t now = time(NULL);
   8.271 +        if(*last != 0 && (*last + SYNC_INHIBIT_TIME) > now ){
   8.272 +            status = PEP_STATEMACHINE_INHIBITED_EVENT;
   8.273 +            goto error;
   8.274 +        }
   8.275 +        *last = now;
   8.276 +    }
   8.277 +
   8.278 +    // partner identity must be explicitely added DB to later
   8.279 +    // be able to communicate securely with it.
   8.280 +    if(partner){
   8.281 +        // protect virtual user IDs 
   8.282 +        if((strncmp("TOFU_", partner->user_id, 6) == 0 &&
   8.283 +           strlen(partner->user_id) == strlen(partner->address) + 6 &&
   8.284 +           strcmp(partner->user_id + 6, partner->address)) ||
   8.285 +        // protect own ID 
   8.286 +           (strcmp(PEP_OWN_USERID, partner->user_id) == 0)){
   8.287 +            status = PEP_SYNC_ILLEGAL_MESSAGE;
   8.288 +            goto error;
   8.289 +        }
   8.290 +
   8.291 +        // partner IDs are UUIDs bound to session lifespan
   8.292 +        // and therefore partner identities are not supposed
   8.293 +        // to mutate over time, but just not be used anymore.
   8.294 +        // It should then be safe to accept given identity if not 
   8.295 +        // already pre-existing
   8.296 +        pEp_identity *stored_identity = NULL;
   8.297 +        status = get_identity(session,
   8.298 +                              partner->address,
   8.299 +                              partner->user_id,
   8.300 +                              &stored_identity);
   8.301 +
   8.302 +        if (!stored_identity) {
   8.303 +            // make a safe copy of partner, with no flags or comm_type
   8.304 +            pEp_identity *tmpident = new_identity(partner->address,
   8.305 +                                                  partner->fpr,
   8.306 +                                                  partner->user_id,
   8.307 +                                                  partner->username);
   8.308 +            if (tmpident == NULL){
   8.309 +                status = PEP_OUT_OF_MEMORY;
   8.310 +                goto error;
   8.311 +            }
   8.312 +
   8.313 +            // finaly add partner to DB
   8.314 +            status = set_identity(session, tmpident);
   8.315 +            assert(status == PEP_STATUS_OK);
   8.316 +            if(status == PEP_STATUS_OK && msgIsFromGroup)
   8.317 +                status = set_identity_flags(session, tmpident, PEP_idf_devicegroup);
   8.318 +            free_identity(tmpident);
   8.319 +            assert(status == PEP_STATUS_OK);
   8.320 +            if (status != PEP_STATUS_OK) {
   8.321 +                goto error;
   8.322 +            }
   8.323 +        }
   8.324 +        else if (status == PEP_STATUS_OK) {
   8.325 +            free_identity(stored_identity);
   8.326 +        } 
   8.327 +        else
   8.328 +            goto error;
   8.329 +    }
   8.330 +
   8.331 +    status = fsm_DeviceState_inject(session, event, partner, extra, timeout);
   8.332 +
   8.333 +error:
   8.334 +
   8.335 +    free_identity(partner);
   8.336 +
   8.337 +    switch(event){
   8.338 +        case GroupKeys:
   8.339 +        {
   8.340 +            free_group_keys_extra((group_keys_extra_t*)extra);
   8.341 +            break;
   8.342 +        }
   8.343 +        case GroupUpdate:
   8.344 +        {
   8.345 +            identity_list *group_keys = (identity_list*) extra;
   8.346 +            free_identity_list(group_keys);
   8.347 +            break;
   8.348 +        }
   8.349 +        default:
   8.350 +            assert(extra==NULL);
   8.351 +            break;
   8.352 +    }
   8.353 +
   8.354 +    free(sync_msg);
   8.355 +
   8.356 +    return status;
   8.357 +}
   8.358 +
   8.359 +// TODO: DYNAMIC_API was here, but broke the windows build. 
   8.360 +// We need to check whether it belongs here or it's a bug.
   8.361 +/* DYNAMIC_API */ void free_sync_msg(sync_msg_t *sync_msg)
   8.362 +{
   8.363 +    if (!sync_msg)
   8.364 +        return;
   8.365 +
   8.366 +    if(sync_msg->is_a_message){
   8.367 +        DeviceGroup_Protocol_t *msg = sync_msg->u.message;
   8.368 +        assert(msg);
   8.369 +        if (!(msg))
   8.370 +            return;
   8.371 +
   8.372 +        ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.373 +    }
   8.374 +    else{
   8.375 +        Identity partner = NULL;
   8.376 +        partner = sync_msg->u.event.partner;
   8.377 +        if(partner != NULL)
   8.378 +            free_identity(partner);
   8.379 +    }
   8.380 +
   8.381 +    free(sync_msg);
   8.382 +
   8.383 +    return;
   8.384 +}
   8.385 +
   8.386 +// from sync.c
   8.387 +int call_inject_sync_msg(PEP_SESSION session, void *msg);
   8.388 +
   8.389 +PEP_STATUS inject_DeviceState_event(
   8.390 +    PEP_SESSION session, 
   8.391 +    DeviceState_event event,
   8.392 +    Identity partner,
   8.393 +    void *extra)
   8.394 +{
   8.395 +    PEP_STATUS status;
   8.396 +
   8.397 +    assert(session);
   8.398 +    if (!(session))
   8.399 +        return PEP_ILLEGAL_VALUE;
   8.400 +
   8.401 +    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
   8.402 +    if(sync_msg == NULL)
   8.403 +        return PEP_OUT_OF_MEMORY;
   8.404 +
   8.405 +    sync_msg->is_a_message = false;
   8.406 +    sync_msg->u.event.partner = partner;
   8.407 +    sync_msg->u.event.extra = extra;
   8.408 +    sync_msg->u.event.event = event;
   8.409 +
   8.410 +    status = call_inject_sync_msg(session, sync_msg);
   8.411 +    if (status == PEP_SYNC_NO_INJECT_CALLBACK){
   8.412 +        free(sync_msg);
   8.413 +    }
   8.414 +
   8.415 +    return status;
   8.416 +}
   8.417 +
   8.418 +PEP_STATUS receive_DeviceState_msg(
   8.419 +    PEP_SESSION session, 
   8.420 +    message *src, 
   8.421 +    PEP_rating rating, 
   8.422 +    stringlist_t *keylist)
   8.423 +{
   8.424 +    assert(session && src);
   8.425 +    if (!(session && src))
   8.426 +        return PEP_ILLEGAL_VALUE;
   8.427 +
   8.428 +    bool consume = false;
   8.429 +    bool discard = false;
   8.430 +    bool force_keep_msg = false;
   8.431 +
   8.432 +    for (bloblist_t *bl = src->attachments; bl && bl->value; bl = bl->next) {
   8.433 +        if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0
   8.434 +                && bl->size) {
   8.435 +            DeviceGroup_Protocol_t *msg = NULL;
   8.436 +            uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **)
   8.437 +                    &msg, bl->value, bl->size);
   8.438 +
   8.439 +            if (msg) {
   8.440 +                PEP_STATUS status = PEP_STATUS_OK;
   8.441 +
   8.442 +                char *user_id = strndup((char *) msg->header.me.user_id->buf,
   8.443 +                        msg->header.me.user_id->size);
   8.444 +                assert(user_id);
   8.445 +                if (!user_id) {
   8.446 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.447 +                    return PEP_OUT_OF_MEMORY;
   8.448 +                }
   8.449 +
   8.450 +                // detect and mitigate address spoofing
   8.451 +                Identity check_me = NULL;
   8.452 +                char* null_terminated_address = 
   8.453 +                    strndup((char *) msg->header.me.address->buf,
   8.454 +                            msg->header.me.address->size);
   8.455 +
   8.456 +                if(null_terminated_address){
   8.457 +                    status = get_identity(session, 
   8.458 +                                          null_terminated_address, 
   8.459 +                                          PEP_OWN_USERID, 
   8.460 +                                          &check_me);
   8.461 +                    free(null_terminated_address);
   8.462 +                } 
   8.463 +                else
   8.464 +                    status = PEP_OUT_OF_MEMORY;
   8.465 +
   8.466 +                if (status == PEP_OUT_OF_MEMORY)
   8.467 +                    goto free_all;
   8.468 +
   8.469 +                free_identity(check_me);
   8.470 +
   8.471 +                bool not_own_address = status != PEP_STATUS_OK;
   8.472 +                status = PEP_STATUS_OK;
   8.473 +
   8.474 +                if (not_own_address || 
   8.475 +                    strncmp(src->from->address,
   8.476 +                            (char *) msg->header.me.address->buf,
   8.477 +                            msg->header.me.address->size) != 0 ||
   8.478 +                    strncmp(src->to->ident->address,
   8.479 +                            (char *) msg->header.me.address->buf,
   8.480 +                            msg->header.me.address->size) != 0) {
   8.481 +                    consume = true;
   8.482 +                    goto free_all;
   8.483 +                }
   8.484 +
   8.485 +                // if encrypted, ensure that header.me.fpr match signer's fpr
   8.486 +                if (rating >= PEP_rating_reliable && (
   8.487 +                        !keylist ||
   8.488 +                        !_same_fpr((char *) msg->header.me.fpr.buf,
   8.489 +                                   msg->header.me.fpr.size,
   8.490 +                                   keylist->value,
   8.491 +                                   strlen(keylist->value)))) {
   8.492 +                    consume = true;
   8.493 +                    goto free_all;
   8.494 +                }
   8.495 +
   8.496 +                // check message expiry 
   8.497 +                if(src->recv) {
   8.498 +                    time_t expiry = timegm(src->recv) + SYNC_MSG_EXPIRE_TIME;
   8.499 +                    time_t now = time(NULL);
   8.500 +                    if(expiry != 0 && now != 0 && expiry < now){
   8.501 +                        consume = true;
   8.502 +                        goto free_all;
   8.503 +                    }
   8.504 +                }
   8.505 +
   8.506 +                int32_t value = (int32_t) msg->header.sequence;
   8.507 +                if (value < 1) {
   8.508 +                    status = PEP_SEQUENCE_VIOLATED;
   8.509 +                } else {
   8.510 +                    status = sequence_value(session, (char *) user_id,
   8.511 +                            &value);
   8.512 +                }
   8.513 +
   8.514 +                if (status == PEP_STATUS_OK) {
   8.515 +                    switch (msg->payload.present) {
   8.516 +                        // HandshakeRequest needs encryption
   8.517 +                        case DeviceGroup_Protocol__payload_PR_handshakeRequest:
   8.518 +                        {
   8.519 +                            UTF8String_t *puuid = 
   8.520 +                              msg->payload.choice.handshakeRequest.partner_id;
   8.521 +                            bool is_for_me = _is_own_uuid(session, puuid);
   8.522 +                            bool is_for_group = !is_for_me && 
   8.523 +                                                _is_own_group_uuid(
   8.524 +                                                    session, puuid, NULL);
   8.525 +
   8.526 +                            // Reject handshake requests not addressed to us
   8.527 +                            if (rating < PEP_rating_reliable ||
   8.528 +                                !(is_for_me || is_for_group)){
   8.529 +                                discard = true;
   8.530 +                                goto free_all;
   8.531 +                            }
   8.532 +
   8.533 +                            // do not consume handshake request for group
   8.534 +                            if(is_for_group){ 
   8.535 +                                force_keep_msg = true;
   8.536 +                            }
   8.537 +                            break;
   8.538 +                        }
   8.539 +                        // accepting GroupKeys needs encryption and trust of peer device
   8.540 +                        case DeviceGroup_Protocol__payload_PR_groupKeys:
   8.541 +                        {
   8.542 +                            UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
   8.543 +                            bool is_for_me = _is_own_uuid(session, puuid);
   8.544 +                            bool is_for_group = !is_for_me &&
   8.545 +                                                _is_own_group_uuid(session, 
   8.546 +                                                    puuid, NULL);
   8.547 +                            if (!keylist || rating < PEP_rating_reliable ||
   8.548 +                                // message is only consumed by instance it is addressed to
   8.549 +                                !(is_for_me || is_for_group)){
   8.550 +                                discard = true;
   8.551 +                                goto free_all;
   8.552 +                            }
   8.553 +
   8.554 +                            // do not consume groupKeys for group
   8.555 +                            if(is_for_group){ 
   8.556 +                                // This happens in case case of groupmerge
   8.557 +                                force_keep_msg = true;
   8.558 +                            }
   8.559 +
   8.560 +                            // Trust check disabled here but it still it should be safe.
   8.561 +                            // SameIdentity checks in state machine ensures that we only
   8.562 +                            // store groupkeys signed by device or group that have been 
   8.563 +                            // previously accepted in handshake.
   8.564 +                            //
   8.565 +                            // // check trust of identity using user_id given in msg.header.me
   8.566 +                            // // to exacly match identity of device, the one trusted in
   8.567 +                            // // case of accepted handshake from a sole device
   8.568 +                            // pEp_identity *_from = new_identity(NULL, 
   8.569 +                            //                                    keylist->value,
   8.570 +                            //                                    user_id,
   8.571 +                            //                                    NULL);
   8.572 +                            // if (_from == NULL){
   8.573 +                            //     status = PEP_OUT_OF_MEMORY;
   8.574 +                            //     goto free_all;
   8.575 +                            // }
   8.576 +                            // status = get_trust(session, _from);
   8.577 +                            // if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
   8.578 +
   8.579 +                            //     // re-try with group_id instead, in case of handshake with pre-existing group
   8.580 +                            //     UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
   8.581 +                            //     free(_from->user_id);
   8.582 +                            //     if ((_from->user_id = strndup((const char*)guuid->buf, guuid->size)) == NULL){
   8.583 +                            //         free_identity(_from);
   8.584 +                            //         status = PEP_OUT_OF_MEMORY;
   8.585 +                            //         goto free_all;
   8.586 +                            //     }
   8.587 +                            //     _from->comm_type = PEP_ct_unknown;
   8.588 +
   8.589 +                            //     status = get_trust(session, _from);
   8.590 +                            //     if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
   8.591 +                            //         status = PEP_STATUS_OK;
   8.592 +                            //         free_identity(_from);
   8.593 +                            //         discard = true;
   8.594 +                            //         goto free_all;
   8.595 +                            //     }
   8.596 +                            // }
   8.597 +                            // free_identity(_from);
   8.598 +                            break;
   8.599 +                        }
   8.600 +                        case DeviceGroup_Protocol__payload_PR_groupUpdate:
   8.601 +                        case DeviceGroup_Protocol__payload_PR_updateRequest:
   8.602 +                        {
   8.603 +                            // inject message but don't consume it, so 
   8.604 +                            // that other group members can also be updated
   8.605 +                            force_keep_msg = true;
   8.606 +                            
   8.607 +                            if (!keylist || rating < PEP_rating_reliable){
   8.608 +                                discard = true;
   8.609 +                                goto free_all;
   8.610 +                            }
   8.611 +                            // GroupUpdate and UpdateRequests come from group.
   8.612 +                            // check trust relation in between signer key and 
   8.613 +                            // own id to be sure.
   8.614 +                            pEp_identity *_from = new_identity(NULL, 
   8.615 +                                                               keylist->value,
   8.616 +                                                               PEP_OWN_USERID,
   8.617 +                                                               NULL);
   8.618 +                            if (_from == NULL){
   8.619 +                                status = PEP_OUT_OF_MEMORY;
   8.620 +                                goto free_all;
   8.621 +                            }
   8.622 +                            status = get_trust(session, _from);
   8.623 +                            if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_pEp) {
   8.624 +                                status = PEP_STATUS_OK;
   8.625 +                                free_identity(_from);
   8.626 +                                discard = true;
   8.627 +                                goto free_all;
   8.628 +                            }
   8.629 +                            free_identity(_from);
   8.630 +                        }
   8.631 +                        default:
   8.632 +                            break;
   8.633 +                    }
   8.634 +
   8.635 +
   8.636 +                    consume = true;
   8.637 +                    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
   8.638 +                    if(sync_msg == NULL){
   8.639 +                        status = PEP_OUT_OF_MEMORY;
   8.640 +                        goto free_all;
   8.641 +                    }
   8.642 +                    sync_msg->is_a_message = true;
   8.643 +                    sync_msg->u.message = msg;
   8.644 +                    status = call_inject_sync_msg(session, sync_msg);
   8.645 +                    if (status != PEP_STATUS_OK){
   8.646 +                        if (status == PEP_SYNC_NO_INJECT_CALLBACK){
   8.647 +                            free(sync_msg);
   8.648 +                        }
   8.649 +                        goto free_all;
   8.650 +                    }
   8.651 +                    // don't free message now that it is in the queue
   8.652 +                    goto free_userid;
   8.653 +                }
   8.654 +                else if (status == PEP_OWN_SEQUENCE || status == PEP_SEQUENCE_VIOLATED) {
   8.655 +                    status = PEP_STATUS_OK;
   8.656 +                    discard = true;
   8.657 +                    goto free_all;
   8.658 +                }
   8.659 +
   8.660 +            free_all:
   8.661 +                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.662 +            free_userid:
   8.663 +                free(user_id);
   8.664 +
   8.665 +                if (status != PEP_STATUS_OK)
   8.666 +                    return status;
   8.667 +            }
   8.668 +        }
   8.669 +    }
   8.670 +
   8.671 +    if (force_keep_msg) {
   8.672 +        return PEP_MESSAGE_IGNORE;
   8.673 +    }
   8.674 +
   8.675 +    if (consume && !session->keep_sync_msg) {
   8.676 +        for (stringpair_list_t *spl = src->opt_fields ; spl && spl->value ;
   8.677 +                spl = spl->next) {
   8.678 +            if (spl->value->key &&
   8.679 +                    strcasecmp(spl->value->key, "pEp-auto-consume") == 0) {
   8.680 +                if (spl->value->value &&
   8.681 +                        strcasecmp(spl->value->value, "yes") == 0)
   8.682 +                    return PEP_MESSAGE_CONSUME;
   8.683 +            }
   8.684 +        }
   8.685 +        return PEP_MESSAGE_IGNORE;
   8.686 +    }
   8.687 +
   8.688 +    if(discard)
   8.689 +        return PEP_MESSAGE_IGNORE;
   8.690 +
   8.691 +    if (!session->keep_sync_msg) {
   8.692 +        bloblist_t *last = NULL;
   8.693 +        for (bloblist_t *bl = src->attachments; bl && bl->value; ) {
   8.694 +            if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0) {
   8.695 +                bloblist_t *b = bl;
   8.696 +                bl = bl->next;
   8.697 +                if (!last)
   8.698 +                    src->attachments = bl;
   8.699 +                else
   8.700 +                    last->next = bl;
   8.701 +                free(b->mime_type);
   8.702 +                free(b->filename);
   8.703 +                free(b->value);
   8.704 +                free(b);
   8.705 +            }
   8.706 +            else {
   8.707 +                last = bl;
   8.708 +                bl = bl->next;
   8.709 +            }
   8.710 +        }
   8.711 +    }
   8.712 +
   8.713 +    return PEP_STATUS_OK;
   8.714 +}
   8.715 +
   8.716 +DeviceGroup_Protocol_t *new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR type)
   8.717 +{
   8.718 +    DeviceGroup_Protocol_t *msg = (DeviceGroup_Protocol_t *)
   8.719 +            calloc(1, sizeof(DeviceGroup_Protocol_t));
   8.720 +    assert(msg);
   8.721 +    if (!msg)
   8.722 +        return NULL;
   8.723 +    msg->payload.present = type;
   8.724 +    return msg;
   8.725 +}
   8.726 +
   8.727 +void free_DeviceGroup_Protocol_msg(DeviceGroup_Protocol_t *msg)
   8.728 +{
   8.729 +    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   8.730 +}
   8.731 +
   8.732 +
   8.733 +#ifndef NDEBUG
   8.734 +static int _append(const void *buffer, size_t size, void *appkey)
   8.735 +{
   8.736 +    char **dest_ptr = (char **)appkey;
   8.737 +    size_t osize = strlen(*dest_ptr);
   8.738 +    size_t nsize = size + osize;
   8.739 +    *dest_ptr = realloc(*dest_ptr, nsize + 1);
   8.740 +    if(*dest_ptr == NULL) return -1;
   8.741 +    memcpy(*dest_ptr + osize, buffer, size);
   8.742 +    (*dest_ptr)[nsize] = '\0';
   8.743 +    return 0;
   8.744 +}
   8.745 +#endif
   8.746 +
   8.747 +PEP_STATUS unicast_msg(
   8.748 +        PEP_SESSION session,
   8.749 +        const Identity partner,
   8.750 +        DeviceState_state state,
   8.751 +        DeviceGroup_Protocol_t *msg,
   8.752 +        bool encrypted
   8.753 +    )
   8.754 +{
   8.755 +    PEP_STATUS status = PEP_STATUS_OK;
   8.756 +    char *payload = NULL;
   8.757 +    message *_message = NULL;
   8.758 +    pEp_identity *me = NULL;
   8.759 +    pEp_identity *_me = NULL;
   8.760 +
   8.761 +    assert(session && partner && state && msg);
   8.762 +    if (!(session && partner && state && msg))
   8.763 +        return PEP_ILLEGAL_VALUE;
   8.764 +
   8.765 +    assert(session->messageToSend);
   8.766 +    if (!session->messageToSend) {
   8.767 +        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
   8.768 +        goto error;
   8.769 +    }
   8.770 +
   8.771 +    msg->header.version.major = SYNC_VERSION_MAJOR;
   8.772 +    msg->header.version.minor = SYNC_VERSION_MINOR;
   8.773 +
   8.774 +    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
   8.775 +    if (status != PEP_STATUS_OK)
   8.776 +        goto error;
   8.777 +    
   8.778 +    int32_t seq = 0;
   8.779 +
   8.780 +    status = sequence_value(session, session->sync_session->sync_uuid, &seq);
   8.781 +    if (status != PEP_OWN_SEQUENCE && status != PEP_STATUS_OK)
   8.782 +        goto error;
   8.783 +
   8.784 +    msg->header.sequence = (long) seq;
   8.785 +
   8.786 +    _me = identity_dup(me);
   8.787 +    if (!_me)
   8.788 +        goto enomem;
   8.789 +
   8.790 +    free(_me->user_id);
   8.791 +    _me->user_id = strndup(session->sync_session->sync_uuid, 36);
   8.792 +    assert(_me->user_id);
   8.793 +    if (!_me->user_id)
   8.794 +        goto enomem;
   8.795 +
   8.796 +    if (Identity_from_Struct(_me, &msg->header.me) == NULL)
   8.797 +        goto enomem;
   8.798 +
   8.799 +    free_identity(_me);
   8.800 +    _me = NULL;
   8.801 +
   8.802 +    msg->header.state = (long) state;
   8.803 +
   8.804 +    bool devicegroup = deviceGrouped(session);
   8.805 +    if (devicegroup)
   8.806 +        msg->header.devicegroup = 1;
   8.807 +    else
   8.808 +        msg->header.devicegroup = 0;
   8.809 +
   8.810 +    if (asn_check_constraints(&asn_DEF_DeviceGroup_Protocol, msg, NULL, NULL)) {
   8.811 +        status = PEP_CONTRAINTS_VIOLATED;
   8.812 +        goto error;
   8.813 +    }
   8.814 +
   8.815 +    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   8.816 +            NULL, msg, (void **) &payload);
   8.817 +    if (size == -1) {
   8.818 +        status = PEP_CANNOT_ENCODE;
   8.819 +        goto error;
   8.820 +    }
   8.821 +
   8.822 +    status = prepare_message(me, partner, payload, size, &_message);
   8.823 +    if (status != PEP_STATUS_OK)
   8.824 +        goto error;
   8.825 +    payload = NULL;
   8.826 +    free_identity(me);
   8.827 +    me = NULL;
   8.828 +
   8.829 +#ifndef NDEBUG
   8.830 +    asn_enc_rval_t er;
   8.831 +    er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg, 
   8.832 +                    XER_F_BASIC, _append, &_message->longmsg);
   8.833 +    if(er.encoded == -1)
   8.834 +        goto error;
   8.835 +#endif
   8.836 +
   8.837 +    if (encrypted) {
   8.838 +        if (msg->payload.present == DeviceGroup_Protocol__payload_PR_groupKeys || 
   8.839 +            msg->payload.present == DeviceGroup_Protocol__payload_PR_groupUpdate) {
   8.840 +            PEP_rating rating = PEP_rating_undefined;
   8.841 +            status = outgoing_message_rating(session, _message, &rating);
   8.842 +            if (status != PEP_STATUS_OK)
   8.843 +                goto error;
   8.844 +            if (rating < PEP_rating_trusted) {
   8.845 +                status = PEP_SYNC_NO_TRUST;
   8.846 +                goto error;
   8.847 +            }
   8.848 +            
   8.849 +            stringlist_t *keylist = NULL;
   8.850 +            status = _own_keys_retrieve(session, &keylist, PEP_idf_not_for_sync);
   8.851 +            if (status != PEP_STATUS_OK)
   8.852 +                goto error;
   8.853 +
   8.854 +            for (stringlist_t *_keylist=keylist; _keylist!=NULL; _keylist=_keylist->next) {
   8.855 +                char *fpr = _keylist->value;
   8.856 +                static char filename[MAX_LINELENGTH];
   8.857 +                int result = snprintf(filename, MAX_LINELENGTH, "file://%s-sec.asc", fpr);
   8.858 +                if (result < 0)
   8.859 +                    goto enomem;
   8.860 +                char *key = NULL;
   8.861 +                size_t size = 0;
   8.862 +                status = export_secrect_key(session, fpr, &key, &size);
   8.863 +                if (status != PEP_STATUS_OK)
   8.864 +                    goto error;
   8.865 +                bloblist_t *bl = bloblist_add(_message->attachments,
   8.866 +                        (char *) key, size, "application/pgp-keys", filename);
   8.867 +                if (!bl)
   8.868 +                    goto enomem;
   8.869 +                if (!_message->attachments)
   8.870 +                    _message->attachments = bl;
   8.871 +            }
   8.872 +        }
   8.873 +
   8.874 +        message *_encrypted = NULL;
   8.875 +        status = encrypt_message(session, _message, NULL, &_encrypted, PEP_enc_PEP, 0);
   8.876 +        if (status != PEP_STATUS_OK)
   8.877 +            goto error;
   8.878 +        free_message(_message);
   8.879 +        _message = _encrypted;
   8.880 +    }
   8.881 +    else {
   8.882 +        attach_own_key(session, _message);
   8.883 +    }
   8.884 +
   8.885 +    status = session->messageToSend(session->sync_obj, _message);
   8.886 +    return status;
   8.887 +
   8.888 +enomem:
   8.889 +    status = PEP_OUT_OF_MEMORY;
   8.890 +error:
   8.891 +    free_identity(_me);
   8.892 +    free(payload);
   8.893 +    free_message(_message);
   8.894 +    free_identity(me);
   8.895 +    return status;
   8.896 +}
   8.897 +
   8.898 +PEP_STATUS multicast_self_msg(
   8.899 +        PEP_SESSION session,
   8.900 +        DeviceState_state state,
   8.901 +        DeviceGroup_Protocol_t *msg,
   8.902 +        bool encrypted
   8.903 +    )
   8.904 +{
   8.905 +    PEP_STATUS status = PEP_STATUS_OK;
   8.906 +
   8.907 +    assert(session && state && msg);
   8.908 +    if (!(session && state && msg))
   8.909 +        return PEP_ILLEGAL_VALUE;
   8.910 +
   8.911 +    identity_list *own_identities = NULL;
   8.912 +    status = _own_identities_retrieve(session, &own_identities, PEP_idf_not_for_sync);
   8.913 +    if (status != PEP_STATUS_OK)
   8.914 +        return status;
   8.915 +
   8.916 +    for (identity_list *_i = own_identities; _i && _i->ident; _i = _i->next) {
   8.917 +        pEp_identity *me = _i->ident;
   8.918 +
   8.919 +        // FIXME: no deep copy for multicast supported yet
   8.920 +        // DeviceGroup_Protocol_t *_msg = malloc(sizeof(DeviceGroup_Protocol_t));
   8.921 +        // assert(_msg);
   8.922 +        // if (_msg == NULL){
   8.923 +        //     status = PEP_OUT_OF_MEMORY;
   8.924 +        //     goto error;
   8.925 +        // }
   8.926 +        // memcpy(_msg, msg, sizeof(DeviceGroup_Protocol_t));
   8.927 +        status = unicast_msg(session, me, state, msg, encrypted);
   8.928 +        //status = unicast_msg(session, me, state, _msg, encrypted);
   8.929 +        //free_DeviceGroup_Protocol_msg(_msg);
   8.930 +    }
   8.931 +
   8.932 +    free_identity_list(own_identities);
   8.933 +    return PEP_STATUS_OK;
   8.934 +
   8.935 +// error:
   8.936 +//     free_identity_list(own_identities);
   8.937 +//     return status;
   8.938 +}
   8.939 +
   8.940 +void free_group_keys_extra(group_keys_extra_t* group_keys_extra)
   8.941 +{
   8.942 +    identity_list *group_keys = group_keys_extra->group_keys;
   8.943 +    char *group_id = group_keys_extra->group_id;
   8.944 +    free_identity_list(group_keys);
   8.945 +    free(group_id);
   8.946 +    free(group_keys_extra);
   8.947 +}
   8.948 +
   8.949 +group_keys_extra_t* group_keys_extra_dup(group_keys_extra_t* group_key_extra_src)
   8.950 +{
   8.951 +    group_keys_extra_t *group_key_extra_dst;
   8.952 +    group_key_extra_dst = calloc(1,sizeof(group_keys_extra_t));
   8.953 +    if(group_key_extra_dst == NULL){
   8.954 +        return NULL;
   8.955 +    }
   8.956 +
   8.957 +    char *group_id = strdup(group_key_extra_src->group_id);
   8.958 +
   8.959 +    if (group_key_extra_dst->group_id && !group_id){
   8.960 +        free(group_key_extra_dst);
   8.961 +        return NULL;
   8.962 +    }
   8.963 +    group_key_extra_dst->group_id = group_id;
   8.964 +
   8.965 +    identity_list *group_keys = identity_list_dup(group_key_extra_src->group_keys);;
   8.966 +    if (!group_keys) {
   8.967 +        free(group_id);
   8.968 +        free(group_key_extra_dst);
   8.969 +        return NULL;
   8.970 +    }
   8.971 +    group_key_extra_dst->group_keys = group_keys;
   8.972 +
   8.973 +    return group_key_extra_dst;
   8.974 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/sync_impl.h	Fri Nov 03 13:32:38 2017 +0100
     9.3 @@ -0,0 +1,64 @@
     9.4 +// This file is under GNU General Public License 3.0
     9.5 +// see LICENSE.txt
     9.6 +
     9.7 +#pragma once
     9.8 +
     9.9 +#include "../asn.1/DeviceGroup-Protocol.h"
    9.10 +#include "message.h"
    9.11 +#include "sync.h"
    9.12 +#include "sync_fsm.h"
    9.13 +
    9.14 +#ifdef __cplusplus
    9.15 +extern "C" {
    9.16 +#endif
    9.17 +
    9.18 +typedef struct _group_keys_extra {
    9.19 +    identity_list *group_keys;
    9.20 +    char *group_id;
    9.21 +} group_keys_extra_t;
    9.22 +
    9.23 +void free_group_keys_extra(group_keys_extra_t* groupkeys);
    9.24 +group_keys_extra_t* group_keys_extra_dup(group_keys_extra_t* groupkeys);
    9.25 +
    9.26 +PEP_STATUS receive_sync_msg(
    9.27 +        PEP_SESSION session,
    9.28 +        sync_msg_t *sync_msg,
    9.29 +        time_t *timeout
    9.30 +    );
    9.31 +
    9.32 +PEP_STATUS inject_DeviceState_event(
    9.33 +    PEP_SESSION session, 
    9.34 +    DeviceState_event event,
    9.35 +    Identity partner,
    9.36 +    void *extra);
    9.37 +
    9.38 +PEP_STATUS receive_DeviceState_msg(
    9.39 +    PEP_SESSION session, 
    9.40 +    message *src, 
    9.41 +    PEP_rating rating, 
    9.42 +    stringlist_t *keylist);
    9.43 +
    9.44 +DeviceGroup_Protocol_t *new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR type);
    9.45 +void free_DeviceGroup_Protocol_msg(DeviceGroup_Protocol_t *msg);
    9.46 +
    9.47 +PEP_STATUS unicast_msg(
    9.48 +        PEP_SESSION session,
    9.49 +        const Identity partner,
    9.50 +        DeviceState_state state,
    9.51 +        DeviceGroup_Protocol_t *msg,
    9.52 +        bool encrypted
    9.53 +    );
    9.54 +
    9.55 +PEP_STATUS multicast_self_msg(
    9.56 +        PEP_SESSION session,
    9.57 +        DeviceState_state state,
    9.58 +        DeviceGroup_Protocol_t *msg,
    9.59 +        bool encrypted
    9.60 +    );
    9.61 +
    9.62 +bool is_double(DeviceGroup_Protocol_t *msg);
    9.63 +
    9.64 +#ifdef __cplusplus
    9.65 +}
    9.66 +#endif
    9.67 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/sync/Makefile	Fri Nov 03 13:32:38 2017 +0100
    10.3 @@ -0,0 +1,38 @@
    10.4 +# Copyright 2017, pEp Foundation
    10.5 +# This file is part of pEpEngine
    10.6 +# This file may be used under the terms of the GNU General Public License version 3
    10.7 +# see LICENSE.txt
    10.8 +
    10.9 +include ../default.conf
   10.10 +
   10.11 +.PHONY: all
   10.12 +all: .codegen
   10.13 +
   10.14 +# Currently not in use, kept for historic reasons
   10.15 +skeleton: .actions
   10.16 +
   10.17 +.codegen: .statemachines .actions
   10.18 +	cp -f generated/*.* ../src
   10.19 +	touch $@
   10.20 +
   10.21 +.actions: devicegroup.fsm gen_actions.ysl2 fsm.yml2 functions.ysl2
   10.22 +	$(YML2_PROC) $(YML2_OPTS) -y gen_actions.ysl2 $< -o $@
   10.23 +
   10.24 +.statemachines: devicegroup.fsm gen_statemachine.ysl2 fsm.yml2 functions.ysl2
   10.25 +	$(YML2_PROC) $(YML2_OPTS) -y gen_statemachine.ysl2 $< -o $@
   10.26 +
   10.27 +.PHONY: clean
   10.28 +clean:
   10.29 +	rm -f *.xml *.xsl *.dot *.svg \
   10.30 +	$(patsubst generated/%,../src/%,$(wildcard generated/*.*)) \
   10.31 +	../generated/* ../skeletons/* .statemachines .actions .codegen \
   10.32 +	generated/Makefile.protocols
   10.33 +
   10.34 +%.xml: %.fsm
   10.35 +	$(YML2_PATH)/yml2c $< -o $@
   10.36 +
   10.37 +%.dot: gen_dot.ysl2 devicegroup.fsm
   10.38 +	$(YML2_PROC) $(YML2_OPTS) -y $^
   10.39 +
   10.40 +%.svg: %.dot
   10.41 +	dot -Tsvg -o $@ $<
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/sync/devicegroup.fsm	Fri Nov 03 13:32:38 2017 +0100
    11.3 @@ -0,0 +1,354 @@
    11.4 +// This file is under GNU General Public License 3.0
    11.5 +// see LICENSE.txt
    11.6 +
    11.7 +// DeviceGroup protocol for p≡p
    11.8 +
    11.9 +// Copyleft (c) 2016, p≡p foundation
   11.10 +
   11.11 +// Written by Volker Birk
   11.12 +
   11.13 +include ./fsm.yml2
   11.14 +
   11.15 +protocol DeviceGroup {
   11.16 +    // all messages have a timestamp, time out and are removed after timeout
   11.17 +
   11.18 +    broadcast sendBeacon;
   11.19 +    broadcast sendGroupUpdate;
   11.20 +    broadcast sendUpdateRequest;
   11.21 +    unencrypted sendBeacon;
   11.22 +
   11.23 +    fsm DeviceState filename=sync {
   11.24 +        condition deviceGrouped();
   11.25 +        condition keyElectionWon(Identity partner);
   11.26 +        condition sameIdentities(Identity a, Identity b);
   11.27 +        condition sameKeyAndAddress(Identity a, Identity b);
   11.28 +
   11.29 +        state InitState {
   11.30 +            on Init {
   11.31 +                if deviceGrouped()
   11.32 +                    go Grouped;
   11.33 +                go Sole;
   11.34 +            }
   11.35 +        }
   11.36 +
   11.37 +        state Sole end=1 {
   11.38 +            on KeyGen {
   11.39 +                do sendBeacon;
   11.40 +                go SoleWaiting;
   11.41 +            }
   11.42 +            on CannotDecrypt {
   11.43 +                do sendBeacon;
   11.44 +                go SoleWaiting;
   11.45 +            }
   11.46 +            on Beacon(Identity partner){
   11.47 +                do sendHandshakeRequest(partner);
   11.48 +                go SoleBeaconed(partner);
   11.49 +            }
   11.50 +            on HandshakeRequest(Identity partner) {
   11.51 +                do sendHandshakeRequest(partner);
   11.52 +                go HandshakingSole(partner);
   11.53 +            }
   11.54 +        }
   11.55 +
   11.56 +        // copy of sole state with a timeout to enable fast polling for a second
   11.57 +        // TODO use more YSLT power here (substates ?) 
   11.58 +        state SoleWaiting timeout=60 {
   11.59 +            on KeyGen {
   11.60 +                do sendBeacon;
   11.61 +            }
   11.62 +            on CannotDecrypt {
   11.63 +                do sendBeacon;
   11.64 +            }
   11.65 +            on Beacon(Identity partner){
   11.66 +                do sendHandshakeRequest(partner);
   11.67 +                go SoleBeaconed(partner);
   11.68 +            }
   11.69 +            on HandshakeRequest(Identity partner) {
   11.70 +                do sendHandshakeRequest(partner);
   11.71 +                go HandshakingSole(partner);
   11.72 +            }
   11.73 +            on Timeout go Sole;
   11.74 +        }
   11.75 +
   11.76 +        state SoleBeaconed timeout=600 (Identity expected) {
   11.77 +            on KeyGen{
   11.78 +                do sendBeacon;
   11.79 +                go Sole;
   11.80 +            }
   11.81 +            on CannotDecrypt{
   11.82 +                do sendBeacon;
   11.83 +                go Sole;
   11.84 +            }
   11.85 +            on Beacon(Identity partner) {
   11.86 +                do sendHandshakeRequest(partner);
   11.87 +                go SoleBeaconed(partner);
   11.88 +            }
   11.89 +            on HandshakeRequest(Identity partner) {
   11.90 +                if sameIdentities(partner, expected) {
   11.91 +                    // do nothing, to avoid sending handshake request twice 
   11.92 +                } else {
   11.93 +                    do sendHandshakeRequest(partner);
   11.94 +                }
   11.95 +                go HandshakingSole(partner);
   11.96 +            }
   11.97 +            on Timeout go Sole;
   11.98 +        }
   11.99 +
  11.100 +        state HandshakingSole timeout=600 (Identity expected) {
  11.101 +            on Init{
  11.102 +                if keyElectionWon(expected) {
  11.103 +                    do notifyInitFormGroup(expected);
  11.104 +                } else {
  11.105 +                    do notifyInitAddOurDevice(expected);
  11.106 +                }
  11.107 +            }
  11.108 +            on HandshakeRejected(Identity partner) {
  11.109 +                do rejectHandshake(partner);
  11.110 +                go Sole;
  11.111 +            }
  11.112 +            on HandshakeAccepted(Identity partner) {
  11.113 +                if sameIdentities(partner, expected) {
  11.114 +                    do acceptHandshake(partner); 
  11.115 +                    if keyElectionWon(partner) {
  11.116 +                        do makeGroup;
  11.117 +                        do sendGroupKeys(partner);
  11.118 +                        do renewUUID;
  11.119 +                        do notifyAcceptedGroupCreated(partner);
  11.120 +                        go Grouped;
  11.121 +                    }
  11.122 +                    go WaitForGroupKeysSole(partner);
  11.123 +                }
  11.124 +                go Sole;
  11.125 +            }
  11.126 +            on Cancel go Sole;
  11.127 +            on GroupKeys(Identity partner, GroupKeys groupkeys) {
  11.128 +                if keyElectionWon(expected) {
  11.129 +                    // not supposed to receive groupkeys - ignore
  11.130 +                } else {
  11.131 +                    // UUID changes in between, so we can only check for same address and fpr
  11.132 +                    if sameKeyAndAddress(partner, expected) {
  11.133 +                        go WaitForAcceptSole(partner, groupkeys);
  11.134 +                    }
  11.135 +                }
  11.136 +            }
  11.137 +            on Timeout {
  11.138 +                do notifyTimeout(expected);
  11.139 +                do sendBeacon;
  11.140 +                go Sole;
  11.141 +            }
  11.142 +        }
  11.143 +    
  11.144 +        state WaitForGroupKeysSole timeout=600 (Identity expected) {
  11.145 +            on GroupKeys(Identity partner, GroupKeys groupkeys) {
  11.146 +                // UUID changes in between, so we can only check for same address and fpr
  11.147 +                if sameKeyAndAddress(partner, expected) {
  11.148 +                    do storeGroupKeys(partner, groupkeys);
  11.149 +                    do sendGroupUpdate;
  11.150 +                    do renewUUID;
  11.151 +                    do notifyAcceptedDeviceAdded(partner);
  11.152 +                    go Grouped;
  11.153 +                }
  11.154 +            }
  11.155 +            on Timeout {
  11.156 +                do notifyTimeout(expected);
  11.157 +                go Sole;
  11.158 +            }
  11.159 +        }
  11.160 +
  11.161 +        state WaitForAcceptSole timeout=600 (Identity expected, GroupKeys groupkeys) {
  11.162 +            on HandshakeRejected(Identity partner) {
  11.163 +                do rejectHandshake(partner);
  11.164 +                go Sole;
  11.165 +            }
  11.166 +            on HandshakeAccepted(Identity partner) {
  11.167 +                // UUID changes in between, so we can only check for same address and fpr
  11.168 +                if sameKeyAndAddress(partner, expected) {
  11.169 +                    do acceptHandshake(partner); 
  11.170 +                    do storeGroupKeys(partner, groupkeys);
  11.171 +                    do sendGroupUpdate;
  11.172 +                    do renewUUID;
  11.173 +                    do notifyAcceptedDeviceAdded(partner);
  11.174 +                    go Grouped;
  11.175 +                }
  11.176 +                go Sole;
  11.177 +            }
  11.178 +            on Cancel go Sole;
  11.179 +            on Timeout {
  11.180 +                do notifyTimeout(expected);
  11.181 +                go Sole;
  11.182 +            }
  11.183 +        }
  11.184 +
  11.185 +        state Grouped end=1 {
  11.186 +            on KeyGen
  11.187 +                do sendGroupUpdate;
  11.188 +            on CannotDecrypt {
  11.189 +                do sendUpdateRequest;
  11.190 +                do sendBeacon;
  11.191 +                go GroupWaiting;
  11.192 +            }
  11.193 +            on UpdateRequest
  11.194 +                do sendGroupUpdate;
  11.195 +            on Beacon(Identity partner){
  11.196 +                do sendHandshakeRequest(partner);
  11.197 +                go GroupedBeaconed(partner);
  11.198 +            }
  11.199 +            on HandshakeRequest(Identity partner) {
  11.200 +                do sendHandshakeRequest(partner);
  11.201 +                go HandshakingGrouped(partner);
  11.202 +            }
  11.203 +            on GroupUpdate(Identity partner, IdentityList keys)
  11.204 +                do storeGroupUpdate(partner, keys);
  11.205 +        }
  11.206 +
  11.207 +        // copy of grouped state, with a timeout to enable fast poling for a minut
  11.208 +        state GroupWaiting timeout=60 {
  11.209 +            on KeyGen
  11.210 +                do sendGroupUpdate;
  11.211 +            on CannotDecrypt {
  11.212 +                do sendUpdateRequest;
  11.213 +                do sendBeacon;
  11.214 +            }
  11.215 +            on UpdateRequest
  11.216 +                do sendGroupUpdate;
  11.217 +            on Beacon(Identity partner){
  11.218 +                do sendHandshakeRequest(partner);
  11.219 +                go GroupedBeaconed(partner);
  11.220 +            }
  11.221 +            on HandshakeRequest(Identity partner) {
  11.222 +                do sendHandshakeRequest(partner);
  11.223 +                go HandshakingGrouped(partner);
  11.224 +            }
  11.225 +            on GroupUpdate(Identity partner, IdentityList keys)
  11.226 +                do storeGroupUpdate(partner, keys);
  11.227 +            on Timeout go Grouped;
  11.228 +        }
  11.229 +
  11.230 +        state GroupedBeaconed timeout=600 (Identity expected){
  11.231 +            on KeyGen
  11.232 +                do sendGroupUpdate;
  11.233 +            on CannotDecrypt {
  11.234 +                do sendUpdateRequest;
  11.235 +                do sendBeacon;
  11.236 +            }
  11.237 +            on UpdateRequest
  11.238 +                do sendGroupUpdate;
  11.239 +            on Beacon(Identity partner){
  11.240 +                do sendHandshakeRequest(partner);
  11.241 +                go GroupedBeaconed(partner);
  11.242 +            }
  11.243 +            on HandshakeRequest(Identity partner) {
  11.244 +                if sameIdentities(partner, expected) {
  11.245 +                    // do nothing, to avoid sending handshake request twice 
  11.246 +                } else {
  11.247 +                    do sendHandshakeRequest(partner);
  11.248 +                }
  11.249 +                go HandshakingGrouped(partner);
  11.250 +            }
  11.251 +            on GroupUpdate(Identity partner, IdentityList keys)
  11.252 +                do storeGroupUpdate(partner, keys);
  11.253 +            on Timeout go Grouped;
  11.254 +        }
  11.255 +
  11.256 +        state HandshakingGrouped timeout=600 (Identity expected) {
  11.257 +            // HandshakeRequest from same group are filtered in receive_sync_msg
  11.258 +            on Init{
  11.259 +                if keyElectionWon(expected) {
  11.260 +                    do notifyInitAddOtherDevice(partner);
  11.261 +                } else {
  11.262 +                    do notifyInitMoveOurDevice(partner);
  11.263 +                }
  11.264 +            }
  11.265 +            on HandshakeRejected(Identity partner) {
  11.266 +                do rejectHandshake(partner);             // stores rejection of partner
  11.267 +                do sendGroupUpdate;
  11.268 +                go Grouped;
  11.269 +            }
  11.270 +            on HandshakeAccepted(Identity partner) {
  11.271 +                do acceptHandshake(partner); 
  11.272 +                do sendGroupUpdate;
  11.273 +                if keyElectionWon(partner) {
  11.274 +                    do sendGroupKeys(partner);
  11.275 +                    do notifyAcceptedDeviceAdded(partner);
  11.276 +                    go Grouped;
  11.277 +                }
  11.278 +                go WaitForGroupKeysGrouped(partner);
  11.279 +            }
  11.280 +            on Cancel go Grouped;
  11.281 +            on GroupKeys(Identity partner, GroupKeys groupkeys) {
  11.282 +                if keyElectionWon(expected) {
  11.283 +                    // not supposed to receive groupkeys - ignore
  11.284 +                } else {
  11.285 +                    // UUID changes in between, so we can only check for same address and fpr
  11.286 +                    if sameKeyAndAddress(partner, expected) {
  11.287 +                        go WaitForAcceptGrouped(partner, groupkeys);
  11.288 +                    }
  11.289 +                }
  11.290 +            }
  11.291 +            on GroupUpdate(Identity partner, IdentityList keys) {
  11.292 +                do notifyOvertaken(partner);
  11.293 +                do storeGroupUpdate(partner, keys);
  11.294 +                go Grouped;
  11.295 +            }
  11.296 +            on Timeout {
  11.297 +                do notifyTimeout(expected);
  11.298 +                go Grouped;
  11.299 +            }
  11.300 +        }
  11.301 +
  11.302 +        state WaitForGroupKeysGrouped timeout=600 (Identity expected) {
  11.303 +            on GroupKeys(Identity partner, GroupKeys groupkeys) {
  11.304 +                if sameIdentities(partner, expected) {
  11.305 +                    do storeGroupKeys(partner, groupkeys);
  11.306 +                    do sendGroupUpdate;
  11.307 +                    do renewUUID;
  11.308 +                    do notifyAcceptedDeviceMoved(partner);
  11.309 +                    go Grouped;
  11.310 +                }
  11.311 +            }
  11.312 +            on GroupUpdate(Identity partner, IdentityList keys) {
  11.313 +                do notifyOvertaken(partner);
  11.314 +                do storeGroupUpdate(partner, keys);
  11.315 +                go Grouped;
  11.316 +            }
  11.317 +            on Timeout {
  11.318 +                do notifyTimeout(expected);
  11.319 +                go Grouped;
  11.320 +            }
  11.321 +        }
  11.322 +
  11.323 +        state WaitForAcceptGrouped timeout=600 (Identity expected, GroupKeys groupkeys) {
  11.324 +            on HandshakeRejected(Identity partner) {
  11.325 +                do rejectHandshake(partner);
  11.326 +                do sendGroupUpdate;
  11.327 +                go Grouped;
  11.328 +            }
  11.329 +            on HandshakeAccepted(Identity partner) {
  11.330 +                if sameIdentities(partner, expected) {
  11.331 +                    do acceptHandshake(partner); 
  11.332 +                    do storeGroupKeys(partner, groupkeys);
  11.333 +                    do sendGroupUpdate;
  11.334 +                    do renewUUID;
  11.335 +                    do notifyAcceptedDeviceMoved(partner);
  11.336 +                }
  11.337 +                go Grouped;
  11.338 +            }
  11.339 +            on Cancel go Grouped;
  11.340 +            on GroupUpdate(Identity partner, IdentityList keys) {
  11.341 +                do notifyOvertaken(partner);
  11.342 +                do storeGroupUpdate(partner, keys);
  11.343 +                go Grouped;
  11.344 +            }
  11.345 +            on Timeout {
  11.346 +                do notifyTimeout(expected);
  11.347 +                go Grouped;
  11.348 +            }
  11.349 +        }
  11.350 +
  11.351 +        tag Init 1;
  11.352 +        tag Beacon 2;
  11.353 +        tag HandshakeRequest 3;
  11.354 +        tag GroupKeys 4;
  11.355 +    }
  11.356 +}
  11.357 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/sync/fsm.yml2	Fri Nov 03 13:32:38 2017 +0100
    12.3 @@ -0,0 +1,19 @@
    12.4 +// This file is under GNU General Public License 3.0
    12.5 +// see LICENSE.txt
    12.6 +
    12.7 +// FSM Y language 1.0
    12.8 +
    12.9 +// Copyleft (c) 2016, p≡p foundation
   12.10 +
   12.11 +// Written by Volker Birk
   12.12 +
   12.13 +decl protocol @name;
   12.14 +decl fsm @name;
   12.15 +decl state @name (timeout=0);
   12.16 +decl event @name, on is event;
   12.17 +decl transition @target, go is transition;
   12.18 +decl action @name, do is action;
   12.19 +decl condition @name, if is condition;
   12.20 +decl alternative, else is alternative;
   12.21 +decl interface @name;
   12.22 +decl tag @name (id);
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/sync/functions.ysl2	Fri Nov 03 13:32:38 2017 +0100
    13.3 @@ -0,0 +1,15 @@
    13.4 +// This file is under GNU General Public License 3.0
    13.5 +// see LICENSE.txt
    13.6 +
    13.7 +// function library
    13.8 +
    13.9 +def "func:distinctName" {
   13.10 +    param "nodes", "/..";
   13.11 +    choose {
   13.12 +        when "not($nodes)"
   13.13 +            result "/..";
   13.14 +        otherwise {
   13.15 +            result "$nodes[1] | func:distinctName($nodes[position() > 1])[@name != $nodes[1]/@name]";
   13.16 +        }
   13.17 +    }
   13.18 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/sync/gen_actions.ysl2	Fri Nov 03 13:32:38 2017 +0100
    14.3 @@ -0,0 +1,300 @@
    14.4 +// This file is under GNU General Public License 3.0
    14.5 +// see LICENSE.txt
    14.6 +
    14.7 +// generate actions skeleton
    14.8 +
    14.9 +// Copyleft (c) 2016, p≡p foundation
   14.10 +
   14.11 +// Written by Volker Birk
   14.12 +
   14.13 +include yslt.yml2
   14.14 +
   14.15 +tstylesheet {
   14.16 +    include standardlib.ysl2
   14.17 +    include ./functions.ysl2
   14.18 +
   14.19 +    template "/protocol" {
   14.20 +        apply "fsm", mode=send, 0;
   14.21 +        apply "fsm", mode=other, 0;
   14.22 +    }
   14.23 +
   14.24 +    template "fsm", mode=send document "generated/{@filename}_send_actions.c", "text" {
   14.25 +        const "name", "@name";
   14.26 +        const "filename", "@filename";
   14.27 +        ||
   14.28 +        // Send Actions for «@name» state machine
   14.29 +
   14.30 +        #include <assert.h>
   14.31 +        #include "pEp_internal.h"
   14.32 +        #include "keymanagement.h"
   14.33 +        #include "message.h"
   14.34 +        #include "«@filename»_fsm.h"
   14.35 +        #include "baseprotocol.h"
   14.36 +        #include "map_asn1.h"
   14.37 +        #include "../asn.1/DeviceGroup-Protocol.h"
   14.38 +        #include "sync_impl.h"
   14.39 +        ||
   14.40 +        for "func:distinctName(//action)"
   14.41 +            if "substring(@name, 1, 4) = 'send'"
   14.42 +                | #include "../asn.1/«substring(@name, 5, 255)».h"
   14.43 +        |
   14.44 +        for "func:distinctName(//action)"
   14.45 +            if "substring(@name, 1, 4) = 'send'"
   14.46 +                call "send_action"
   14.47 +                    with "action", ".",
   14.48 +                    with "fsm", "$name",
   14.49 +                    with "filename", "$filename";
   14.50 +
   14.51 +        ||
   14.52 +
   14.53 +        PEP_STATUS _notifyHandshake(
   14.54 +                PEP_SESSION session,
   14.55 +                Identity partner,
   14.56 +                sync_handshake_signal signal
   14.57 +            );
   14.58 +        ||
   14.59 +
   14.60 +        for "func:distinctName(//action)"
   14.61 +            if "substring(@name, 1, 6) = 'notify'"
   14.62 +                call "notify_action"
   14.63 +                    with "action", ".",
   14.64 +                    with "fsm", "$name",
   14.65 +                    with "filename", "$filename";
   14.66 +    }
   14.67 +
   14.68 +    template "fsm", mode=other document "skeletons/{@filename}_actions.c", "text" {
   14.69 +        const "name", "@name";
   14.70 +        const "filename", "@filename";
   14.71 +        ||
   14.72 +        // Actions for «@name» state machine
   14.73 +
   14.74 +        #include <assert.h>
   14.75 +        #include "pEp_internal.h"
   14.76 +        #include "keymanagement.h"
   14.77 +        #include "message.h"
   14.78 +        #include "«@filename»_fsm.h"
   14.79 +        #include "../asn.1/DeviceGroup-Protocol.h"
   14.80 +
   14.81 +        ||
   14.82 +        for "func:distinctName(//action)"
   14.83 +            if "substring(@name, 1, 4) != 'send'"
   14.84 +                call "other_action"
   14.85 +                    with "action", ".",
   14.86 +                    with "fsm", "$name",
   14.87 +                    with "filename", "$filename";
   14.88 +    }
   14.89 +
   14.90 +    function "paramcheck" {
   14.91 +        param "partner";
   14.92 +        |> assert(session);
   14.93 +        choose {
   14.94 +            when "$partner"
   14.95 +            ||
   14.96 +                assert(partner);
   14.97 +                if (!(session && partner))
   14.98 +                    return PEP_ILLEGAL_VALUE;
   14.99 +            ||
  14.100 +            otherwise
  14.101 +            ||
  14.102 +                assert(!partner);
  14.103 +                if (!(session && !partner))
  14.104 +                    return PEP_ILLEGAL_VALUE;
  14.105 +            ||
  14.106 +        }
  14.107 +    }
  14.108 +
  14.109 +    function "other_action" {
  14.110 +        param "action";
  14.111 +        param "fsm";
  14.112 +        param "filename", "'###'";
  14.113 +
  14.114 +        ||
  14.115 +
  14.116 +        // «$action/@name»() - 
  14.117 +        //
  14.118 +        //  params:
  14.119 +        //      session (in)        session handle
  14.120 +        //      state (in)          state the state machine is in
  14.121 +        `` if "parm"        | //      partner (in)        partner to communicate with
  14.122 +        `` if "not(parm)"   | //      partner (in)        (must be NULL)
  14.123 +        //
  14.124 +        //  returns:
  14.125 +        //      PEP_STATUS_OK or any other value on error
  14.126 +
  14.127 +        PEP_STATUS «$action/@name»(
  14.128 +                PEP_SESSION session,
  14.129 +                «$fsm»_state state,
  14.130 +                Identity partner,
  14.131 +                void *extra
  14.132 +            )
  14.133 +        {
  14.134 +            PEP_STATUS status = PEP_STATUS_OK;
  14.135 +
  14.136 +            `` call "paramcheck" with "partner", "parm/partner";
  14.137 +
  14.138 +            // working code
  14.139 +
  14.140 +            // free extra
  14.141 +            return status;
  14.142 +
  14.143 +        enomem:
  14.144 +            status = PEP_OUT_OF_MEMORY;
  14.145 +        error:
  14.146 +            // free extra
  14.147 +            return status;
  14.148 +        }
  14.149 +
  14.150 +        ||
  14.151 +    }
  14.152 +
  14.153 +    function "send_action" {
  14.154 +        param "action";
  14.155 +        param "fsm";
  14.156 +        param "filename", "'###'";
  14.157 +        const "name", "substring($action/@name, 5, 255)";
  14.158 +        const "lname", "concat(yml:lcase(substring($name, 1, 1)), substring($name, 2))";
  14.159 +
  14.160 +        ||
  14.161 +
  14.162 +        // «$action/@name»() - send «$name» message
  14.163 +        //
  14.164 +        //  params:
  14.165 +        //      session (in)        session handle
  14.166 +        //      state (in)          state the state machine is in
  14.167 +        `` if "parm"        | //      partner (in)        partner to communicate with
  14.168 +        `` if "not(parm)"   | //      partner (in)        (must be NULL)
  14.169 +        //
  14.170 +        //  returns:
  14.171 +        //      PEP_STATUS_OK or any other value on error
  14.172 +
  14.173 +        PEP_STATUS «$action/@name»(
  14.174 +                PEP_SESSION session,
  14.175 +                «$fsm»_state state,
  14.176 +                Identity partner,
  14.177 +                void *extra
  14.178 +            )
  14.179 +        {
  14.180 +            assert(session && state);
  14.181 +            if (!(session && state))
  14.182 +                return PEP_ILLEGAL_VALUE;
  14.183 +
  14.184 +            PEP_STATUS status = PEP_STATUS_OK;
  14.185 +            `` if "$name='GroupKeys' or $name='GroupUpdate'" |> identity_list *kl = new_identity_list(NULL);
  14.186 +
  14.187 +            DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_«$lname»);
  14.188 +            if (!msg)
  14.189 +                goto enomem;
  14.190 +        ||
  14.191 +        choose {
  14.192 +            when "$name='GroupKeys' or $name='GroupUpdate'" {
  14.193 +                |
  14.194 +                |> status = _own_identities_retrieve(session, &kl, PEP_idf_not_for_sync);
  14.195 +                |> if (status != PEP_STATUS_OK)
  14.196 +                |>> goto error;
  14.197 +                |> if (IdentityList_from_identity_list(kl, &msg->payload.choice.«$lname».ownIdentities) == NULL)
  14.198 +                |>> goto enomem;
  14.199 +            }
  14.200 +        }
  14.201 +        choose {
  14.202 +            when "$name='GroupKeys' or $name='HandshakeRequest'" {
  14.203 +                |
  14.204 +                |> msg->payload.choice.«$lname».partner_id = 
  14.205 +                |>     OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
  14.206 +                |>                              partner->user_id, -1);
  14.207 +                |> if (partner->user_id && !msg->payload.choice.«$lname».partner_id)
  14.208 +                |>    goto enomem;
  14.209 +                |
  14.210 +                |> char *devgrp = NULL;
  14.211 +                |> status = get_device_group(session, &devgrp);
  14.212 +                |> if (status == PEP_STATUS_OK && devgrp && devgrp[0])
  14.213 +                |> msg->payload.choice.«$lname».group_id = 
  14.214 +                |>     OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
  14.215 +                |>                              devgrp, -1);
  14.216 +                |> free(devgrp);
  14.217 +                |> if (devgrp && !msg->payload.choice.«$lname».partner_id)
  14.218 +                |>    goto enomem;
  14.219 +            }
  14.220 +        }
  14.221 +        ||
  14.222 +
  14.223 +        ||
  14.224 +        choose {
  14.225 +            when "count(/protocol/unencrypted/*[name()=$action/@name]) = 0"
  14.226 +                |> bool encrypted = true;
  14.227 +            otherwise
  14.228 +                |> bool encrypted = false;
  14.229 +        }
  14.230 +        choose {
  14.231 +            when "count(/protocol/broadcast/*[name()=$action/@name]) = 0"
  14.232 +                |> status = unicast_msg(session, partner, state, msg, encrypted);
  14.233 +            otherwise
  14.234 +                |> status = multicast_self_msg(session, state, msg, encrypted);
  14.235 +        }
  14.236 +        ||
  14.237 +            if (status != PEP_STATUS_OK)
  14.238 +                goto error;
  14.239 +
  14.240 +            `` if "$name='GroupKeys' or $name='GroupUpdate'" |> free_identity_list(kl);
  14.241 +            free_DeviceGroup_Protocol_msg(msg);
  14.242 +            return PEP_STATUS_OK;
  14.243 +
  14.244 +        enomem:
  14.245 +            status = PEP_OUT_OF_MEMORY;
  14.246 +        error:
  14.247 +            free_DeviceGroup_Protocol_msg(msg);
  14.248 +            `` if "$name='GroupKeys'" |> free_identity_list(kl);
  14.249 +            return status;
  14.250 +        }
  14.251 +
  14.252 +        ||
  14.253 +    }
  14.254 +
  14.255 +    function "UnCamelUp" {
  14.256 +        param "text";
  14.257 +        const "tokens", "str:tokenize($text, '')";
  14.258 +
  14.259 +        for "$tokens" {
  14.260 +            choose {
  14.261 +                when "contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ',.)" > _«.»
  14.262 +                otherwise value "yml:ucase(.)";
  14.263 +            }
  14.264 +        }
  14.265 +    }
  14.266 +
  14.267 +    function "notify_action" {
  14.268 +        param "action";
  14.269 +        param "fsm";
  14.270 +        param "filename", "'###'";
  14.271 +        const "name", "substring($action/@name, 7, 255)";
  14.272 +        const "uname" call "UnCamelUp" with "text", "$name";
  14.273 +        ||
  14.274 +
  14.275 +        // «$action/@name»() - notify «$name» to app
  14.276 +        //
  14.277 +        //  params:
  14.278 +        //      session (in)        session handle
  14.279 +        //      state (in)          state the state machine is in
  14.280 +        //      partner (in)        partner to communicate with
  14.281 +        //
  14.282 +        //  returns:
  14.283 +        //      PEP_STATUS_OK or any other value on error
  14.284 +
  14.285 +        PEP_STATUS «$action/@name»(
  14.286 +                PEP_SESSION session,
  14.287 +                «$fsm»_state state,
  14.288 +                Identity partner,
  14.289 +                void *extra
  14.290 +            )
  14.291 +        {
  14.292 +            assert(session && state);
  14.293 +            assert(extra == NULL);
  14.294 +            if (!(session && state && extra == NULL))
  14.295 +                return PEP_ILLEGAL_VALUE;
  14.296 +
  14.297 +            return _notifyHandshake(session, partner, SYNC_NOTIFY«$uname»);
  14.298 +        }
  14.299 +
  14.300 +        ||
  14.301 +    }
  14.302 +}
  14.303 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/sync/gen_dot.ysl2	Fri Nov 03 13:32:38 2017 +0100
    15.3 @@ -0,0 +1,42 @@
    15.4 +// This file is under GNU General Public License 3.0
    15.5 +// see LICENSE.txt
    15.6 +
    15.7 +include yslt.yml2
    15.8 +
    15.9 +tstylesheet {
   15.10 +    template "protocol/fsm" document "{@filename}.dot", "text"
   15.11 +    ||
   15.12 +    digraph finite_state_machine {
   15.13 +        rankdir=LR;
   15.14 +        node [shape = doublecircle];
   15.15 +        `apply "state[@end='1']" mode=end`;
   15.16 +        node [shape = circle];
   15.17 +
   15.18 +        `` apply "state" mode=do
   15.19 +    }
   15.20 +    ||
   15.21 +
   15.22 +    template "state", mode=end > «@name» 
   15.23 +    template "state", mode=do apply "event", 0 with "state", "@name";
   15.24 +
   15.25 +    template "event" {
   15.26 +        param "state";
   15.27 +        const "transitions", "transition|descendant::condition/transition|descendant::alternative/transition";
   15.28 +        choose {
   15.29 +            when "count($transitions) > 0"
   15.30 +                apply "$transitions", 0
   15.31 +                    with "state", "$state", with "event", "@name";
   15.32 +            otherwise
   15.33 +                if "@name != 'Init'"
   15.34 +                    | «$state» -> «$state» [ label="«@name»" ];
   15.35 +        }
   15.36 +    }
   15.37 +
   15.38 +    template "transition" {
   15.39 +        param "state";
   15.40 +        param "event";
   15.41 +
   15.42 +        | «$state» -> «@target» [ label ="«$event»" ];
   15.43 +    }
   15.44 +}
   15.45 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/sync/gen_statemachine.ysl2	Fri Nov 03 13:32:38 2017 +0100
    16.3 @@ -0,0 +1,415 @@
    16.4 +// This file is under GNU General Public License 3.0
    16.5 +// see LICENSE.txt
    16.6 +
    16.7 +// generate state machine code
    16.8 +
    16.9 +// Copyleft (c) 2016, p≡p foundation
   16.10 +
   16.11 +// Written by Volker Birk
   16.12 +
   16.13 +include yslt.yml2
   16.14 +
   16.15 +tstylesheet {
   16.16 +    include standardlib.ysl2
   16.17 +    include ./functions.ysl2
   16.18 +
   16.19 +    template "/protocol" {
   16.20 +        document "generated/Makefile.protocols", "text"
   16.21 +            apply "fsm", 0, mode="make";
   16.22 +        apply "fsm", 0, mode=gen;
   16.23 +    }
   16.24 +
   16.25 +    template "fsm", mode=make
   16.26 +    ||
   16.27 +    «@filename»_fsm.c: ../sync/devicegroup.fsm
   16.28 +    \tmake -C ../«@filename»
   16.29 +    ||
   16.30 +
   16.31 +    template "fsm", mode=gen {
   16.32 +        document "generated/{@filename}_fsm.h", "text" {
   16.33 +        ||
   16.34 +        #pragma once
   16.35 +
   16.36 +        // state machine for «@name»
   16.37 +
   16.38 +        #include "message_api.h"
   16.39 +        
   16.40 +        #ifdef __cplusplus
   16.41 +        extern "C" {
   16.42 +        #endif
   16.43 +
   16.44 +        // types
   16.45 +
   16.46 +        typedef pEp_identity * Identity;
   16.47 +        typedef stringlist_t * Stringlist;
   16.48 +
   16.49 +        // error values
   16.50 +
   16.51 +        typedef enum _fsm_error {
   16.52 +            // these error values are corresponding to
   16.53 +            // PEP_SYNC_STATEMACHINE_ERROR - value
   16.54 +            invalid_state = -2,
   16.55 +            invalid_event = -3,
   16.56 +            invalid_condition = -4,
   16.57 +            invalid_action = -5,
   16.58 +
   16.59 +            // out of memory condition
   16.60 +            invalid_out_of_memory = -128
   16.61 +        } fsm_error;
   16.62 +
   16.63 +        // conditions
   16.64 +
   16.65 +        `` for "func:distinctName(condition)" | int «@name»(PEP_SESSION session`apply "parm", 0`);
   16.66 +
   16.67 +        // states
   16.68 +
   16.69 +        typedef enum _«@name»_state {
   16.70 +            // error values also in this namespace
   16.71 +            «@name»_state_invalid_state = (int) invalid_state,
   16.72 +            «@name»_state_invalid_event = (int) invalid_event,
   16.73 +            «@name»_state_invalid_condition = (int) invalid_condition,
   16.74 +            «@name»_state_invalid_action = (int) invalid_action,
   16.75 +            «@name»_state_invalid_out_of_memory = (int) invalid_out_of_memory,
   16.76 +
   16.77 +            «@name»_state_NONE = 0,
   16.78 +        `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
   16.79 +        } «@name»_state;
   16.80 +
   16.81 +        // events
   16.82 +
   16.83 +        typedef enum _«@name»_event {
   16.84 +            «@name»_event_NONE = 0,
   16.85 +        ||
   16.86 +        for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
   16.87 +            const "name", "@name";
   16.88 +            |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
   16.89 +        }
   16.90 +        for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
   16.91 +            |> «@name»`if "position()!=last()" > , `
   16.92 +        ||
   16.93 +        } «@name»_event;
   16.94 +
   16.95 +        // actions
   16.96 +
   16.97 +        `` const "name", "@name"
   16.98 +        `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
   16.99 +
  16.100 +        // event injector
  16.101 +
  16.102 +        PEP_STATUS inject_DeviceState_event(
  16.103 +            PEP_SESSION session, 
  16.104 +            DeviceState_event event,
  16.105 +            Identity partner,
  16.106 +            void *extra);
  16.107 +
  16.108 +        // message receiver
  16.109 +        
  16.110 +        PEP_STATUS receive_DeviceState_msg(
  16.111 +                PEP_SESSION session, 
  16.112 +                message *src, 
  16.113 +                PEP_rating rating, 
  16.114 +                stringlist_t *keylist
  16.115 +            );
  16.116 +
  16.117 +        // state machine
  16.118 +
  16.119 +        «@name»_state fsm_«@name»(
  16.120 +                PEP_SESSION session,
  16.121 +                «@name»_state state,
  16.122 +                «@name»_event event,
  16.123 +                Identity partner,
  16.124 +                void *extra,
  16.125 +                time_t *timeout
  16.126 +            );
  16.127 +
  16.128 +        // driver
  16.129 +
  16.130 +        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
  16.131 +                PEP_SESSION session,
  16.132 +                «@name»_event event,
  16.133 +                Identity partner,
  16.134 +                void *extra,
  16.135 +                time_t *timeout
  16.136 +            );
  16.137 +
  16.138 +        #ifdef __cplusplus
  16.139 +        }
  16.140 +        #endif
  16.141 +
  16.142 +        ||
  16.143 +        }
  16.144 +        document "generated/{@filename}_driver.c", "text"
  16.145 +        ||
  16.146 +        // Driver for «@name» state machine
  16.147 +
  16.148 +        #include <assert.h>
  16.149 +        #include "pEp_internal.h"
  16.150 +
  16.151 +
  16.152 +        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
  16.153 +                PEP_SESSION session,
  16.154 +                «@name»_event event,
  16.155 +                Identity partner,
  16.156 +                void *extra,
  16.157 +                time_t *timeout
  16.158 +            )
  16.159 +        {
  16.160 +            assert(session);
  16.161 +            if (!session)
  16.162 +                return PEP_ILLEGAL_VALUE;
  16.163 +
  16.164 +            while(true)
  16.165 +            {
  16.166 +                «@name»_state new_state = fsm_«@name»(session,
  16.167 +                    session->«@filename»_state, event, partner, extra, timeout);
  16.168 +
  16.169 +                if (new_state == «@name»_state_invalid_out_of_memory)
  16.170 +                    return PEP_OUT_OF_MEMORY;
  16.171 +
  16.172 +                if (new_state < 0)
  16.173 +                    return PEP_SYNC_STATEMACHINE_ERROR - new_state;
  16.174 +                
  16.175 +                if (new_state == session->«@filename»_state)
  16.176 +                    break;
  16.177 +
  16.178 +                event = Init;
  16.179 +                extra = NULL;
  16.180 +                session->«@filename»_state = new_state;
  16.181 +            } 
  16.182 +
  16.183 +            return PEP_STATUS_OK;
  16.184 +        }
  16.185 +
  16.186 +        ||
  16.187 +        document "generated/{@filename}_fsm.c", "text"
  16.188 +        ||
  16.189 +        #include "pEp_internal.h"
  16.190 +        #include "«@filename»_fsm.h"
  16.191 +        #include "«@filename»_impl.h"
  16.192 +
  16.193 +        // local definitions for «@name»'s state machine 
  16.194 +
  16.195 +        `` apply "state", 0 mode="declStatePayload"
  16.196 +
  16.197 +        // state machine for «@name»
  16.198 +
  16.199 +        «@name»_state fsm_«@name»(
  16.200 +                PEP_SESSION session,
  16.201 +                «@name»_state state,
  16.202 +                «@name»_event event,
  16.203 +                Identity partner,
  16.204 +                void *extra,
  16.205 +                time_t *timeout
  16.206 +            )
  16.207 +        {
  16.208 +            PEP_STATUS status = PEP_STATUS_OK;
  16.209 +
  16.210 +            switch (state) {
  16.211 +            `` apply "state", 2
  16.212 +                default:
  16.213 +                    return («@name»_state) invalid_state;
  16.214 +            }
  16.215 +
  16.216 +            return state;
  16.217 +        }
  16.218 +
  16.219 +        ||
  16.220 +    }
  16.221 +
  16.222 +    template "state" {
  16.223 +        ||
  16.224 +        case «@name»:
  16.225 +        {
  16.226 +            DEBUG_LOG("Entering FSM state", "«../@filename»_fsm.c", "state=«@name»")
  16.227 +        ||
  16.228 +
  16.229 +        if "count(parm) > 0" 
  16.230 +        || 
  16.231 +            assert(session->sync_state_payload);
  16.232 +            if(!session->sync_state_payload) return («../@name»_state) invalid_state;
  16.233 +            `` apply "parm", 1 mode="unpackStatePayloadParm" with "stateName", "@name"
  16.234 +        ||
  16.235 +
  16.236 +        ||
  16.237 +            switch (event) {
  16.238 +        ||
  16.239 +
  16.240 +        if "not(event[@name='Init'])" 
  16.241 +        ||
  16.242 +                case Init: 
  16.243 +                    DEBUG_LOG("FSM event", "«../@filename»_fsm.c, state=«@name»", "event=Init") 
  16.244 +                    *timeout = «@timeout»;
  16.245 +                    break;
  16.246 +        ||
  16.247 +
  16.248 +        apply "event", 2;
  16.249 +
  16.250 +        ||
  16.251 +                default:
  16.252 +                    return («../@name»_state) invalid_event;
  16.253 +            }
  16.254 +            break;
  16.255 +        }
  16.256 +        ||
  16.257 +    }
  16.258 +
  16.259 +    function "pEp_type" {
  16.260 +        param "type";
  16.261 +
  16.262 +        choose {
  16.263 +            when "$type = 'Identity'" > Identity
  16.264 +            when "$type = 'IdentityList'" > identity_list*
  16.265 +            when "$type = 'GroupKeys'" > group_keys_extra_t*
  16.266 +            otherwise value "$type";
  16.267 +        }
  16.268 +    }
  16.269 +
  16.270 +    function "pEp_type_op_radix" {
  16.271 +        param "type";
  16.272 +
  16.273 +        choose {
  16.274 +            when "$type = 'Identity'" > identity
  16.275 +            when "$type = 'IdentityList'" > identity_list
  16.276 +            when "$type = 'GroupKeys'" > group_keys_extra
  16.277 +            otherwise call "pEp_type" with "type", "$type";
  16.278 +        }
  16.279 +    }
  16.280 +
  16.281 +    template "parm" mode="unpackStatePayloadParm" 
  16.282 +    {
  16.283 +        param "stateName";
  16.284 +        const "pEpType" call "pEp_type" with "type","name(*[1])"; 
  16.285 +        | «$pEpType» «name(*[2])» = ((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])»;
  16.286 +    }
  16.287 +
  16.288 +    template "state" mode="declStatePayload" if "count(parm) > 0"
  16.289 +    ||
  16.290 +    typedef struct _«@name»_state_payload {
  16.291 +        `` apply "parm", 1 mode="declStatePayloadParm"
  16.292 +    } «@name»_state_payload_t;
  16.293 +
  16.294 +    ||
  16.295 +
  16.296 +    template "parm" mode="declStatePayloadParm" {
  16.297 +        const "pEpType" call "pEp_type" with "type","name(*[1])"; 
  16.298 +        | «$pEpType» «name(*[2])»;
  16.299 +    }
  16.300 +
  16.301 +    template "event" {
  16.302 +        ||
  16.303 +        case «@name»:
  16.304 +        {
  16.305 +            DEBUG_LOG("FSM event", "«../../@filename»_fsm.c, state=«../@name»", "event=«@name»")
  16.306 +        `` if "@name='Init'" |> *timeout = «../@timeout»;
  16.307 +        ||
  16.308 +
  16.309 +        if "count(parm) > 1" {
  16.310 +            // TODO get ride of void *extra, pass per-event struct incl all params.
  16.311 +            const "extrapEpType" call "pEp_type" with "type","name(parm[2]/*[1])"; 
  16.312 +            const "extraArgName","name(parm[2]/*[2])"; 
  16.313 +            |> «$extrapEpType» «$extraArgName» = («$extrapEpType»)extra;
  16.314 +        }
  16.315 +
  16.316 +        ||
  16.317 +        `` apply "action|transition|condition";
  16.318 +        `` if "name(*[position()=last()]) != 'transition'" |> break;
  16.319 +        }
  16.320 +        ||
  16.321 +    }
  16.322 +
  16.323 +    template "action" {
  16.324 +        | DEBUG_LOG("FSM action", "«ancestor::fsm/@filename»_fsm.c, state=«ancestor::state/@name», event=«ancestor::event/@name»", "action=«@name»")
  16.325 +        indent(0);
  16.326 +        > status = «@name»(session, state, 
  16.327 +        choose {
  16.328 +            when "parm" > «name(parm/*)»
  16.329 +            otherwise > NULL
  16.330 +        }
  16.331 +        choose {
  16.332 +            when "count(parm) > 1" > , «name(parm[2]/*)»
  16.333 +            otherwise > , NULL
  16.334 +        }
  16.335 +        > );\n
  16.336 +        | if (status == PEP_OUT_OF_MEMORY)
  16.337 +        |> return (int) invalid_out_of_memory;
  16.338 +        | if (status != PEP_STATUS_OK)
  16.339 +        |> return (int) invalid_action;
  16.340 +    }
  16.341 +
  16.342 +    template "condition" {
  16.343 +        | {
  16.344 +        |> int cond_result = «@name»(session`apply "parm", 0`);
  16.345 +        |> #ifndef NDEBUG
  16.346 +        |> char resstr[11] = {0,};
  16.347 +        |> snprintf(resstr,10,"result=%d",cond_result);
  16.348 +        |> #endif
  16.349 +        |> DEBUG_LOG("FSM condition", "«ancestor::fsm/@filename»_fsm.c, state=«ancestor::state/@name», event=«ancestor::event/@name», condition=«@name»", resstr)
  16.350 +        |> if (cond_result < 0)
  16.351 +        |>> return cond_result;
  16.352 +        |> if (cond_result) {
  16.353 +        apply "action|transition|condition";
  16.354 +        |> }
  16.355 +        const "alternative", "./following-sibling::*[position()=1][name(.)='alternative']";
  16.356 +        if "$alternative" {
  16.357 +        |> else {
  16.358 +        apply "$alternative/action|$alternative/transition|$alternative/condition";
  16.359 +        |> }
  16.360 +        }
  16.361 +        | }
  16.362 +    }
  16.363 +
  16.364 +    template "parm" choose {
  16.365 +        when "count(*) = 1"
  16.366 +            > , «name(*)»
  16.367 +        otherwise
  16.368 +            > , «name(*[1])» «name(*[2])»
  16.369 +    }
  16.370 +
  16.371 +    template "transition"{
  16.372 +        const "stateparm", "ancestor::state/child::parm";
  16.373 +        if "count($stateparm) > 0" {
  16.374 +            ||
  16.375 +            assert(session->sync_state_payload);
  16.376 +            if(!session->sync_state_payload) return («ancestor::fsm/@name»_state) invalid_state;
  16.377 +            `` apply "$stateparm", 0 mode="freeStatePayloadParm" with "stateName", "ancestor::state/@name"
  16.378 +            free(session->sync_state_payload);
  16.379 +            session->sync_state_payload = NULL;
  16.380 +            ||
  16.381 +        }
  16.382 +        if "count(parm) > 0" {
  16.383 +            const "nextstatename", "@target";
  16.384 +            const "nextstateparm", "ancestor::fsm/child::state[@name = $nextstatename]/child::parm";
  16.385 +            if "count(parm) != count($nextstateparm)" 
  16.386 +                error > different state parameters and transition parameters count state=«ancestor::state/@name», event=«ancestor::event/@name» target=«@target»
  16.387 +            ||
  16.388 +            session->sync_state_payload = malloc(sizeof(«$nextstatename»_state_payload_t));
  16.389 +            assert(session->sync_state_payload);
  16.390 +            if(!session->sync_state_payload) return («ancestor::fsm/@name»_state) invalid_out_of_memory;
  16.391 +            ||
  16.392 +            apply "$nextstateparm", 0 mode="dupStatePayloadParm" {
  16.393 +                with "stateName", "$nextstatename";
  16.394 +                with "transitionParms", "parm";
  16.395 +            }
  16.396 +        }
  16.397 +        | DEBUG_LOG("FSM transition", "«ancestor::fsm/@filename»_fsm.c, state=«ancestor::state/@name», event=«ancestor::event/@name»", "target=«@target»")
  16.398 +        | return «@target»;
  16.399 +    }
  16.400 +
  16.401 +    template "parm" mode="freeStatePayloadParm" 
  16.402 +    {
  16.403 +        param "stateName";
  16.404 +        const "pEpTypeOpRadix" call "pEp_type_op_radix" with "type","name(*[1])"; 
  16.405 +        | free_«$pEpTypeOpRadix»(((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])»);
  16.406 +    }
  16.407 +
  16.408 +    template "parm" mode="dupStatePayloadParm" 
  16.409 +    {
  16.410 +        param "stateName";
  16.411 +        param "transitionParms";
  16.412 +        const "pEpTypeOpRadix" call "pEp_type_op_radix" with "type","name(*[1])"; 
  16.413 +        const "pos", "position()";
  16.414 +        | ((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])» =
  16.415 +        |     «$pEpTypeOpRadix»_dup(«name($transitionParms[$pos]/*)»);
  16.416 +    }
  16.417 +}
  16.418 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/sync/generated/README	Fri Nov 03 13:32:38 2017 +0100
    17.3 @@ -0,0 +1,11 @@
    17.4 +Code is generated here before beeing copied to /src during build process.
    17.5 +
    17.6 +This code is intended to be commited and reviewed, while the original files 
    17.7 +in src/ aren't tracked in mercurial (.hgignore). 
    17.8 +
    17.9 +Generated code must be generated out of source code systematically at build,
   17.10 +since generation could be influenced by build environment and parameters.
   17.11 +
   17.12 +Depending on build host, version control tool or unharchiving tool, generated
   17.13 +files timestamp may prevent re-generation. They must then be excluded from repo.
   17.14 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/sync/generated/sync_driver.c	Fri Nov 03 13:32:38 2017 +0100
    18.3 @@ -0,0 +1,40 @@
    18.4 +// Driver for DeviceState state machine
    18.5 +
    18.6 +#include <assert.h>
    18.7 +#include "pEp_internal.h"
    18.8 +
    18.9 +
   18.10 +DYNAMIC_API PEP_STATUS fsm_DeviceState_inject(
   18.11 +        PEP_SESSION session,
   18.12 +        DeviceState_event event,
   18.13 +        Identity partner,
   18.14 +        void *extra,
   18.15 +        time_t *timeout
   18.16 +    )
   18.17 +{
   18.18 +    assert(session);
   18.19 +    if (!session)
   18.20 +        return PEP_ILLEGAL_VALUE;
   18.21 +
   18.22 +    while(true)
   18.23 +    {
   18.24 +        DeviceState_state new_state = fsm_DeviceState(session,
   18.25 +            session->sync_state, event, partner, extra, timeout);
   18.26 +
   18.27 +        if (new_state == DeviceState_state_invalid_out_of_memory)
   18.28 +            return PEP_OUT_OF_MEMORY;
   18.29 +
   18.30 +        if (new_state < 0)
   18.31 +            return PEP_SYNC_STATEMACHINE_ERROR - new_state;
   18.32 +        
   18.33 +        if (new_state == session->sync_state)
   18.34 +            break;
   18.35 +
   18.36 +        event = Init;
   18.37 +        extra = NULL;
   18.38 +        session->sync_state = new_state;
   18.39 +    } 
   18.40 +
   18.41 +    return PEP_STATUS_OK;
   18.42 +}
   18.43 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/sync/generated/sync_fsm.c	Fri Nov 03 13:32:38 2017 +0100
    19.3 @@ -0,0 +1,1610 @@
    19.4 +#include "pEp_internal.h"
    19.5 +#include "sync_fsm.h"
    19.6 +#include "sync_impl.h"
    19.7 +
    19.8 +// local definitions for DeviceState's state machine 
    19.9 +
   19.10 +typedef struct _SoleBeaconed_state_payload {
   19.11 +    Identity expected;
   19.12 +} SoleBeaconed_state_payload_t;
   19.13 +
   19.14 +typedef struct _HandshakingSole_state_payload {
   19.15 +    Identity expected;
   19.16 +} HandshakingSole_state_payload_t;
   19.17 +
   19.18 +typedef struct _WaitForGroupKeysSole_state_payload {
   19.19 +    Identity expected;
   19.20 +} WaitForGroupKeysSole_state_payload_t;
   19.21 +
   19.22 +typedef struct _WaitForAcceptSole_state_payload {
   19.23 +    Identity expected;
   19.24 +    group_keys_extra_t* groupkeys;
   19.25 +} WaitForAcceptSole_state_payload_t;
   19.26 +
   19.27 +typedef struct _GroupedBeaconed_state_payload {
   19.28 +    Identity expected;
   19.29 +} GroupedBeaconed_state_payload_t;
   19.30 +
   19.31 +typedef struct _HandshakingGrouped_state_payload {
   19.32 +    Identity expected;
   19.33 +} HandshakingGrouped_state_payload_t;
   19.34 +
   19.35 +typedef struct _WaitForGroupKeysGrouped_state_payload {
   19.36 +    Identity expected;
   19.37 +} WaitForGroupKeysGrouped_state_payload_t;
   19.38 +
   19.39 +typedef struct _WaitForAcceptGrouped_state_payload {
   19.40 +    Identity expected;
   19.41 +    group_keys_extra_t* groupkeys;
   19.42 +} WaitForAcceptGrouped_state_payload_t;
   19.43 +
   19.44 +
   19.45 +// state machine for DeviceState
   19.46 +
   19.47 +DeviceState_state fsm_DeviceState(
   19.48 +        PEP_SESSION session,
   19.49 +        DeviceState_state state,
   19.50 +        DeviceState_event event,
   19.51 +        Identity partner,
   19.52 +        void *extra,
   19.53 +        time_t *timeout
   19.54 +    )
   19.55 +{
   19.56 +    PEP_STATUS status = PEP_STATUS_OK;
   19.57 +
   19.58 +    switch (state) {
   19.59 +        case InitState:
   19.60 +        {
   19.61 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=InitState")
   19.62 +            switch (event) {
   19.63 +                case Init:
   19.64 +                {
   19.65 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=InitState", "event=Init")
   19.66 +                    *timeout = 0;
   19.67 +                    {
   19.68 +                        int cond_result = deviceGrouped(session);
   19.69 +                        #ifndef NDEBUG
   19.70 +                        char resstr[11] = {0,};
   19.71 +                        snprintf(resstr,10,"result=%d",cond_result);
   19.72 +                        #endif
   19.73 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=InitState, event=Init, condition=deviceGrouped", resstr)
   19.74 +                        if (cond_result < 0)
   19.75 +                            return cond_result;
   19.76 +                        if (cond_result) {
   19.77 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=InitState, event=Init", "target=Grouped")
   19.78 +                        return Grouped;
   19.79 +                        }
   19.80 +                    }
   19.81 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=InitState, event=Init", "target=Sole")
   19.82 +                    return Sole;
   19.83 +                }
   19.84 +                default:
   19.85 +                    return (DeviceState_state) invalid_event;
   19.86 +            }
   19.87 +            break;
   19.88 +        }
   19.89 +        case Sole:
   19.90 +        {
   19.91 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=Sole")
   19.92 +            switch (event) {
   19.93 +                case Init: 
   19.94 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=Init") 
   19.95 +                    *timeout = 0;
   19.96 +                    break;
   19.97 +                case KeyGen:
   19.98 +                {
   19.99 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=KeyGen")
  19.100 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Sole, event=KeyGen", "action=sendBeacon")
  19.101 +                    status = sendBeacon(session, state, NULL, NULL);
  19.102 +                    if (status == PEP_OUT_OF_MEMORY)
  19.103 +                        return (int) invalid_out_of_memory;
  19.104 +                    if (status != PEP_STATUS_OK)
  19.105 +                        return (int) invalid_action;
  19.106 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=KeyGen", "target=SoleWaiting")
  19.107 +                    return SoleWaiting;
  19.108 +                }
  19.109 +                case CannotDecrypt:
  19.110 +                {
  19.111 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=CannotDecrypt")
  19.112 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Sole, event=CannotDecrypt", "action=sendBeacon")
  19.113 +                    status = sendBeacon(session, state, NULL, NULL);
  19.114 +                    if (status == PEP_OUT_OF_MEMORY)
  19.115 +                        return (int) invalid_out_of_memory;
  19.116 +                    if (status != PEP_STATUS_OK)
  19.117 +                        return (int) invalid_action;
  19.118 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=CannotDecrypt", "target=SoleWaiting")
  19.119 +                    return SoleWaiting;
  19.120 +                }
  19.121 +                case Beacon:
  19.122 +                {
  19.123 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=Beacon")
  19.124 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Sole, event=Beacon", "action=sendHandshakeRequest")
  19.125 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.126 +                    if (status == PEP_OUT_OF_MEMORY)
  19.127 +                        return (int) invalid_out_of_memory;
  19.128 +                    if (status != PEP_STATUS_OK)
  19.129 +                        return (int) invalid_action;
  19.130 +                    session->sync_state_payload = malloc(sizeof(SoleBeaconed_state_payload_t));
  19.131 +                    assert(session->sync_state_payload);
  19.132 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.133 +                    ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  19.134 +                        identity_dup(partner);
  19.135 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=Beacon", "target=SoleBeaconed")
  19.136 +                    return SoleBeaconed;
  19.137 +                }
  19.138 +                case HandshakeRequest:
  19.139 +                {
  19.140 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=HandshakeRequest")
  19.141 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Sole, event=HandshakeRequest", "action=sendHandshakeRequest")
  19.142 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.143 +                    if (status == PEP_OUT_OF_MEMORY)
  19.144 +                        return (int) invalid_out_of_memory;
  19.145 +                    if (status != PEP_STATUS_OK)
  19.146 +                        return (int) invalid_action;
  19.147 +                    session->sync_state_payload = malloc(sizeof(HandshakingSole_state_payload_t));
  19.148 +                    assert(session->sync_state_payload);
  19.149 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.150 +                    ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected =
  19.151 +                        identity_dup(partner);
  19.152 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=HandshakeRequest", "target=HandshakingSole")
  19.153 +                    return HandshakingSole;
  19.154 +                }
  19.155 +                default:
  19.156 +                    return (DeviceState_state) invalid_event;
  19.157 +            }
  19.158 +            break;
  19.159 +        }
  19.160 +        case SoleWaiting:
  19.161 +        {
  19.162 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleWaiting")
  19.163 +            switch (event) {
  19.164 +                case Init: 
  19.165 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Init") 
  19.166 +                    *timeout = 60;
  19.167 +                    break;
  19.168 +                case KeyGen:
  19.169 +                {
  19.170 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=KeyGen")
  19.171 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=KeyGen", "action=sendBeacon")
  19.172 +                    status = sendBeacon(session, state, NULL, NULL);
  19.173 +                    if (status == PEP_OUT_OF_MEMORY)
  19.174 +                        return (int) invalid_out_of_memory;
  19.175 +                    if (status != PEP_STATUS_OK)
  19.176 +                        return (int) invalid_action;
  19.177 +                    break;
  19.178 +                }
  19.179 +                case CannotDecrypt:
  19.180 +                {
  19.181 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=CannotDecrypt")
  19.182 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=CannotDecrypt", "action=sendBeacon")
  19.183 +                    status = sendBeacon(session, state, NULL, NULL);
  19.184 +                    if (status == PEP_OUT_OF_MEMORY)
  19.185 +                        return (int) invalid_out_of_memory;
  19.186 +                    if (status != PEP_STATUS_OK)
  19.187 +                        return (int) invalid_action;
  19.188 +                    break;
  19.189 +                }
  19.190 +                case Beacon:
  19.191 +                {
  19.192 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Beacon")
  19.193 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=Beacon", "action=sendHandshakeRequest")
  19.194 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.195 +                    if (status == PEP_OUT_OF_MEMORY)
  19.196 +                        return (int) invalid_out_of_memory;
  19.197 +                    if (status != PEP_STATUS_OK)
  19.198 +                        return (int) invalid_action;
  19.199 +                    session->sync_state_payload = malloc(sizeof(SoleBeaconed_state_payload_t));
  19.200 +                    assert(session->sync_state_payload);
  19.201 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.202 +                    ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  19.203 +                        identity_dup(partner);
  19.204 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Beacon", "target=SoleBeaconed")
  19.205 +                    return SoleBeaconed;
  19.206 +                }
  19.207 +                case HandshakeRequest:
  19.208 +                {
  19.209 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=HandshakeRequest")
  19.210 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
  19.211 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.212 +                    if (status == PEP_OUT_OF_MEMORY)
  19.213 +                        return (int) invalid_out_of_memory;
  19.214 +                    if (status != PEP_STATUS_OK)
  19.215 +                        return (int) invalid_action;
  19.216 +                    session->sync_state_payload = malloc(sizeof(HandshakingSole_state_payload_t));
  19.217 +                    assert(session->sync_state_payload);
  19.218 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.219 +                    ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected =
  19.220 +                        identity_dup(partner);
  19.221 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "target=HandshakingSole")
  19.222 +                    return HandshakingSole;
  19.223 +                }
  19.224 +                case Timeout:
  19.225 +                {
  19.226 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Timeout")
  19.227 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Timeout", "target=Sole")
  19.228 +                    return Sole;
  19.229 +                }
  19.230 +                default:
  19.231 +                    return (DeviceState_state) invalid_event;
  19.232 +            }
  19.233 +            break;
  19.234 +        }
  19.235 +        case SoleBeaconed:
  19.236 +        {
  19.237 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleBeaconed")
  19.238 +            assert(session->sync_state_payload);
  19.239 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.240 +            Identity expected = ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected;
  19.241 +            switch (event) {
  19.242 +                case Init: 
  19.243 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Init") 
  19.244 +                    *timeout = 600;
  19.245 +                    break;
  19.246 +                case KeyGen:
  19.247 +                {
  19.248 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=KeyGen")
  19.249 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=KeyGen", "action=sendBeacon")
  19.250 +                    status = sendBeacon(session, state, NULL, NULL);
  19.251 +                    if (status == PEP_OUT_OF_MEMORY)
  19.252 +                        return (int) invalid_out_of_memory;
  19.253 +                    if (status != PEP_STATUS_OK)
  19.254 +                        return (int) invalid_action;
  19.255 +                    assert(session->sync_state_payload);
  19.256 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.257 +                    free_identity(((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected);
  19.258 +                    free(session->sync_state_payload);
  19.259 +                    session->sync_state_payload = NULL;
  19.260 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=KeyGen", "target=Sole")
  19.261 +                    return Sole;
  19.262 +                }
  19.263 +                case CannotDecrypt:
  19.264 +                {
  19.265 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=CannotDecrypt")
  19.266 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=CannotDecrypt", "action=sendBeacon")
  19.267 +                    status = sendBeacon(session, state, NULL, NULL);
  19.268 +                    if (status == PEP_OUT_OF_MEMORY)
  19.269 +                        return (int) invalid_out_of_memory;
  19.270 +                    if (status != PEP_STATUS_OK)
  19.271 +                        return (int) invalid_action;
  19.272 +                    assert(session->sync_state_payload);
  19.273 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.274 +                    free_identity(((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected);
  19.275 +                    free(session->sync_state_payload);
  19.276 +                    session->sync_state_payload = NULL;
  19.277 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=CannotDecrypt", "target=Sole")
  19.278 +                    return Sole;
  19.279 +                }
  19.280 +                case Beacon:
  19.281 +                {
  19.282 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Beacon")
  19.283 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=Beacon", "action=sendHandshakeRequest")
  19.284 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.285 +                    if (status == PEP_OUT_OF_MEMORY)
  19.286 +                        return (int) invalid_out_of_memory;
  19.287 +                    if (status != PEP_STATUS_OK)
  19.288 +                        return (int) invalid_action;
  19.289 +                    assert(session->sync_state_payload);
  19.290 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.291 +                    free_identity(((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected);
  19.292 +                    free(session->sync_state_payload);
  19.293 +                    session->sync_state_payload = NULL;
  19.294 +                    session->sync_state_payload = malloc(sizeof(SoleBeaconed_state_payload_t));
  19.295 +                    assert(session->sync_state_payload);
  19.296 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.297 +                    ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  19.298 +                        identity_dup(partner);
  19.299 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=Beacon", "target=SoleBeaconed")
  19.300 +                    return SoleBeaconed;
  19.301 +                }
  19.302 +                case HandshakeRequest:
  19.303 +                {
  19.304 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=HandshakeRequest")
  19.305 +                    {
  19.306 +                        int cond_result = sameIdentities(session, partner, expected);
  19.307 +                        #ifndef NDEBUG
  19.308 +                        char resstr[11] = {0,};
  19.309 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.310 +                        #endif
  19.311 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest, condition=sameIdentities", resstr)
  19.312 +                        if (cond_result < 0)
  19.313 +                            return cond_result;
  19.314 +                        if (cond_result) {
  19.315 +                        }
  19.316 +                        else {
  19.317 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest", "action=sendHandshakeRequest")
  19.318 +                        status = sendHandshakeRequest(session, state, partner, NULL);
  19.319 +                        if (status == PEP_OUT_OF_MEMORY)
  19.320 +                            return (int) invalid_out_of_memory;
  19.321 +                        if (status != PEP_STATUS_OK)
  19.322 +                            return (int) invalid_action;
  19.323 +                        }
  19.324 +                    }
  19.325 +                    assert(session->sync_state_payload);
  19.326 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.327 +                    free_identity(((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected);
  19.328 +                    free(session->sync_state_payload);
  19.329 +                    session->sync_state_payload = NULL;
  19.330 +                    session->sync_state_payload = malloc(sizeof(HandshakingSole_state_payload_t));
  19.331 +                    assert(session->sync_state_payload);
  19.332 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.333 +                    ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected =
  19.334 +                        identity_dup(partner);
  19.335 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest", "target=HandshakingSole")
  19.336 +                    return HandshakingSole;
  19.337 +                }
  19.338 +                case Timeout:
  19.339 +                {
  19.340 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Timeout")
  19.341 +                    assert(session->sync_state_payload);
  19.342 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.343 +                    free_identity(((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected);
  19.344 +                    free(session->sync_state_payload);
  19.345 +                    session->sync_state_payload = NULL;
  19.346 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=Timeout", "target=Sole")
  19.347 +                    return Sole;
  19.348 +                }
  19.349 +                default:
  19.350 +                    return (DeviceState_state) invalid_event;
  19.351 +            }
  19.352 +            break;
  19.353 +        }
  19.354 +        case HandshakingSole:
  19.355 +        {
  19.356 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=HandshakingSole")
  19.357 +            assert(session->sync_state_payload);
  19.358 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.359 +            Identity expected = ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected;
  19.360 +            switch (event) {
  19.361 +                case Init:
  19.362 +                {
  19.363 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=Init")
  19.364 +                    *timeout = 600;
  19.365 +                    {
  19.366 +                        int cond_result = keyElectionWon(session, expected);
  19.367 +                        #ifndef NDEBUG
  19.368 +                        char resstr[11] = {0,};
  19.369 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.370 +                        #endif
  19.371 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=Init, condition=keyElectionWon", resstr)
  19.372 +                        if (cond_result < 0)
  19.373 +                            return cond_result;
  19.374 +                        if (cond_result) {
  19.375 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Init", "action=notifyInitFormGroup")
  19.376 +                        status = notifyInitFormGroup(session, state, expected, NULL);
  19.377 +                        if (status == PEP_OUT_OF_MEMORY)
  19.378 +                            return (int) invalid_out_of_memory;
  19.379 +                        if (status != PEP_STATUS_OK)
  19.380 +                            return (int) invalid_action;
  19.381 +                        }
  19.382 +                        else {
  19.383 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Init", "action=notifyInitAddOurDevice")
  19.384 +                        status = notifyInitAddOurDevice(session, state, expected, NULL);
  19.385 +                        if (status == PEP_OUT_OF_MEMORY)
  19.386 +                            return (int) invalid_out_of_memory;
  19.387 +                        if (status != PEP_STATUS_OK)
  19.388 +                            return (int) invalid_action;
  19.389 +                        }
  19.390 +                    }
  19.391 +                    break;
  19.392 +                }
  19.393 +                case HandshakeRejected:
  19.394 +                {
  19.395 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=HandshakeRejected")
  19.396 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeRejected", "action=rejectHandshake")
  19.397 +                    status = rejectHandshake(session, state, partner, NULL);
  19.398 +                    if (status == PEP_OUT_OF_MEMORY)
  19.399 +                        return (int) invalid_out_of_memory;
  19.400 +                    if (status != PEP_STATUS_OK)
  19.401 +                        return (int) invalid_action;
  19.402 +                    assert(session->sync_state_payload);
  19.403 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.404 +                    free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.405 +                    free(session->sync_state_payload);
  19.406 +                    session->sync_state_payload = NULL;
  19.407 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeRejected", "target=Sole")
  19.408 +                    return Sole;
  19.409 +                }
  19.410 +                case HandshakeAccepted:
  19.411 +                {
  19.412 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=HandshakeAccepted")
  19.413 +                    {
  19.414 +                        int cond_result = sameIdentities(session, partner, expected);
  19.415 +                        #ifndef NDEBUG
  19.416 +                        char resstr[11] = {0,};
  19.417 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.418 +                        #endif
  19.419 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted, condition=sameIdentities", resstr)
  19.420 +                        if (cond_result < 0)
  19.421 +                            return cond_result;
  19.422 +                        if (cond_result) {
  19.423 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=acceptHandshake")
  19.424 +                        status = acceptHandshake(session, state, partner, NULL);
  19.425 +                        if (status == PEP_OUT_OF_MEMORY)
  19.426 +                            return (int) invalid_out_of_memory;
  19.427 +                        if (status != PEP_STATUS_OK)
  19.428 +                            return (int) invalid_action;
  19.429 +                        {
  19.430 +                            int cond_result = keyElectionWon(session, partner);
  19.431 +                            #ifndef NDEBUG
  19.432 +                            char resstr[11] = {0,};
  19.433 +                            snprintf(resstr,10,"result=%d",cond_result);
  19.434 +                            #endif
  19.435 +                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted, condition=keyElectionWon", resstr)
  19.436 +                            if (cond_result < 0)
  19.437 +                                return cond_result;
  19.438 +                            if (cond_result) {
  19.439 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=makeGroup")
  19.440 +                            status = makeGroup(session, state, NULL, NULL);
  19.441 +                            if (status == PEP_OUT_OF_MEMORY)
  19.442 +                                return (int) invalid_out_of_memory;
  19.443 +                            if (status != PEP_STATUS_OK)
  19.444 +                                return (int) invalid_action;
  19.445 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=sendGroupKeys")
  19.446 +                            status = sendGroupKeys(session, state, partner, NULL);
  19.447 +                            if (status == PEP_OUT_OF_MEMORY)
  19.448 +                                return (int) invalid_out_of_memory;
  19.449 +                            if (status != PEP_STATUS_OK)
  19.450 +                                return (int) invalid_action;
  19.451 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=renewUUID")
  19.452 +                            status = renewUUID(session, state, NULL, NULL);
  19.453 +                            if (status == PEP_OUT_OF_MEMORY)
  19.454 +                                return (int) invalid_out_of_memory;
  19.455 +                            if (status != PEP_STATUS_OK)
  19.456 +                                return (int) invalid_action;
  19.457 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=notifyAcceptedGroupCreated")
  19.458 +                            status = notifyAcceptedGroupCreated(session, state, partner, NULL);
  19.459 +                            if (status == PEP_OUT_OF_MEMORY)
  19.460 +                                return (int) invalid_out_of_memory;
  19.461 +                            if (status != PEP_STATUS_OK)
  19.462 +                                return (int) invalid_action;
  19.463 +                            assert(session->sync_state_payload);
  19.464 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.465 +                            free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.466 +                            free(session->sync_state_payload);
  19.467 +                            session->sync_state_payload = NULL;
  19.468 +                            DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=Grouped")
  19.469 +                            return Grouped;
  19.470 +                            }
  19.471 +                        }
  19.472 +                        assert(session->sync_state_payload);
  19.473 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.474 +                        free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.475 +                        free(session->sync_state_payload);
  19.476 +                        session->sync_state_payload = NULL;
  19.477 +                        session->sync_state_payload = malloc(sizeof(WaitForGroupKeysSole_state_payload_t));
  19.478 +                        assert(session->sync_state_payload);
  19.479 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.480 +                        ((WaitForGroupKeysSole_state_payload_t*)session->sync_state_payload)->expected =
  19.481 +                            identity_dup(partner);
  19.482 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=WaitForGroupKeysSole")
  19.483 +                        return WaitForGroupKeysSole;
  19.484 +                        }
  19.485 +                    }
  19.486 +                    assert(session->sync_state_payload);
  19.487 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.488 +                    free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.489 +                    free(session->sync_state_payload);
  19.490 +                    session->sync_state_payload = NULL;
  19.491 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=Sole")
  19.492 +                    return Sole;
  19.493 +                }
  19.494 +                case Cancel:
  19.495 +                {
  19.496 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=Cancel")
  19.497 +                    assert(session->sync_state_payload);
  19.498 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.499 +                    free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.500 +                    free(session->sync_state_payload);
  19.501 +                    session->sync_state_payload = NULL;
  19.502 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=Cancel", "target=Sole")
  19.503 +                    return Sole;
  19.504 +                }
  19.505 +                case GroupKeys:
  19.506 +                {
  19.507 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=GroupKeys")
  19.508 +                    group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
  19.509 +                    {
  19.510 +                        int cond_result = keyElectionWon(session, expected);
  19.511 +                        #ifndef NDEBUG
  19.512 +                        char resstr[11] = {0,};
  19.513 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.514 +                        #endif
  19.515 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=GroupKeys, condition=keyElectionWon", resstr)
  19.516 +                        if (cond_result < 0)
  19.517 +                            return cond_result;
  19.518 +                        if (cond_result) {
  19.519 +                        }
  19.520 +                        else {
  19.521 +                        {
  19.522 +                            int cond_result = sameKeyAndAddress(session, partner, expected);
  19.523 +                            #ifndef NDEBUG
  19.524 +                            char resstr[11] = {0,};
  19.525 +                            snprintf(resstr,10,"result=%d",cond_result);
  19.526 +                            #endif
  19.527 +                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=GroupKeys, condition=sameKeyAndAddress", resstr)
  19.528 +                            if (cond_result < 0)
  19.529 +                                return cond_result;
  19.530 +                            if (cond_result) {
  19.531 +                            assert(session->sync_state_payload);
  19.532 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.533 +                            free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.534 +                            free(session->sync_state_payload);
  19.535 +                            session->sync_state_payload = NULL;
  19.536 +                            session->sync_state_payload = malloc(sizeof(WaitForAcceptSole_state_payload_t));
  19.537 +                            assert(session->sync_state_payload);
  19.538 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.539 +                            ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected =
  19.540 +                                identity_dup(partner);
  19.541 +                            ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys =
  19.542 +                                group_keys_extra_dup(groupkeys);
  19.543 +                            DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=GroupKeys", "target=WaitForAcceptSole")
  19.544 +                            return WaitForAcceptSole;
  19.545 +                            }
  19.546 +                        }
  19.547 +                        }
  19.548 +                    }
  19.549 +                    break;
  19.550 +                }
  19.551 +                case Timeout:
  19.552 +                {
  19.553 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=Timeout")
  19.554 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Timeout", "action=notifyTimeout")
  19.555 +                    status = notifyTimeout(session, state, expected, NULL);
  19.556 +                    if (status == PEP_OUT_OF_MEMORY)
  19.557 +                        return (int) invalid_out_of_memory;
  19.558 +                    if (status != PEP_STATUS_OK)
  19.559 +                        return (int) invalid_action;
  19.560 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Timeout", "action=sendBeacon")
  19.561 +                    status = sendBeacon(session, state, NULL, NULL);
  19.562 +                    if (status == PEP_OUT_OF_MEMORY)
  19.563 +                        return (int) invalid_out_of_memory;
  19.564 +                    if (status != PEP_STATUS_OK)
  19.565 +                        return (int) invalid_action;
  19.566 +                    assert(session->sync_state_payload);
  19.567 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.568 +                    free_identity(((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected);
  19.569 +                    free(session->sync_state_payload);
  19.570 +                    session->sync_state_payload = NULL;
  19.571 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=Timeout", "target=Sole")
  19.572 +                    return Sole;
  19.573 +                }
  19.574 +                default:
  19.575 +                    return (DeviceState_state) invalid_event;
  19.576 +            }
  19.577 +            break;
  19.578 +        }
  19.579 +        case WaitForGroupKeysSole:
  19.580 +        {
  19.581 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=WaitForGroupKeysSole")
  19.582 +            assert(session->sync_state_payload);
  19.583 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.584 +            Identity expected = ((WaitForGroupKeysSole_state_payload_t*)session->sync_state_payload)->expected;
  19.585 +            switch (event) {
  19.586 +                case Init: 
  19.587 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=Init") 
  19.588 +                    *timeout = 600;
  19.589 +                    break;
  19.590 +                case GroupKeys:
  19.591 +                {
  19.592 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=GroupKeys")
  19.593 +                    group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
  19.594 +                    {
  19.595 +                        int cond_result = sameKeyAndAddress(session, partner, expected);
  19.596 +                        #ifndef NDEBUG
  19.597 +                        char resstr[11] = {0,};
  19.598 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.599 +                        #endif
  19.600 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys, condition=sameKeyAndAddress", resstr)
  19.601 +                        if (cond_result < 0)
  19.602 +                            return cond_result;
  19.603 +                        if (cond_result) {
  19.604 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=storeGroupKeys")
  19.605 +                        status = storeGroupKeys(session, state, partner, groupkeys);
  19.606 +                        if (status == PEP_OUT_OF_MEMORY)
  19.607 +                            return (int) invalid_out_of_memory;
  19.608 +                        if (status != PEP_STATUS_OK)
  19.609 +                            return (int) invalid_action;
  19.610 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=sendGroupUpdate")
  19.611 +                        status = sendGroupUpdate(session, state, NULL, NULL);
  19.612 +                        if (status == PEP_OUT_OF_MEMORY)
  19.613 +                            return (int) invalid_out_of_memory;
  19.614 +                        if (status != PEP_STATUS_OK)
  19.615 +                            return (int) invalid_action;
  19.616 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=renewUUID")
  19.617 +                        status = renewUUID(session, state, NULL, NULL);
  19.618 +                        if (status == PEP_OUT_OF_MEMORY)
  19.619 +                            return (int) invalid_out_of_memory;
  19.620 +                        if (status != PEP_STATUS_OK)
  19.621 +                            return (int) invalid_action;
  19.622 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=notifyAcceptedDeviceAdded")
  19.623 +                        status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
  19.624 +                        if (status == PEP_OUT_OF_MEMORY)
  19.625 +                            return (int) invalid_out_of_memory;
  19.626 +                        if (status != PEP_STATUS_OK)
  19.627 +                            return (int) invalid_action;
  19.628 +                        assert(session->sync_state_payload);
  19.629 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.630 +                        free_identity(((WaitForGroupKeysSole_state_payload_t*)session->sync_state_payload)->expected);
  19.631 +                        free(session->sync_state_payload);
  19.632 +                        session->sync_state_payload = NULL;
  19.633 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "target=Grouped")
  19.634 +                        return Grouped;
  19.635 +                        }
  19.636 +                    }
  19.637 +                    break;
  19.638 +                }
  19.639 +                case Timeout:
  19.640 +                {
  19.641 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=Timeout")
  19.642 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=Timeout", "action=notifyTimeout")
  19.643 +                    status = notifyTimeout(session, state, expected, NULL);
  19.644 +                    if (status == PEP_OUT_OF_MEMORY)
  19.645 +                        return (int) invalid_out_of_memory;
  19.646 +                    if (status != PEP_STATUS_OK)
  19.647 +                        return (int) invalid_action;
  19.648 +                    assert(session->sync_state_payload);
  19.649 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.650 +                    free_identity(((WaitForGroupKeysSole_state_payload_t*)session->sync_state_payload)->expected);
  19.651 +                    free(session->sync_state_payload);
  19.652 +                    session->sync_state_payload = NULL;
  19.653 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysSole, event=Timeout", "target=Sole")
  19.654 +                    return Sole;
  19.655 +                }
  19.656 +                default:
  19.657 +                    return (DeviceState_state) invalid_event;
  19.658 +            }
  19.659 +            break;
  19.660 +        }
  19.661 +        case WaitForAcceptSole:
  19.662 +        {
  19.663 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=WaitForAcceptSole")
  19.664 +            assert(session->sync_state_payload);
  19.665 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.666 +            Identity expected = ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected;
  19.667 +            group_keys_extra_t* groupkeys = ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys;
  19.668 +            switch (event) {
  19.669 +                case Init: 
  19.670 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=Init") 
  19.671 +                    *timeout = 600;
  19.672 +                    break;
  19.673 +                case HandshakeRejected:
  19.674 +                {
  19.675 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=HandshakeRejected")
  19.676 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeRejected", "action=rejectHandshake")
  19.677 +                    status = rejectHandshake(session, state, partner, NULL);
  19.678 +                    if (status == PEP_OUT_OF_MEMORY)
  19.679 +                        return (int) invalid_out_of_memory;
  19.680 +                    if (status != PEP_STATUS_OK)
  19.681 +                        return (int) invalid_action;
  19.682 +                    assert(session->sync_state_payload);
  19.683 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.684 +                    free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
  19.685 +                    free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
  19.686 +                    free(session->sync_state_payload);
  19.687 +                    session->sync_state_payload = NULL;
  19.688 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeRejected", "target=Sole")
  19.689 +                    return Sole;
  19.690 +                }
  19.691 +                case HandshakeAccepted:
  19.692 +                {
  19.693 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=HandshakeAccepted")
  19.694 +                    {
  19.695 +                        int cond_result = sameKeyAndAddress(session, partner, expected);
  19.696 +                        #ifndef NDEBUG
  19.697 +                        char resstr[11] = {0,};
  19.698 +                        snprintf(resstr,10,"result=%d",cond_result);
  19.699 +                        #endif
  19.700 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted, condition=sameKeyAndAddress", resstr)
  19.701 +                        if (cond_result < 0)
  19.702 +                            return cond_result;
  19.703 +                        if (cond_result) {
  19.704 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "action=acceptHandshake")
  19.705 +                        status = acceptHandshake(session, state, partner, NULL);
  19.706 +                        if (status == PEP_OUT_OF_MEMORY)
  19.707 +                            return (int) invalid_out_of_memory;
  19.708 +                        if (status != PEP_STATUS_OK)
  19.709 +                            return (int) invalid_action;
  19.710 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "action=storeGroupKeys")
  19.711 +                        status = storeGroupKeys(session, state, partner, groupkeys);
  19.712 +                        if (status == PEP_OUT_OF_MEMORY)
  19.713 +                            return (int) invalid_out_of_memory;
  19.714 +                        if (status != PEP_STATUS_OK)
  19.715 +                            return (int) invalid_action;
  19.716 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "action=sendGroupUpdate")
  19.717 +                        status = sendGroupUpdate(session, state, NULL, NULL);
  19.718 +                        if (status == PEP_OUT_OF_MEMORY)
  19.719 +                            return (int) invalid_out_of_memory;
  19.720 +                        if (status != PEP_STATUS_OK)
  19.721 +                            return (int) invalid_action;
  19.722 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "action=renewUUID")
  19.723 +                        status = renewUUID(session, state, NULL, NULL);
  19.724 +                        if (status == PEP_OUT_OF_MEMORY)
  19.725 +                            return (int) invalid_out_of_memory;
  19.726 +                        if (status != PEP_STATUS_OK)
  19.727 +                            return (int) invalid_action;
  19.728 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "action=notifyAcceptedDeviceAdded")
  19.729 +                        status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
  19.730 +                        if (status == PEP_OUT_OF_MEMORY)
  19.731 +                            return (int) invalid_out_of_memory;
  19.732 +                        if (status != PEP_STATUS_OK)
  19.733 +                            return (int) invalid_action;
  19.734 +                        assert(session->sync_state_payload);
  19.735 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.736 +                        free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
  19.737 +                        free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
  19.738 +                        free(session->sync_state_payload);
  19.739 +                        session->sync_state_payload = NULL;
  19.740 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "target=Grouped")
  19.741 +                        return Grouped;
  19.742 +                        }
  19.743 +                    }
  19.744 +                    assert(session->sync_state_payload);
  19.745 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.746 +                    free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
  19.747 +                    free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
  19.748 +                    free(session->sync_state_payload);
  19.749 +                    session->sync_state_payload = NULL;
  19.750 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "target=Sole")
  19.751 +                    return Sole;
  19.752 +                }
  19.753 +                case Cancel:
  19.754 +                {
  19.755 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=Cancel")
  19.756 +                    assert(session->sync_state_payload);
  19.757 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.758 +                    free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
  19.759 +                    free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
  19.760 +                    free(session->sync_state_payload);
  19.761 +                    session->sync_state_payload = NULL;
  19.762 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=Cancel", "target=Sole")
  19.763 +                    return Sole;
  19.764 +                }
  19.765 +                case Timeout:
  19.766 +                {
  19.767 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=Timeout")
  19.768 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptSole, event=Timeout", "action=notifyTimeout")
  19.769 +                    status = notifyTimeout(session, state, expected, NULL);
  19.770 +                    if (status == PEP_OUT_OF_MEMORY)
  19.771 +                        return (int) invalid_out_of_memory;
  19.772 +                    if (status != PEP_STATUS_OK)
  19.773 +                        return (int) invalid_action;
  19.774 +                    assert(session->sync_state_payload);
  19.775 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.776 +                    free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
  19.777 +                    free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
  19.778 +                    free(session->sync_state_payload);
  19.779 +                    session->sync_state_payload = NULL;
  19.780 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=Timeout", "target=Sole")
  19.781 +                    return Sole;
  19.782 +                }
  19.783 +                default:
  19.784 +                    return (DeviceState_state) invalid_event;
  19.785 +            }
  19.786 +            break;
  19.787 +        }
  19.788 +        case Grouped:
  19.789 +        {
  19.790 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=Grouped")
  19.791 +            switch (event) {
  19.792 +                case Init: 
  19.793 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=Init") 
  19.794 +                    *timeout = 0;
  19.795 +                    break;
  19.796 +                case KeyGen:
  19.797 +                {
  19.798 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=KeyGen")
  19.799 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=KeyGen", "action=sendGroupUpdate")
  19.800 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  19.801 +                    if (status == PEP_OUT_OF_MEMORY)
  19.802 +                        return (int) invalid_out_of_memory;
  19.803 +                    if (status != PEP_STATUS_OK)
  19.804 +                        return (int) invalid_action;
  19.805 +                    break;
  19.806 +                }
  19.807 +                case CannotDecrypt:
  19.808 +                {
  19.809 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=CannotDecrypt")
  19.810 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "action=sendUpdateRequest")
  19.811 +                    status = sendUpdateRequest(session, state, NULL, NULL);
  19.812 +                    if (status == PEP_OUT_OF_MEMORY)
  19.813 +                        return (int) invalid_out_of_memory;
  19.814 +                    if (status != PEP_STATUS_OK)
  19.815 +                        return (int) invalid_action;
  19.816 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "action=sendBeacon")
  19.817 +                    status = sendBeacon(session, state, NULL, NULL);
  19.818 +                    if (status == PEP_OUT_OF_MEMORY)
  19.819 +                        return (int) invalid_out_of_memory;
  19.820 +                    if (status != PEP_STATUS_OK)
  19.821 +                        return (int) invalid_action;
  19.822 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "target=GroupWaiting")
  19.823 +                    return GroupWaiting;
  19.824 +                }
  19.825 +                case UpdateRequest:
  19.826 +                {
  19.827 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=UpdateRequest")
  19.828 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=UpdateRequest", "action=sendGroupUpdate")
  19.829 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  19.830 +                    if (status == PEP_OUT_OF_MEMORY)
  19.831 +                        return (int) invalid_out_of_memory;
  19.832 +                    if (status != PEP_STATUS_OK)
  19.833 +                        return (int) invalid_action;
  19.834 +                    break;
  19.835 +                }
  19.836 +                case Beacon:
  19.837 +                {
  19.838 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=Beacon")
  19.839 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=Beacon", "action=sendHandshakeRequest")
  19.840 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.841 +                    if (status == PEP_OUT_OF_MEMORY)
  19.842 +                        return (int) invalid_out_of_memory;
  19.843 +                    if (status != PEP_STATUS_OK)
  19.844 +                        return (int) invalid_action;
  19.845 +                    session->sync_state_payload = malloc(sizeof(GroupedBeaconed_state_payload_t));
  19.846 +                    assert(session->sync_state_payload);
  19.847 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.848 +                    ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  19.849 +                        identity_dup(partner);
  19.850 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=Beacon", "target=GroupedBeaconed")
  19.851 +                    return GroupedBeaconed;
  19.852 +                }
  19.853 +                case HandshakeRequest:
  19.854 +                {
  19.855 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=HandshakeRequest")
  19.856 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=HandshakeRequest", "action=sendHandshakeRequest")
  19.857 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.858 +                    if (status == PEP_OUT_OF_MEMORY)
  19.859 +                        return (int) invalid_out_of_memory;
  19.860 +                    if (status != PEP_STATUS_OK)
  19.861 +                        return (int) invalid_action;
  19.862 +                    session->sync_state_payload = malloc(sizeof(HandshakingGrouped_state_payload_t));
  19.863 +                    assert(session->sync_state_payload);
  19.864 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.865 +                    ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected =
  19.866 +                        identity_dup(partner);
  19.867 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=HandshakeRequest", "target=HandshakingGrouped")
  19.868 +                    return HandshakingGrouped;
  19.869 +                }
  19.870 +                case GroupUpdate:
  19.871 +                {
  19.872 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=GroupUpdate")
  19.873 +                    identity_list* keys = (identity_list*)extra;
  19.874 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=GroupUpdate", "action=storeGroupUpdate")
  19.875 +                    status = storeGroupUpdate(session, state, partner, keys);
  19.876 +                    if (status == PEP_OUT_OF_MEMORY)
  19.877 +                        return (int) invalid_out_of_memory;
  19.878 +                    if (status != PEP_STATUS_OK)
  19.879 +                        return (int) invalid_action;
  19.880 +                    break;
  19.881 +                }
  19.882 +                default:
  19.883 +                    return (DeviceState_state) invalid_event;
  19.884 +            }
  19.885 +            break;
  19.886 +        }
  19.887 +        case GroupWaiting:
  19.888 +        {
  19.889 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupWaiting")
  19.890 +            switch (event) {
  19.891 +                case Init: 
  19.892 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Init") 
  19.893 +                    *timeout = 60;
  19.894 +                    break;
  19.895 +                case KeyGen:
  19.896 +                {
  19.897 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=KeyGen")
  19.898 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=KeyGen", "action=sendGroupUpdate")
  19.899 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  19.900 +                    if (status == PEP_OUT_OF_MEMORY)
  19.901 +                        return (int) invalid_out_of_memory;
  19.902 +                    if (status != PEP_STATUS_OK)
  19.903 +                        return (int) invalid_action;
  19.904 +                    break;
  19.905 +                }
  19.906 +                case CannotDecrypt:
  19.907 +                {
  19.908 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=CannotDecrypt")
  19.909 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendUpdateRequest")
  19.910 +                    status = sendUpdateRequest(session, state, NULL, NULL);
  19.911 +                    if (status == PEP_OUT_OF_MEMORY)
  19.912 +                        return (int) invalid_out_of_memory;
  19.913 +                    if (status != PEP_STATUS_OK)
  19.914 +                        return (int) invalid_action;
  19.915 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendBeacon")
  19.916 +                    status = sendBeacon(session, state, NULL, NULL);
  19.917 +                    if (status == PEP_OUT_OF_MEMORY)
  19.918 +                        return (int) invalid_out_of_memory;
  19.919 +                    if (status != PEP_STATUS_OK)
  19.920 +                        return (int) invalid_action;
  19.921 +                    break;
  19.922 +                }
  19.923 +                case UpdateRequest:
  19.924 +                {
  19.925 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=UpdateRequest")
  19.926 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=UpdateRequest", "action=sendGroupUpdate")
  19.927 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  19.928 +                    if (status == PEP_OUT_OF_MEMORY)
  19.929 +                        return (int) invalid_out_of_memory;
  19.930 +                    if (status != PEP_STATUS_OK)
  19.931 +                        return (int) invalid_action;
  19.932 +                    break;
  19.933 +                }
  19.934 +                case Beacon:
  19.935 +                {
  19.936 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Beacon")
  19.937 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=Beacon", "action=sendHandshakeRequest")
  19.938 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.939 +                    if (status == PEP_OUT_OF_MEMORY)
  19.940 +                        return (int) invalid_out_of_memory;
  19.941 +                    if (status != PEP_STATUS_OK)
  19.942 +                        return (int) invalid_action;
  19.943 +                    session->sync_state_payload = malloc(sizeof(GroupedBeaconed_state_payload_t));
  19.944 +                    assert(session->sync_state_payload);
  19.945 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.946 +                    ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  19.947 +                        identity_dup(partner);
  19.948 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Beacon", "target=GroupedBeaconed")
  19.949 +                    return GroupedBeaconed;
  19.950 +                }
  19.951 +                case HandshakeRequest:
  19.952 +                {
  19.953 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=HandshakeRequest")
  19.954 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
  19.955 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  19.956 +                    if (status == PEP_OUT_OF_MEMORY)
  19.957 +                        return (int) invalid_out_of_memory;
  19.958 +                    if (status != PEP_STATUS_OK)
  19.959 +                        return (int) invalid_action;
  19.960 +                    session->sync_state_payload = malloc(sizeof(HandshakingGrouped_state_payload_t));
  19.961 +                    assert(session->sync_state_payload);
  19.962 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  19.963 +                    ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected =
  19.964 +                        identity_dup(partner);
  19.965 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "target=HandshakingGrouped")
  19.966 +                    return HandshakingGrouped;
  19.967 +                }
  19.968 +                case GroupUpdate:
  19.969 +                {
  19.970 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=GroupUpdate")
  19.971 +                    identity_list* keys = (identity_list*)extra;
  19.972 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=GroupUpdate", "action=storeGroupUpdate")
  19.973 +                    status = storeGroupUpdate(session, state, partner, keys);
  19.974 +                    if (status == PEP_OUT_OF_MEMORY)
  19.975 +                        return (int) invalid_out_of_memory;
  19.976 +                    if (status != PEP_STATUS_OK)
  19.977 +                        return (int) invalid_action;
  19.978 +                    break;
  19.979 +                }
  19.980 +                case Timeout:
  19.981 +                {
  19.982 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Timeout")
  19.983 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Timeout", "target=Grouped")
  19.984 +                    return Grouped;
  19.985 +                }
  19.986 +                default:
  19.987 +                    return (DeviceState_state) invalid_event;
  19.988 +            }
  19.989 +            break;
  19.990 +        }
  19.991 +        case GroupedBeaconed:
  19.992 +        {
  19.993 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupedBeaconed")
  19.994 +            assert(session->sync_state_payload);
  19.995 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  19.996 +            Identity expected = ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected;
  19.997 +            switch (event) {
  19.998 +                case Init: 
  19.999 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Init") 
 19.1000 +                    *timeout = 600;
 19.1001 +                    break;
 19.1002 +                case KeyGen:
 19.1003 +                {
 19.1004 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=KeyGen")
 19.1005 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=KeyGen", "action=sendGroupUpdate")
 19.1006 +                    status = sendGroupUpdate(session, state, NULL, NULL);
 19.1007 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1008 +                        return (int) invalid_out_of_memory;
 19.1009 +                    if (status != PEP_STATUS_OK)
 19.1010 +                        return (int) invalid_action;
 19.1011 +                    break;
 19.1012 +                }
 19.1013 +                case CannotDecrypt:
 19.1014 +                {
 19.1015 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=CannotDecrypt")
 19.1016 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=CannotDecrypt", "action=sendUpdateRequest")
 19.1017 +                    status = sendUpdateRequest(session, state, NULL, NULL);
 19.1018 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1019 +                        return (int) invalid_out_of_memory;
 19.1020 +                    if (status != PEP_STATUS_OK)
 19.1021 +                        return (int) invalid_action;
 19.1022 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=CannotDecrypt", "action=sendBeacon")
 19.1023 +                    status = sendBeacon(session, state, NULL, NULL);
 19.1024 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1025 +                        return (int) invalid_out_of_memory;
 19.1026 +                    if (status != PEP_STATUS_OK)
 19.1027 +                        return (int) invalid_action;
 19.1028 +                    break;
 19.1029 +                }
 19.1030 +                case UpdateRequest:
 19.1031 +                {
 19.1032 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=UpdateRequest")
 19.1033 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=UpdateRequest", "action=sendGroupUpdate")
 19.1034 +                    status = sendGroupUpdate(session, state, NULL, NULL);
 19.1035 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1036 +                        return (int) invalid_out_of_memory;
 19.1037 +                    if (status != PEP_STATUS_OK)
 19.1038 +                        return (int) invalid_action;
 19.1039 +                    break;
 19.1040 +                }
 19.1041 +                case Beacon:
 19.1042 +                {
 19.1043 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Beacon")
 19.1044 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=Beacon", "action=sendHandshakeRequest")
 19.1045 +                    status = sendHandshakeRequest(session, state, partner, NULL);
 19.1046 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1047 +                        return (int) invalid_out_of_memory;
 19.1048 +                    if (status != PEP_STATUS_OK)
 19.1049 +                        return (int) invalid_action;
 19.1050 +                    assert(session->sync_state_payload);
 19.1051 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1052 +                    free_identity(((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected);
 19.1053 +                    free(session->sync_state_payload);
 19.1054 +                    session->sync_state_payload = NULL;
 19.1055 +                    session->sync_state_payload = malloc(sizeof(GroupedBeaconed_state_payload_t));
 19.1056 +                    assert(session->sync_state_payload);
 19.1057 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
 19.1058 +                    ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected =
 19.1059 +                        identity_dup(partner);
 19.1060 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=Beacon", "target=GroupedBeaconed")
 19.1061 +                    return GroupedBeaconed;
 19.1062 +                }
 19.1063 +                case HandshakeRequest:
 19.1064 +                {
 19.1065 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=HandshakeRequest")
 19.1066 +                    {
 19.1067 +                        int cond_result = sameIdentities(session, partner, expected);
 19.1068 +                        #ifndef NDEBUG
 19.1069 +                        char resstr[11] = {0,};
 19.1070 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1071 +                        #endif
 19.1072 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest, condition=sameIdentities", resstr)
 19.1073 +                        if (cond_result < 0)
 19.1074 +                            return cond_result;
 19.1075 +                        if (cond_result) {
 19.1076 +                        }
 19.1077 +                        else {
 19.1078 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest", "action=sendHandshakeRequest")
 19.1079 +                        status = sendHandshakeRequest(session, state, partner, NULL);
 19.1080 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1081 +                            return (int) invalid_out_of_memory;
 19.1082 +                        if (status != PEP_STATUS_OK)
 19.1083 +                            return (int) invalid_action;
 19.1084 +                        }
 19.1085 +                    }
 19.1086 +                    assert(session->sync_state_payload);
 19.1087 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1088 +                    free_identity(((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected);
 19.1089 +                    free(session->sync_state_payload);
 19.1090 +                    session->sync_state_payload = NULL;
 19.1091 +                    session->sync_state_payload = malloc(sizeof(HandshakingGrouped_state_payload_t));
 19.1092 +                    assert(session->sync_state_payload);
 19.1093 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
 19.1094 +                    ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected =
 19.1095 +                        identity_dup(partner);
 19.1096 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest", "target=HandshakingGrouped")
 19.1097 +                    return HandshakingGrouped;
 19.1098 +                }
 19.1099 +                case GroupUpdate:
 19.1100 +                {
 19.1101 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=GroupUpdate")
 19.1102 +                    identity_list* keys = (identity_list*)extra;
 19.1103 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=GroupUpdate", "action=storeGroupUpdate")
 19.1104 +                    status = storeGroupUpdate(session, state, partner, keys);
 19.1105 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1106 +                        return (int) invalid_out_of_memory;
 19.1107 +                    if (status != PEP_STATUS_OK)
 19.1108 +                        return (int) invalid_action;
 19.1109 +                    break;
 19.1110 +                }
 19.1111 +                case Timeout:
 19.1112 +                {
 19.1113 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Timeout")
 19.1114 +                    assert(session->sync_state_payload);
 19.1115 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1116 +                    free_identity(((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected);
 19.1117 +                    free(session->sync_state_payload);
 19.1118 +                    session->sync_state_payload = NULL;
 19.1119 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=Timeout", "target=Grouped")
 19.1120 +                    return Grouped;
 19.1121 +                }
 19.1122 +                default:
 19.1123 +                    return (DeviceState_state) invalid_event;
 19.1124 +            }
 19.1125 +            break;
 19.1126 +        }
 19.1127 +        case HandshakingGrouped:
 19.1128 +        {
 19.1129 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=HandshakingGrouped")
 19.1130 +            assert(session->sync_state_payload);
 19.1131 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1132 +            Identity expected = ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected;
 19.1133 +            switch (event) {
 19.1134 +                case Init:
 19.1135 +                {
 19.1136 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Init")
 19.1137 +                    *timeout = 600;
 19.1138 +                    {
 19.1139 +                        int cond_result = keyElectionWon(session, expected);
 19.1140 +                        #ifndef NDEBUG
 19.1141 +                        char resstr[11] = {0,};
 19.1142 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1143 +                        #endif
 19.1144 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=Init, condition=keyElectionWon", resstr)
 19.1145 +                        if (cond_result < 0)
 19.1146 +                            return cond_result;
 19.1147 +                        if (cond_result) {
 19.1148 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Init", "action=notifyInitAddOtherDevice")
 19.1149 +                        status = notifyInitAddOtherDevice(session, state, partner, NULL);
 19.1150 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1151 +                            return (int) invalid_out_of_memory;
 19.1152 +                        if (status != PEP_STATUS_OK)
 19.1153 +                            return (int) invalid_action;
 19.1154 +                        }
 19.1155 +                        else {
 19.1156 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Init", "action=notifyInitMoveOurDevice")
 19.1157 +                        status = notifyInitMoveOurDevice(session, state, partner, NULL);
 19.1158 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1159 +                            return (int) invalid_out_of_memory;
 19.1160 +                        if (status != PEP_STATUS_OK)
 19.1161 +                            return (int) invalid_action;
 19.1162 +                        }
 19.1163 +                    }
 19.1164 +                    break;
 19.1165 +                }
 19.1166 +                case HandshakeRejected:
 19.1167 +                {
 19.1168 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=HandshakeRejected")
 19.1169 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeRejected", "action=rejectHandshake")
 19.1170 +                    status = rejectHandshake(session, state, partner, NULL);
 19.1171 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1172 +                        return (int) invalid_out_of_memory;
 19.1173 +                    if (status != PEP_STATUS_OK)
 19.1174 +                        return (int) invalid_action;
 19.1175 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeRejected", "action=sendGroupUpdate")
 19.1176 +                    status = sendGroupUpdate(session, state, NULL, NULL);
 19.1177 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1178 +                        return (int) invalid_out_of_memory;
 19.1179 +                    if (status != PEP_STATUS_OK)
 19.1180 +                        return (int) invalid_action;
 19.1181 +                    assert(session->sync_state_payload);
 19.1182 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1183 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1184 +                    free(session->sync_state_payload);
 19.1185 +                    session->sync_state_payload = NULL;
 19.1186 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeRejected", "target=Grouped")
 19.1187 +                    return Grouped;
 19.1188 +                }
 19.1189 +                case HandshakeAccepted:
 19.1190 +                {
 19.1191 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=HandshakeAccepted")
 19.1192 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=acceptHandshake")
 19.1193 +                    status = acceptHandshake(session, state, partner, NULL);
 19.1194 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1195 +                        return (int) invalid_out_of_memory;
 19.1196 +                    if (status != PEP_STATUS_OK)
 19.1197 +                        return (int) invalid_action;
 19.1198 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=sendGroupUpdate")
 19.1199 +                    status = sendGroupUpdate(session, state, NULL, NULL);
 19.1200 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1201 +                        return (int) invalid_out_of_memory;
 19.1202 +                    if (status != PEP_STATUS_OK)
 19.1203 +                        return (int) invalid_action;
 19.1204 +                    {
 19.1205 +                        int cond_result = keyElectionWon(session, partner);
 19.1206 +                        #ifndef NDEBUG
 19.1207 +                        char resstr[11] = {0,};
 19.1208 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1209 +                        #endif
 19.1210 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted, condition=keyElectionWon", resstr)
 19.1211 +                        if (cond_result < 0)
 19.1212 +                            return cond_result;
 19.1213 +                        if (cond_result) {
 19.1214 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=sendGroupKeys")
 19.1215 +                        status = sendGroupKeys(session, state, partner, NULL);
 19.1216 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1217 +                            return (int) invalid_out_of_memory;
 19.1218 +                        if (status != PEP_STATUS_OK)
 19.1219 +                            return (int) invalid_action;
 19.1220 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=notifyAcceptedDeviceAdded")
 19.1221 +                        status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
 19.1222 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1223 +                            return (int) invalid_out_of_memory;
 19.1224 +                        if (status != PEP_STATUS_OK)
 19.1225 +                            return (int) invalid_action;
 19.1226 +                        assert(session->sync_state_payload);
 19.1227 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1228 +                        free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1229 +                        free(session->sync_state_payload);
 19.1230 +                        session->sync_state_payload = NULL;
 19.1231 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "target=Grouped")
 19.1232 +                        return Grouped;
 19.1233 +                        }
 19.1234 +                    }
 19.1235 +                    assert(session->sync_state_payload);
 19.1236 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1237 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1238 +                    free(session->sync_state_payload);
 19.1239 +                    session->sync_state_payload = NULL;
 19.1240 +                    session->sync_state_payload = malloc(sizeof(WaitForGroupKeysGrouped_state_payload_t));
 19.1241 +                    assert(session->sync_state_payload);
 19.1242 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
 19.1243 +                    ((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected =
 19.1244 +                        identity_dup(partner);
 19.1245 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "target=WaitForGroupKeysGrouped")
 19.1246 +                    return WaitForGroupKeysGrouped;
 19.1247 +                }
 19.1248 +                case Cancel:
 19.1249 +                {
 19.1250 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Cancel")
 19.1251 +                    assert(session->sync_state_payload);
 19.1252 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1253 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1254 +                    free(session->sync_state_payload);
 19.1255 +                    session->sync_state_payload = NULL;
 19.1256 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=Cancel", "target=Grouped")
 19.1257 +                    return Grouped;
 19.1258 +                }
 19.1259 +                case GroupKeys:
 19.1260 +                {
 19.1261 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=GroupKeys")
 19.1262 +                    group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
 19.1263 +                    {
 19.1264 +                        int cond_result = keyElectionWon(session, expected);
 19.1265 +                        #ifndef NDEBUG
 19.1266 +                        char resstr[11] = {0,};
 19.1267 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1268 +                        #endif
 19.1269 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys, condition=keyElectionWon", resstr)
 19.1270 +                        if (cond_result < 0)
 19.1271 +                            return cond_result;
 19.1272 +                        if (cond_result) {
 19.1273 +                        }
 19.1274 +                        else {
 19.1275 +                        {
 19.1276 +                            int cond_result = sameKeyAndAddress(session, partner, expected);
 19.1277 +                            #ifndef NDEBUG
 19.1278 +                            char resstr[11] = {0,};
 19.1279 +                            snprintf(resstr,10,"result=%d",cond_result);
 19.1280 +                            #endif
 19.1281 +                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys, condition=sameKeyAndAddress", resstr)
 19.1282 +                            if (cond_result < 0)
 19.1283 +                                return cond_result;
 19.1284 +                            if (cond_result) {
 19.1285 +                            assert(session->sync_state_payload);
 19.1286 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1287 +                            free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1288 +                            free(session->sync_state_payload);
 19.1289 +                            session->sync_state_payload = NULL;
 19.1290 +                            session->sync_state_payload = malloc(sizeof(WaitForAcceptGrouped_state_payload_t));
 19.1291 +                            assert(session->sync_state_payload);
 19.1292 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
 19.1293 +                            ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected =
 19.1294 +                                identity_dup(partner);
 19.1295 +                            ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys =
 19.1296 +                                group_keys_extra_dup(groupkeys);
 19.1297 +                            DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys", "target=WaitForAcceptGrouped")
 19.1298 +                            return WaitForAcceptGrouped;
 19.1299 +                            }
 19.1300 +                        }
 19.1301 +                        }
 19.1302 +                    }
 19.1303 +                    break;
 19.1304 +                }
 19.1305 +                case GroupUpdate:
 19.1306 +                {
 19.1307 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=GroupUpdate")
 19.1308 +                    identity_list* keys = (identity_list*)extra;
 19.1309 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "action=notifyOvertaken")
 19.1310 +                    status = notifyOvertaken(session, state, partner, NULL);
 19.1311 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1312 +                        return (int) invalid_out_of_memory;
 19.1313 +                    if (status != PEP_STATUS_OK)
 19.1314 +                        return (int) invalid_action;
 19.1315 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "action=storeGroupUpdate")
 19.1316 +                    status = storeGroupUpdate(session, state, partner, keys);
 19.1317 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1318 +                        return (int) invalid_out_of_memory;
 19.1319 +                    if (status != PEP_STATUS_OK)
 19.1320 +                        return (int) invalid_action;
 19.1321 +                    assert(session->sync_state_payload);
 19.1322 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1323 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1324 +                    free(session->sync_state_payload);
 19.1325 +                    session->sync_state_payload = NULL;
 19.1326 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "target=Grouped")
 19.1327 +                    return Grouped;
 19.1328 +                }
 19.1329 +                case Timeout:
 19.1330 +                {
 19.1331 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Timeout")
 19.1332 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Timeout", "action=notifyTimeout")
 19.1333 +                    status = notifyTimeout(session, state, expected, NULL);
 19.1334 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1335 +                        return (int) invalid_out_of_memory;
 19.1336 +                    if (status != PEP_STATUS_OK)
 19.1337 +                        return (int) invalid_action;
 19.1338 +                    assert(session->sync_state_payload);
 19.1339 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1340 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1341 +                    free(session->sync_state_payload);
 19.1342 +                    session->sync_state_payload = NULL;
 19.1343 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=Timeout", "target=Grouped")
 19.1344 +                    return Grouped;
 19.1345 +                }
 19.1346 +                default:
 19.1347 +                    return (DeviceState_state) invalid_event;
 19.1348 +            }
 19.1349 +            break;
 19.1350 +        }
 19.1351 +        case WaitForGroupKeysGrouped:
 19.1352 +        {
 19.1353 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=WaitForGroupKeysGrouped")
 19.1354 +            assert(session->sync_state_payload);
 19.1355 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1356 +            Identity expected = ((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected;
 19.1357 +            switch (event) {
 19.1358 +                case Init: 
 19.1359 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Init") 
 19.1360 +                    *timeout = 600;
 19.1361 +                    break;
 19.1362 +                case GroupKeys:
 19.1363 +                {
 19.1364 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=GroupKeys")
 19.1365 +                    group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
 19.1366 +                    {
 19.1367 +                        int cond_result = sameIdentities(session, partner, expected);
 19.1368 +                        #ifndef NDEBUG
 19.1369 +                        char resstr[11] = {0,};
 19.1370 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1371 +                        #endif
 19.1372 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys, condition=sameIdentities", resstr)
 19.1373 +                        if (cond_result < 0)
 19.1374 +                            return cond_result;
 19.1375 +                        if (cond_result) {
 19.1376 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=storeGroupKeys")
 19.1377 +                        status = storeGroupKeys(session, state, partner, groupkeys);
 19.1378 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1379 +                            return (int) invalid_out_of_memory;
 19.1380 +                        if (status != PEP_STATUS_OK)
 19.1381 +                            return (int) invalid_action;
 19.1382 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=sendGroupUpdate")
 19.1383 +                        status = sendGroupUpdate(session, state, NULL, NULL);
 19.1384 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1385 +                            return (int) invalid_out_of_memory;
 19.1386 +                        if (status != PEP_STATUS_OK)
 19.1387 +                            return (int) invalid_action;
 19.1388 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=renewUUID")
 19.1389 +                        status = renewUUID(session, state, NULL, NULL);
 19.1390 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1391 +                            return (int) invalid_out_of_memory;
 19.1392 +                        if (status != PEP_STATUS_OK)
 19.1393 +                            return (int) invalid_action;
 19.1394 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=notifyAcceptedDeviceMoved")
 19.1395 +                        status = notifyAcceptedDeviceMoved(session, state, partner, NULL);
 19.1396 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1397 +                            return (int) invalid_out_of_memory;
 19.1398 +                        if (status != PEP_STATUS_OK)
 19.1399 +                            return (int) invalid_action;
 19.1400 +                        assert(session->sync_state_payload);
 19.1401 +                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1402 +                        free_identity(((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1403 +                        free(session->sync_state_payload);
 19.1404 +                        session->sync_state_payload = NULL;
 19.1405 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "target=Grouped")
 19.1406 +                        return Grouped;
 19.1407 +                        }
 19.1408 +                    }
 19.1409 +                    break;
 19.1410 +                }
 19.1411 +                case GroupUpdate:
 19.1412 +                {
 19.1413 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=GroupUpdate")
 19.1414 +                    identity_list* keys = (identity_list*)extra;
 19.1415 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "action=notifyOvertaken")
 19.1416 +                    status = notifyOvertaken(session, state, partner, NULL);
 19.1417 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1418 +                        return (int) invalid_out_of_memory;
 19.1419 +                    if (status != PEP_STATUS_OK)
 19.1420 +                        return (int) invalid_action;
 19.1421 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "action=storeGroupUpdate")
 19.1422 +                    status = storeGroupUpdate(session, state, partner, keys);
 19.1423 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1424 +                        return (int) invalid_out_of_memory;
 19.1425 +                    if (status != PEP_STATUS_OK)
 19.1426 +                        return (int) invalid_action;
 19.1427 +                    assert(session->sync_state_payload);
 19.1428 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1429 +                    free_identity(((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1430 +                    free(session->sync_state_payload);
 19.1431 +                    session->sync_state_payload = NULL;
 19.1432 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "target=Grouped")
 19.1433 +                    return Grouped;
 19.1434 +                }
 19.1435 +                case Timeout:
 19.1436 +                {
 19.1437 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Timeout")
 19.1438 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=Timeout", "action=notifyTimeout")
 19.1439 +                    status = notifyTimeout(session, state, expected, NULL);
 19.1440 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1441 +                        return (int) invalid_out_of_memory;
 19.1442 +                    if (status != PEP_STATUS_OK)
 19.1443 +                        return (int) invalid_action;
 19.1444 +                    assert(session->sync_state_payload);
 19.1445 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1446 +                    free_identity(((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1447 +                    free(session->sync_state_payload);
 19.1448 +                    session->sync_state_payload = NULL;
 19.1449 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=Timeout", "target=Grouped")
 19.1450 +                    return Grouped;
 19.1451 +                }
 19.1452 +                default:
 19.1453 +                    return (DeviceState_state) invalid_event;
 19.1454 +            }
 19.1455 +            break;
 19.1456 +        }
 19.1457 +        case WaitForAcceptGrouped:
 19.1458 +        {
 19.1459 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=WaitForAcceptGrouped")
 19.1460 +            assert(session->sync_state_payload);
 19.1461 +            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1462 +            Identity expected = ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected;
 19.1463 +            group_keys_extra_t* groupkeys = ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys;
 19.1464 +            switch (event) {
 19.1465 +                case Init: 
 19.1466 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=Init") 
 19.1467 +                    *timeout = 600;
 19.1468 +                    break;
 19.1469 +                case HandshakeRejected:
 19.1470 +                {
 19.1471 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=HandshakeRejected")
 19.1472 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeRejected", "action=rejectHandshake")
 19.1473 +                    status = rejectHandshake(session, state, partner, NULL);
 19.1474 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1475 +                        return (int) invalid_out_of_memory;
 19.1476 +                    if (status != PEP_STATUS_OK)
 19.1477 +                        return (int) invalid_action;
 19.1478 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeRejected", "action=sendGroupUpdate")
 19.1479 +                    status = sendGroupUpdate(session, state, NULL, NULL);
 19.1480 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1481 +                        return (int) invalid_out_of_memory;
 19.1482 +                    if (status != PEP_STATUS_OK)
 19.1483 +                        return (int) invalid_action;
 19.1484 +                    assert(session->sync_state_payload);
 19.1485 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1486 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1487 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
 19.1488 +                    free(session->sync_state_payload);
 19.1489 +                    session->sync_state_payload = NULL;
 19.1490 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeRejected", "target=Grouped")
 19.1491 +                    return Grouped;
 19.1492 +                }
 19.1493 +                case HandshakeAccepted:
 19.1494 +                {
 19.1495 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=HandshakeAccepted")
 19.1496 +                    {
 19.1497 +                        int cond_result = sameIdentities(session, partner, expected);
 19.1498 +                        #ifndef NDEBUG
 19.1499 +                        char resstr[11] = {0,};
 19.1500 +                        snprintf(resstr,10,"result=%d",cond_result);
 19.1501 +                        #endif
 19.1502 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted, condition=sameIdentities", resstr)
 19.1503 +                        if (cond_result < 0)
 19.1504 +                            return cond_result;
 19.1505 +                        if (cond_result) {
 19.1506 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=acceptHandshake")
 19.1507 +                        status = acceptHandshake(session, state, partner, NULL);
 19.1508 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1509 +                            return (int) invalid_out_of_memory;
 19.1510 +                        if (status != PEP_STATUS_OK)
 19.1511 +                            return (int) invalid_action;
 19.1512 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=storeGroupKeys")
 19.1513 +                        status = storeGroupKeys(session, state, partner, groupkeys);
 19.1514 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1515 +                            return (int) invalid_out_of_memory;
 19.1516 +                        if (status != PEP_STATUS_OK)
 19.1517 +                            return (int) invalid_action;
 19.1518 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=sendGroupUpdate")
 19.1519 +                        status = sendGroupUpdate(session, state, NULL, NULL);
 19.1520 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1521 +                            return (int) invalid_out_of_memory;
 19.1522 +                        if (status != PEP_STATUS_OK)
 19.1523 +                            return (int) invalid_action;
 19.1524 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=renewUUID")
 19.1525 +                        status = renewUUID(session, state, NULL, NULL);
 19.1526 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1527 +                            return (int) invalid_out_of_memory;
 19.1528 +                        if (status != PEP_STATUS_OK)
 19.1529 +                            return (int) invalid_action;
 19.1530 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=notifyAcceptedDeviceMoved")
 19.1531 +                        status = notifyAcceptedDeviceMoved(session, state, partner, NULL);
 19.1532 +                        if (status == PEP_OUT_OF_MEMORY)
 19.1533 +                            return (int) invalid_out_of_memory;
 19.1534 +                        if (status != PEP_STATUS_OK)
 19.1535 +                            return (int) invalid_action;
 19.1536 +                        }
 19.1537 +                    }
 19.1538 +                    assert(session->sync_state_payload);
 19.1539 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1540 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1541 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
 19.1542 +                    free(session->sync_state_payload);
 19.1543 +                    session->sync_state_payload = NULL;
 19.1544 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "target=Grouped")
 19.1545 +                    return Grouped;
 19.1546 +                }
 19.1547 +                case Cancel:
 19.1548 +                {
 19.1549 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=Cancel")
 19.1550 +                    assert(session->sync_state_payload);
 19.1551 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1552 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1553 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
 19.1554 +                    free(session->sync_state_payload);
 19.1555 +                    session->sync_state_payload = NULL;
 19.1556 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=Cancel", "target=Grouped")
 19.1557 +                    return Grouped;
 19.1558 +                }
 19.1559 +                case GroupUpdate:
 19.1560 +                {
 19.1561 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=GroupUpdate")
 19.1562 +                    identity_list* keys = (identity_list*)extra;
 19.1563 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "action=notifyOvertaken")
 19.1564 +                    status = notifyOvertaken(session, state, partner, NULL);
 19.1565 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1566 +                        return (int) invalid_out_of_memory;
 19.1567 +                    if (status != PEP_STATUS_OK)
 19.1568 +                        return (int) invalid_action;
 19.1569 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "action=storeGroupUpdate")
 19.1570 +                    status = storeGroupUpdate(session, state, partner, keys);
 19.1571 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1572 +                        return (int) invalid_out_of_memory;
 19.1573 +                    if (status != PEP_STATUS_OK)
 19.1574 +                        return (int) invalid_action;
 19.1575 +                    assert(session->sync_state_payload);
 19.1576 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1577 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1578 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
 19.1579 +                    free(session->sync_state_payload);
 19.1580 +                    session->sync_state_payload = NULL;
 19.1581 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "target=Grouped")
 19.1582 +                    return Grouped;
 19.1583 +                }
 19.1584 +                case Timeout:
 19.1585 +                {
 19.1586 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=Timeout")
 19.1587 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=Timeout", "action=notifyTimeout")
 19.1588 +                    status = notifyTimeout(session, state, expected, NULL);
 19.1589 +                    if (status == PEP_OUT_OF_MEMORY)
 19.1590 +                        return (int) invalid_out_of_memory;
 19.1591 +                    if (status != PEP_STATUS_OK)
 19.1592 +                        return (int) invalid_action;
 19.1593 +                    assert(session->sync_state_payload);
 19.1594 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
 19.1595 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
 19.1596 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
 19.1597 +                    free(session->sync_state_payload);
 19.1598 +                    session->sync_state_payload = NULL;
 19.1599 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=Timeout", "target=Grouped")
 19.1600 +                    return Grouped;
 19.1601 +                }
 19.1602 +                default:
 19.1603 +                    return (DeviceState_state) invalid_event;
 19.1604 +            }
 19.1605 +            break;
 19.1606 +        }
 19.1607 +        default:
 19.1608 +            return (DeviceState_state) invalid_state;
 19.1609 +    }
 19.1610 +
 19.1611 +    return state;
 19.1612 +}
 19.1613 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/sync/generated/sync_fsm.h	Fri Nov 03 13:32:38 2017 +0100
    20.3 @@ -0,0 +1,145 @@
    20.4 +#pragma once
    20.5 +
    20.6 +// state machine for DeviceState
    20.7 +
    20.8 +#include "message_api.h"
    20.9 +
   20.10 +#ifdef __cplusplus
   20.11 +extern "C" {
   20.12 +#endif
   20.13 +
   20.14 +// types
   20.15 +
   20.16 +typedef pEp_identity * Identity;
   20.17 +typedef stringlist_t * Stringlist;
   20.18 +
   20.19 +// error values
   20.20 +
   20.21 +typedef enum _fsm_error {
   20.22 +    // these error values are corresponding to
   20.23 +    // PEP_SYNC_STATEMACHINE_ERROR - value
   20.24 +    invalid_state = -2,
   20.25 +    invalid_event = -3,
   20.26 +    invalid_condition = -4,
   20.27 +    invalid_action = -5,
   20.28 +
   20.29 +    // out of memory condition
   20.30 +    invalid_out_of_memory = -128
   20.31 +} fsm_error;
   20.32 +
   20.33 +// conditions
   20.34 +
   20.35 +int deviceGrouped(PEP_SESSION session);
   20.36 +int keyElectionWon(PEP_SESSION session, Identity partner);
   20.37 +int sameIdentities(PEP_SESSION session, Identity a, Identity b);
   20.38 +int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b);
   20.39 +
   20.40 +// states
   20.41 +
   20.42 +typedef enum _DeviceState_state {
   20.43 +    // error values also in this namespace
   20.44 +    DeviceState_state_invalid_state = (int) invalid_state,
   20.45 +    DeviceState_state_invalid_event = (int) invalid_event,
   20.46 +    DeviceState_state_invalid_condition = (int) invalid_condition,
   20.47 +    DeviceState_state_invalid_action = (int) invalid_action,
   20.48 +    DeviceState_state_invalid_out_of_memory = (int) invalid_out_of_memory,
   20.49 +
   20.50 +    DeviceState_state_NONE = 0,
   20.51 +    InitState, 
   20.52 +    Sole, 
   20.53 +    SoleWaiting, 
   20.54 +    SoleBeaconed, 
   20.55 +    HandshakingSole, 
   20.56 +    WaitForGroupKeysSole, 
   20.57 +    WaitForAcceptSole, 
   20.58 +    Grouped, 
   20.59 +    GroupWaiting, 
   20.60 +    GroupedBeaconed, 
   20.61 +    HandshakingGrouped, 
   20.62 +    WaitForGroupKeysGrouped, 
   20.63 +    WaitForAcceptGrouped
   20.64 +} DeviceState_state;
   20.65 +
   20.66 +// events
   20.67 +
   20.68 +typedef enum _DeviceState_event {
   20.69 +    DeviceState_event_NONE = 0,
   20.70 +    Init = 1,
   20.71 +    Beacon = 2,
   20.72 +    HandshakeRequest = 3,
   20.73 +    GroupKeys = 4,
   20.74 +    KeyGen, 
   20.75 +    CannotDecrypt, 
   20.76 +    Timeout, 
   20.77 +    HandshakeRejected, 
   20.78 +    HandshakeAccepted, 
   20.79 +    Cancel, 
   20.80 +    UpdateRequest, 
   20.81 +    GroupUpdate
   20.82 +} DeviceState_event;
   20.83 +
   20.84 +// actions
   20.85 +
   20.86 +PEP_STATUS sendBeacon(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.87 +PEP_STATUS sendHandshakeRequest(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.88 +PEP_STATUS notifyInitFormGroup(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.89 +PEP_STATUS notifyInitAddOurDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.90 +PEP_STATUS rejectHandshake(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.91 +PEP_STATUS acceptHandshake(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.92 +PEP_STATUS makeGroup(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.93 +PEP_STATUS sendGroupKeys(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.94 +PEP_STATUS renewUUID(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.95 +PEP_STATUS notifyAcceptedGroupCreated(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.96 +PEP_STATUS notifyTimeout(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.97 +PEP_STATUS storeGroupKeys(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.98 +PEP_STATUS sendGroupUpdate(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   20.99 +PEP_STATUS notifyAcceptedDeviceAdded(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.100 +PEP_STATUS sendUpdateRequest(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.101 +PEP_STATUS storeGroupUpdate(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.102 +PEP_STATUS notifyInitAddOtherDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.103 +PEP_STATUS notifyInitMoveOurDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.104 +PEP_STATUS notifyOvertaken(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.105 +PEP_STATUS notifyAcceptedDeviceMoved(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
  20.106 +
  20.107 +// event injector
  20.108 +
  20.109 +PEP_STATUS inject_DeviceState_event(
  20.110 +    PEP_SESSION session, 
  20.111 +    DeviceState_event event,
  20.112 +    Identity partner,
  20.113 +    void *extra);
  20.114 +
  20.115 +// message receiver
  20.116 +
  20.117 +PEP_STATUS receive_DeviceState_msg(
  20.118 +        PEP_SESSION session, 
  20.119 +        message *src, 
  20.120 +        PEP_rating rating, 
  20.121 +        stringlist_t *keylist
  20.122 +    );
  20.123 +
  20.124 +// state machine
  20.125 +
  20.126 +DeviceState_state fsm_DeviceState(
  20.127 +        PEP_SESSION session,
  20.128 +        DeviceState_state state,
  20.129 +        DeviceState_event event,
  20.130 +        Identity partner,
  20.131 +        void *extra,
  20.132 +        time_t *timeout
  20.133 +    );
  20.134 +
  20.135 +// driver
  20.136 +
  20.137 +DYNAMIC_API PEP_STATUS fsm_DeviceState_inject(
  20.138 +        PEP_SESSION session,
  20.139 +        DeviceState_event event,
  20.140 +        Identity partner,
  20.141 +        void *extra,
  20.142 +        time_t *timeout
  20.143 +    );
  20.144 +
  20.145 +#ifdef __cplusplus
  20.146 +}
  20.147 +#endif
  20.148 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/sync/generated/sync_send_actions.c	Fri Nov 03 13:32:38 2017 +0100
    21.3 @@ -0,0 +1,521 @@
    21.4 +// Send Actions for DeviceState state machine
    21.5 +
    21.6 +#include <assert.h>
    21.7 +#include "pEp_internal.h"
    21.8 +#include "keymanagement.h"
    21.9 +#include "message.h"
   21.10 +#include "sync_fsm.h"
   21.11 +#include "baseprotocol.h"
   21.12 +#include "map_asn1.h"
   21.13 +#include "../asn.1/DeviceGroup-Protocol.h"
   21.14 +#include "sync_impl.h"
   21.15 +#include "../asn.1/Beacon.h"
   21.16 +#include "../asn.1/HandshakeRequest.h"
   21.17 +#include "../asn.1/GroupKeys.h"
   21.18 +#include "../asn.1/GroupUpdate.h"
   21.19 +#include "../asn.1/UpdateRequest.h"
   21.20 +
   21.21 +
   21.22 +// sendBeacon() - send Beacon message
   21.23 +//
   21.24 +//  params:
   21.25 +//      session (in)        session handle
   21.26 +//      state (in)          state the state machine is in
   21.27 +//      partner (in)        (must be NULL)
   21.28 +//
   21.29 +//  returns:
   21.30 +//      PEP_STATUS_OK or any other value on error
   21.31 +
   21.32 +PEP_STATUS sendBeacon(
   21.33 +        PEP_SESSION session,
   21.34 +        DeviceState_state state,
   21.35 +        Identity partner,
   21.36 +        void *extra
   21.37 +    )
   21.38 +{
   21.39 +    assert(session && state);
   21.40 +    if (!(session && state))
   21.41 +        return PEP_ILLEGAL_VALUE;
   21.42 +
   21.43 +    PEP_STATUS status = PEP_STATUS_OK;
   21.44 +
   21.45 +    DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_beacon);
   21.46 +    if (!msg)
   21.47 +        goto enomem;
   21.48 +
   21.49 +    bool encrypted = false;
   21.50 +    status = multicast_self_msg(session, state, msg, encrypted);
   21.51 +    if (status != PEP_STATUS_OK)
   21.52 +        goto error;
   21.53 +
   21.54 +    free_DeviceGroup_Protocol_msg(msg);
   21.55 +    return PEP_STATUS_OK;
   21.56 +
   21.57 +enomem:
   21.58 +    status = PEP_OUT_OF_MEMORY;
   21.59 +error:
   21.60 +    free_DeviceGroup_Protocol_msg(msg);
   21.61 +    return status;
   21.62 +}
   21.63 +
   21.64 +
   21.65 +// sendHandshakeRequest() - send HandshakeRequest message
   21.66 +//
   21.67 +//  params:
   21.68 +//      session (in)        session handle
   21.69 +//      state (in)          state the state machine is in
   21.70 +//      partner (in)        partner to communicate with
   21.71 +//
   21.72 +//  returns:
   21.73 +//      PEP_STATUS_OK or any other value on error
   21.74 +
   21.75 +PEP_STATUS sendHandshakeRequest(
   21.76 +        PEP_SESSION session,
   21.77 +        DeviceState_state state,
   21.78 +        Identity partner,
   21.79 +        void *extra
   21.80 +    )
   21.81 +{
   21.82 +    assert(session && state);
   21.83 +    if (!(session && state))
   21.84 +        return PEP_ILLEGAL_VALUE;
   21.85 +
   21.86 +    PEP_STATUS status = PEP_STATUS_OK;
   21.87 +
   21.88 +    DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_handshakeRequest);
   21.89 +    if (!msg)
   21.90 +        goto enomem;
   21.91 +
   21.92 +    msg->payload.choice.handshakeRequest.partner_id = 
   21.93 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
   21.94 +                                 partner->user_id, -1);
   21.95 +    if (partner->user_id && !msg->payload.choice.handshakeRequest.partner_id)
   21.96 +       goto enomem;
   21.97 +
   21.98 +    char *devgrp = NULL;
   21.99 +    status = get_device_group(session, &devgrp);
  21.100 +    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
  21.101 +    msg->payload.choice.handshakeRequest.group_id = 
  21.102 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
  21.103 +                                 devgrp, -1);
  21.104 +    free(devgrp);
  21.105 +    if (devgrp && !msg->payload.choice.handshakeRequest.partner_id)
  21.106 +       goto enomem;
  21.107 +
  21.108 +    bool encrypted = true;
  21.109 +    status = unicast_msg(session, partner, state, msg, encrypted);
  21.110 +    if (status != PEP_STATUS_OK)
  21.111 +        goto error;
  21.112 +
  21.113 +    free_DeviceGroup_Protocol_msg(msg);
  21.114 +    return PEP_STATUS_OK;
  21.115 +
  21.116 +enomem:
  21.117 +    status = PEP_OUT_OF_MEMORY;
  21.118 +error:
  21.119 +    free_DeviceGroup_Protocol_msg(msg);
  21.120 +    return status;
  21.121 +}
  21.122 +
  21.123 +
  21.124 +// sendGroupKeys() - send GroupKeys message
  21.125 +//
  21.126 +//  params:
  21.127 +//      session (in)        session handle
  21.128 +//      state (in)          state the state machine is in
  21.129 +//      partner (in)        partner to communicate with
  21.130 +//
  21.131 +//  returns:
  21.132 +//      PEP_STATUS_OK or any other value on error
  21.133 +
  21.134 +PEP_STATUS sendGroupKeys(
  21.135 +        PEP_SESSION session,
  21.136 +        DeviceState_state state,
  21.137 +        Identity partner,
  21.138 +        void *extra
  21.139 +    )
  21.140 +{
  21.141 +    assert(session && state);
  21.142 +    if (!(session && state))
  21.143 +        return PEP_ILLEGAL_VALUE;
  21.144 +
  21.145 +    PEP_STATUS status = PEP_STATUS_OK;
  21.146 +    identity_list *kl = new_identity_list(NULL);
  21.147 +
  21.148 +    DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_groupKeys);
  21.149 +    if (!msg)
  21.150 +        goto enomem;
  21.151 +
  21.152 +    status = _own_identities_retrieve(session, &kl, PEP_idf_not_for_sync);
  21.153 +    if (status != PEP_STATUS_OK)
  21.154 +        goto error;
  21.155 +    if (IdentityList_from_identity_list(kl, &msg->payload.choice.groupKeys.ownIdentities) == NULL)
  21.156 +        goto enomem;
  21.157 +
  21.158 +    msg->payload.choice.groupKeys.partner_id = 
  21.159 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
  21.160 +                                 partner->user_id, -1);
  21.161 +    if (partner->user_id && !msg->payload.choice.groupKeys.partner_id)
  21.162 +       goto enomem;
  21.163 +
  21.164 +    char *devgrp = NULL;
  21.165 +    status = get_device_group(session, &devgrp);
  21.166 +    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
  21.167 +    msg->payload.choice.groupKeys.group_id = 
  21.168 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
  21.169 +                                 devgrp, -1);
  21.170 +    free(devgrp);
  21.171 +    if (devgrp && !msg->payload.choice.groupKeys.partner_id)
  21.172 +       goto enomem;
  21.173 +
  21.174 +    bool encrypted = true;
  21.175 +    status = unicast_msg(session, partner, state, msg, encrypted);
  21.176 +    if (status != PEP_STATUS_OK)
  21.177 +        goto error;
  21.178 +
  21.179 +    free_identity_list(kl);
  21.180 +    free_DeviceGroup_Protocol_msg(msg);
  21.181 +    return PEP_STATUS_OK;
  21.182 +
  21.183 +enomem:
  21.184 +    status = PEP_OUT_OF_MEMORY;
  21.185 +error:
  21.186 +    free_DeviceGroup_Protocol_msg(msg);
  21.187 +    free_identity_list(kl);
  21.188 +    return status;
  21.189 +}
  21.190 +
  21.191 +
  21.192 +// sendGroupUpdate() - send GroupUpdate message
  21.193 +//
  21.194 +//  params:
  21.195 +//      session (in)        session handle
  21.196 +//      state (in)          state the state machine is in
  21.197 +//      partner (in)        (must be NULL)
  21.198 +//
  21.199 +//  returns:
  21.200 +//      PEP_STATUS_OK or any other value on error
  21.201 +
  21.202 +PEP_STATUS sendGroupUpdate(
  21.203 +        PEP_SESSION session,
  21.204 +        DeviceState_state state,
  21.205 +        Identity partner,
  21.206 +        void *extra
  21.207 +    )
  21.208 +{
  21.209 +    assert(session && state);
  21.210 +    if (!(session && state))
  21.211 +        return PEP_ILLEGAL_VALUE;
  21.212 +
  21.213 +    PEP_STATUS status = PEP_STATUS_OK;
  21.214 +    identity_list *kl = new_identity_list(NULL);
  21.215 +
  21.216 +    DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_groupUpdate);
  21.217 +    if (!msg)
  21.218 +        goto enomem;
  21.219 +
  21.220 +    status = _own_identities_retrieve(session, &kl, PEP_idf_not_for_sync);
  21.221 +    if (status != PEP_STATUS_OK)
  21.222 +        goto error;
  21.223 +    if (IdentityList_from_identity_list(kl, &msg->payload.choice.groupUpdate.ownIdentities) == NULL)
  21.224 +        goto enomem;
  21.225 +
  21.226 +    bool encrypted = true;
  21.227 +    status = multicast_self_msg(session, state, msg, encrypted);
  21.228 +    if (status != PEP_STATUS_OK)
  21.229 +        goto error;
  21.230 +
  21.231 +    free_identity_list(kl);
  21.232 +    free_DeviceGroup_Protocol_msg(msg);
  21.233 +    return PEP_STATUS_OK;
  21.234 +
  21.235 +enomem:
  21.236 +    status = PEP_OUT_OF_MEMORY;
  21.237 +error:
  21.238 +    free_DeviceGroup_Protocol_msg(msg);
  21.239 +    return status;
  21.240 +}
  21.241 +
  21.242 +
  21.243 +// sendUpdateRequest() - send UpdateRequest message
  21.244 +//
  21.245 +//  params:
  21.246 +//      session (in)        session handle
  21.247 +//      state (in)          state the state machine is in
  21.248 +//      partner (in)        (must be NULL)
  21.249 +//
  21.250 +//  returns:
  21.251 +//      PEP_STATUS_OK or any other value on error
  21.252 +
  21.253 +PEP_STATUS sendUpdateRequest(
  21.254 +        PEP_SESSION session,
  21.255 +        DeviceState_state state,
  21.256 +        Identity partner,
  21.257 +        void *extra
  21.258 +    )
  21.259 +{
  21.260 +    assert(session && state);
  21.261 +    if (!(session && state))
  21.262 +        return PEP_ILLEGAL_VALUE;
  21.263 +
  21.264 +    PEP_STATUS status = PEP_STATUS_OK;
  21.265 +
  21.266 +    DeviceGroup_Protocol_t *msg = new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR_updateRequest);
  21.267 +    if (!msg)
  21.268 +        goto enomem;
  21.269 +
  21.270 +    bool encrypted = true;
  21.271 +    status = multicast_self_msg(session, state, msg, encrypted);
  21.272 +    if (status != PEP_STATUS_OK)
  21.273 +        goto error;
  21.274 +
  21.275 +    free_DeviceGroup_Protocol_msg(msg);
  21.276 +    return PEP_STATUS_OK;
  21.277 +
  21.278 +enomem:
  21.279 +    status = PEP_OUT_OF_MEMORY;
  21.280 +error:
  21.281 +    free_DeviceGroup_Protocol_msg(msg);
  21.282 +    return status;
  21.283 +}
  21.284 +
  21.285 +
  21.286 +PEP_STATUS _notifyHandshake(
  21.287 +        PEP_SESSION session,
  21.288 +        Identity partner,
  21.289 +        sync_handshake_signal signal
  21.290 +    );
  21.291 +
  21.292 +// notifyInitFormGroup() - notify InitFormGroup to app
  21.293 +//
  21.294 +//  params:
  21.295 +//      session (in)        session handle
  21.296 +//      state (in)          state the state machine is in
  21.297 +//      partner (in)        partner to communicate with
  21.298 +//
  21.299 +//  returns:
  21.300 +//      PEP_STATUS_OK or any other value on error
  21.301 +
  21.302 +PEP_STATUS notifyInitFormGroup(
  21.303 +        PEP_SESSION session,
  21.304 +        DeviceState_state state,
  21.305 +        Identity partner,
  21.306 +        void *extra
  21.307 +    )
  21.308 +{
  21.309 +    assert(session && state);
  21.310 +    assert(extra == NULL);
  21.311 +    if (!(session && state && extra == NULL))
  21.312 +        return PEP_ILLEGAL_VALUE;
  21.313 +
  21.314 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_FORM_GROUP);
  21.315 +}
  21.316 +
  21.317 +
  21.318 +// notifyInitAddOurDevice() - notify InitAddOurDevice to app
  21.319 +//
  21.320 +//  params:
  21.321 +//      session (in)        session handle
  21.322 +//      state (in)          state the state machine is in
  21.323 +//      partner (in)        partner to communicate with
  21.324 +//
  21.325 +//  returns:
  21.326 +//      PEP_STATUS_OK or any other value on error
  21.327 +
  21.328 +PEP_STATUS notifyInitAddOurDevice(
  21.329 +        PEP_SESSION session,
  21.330 +        DeviceState_state state,
  21.331 +        Identity partner,
  21.332 +        void *extra
  21.333 +    )
  21.334 +{
  21.335 +    assert(session && state);
  21.336 +    assert(extra == NULL);
  21.337 +    if (!(session && state && extra == NULL))
  21.338 +        return PEP_ILLEGAL_VALUE;
  21.339 +
  21.340 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_ADD_OUR_DEVICE);
  21.341 +}
  21.342 +
  21.343 +
  21.344 +// notifyAcceptedGroupCreated() - notify AcceptedGroupCreated to app
  21.345 +//
  21.346 +//  params:
  21.347 +//      session (in)        session handle
  21.348 +//      state (in)          state the state machine is in
  21.349 +//      partner (in)        partner to communicate with
  21.350 +//
  21.351 +//  returns:
  21.352 +//      PEP_STATUS_OK or any other value on error
  21.353 +
  21.354 +PEP_STATUS notifyAcceptedGroupCreated(
  21.355 +        PEP_SESSION session,
  21.356 +        DeviceState_state state,
  21.357 +        Identity partner,
  21.358 +        void *extra
  21.359 +    )
  21.360 +{
  21.361 +    assert(session && state);
  21.362 +    assert(extra == NULL);
  21.363 +    if (!(session && state && extra == NULL))
  21.364 +        return PEP_ILLEGAL_VALUE;
  21.365 +
  21.366 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_ACCEPTED_GROUP_CREATED);
  21.367 +}
  21.368 +
  21.369 +
  21.370 +// notifyTimeout() - notify Timeout to app
  21.371 +//
  21.372 +//  params:
  21.373 +//      session (in)        session handle
  21.374 +//      state (in)          state the state machine is in
  21.375 +//      partner (in)        partner to communicate with
  21.376 +//
  21.377 +//  returns:
  21.378 +//      PEP_STATUS_OK or any other value on error
  21.379 +
  21.380 +PEP_STATUS notifyTimeout(
  21.381 +        PEP_SESSION session,
  21.382 +        DeviceState_state state,
  21.383 +        Identity partner,
  21.384 +        void *extra
  21.385 +    )
  21.386 +{
  21.387 +    assert(session && state);
  21.388 +    assert(extra == NULL);
  21.389 +    if (!(session && state && extra == NULL))
  21.390 +        return PEP_ILLEGAL_VALUE;
  21.391 +
  21.392 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_TIMEOUT);
  21.393 +}
  21.394 +
  21.395 +
  21.396 +// notifyAcceptedDeviceAdded() - notify AcceptedDeviceAdded to app
  21.397 +//
  21.398 +//  params:
  21.399 +//      session (in)        session handle
  21.400 +//      state (in)          state the state machine is in
  21.401 +//      partner (in)        partner to communicate with
  21.402 +//
  21.403 +//  returns:
  21.404 +//      PEP_STATUS_OK or any other value on error
  21.405 +
  21.406 +PEP_STATUS notifyAcceptedDeviceAdded(
  21.407 +        PEP_SESSION session,
  21.408 +        DeviceState_state state,
  21.409 +        Identity partner,
  21.410 +        void *extra
  21.411 +    )
  21.412 +{
  21.413 +    assert(session && state);
  21.414 +    assert(extra == NULL);
  21.415 +    if (!(session && state && extra == NULL))
  21.416 +        return PEP_ILLEGAL_VALUE;
  21.417 +
  21.418 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED);
  21.419 +}
  21.420 +
  21.421 +
  21.422 +// notifyInitAddOtherDevice() - notify InitAddOtherDevice to app
  21.423 +//
  21.424 +//  params:
  21.425 +//      session (in)        session handle
  21.426 +//      state (in)          state the state machine is in
  21.427 +//      partner (in)        partner to communicate with
  21.428 +//
  21.429 +//  returns:
  21.430 +//      PEP_STATUS_OK or any other value on error
  21.431 +
  21.432 +PEP_STATUS notifyInitAddOtherDevice(
  21.433 +        PEP_SESSION session,
  21.434 +        DeviceState_state state,
  21.435 +        Identity partner,
  21.436 +        void *extra
  21.437 +    )
  21.438 +{
  21.439 +    assert(session && state);
  21.440 +    assert(extra == NULL);
  21.441 +    if (!(session && state && extra == NULL))
  21.442 +        return PEP_ILLEGAL_VALUE;
  21.443 +
  21.444 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE);
  21.445 +}
  21.446 +
  21.447 +
  21.448 +// notifyInitMoveOurDevice() - notify InitMoveOurDevice to app
  21.449 +//
  21.450 +//  params:
  21.451 +//      session (in)        session handle
  21.452 +//      state (in)          state the state machine is in
  21.453 +//      partner (in)        partner to communicate with
  21.454 +//
  21.455 +//  returns:
  21.456 +//      PEP_STATUS_OK or any other value on error
  21.457 +
  21.458 +PEP_STATUS notifyInitMoveOurDevice(
  21.459 +        PEP_SESSION session,
  21.460 +        DeviceState_state state,
  21.461 +        Identity partner,
  21.462 +        void *extra
  21.463 +    )
  21.464 +{
  21.465 +    assert(session && state);
  21.466 +    assert(extra == NULL);
  21.467 +    if (!(session && state && extra == NULL))
  21.468 +        return PEP_ILLEGAL_VALUE;
  21.469 +
  21.470 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE);
  21.471 +}
  21.472 +
  21.473 +
  21.474 +// notifyOvertaken() - notify Overtaken to app
  21.475 +//
  21.476 +//  params:
  21.477 +//      session (in)        session handle
  21.478 +//      state (in)          state the state machine is in
  21.479 +//      partner (in)        partner to communicate with
  21.480 +//
  21.481 +//  returns:
  21.482 +//      PEP_STATUS_OK or any other value on error
  21.483 +
  21.484 +PEP_STATUS notifyOvertaken(
  21.485 +        PEP_SESSION session,
  21.486 +        DeviceState_state state,
  21.487 +        Identity partner,
  21.488 +        void *extra
  21.489 +    )
  21.490 +{
  21.491 +    assert(session && state);
  21.492 +    assert(extra == NULL);
  21.493 +    if (!(session && state && extra == NULL))
  21.494 +        return PEP_ILLEGAL_VALUE;
  21.495 +
  21.496 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_OVERTAKEN);
  21.497 +}
  21.498 +
  21.499 +
  21.500 +// notifyAcceptedDeviceMoved() - notify AcceptedDeviceMoved to app
  21.501 +//
  21.502 +//  params:
  21.503 +//      session (in)        session handle
  21.504 +//      state (in)          state the state machine is in
  21.505 +//      partner (in)        partner to communicate with
  21.506 +//
  21.507 +//  returns:
  21.508 +//      PEP_STATUS_OK or any other value on error
  21.509 +
  21.510 +PEP_STATUS notifyAcceptedDeviceMoved(
  21.511 +        PEP_SESSION session,
  21.512 +        DeviceState_state state,
  21.513 +        Identity partner,
  21.514 +        void *extra
  21.515 +    )
  21.516 +{
  21.517 +    assert(session && state);
  21.518 +    assert(extra == NULL);
  21.519 +    if (!(session && state && extra == NULL))
  21.520 +        return PEP_ILLEGAL_VALUE;
  21.521 +
  21.522 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED);
  21.523 +}
  21.524 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/sync/skeletons/sync_actions.c	Fri Nov 03 13:32:38 2017 +0100
    22.3 @@ -0,0 +1,564 @@
    22.4 +// Actions for DeviceState state machine
    22.5 +
    22.6 +#include <assert.h>
    22.7 +#include "pEp_internal.h"
    22.8 +#include "keymanagement.h"
    22.9 +#include "message.h"
   22.10 +#include "sync_fsm.h"
   22.11 +#include "../asn.1/DeviceGroup-Protocol.h"
   22.12 +
   22.13 +
   22.14 +// notifyInitFormGroup() - 
   22.15 +//
   22.16 +//  params:
   22.17 +//      session (in)        session handle
   22.18 +//      state (in)          state the state machine is in
   22.19 +//      partner (in)        partner to communicate with
   22.20 +//
   22.21 +//  returns:
   22.22 +//      PEP_STATUS_OK or any other value on error
   22.23 +
   22.24 +PEP_STATUS notifyInitFormGroup(
   22.25 +        PEP_SESSION session,
   22.26 +        DeviceState_state state,
   22.27 +        Identity partner,
   22.28 +        void *extra
   22.29 +    )
   22.30 +{
   22.31 +    PEP_STATUS status = PEP_STATUS_OK;
   22.32 +
   22.33 +    assert(session);
   22.34 +    assert(!partner);
   22.35 +    if (!(session && !partner))
   22.36 +        return PEP_ILLEGAL_VALUE;
   22.37 +
   22.38 +    // working code
   22.39 +
   22.40 +    // free extra
   22.41 +    return status;
   22.42 +
   22.43 +enomem:
   22.44 +    status = PEP_OUT_OF_MEMORY;
   22.45 +error:
   22.46 +    // free extra
   22.47 +    return status;
   22.48 +}
   22.49 +
   22.50 +
   22.51 +// notifyInitAddOurDevice() - 
   22.52 +//
   22.53 +//  params:
   22.54 +//      session (in)        session handle
   22.55 +//      state (in)          state the state machine is in
   22.56 +//      partner (in)        partner to communicate with
   22.57 +//
   22.58 +//  returns:
   22.59 +//      PEP_STATUS_OK or any other value on error
   22.60 +
   22.61 +PEP_STATUS notifyInitAddOurDevice(
   22.62 +        PEP_SESSION session,
   22.63 +        DeviceState_state state,
   22.64 +        Identity partner,
   22.65 +        void *extra
   22.66 +    )
   22.67 +{
   22.68 +    PEP_STATUS status = PEP_STATUS_OK;
   22.69 +
   22.70 +    assert(session);
   22.71 +    assert(!partner);
   22.72 +    if (!(session && !partner))
   22.73 +        return PEP_ILLEGAL_VALUE;
   22.74 +
   22.75 +    // working code
   22.76 +
   22.77 +    // free extra
   22.78 +    return status;
   22.79 +
   22.80 +enomem:
   22.81 +    status = PEP_OUT_OF_MEMORY;
   22.82 +error:
   22.83 +    // free extra
   22.84 +    return status;
   22.85 +}
   22.86 +
   22.87 +
   22.88 +// rejectHandshake() - 
   22.89 +//
   22.90 +//  params:
   22.91 +//      session (in)        session handle
   22.92 +//      state (in)          state the state machine is in
   22.93 +//      partner (in)        partner to communicate with
   22.94 +//
   22.95 +//  returns:
   22.96 +//      PEP_STATUS_OK or any other value on error
   22.97 +
   22.98 +PEP_STATUS rejectHandshake(
   22.99 +        PEP_SESSION session,
  22.100 +        DeviceState_state state,
  22.101 +        Identity partner,
  22.102 +        void *extra
  22.103 +    )
  22.104 +{
  22.105 +    PEP_STATUS status = PEP_STATUS_OK;
  22.106 +
  22.107 +    assert(session);
  22.108 +    assert(partner);
  22.109 +    if (!(session && partner))
  22.110 +        return PEP_ILLEGAL_VALUE;
  22.111 +
  22.112 +    // working code
  22.113 +
  22.114 +    // free extra
  22.115 +    return status;
  22.116 +
  22.117 +enomem:
  22.118 +    status = PEP_OUT_OF_MEMORY;
  22.119 +error:
  22.120 +    // free extra
  22.121 +    return status;
  22.122 +}
  22.123 +
  22.124 +
  22.125 +// acceptHandshake() - 
  22.126 +//
  22.127 +//  params:
  22.128 +//      session (in)        session handle
  22.129 +//      state (in)          state the state machine is in
  22.130 +//      partner (in)        partner to communicate with
  22.131 +//
  22.132 +//  returns:
  22.133 +//      PEP_STATUS_OK or any other value on error
  22.134 +
  22.135 +PEP_STATUS acceptHandshake(
  22.136 +        PEP_SESSION session,
  22.137 +        DeviceState_state state,
  22.138 +        Identity partner,
  22.139 +        void *extra
  22.140 +    )
  22.141 +{
  22.142 +    PEP_STATUS status = PEP_STATUS_OK;
  22.143 +
  22.144 +    assert(session);
  22.145 +    assert(partner);
  22.146 +    if (!(session && partner))
  22.147 +        return PEP_ILLEGAL_VALUE;
  22.148 +
  22.149 +    // working code
  22.150 +
  22.151 +    // free extra
  22.152 +    return status;
  22.153 +
  22.154 +enomem:
  22.155 +    status = PEP_OUT_OF_MEMORY;
  22.156 +error:
  22.157 +    // free extra
  22.158 +    return status;
  22.159 +}
  22.160 +
  22.161 +
  22.162 +// makeGroup() - 
  22.163 +//
  22.164 +//  params:
  22.165 +//      session (in)        session handle
  22.166 +//      state (in)          state the state machine is in
  22.167 +//      partner (in)        (must be NULL)
  22.168 +//
  22.169 +//  returns:
  22.170 +//      PEP_STATUS_OK or any other value on error
  22.171 +
  22.172 +PEP_STATUS makeGroup(
  22.173 +        PEP_SESSION session,
  22.174 +        DeviceState_state state,
  22.175 +        Identity partner,
  22.176 +        void *extra
  22.177 +    )
  22.178 +{
  22.179 +    PEP_STATUS status = PEP_STATUS_OK;
  22.180 +
  22.181 +    assert(session);
  22.182 +    assert(!partner);
  22.183 +    if (!(session && !partner))
  22.184 +        return PEP_ILLEGAL_VALUE;
  22.185 +
  22.186 +    // working code
  22.187 +
  22.188 +    // free extra
  22.189 +    return status;
  22.190 +
  22.191 +enomem:
  22.192 +    status = PEP_OUT_OF_MEMORY;
  22.193 +error:
  22.194 +    // free extra
  22.195 +    return status;
  22.196 +}
  22.197 +
  22.198 +
  22.199 +// renewUUID() - 
  22.200 +//
  22.201 +//  params:
  22.202 +//      session (in)        session handle
  22.203 +//      state (in)          state the state machine is in
  22.204 +//      partner (in)        (must be NULL)
  22.205 +//
  22.206 +//  returns:
  22.207 +//      PEP_STATUS_OK or any other value on error
  22.208 +
  22.209 +PEP_STATUS renewUUID(
  22.210 +        PEP_SESSION session,
  22.211 +        DeviceState_state state,
  22.212 +        Identity partner,
  22.213 +        void *extra
  22.214 +    )
  22.215 +{
  22.216 +    PEP_STATUS status = PEP_STATUS_OK;
  22.217 +
  22.218 +    assert(session);
  22.219 +    assert(!partner);
  22.220 +    if (!(session && !partner))
  22.221 +        return PEP_ILLEGAL_VALUE;
  22.222 +
  22.223 +    // working code
  22.224 +
  22.225 +    // free extra
  22.226 +    return status;
  22.227 +
  22.228 +enomem:
  22.229 +    status = PEP_OUT_OF_MEMORY;
  22.230 +error:
  22.231 +    // free extra
  22.232 +    return status;
  22.233 +}
  22.234 +
  22.235 +
  22.236 +// notifyAcceptedGroupCreated() - 
  22.237 +//
  22.238 +//  params:
  22.239 +//      session (in)        session handle
  22.240 +//      state (in)          state the state machine is in
  22.241 +//      partner (in)        partner to communicate with
  22.242 +//
  22.243 +//  returns:
  22.244 +//      PEP_STATUS_OK or any other value on error
  22.245 +
  22.246 +PEP_STATUS notifyAcceptedGroupCreated(
  22.247 +        PEP_SESSION session,
  22.248 +        DeviceState_state state,
  22.249 +        Identity partner,
  22.250 +        void *extra
  22.251 +    )
  22.252 +{
  22.253 +    PEP_STATUS status = PEP_STATUS_OK;
  22.254 +
  22.255 +    assert(session);
  22.256 +    assert(partner);
  22.257 +    if (!(session && partner))
  22.258 +        return PEP_ILLEGAL_VALUE;
  22.259 +
  22.260 +    // working code
  22.261 +
  22.262 +    // free extra
  22.263 +    return status;
  22.264 +
  22.265 +enomem:
  22.266 +    status = PEP_OUT_OF_MEMORY;
  22.267 +error:
  22.268 +    // free extra
  22.269 +    return status;
  22.270 +}
  22.271 +
  22.272 +
  22.273 +// notifyTimeout() - 
  22.274 +//
  22.275 +//  params:
  22.276 +//      session (in)        session handle
  22.277 +//      state (in)          state the state machine is in
  22.278 +//      partner (in)        partner to communicate with
  22.279 +//
  22.280 +//  returns:
  22.281 +//      PEP_STATUS_OK or any other value on error
  22.282 +
  22.283 +PEP_STATUS notifyTimeout(
  22.284 +        PEP_SESSION session,
  22.285 +        DeviceState_state state,
  22.286 +        Identity partner,
  22.287 +        void *extra
  22.288 +    )
  22.289 +{
  22.290 +    PEP_STATUS status = PEP_STATUS_OK;
  22.291 +
  22.292 +    assert(session);
  22.293 +    assert(!partner);
  22.294 +    if (!(session && !partner))
  22.295 +        return PEP_ILLEGAL_VALUE;
  22.296 +
  22.297 +    // working code
  22.298 +
  22.299 +    // free extra
  22.300 +    return status;
  22.301 +
  22.302 +enomem:
  22.303 +    status = PEP_OUT_OF_MEMORY;
  22.304 +error:
  22.305 +    // free extra
  22.306 +    return status;
  22.307 +}
  22.308 +
  22.309 +
  22.310 +// storeGroupKeys() - 
  22.311 +//
  22.312 +//  params:
  22.313 +//      session (in)        session handle
  22.314 +//      state (in)          state the state machine is in
  22.315 +//      partner (in)        partner to communicate with
  22.316 +//
  22.317 +//  returns:
  22.318 +//      PEP_STATUS_OK or any other value on error
  22.319 +
  22.320 +PEP_STATUS storeGroupKeys(
  22.321 +        PEP_SESSION session,
  22.322 +        DeviceState_state state,
  22.323 +        Identity partner,
  22.324 +        void *extra
  22.325 +    )
  22.326 +{
  22.327 +    PEP_STATUS status = PEP_STATUS_OK;
  22.328 +
  22.329 +    assert(session);
  22.330 +    assert(partner);
  22.331 +    if (!(session && partner))
  22.332 +        return PEP_ILLEGAL_VALUE;
  22.333 +
  22.334 +    // working code
  22.335 +
  22.336 +    // free extra
  22.337 +    return status;
  22.338 +
  22.339 +enomem:
  22.340 +    status = PEP_OUT_OF_MEMORY;
  22.341 +error:
  22.342 +    // free extra
  22.343 +    return status;
  22.344 +}
  22.345 +
  22.346 +
  22.347 +// notifyAcceptedDeviceAdded() - 
  22.348 +//
  22.349 +//  params:
  22.350 +//      session (in)        session handle
  22.351 +//      state (in)          state the state machine is in
  22.352 +//      partner (in)        partner to communicate with
  22.353 +//
  22.354 +//  returns:
  22.355 +//      PEP_STATUS_OK or any other value on error
  22.356 +
  22.357 +PEP_STATUS notifyAcceptedDeviceAdded(
  22.358 +        PEP_SESSION session,
  22.359 +        DeviceState_state state,
  22.360 +        Identity partner,
  22.361 +        void *extra
  22.362 +    )
  22.363 +{
  22.364 +    PEP_STATUS status = PEP_STATUS_OK;
  22.365 +
  22.366 +    assert(session);
  22.367 +    assert(partner);
  22.368 +    if (!(session && partner))
  22.369 +        return PEP_ILLEGAL_VALUE;
  22.370 +
  22.371 +    // working code
  22.372 +
  22.373 +    // free extra
  22.374 +    return status;
  22.375 +
  22.376 +enomem:
  22.377 +    status = PEP_OUT_OF_MEMORY;
  22.378 +error:
  22.379 +    // free extra
  22.380 +    return status;
  22.381 +}
  22.382 +
  22.383 +
  22.384 +// storeGroupUpdate() - 
  22.385 +//
  22.386 +//  params:
  22.387 +//      session (in)        session handle
  22.388 +//      state (in)          state the state machine is in
  22.389 +//      partner (in)        partner to communicate with
  22.390 +//
  22.391 +//  returns:
  22.392 +//      PEP_STATUS_OK or any other value on error
  22.393 +
  22.394 +PEP_STATUS storeGroupUpdate(
  22.395 +        PEP_SESSION session,
  22.396 +        DeviceState_state state,
  22.397 +        Identity partner,
  22.398 +        void *extra
  22.399 +    )
  22.400 +{
  22.401 +    PEP_STATUS status = PEP_STATUS_OK;
  22.402 +
  22.403 +    assert(session);
  22.404 +    assert(partner);
  22.405 +    if (!(session && partner))
  22.406 +        return PEP_ILLEGAL_VALUE;
  22.407 +
  22.408 +    // working code
  22.409 +
  22.410 +    // free extra
  22.411 +    return status;
  22.412 +
  22.413 +enomem:
  22.414 +    status = PEP_OUT_OF_MEMORY;
  22.415 +error:
  22.416 +    // free extra
  22.417 +    return status;
  22.418 +}
  22.419 +
  22.420 +
  22.421 +// notifyInitAddOtherDevice() - 
  22.422 +//
  22.423 +//  params:
  22.424 +//      session (in)        session handle
  22.425 +//      state (in)          state the state machine is in
  22.426 +//      partner (in)        partner to communicate with
  22.427 +//
  22.428 +//  returns:
  22.429 +//      PEP_STATUS_OK or any other value on error
  22.430 +
  22.431 +PEP_STATUS notifyInitAddOtherDevice(
  22.432 +        PEP_SESSION session,
  22.433 +        DeviceState_state state,
  22.434 +        Identity partner,
  22.435 +        void *extra
  22.436 +    )
  22.437 +{
  22.438 +    PEP_STATUS status = PEP_STATUS_OK;
  22.439 +
  22.440 +    assert(session);
  22.441 +    assert(partner);
  22.442 +    if (!(session && partner))
  22.443 +        return PEP_ILLEGAL_VALUE;
  22.444 +
  22.445 +    // working code
  22.446 +
  22.447 +    // free extra
  22.448 +    return status;
  22.449 +
  22.450 +enomem:
  22.451 +    status = PEP_OUT_OF_MEMORY;
  22.452 +error:
  22.453 +    // free extra
  22.454 +    return status;
  22.455 +}
  22.456 +
  22.457 +
  22.458 +// notifyInitMoveOurDevice() - 
  22.459 +//
  22.460 +//  params:
  22.461 +//      session (in)        session handle
  22.462 +//      state (in)          state the state machine is in
  22.463 +//      partner (in)        partner to communicate with
  22.464 +//
  22.465 +//  returns:
  22.466 +//      PEP_STATUS_OK or any other value on error
  22.467 +
  22.468 +PEP_STATUS notifyInitMoveOurDevice(
  22.469 +        PEP_SESSION session,
  22.470 +        DeviceState_state state,
  22.471 +        Identity partner,
  22.472 +        void *extra
  22.473 +    )
  22.474 +{
  22.475 +    PEP_STATUS status = PEP_STATUS_OK;
  22.476 +
  22.477 +    assert(session);
  22.478 +    assert(partner);
  22.479 +    if (!(session && partner))
  22.480 +        return PEP_ILLEGAL_VALUE;
  22.481 +
  22.482 +    // working code
  22.483 +
  22.484 +    // free extra
  22.485 +    return status;
  22.486 +
  22.487 +enomem:
  22.488 +    status = PEP_OUT_OF_MEMORY;
  22.489 +error:
  22.490 +    // free extra
  22.491 +    return status;
  22.492 +}
  22.493 +
  22.494 +
  22.495 +// notifyOvertaken() - 
  22.496 +//
  22.497 +//  params:
  22.498 +//      session (in)        session handle
  22.499 +//      state (in)          state the state machine is in
  22.500 +//      partner (in)        partner to communicate with
  22.501 +//
  22.502 +//  returns:
  22.503 +//      PEP_STATUS_OK or any other value on error
  22.504 +
  22.505 +PEP_STATUS notifyOvertaken(
  22.506 +        PEP_SESSION session,
  22.507 +        DeviceState_state state,
  22.508 +        Identity partner,
  22.509 +        void *extra
  22.510 +    )
  22.511 +{
  22.512 +    PEP_STATUS status = PEP_STATUS_OK;
  22.513 +
  22.514 +    assert(session);
  22.515 +    assert(partner);
  22.516 +    if (!(session && partner))
  22.517 +        return PEP_ILLEGAL_VALUE;
  22.518 +
  22.519 +    // working code
  22.520 +
  22.521 +    // free extra
  22.522 +    return status;
  22.523 +
  22.524 +enomem:
  22.525 +    status = PEP_OUT_OF_MEMORY;
  22.526 +error:
  22.527 +    // free extra
  22.528 +    return status;
  22.529 +}
  22.530 +
  22.531 +
  22.532 +// notifyAcceptedDeviceMoved() - 
  22.533 +//
  22.534 +//  params:
  22.535 +//      session (in)        session handle
  22.536 +//      state (in)          state the state machine is in
  22.537 +//      partner (in)        partner to communicate with
  22.538 +//
  22.539 +//  returns:
  22.540 +//      PEP_STATUS_OK or any other value on error
  22.541 +
  22.542 +PEP_STATUS notifyAcceptedDeviceMoved(
  22.543 +        PEP_SESSION session,
  22.544 +        DeviceState_state state,
  22.545 +        Identity partner,
  22.546 +        void *extra
  22.547 +    )
  22.548 +{
  22.549 +    PEP_STATUS status = PEP_STATUS_OK;
  22.550 +
  22.551 +    assert(session);
  22.552 +    assert(partner);
  22.553 +    if (!(session && partner))
  22.554 +        return PEP_ILLEGAL_VALUE;
  22.555 +
  22.556 +    // working code
  22.557 +
  22.558 +    // free extra
  22.559 +    return status;
  22.560 +
  22.561 +enomem:
  22.562 +    status = PEP_OUT_OF_MEMORY;
  22.563 +error:
  22.564 +    // free extra
  22.565 +    return status;
  22.566 +}
  22.567 +