src/sync.h
author Edouard Tisserant <edouard@pep-project.org>
Tue, 17 Jan 2017 10:30:10 +0100
changeset 1541 5f4d0eb0140d
parent 1538 28443c7edc0f
child 1547 6c7051a7f0d5
permissions -rw-r--r--
Avoid unicode is ascii diagrams
vb@1517
     1
// This file is under GNU General Public License 3.0
vb@1517
     2
// see LICENSE.txt
vb@1517
     3
vb@1471
     4
/*
vb@1471
     5
====================================
vb@1471
     6
Engine/adapter/app KeySync interface 
vb@1471
     7
====================================
vb@1471
     8
edouard@1538
     9
edouard@1538
    10
         Engine         |          Adapter            |          App
edouard@1538
    11
                        |                             |
edouard@1538
    12
 . . . . . . . . . . . .|. . . . . . . . . . . . . . .|. . Attached session .  
edouard@1538
    13
     ,---------,        |                             |
edouard@1538
    14
   ,-| decrypt |<--------------------------------------- Incomming message 
edouard@1538
    15
   | | message |        |                             |
edouard@1538
    16
   | '---------'        |                             |
edouard@1538
    17
   | ,----------,       |                             |
edouard@1538
    18
   |-| myself   |<-------------------------------------- Create new account
edouard@1538
    19
   | | (keygen) |       |                             |
edouard@1538
    20
   | '----------'       |                             |
edouard@1538
    21
   | ,-----------,      |                             |
edouard@1538
    22
   |-| deliver   |<------------------------------------------- Accept/reject
edouard@1538
    23
   | | handshake |      |                     KeySync |            handshake
edouard@1538
    24
   | | result    |      |                     Message |
edouard@1538
    25
   | '-----------'      |                      Queue  |
edouard@1538
    26
   |                    |                      ,---,  |
edouard@1538
    27
   '-----------------------inject_sync_msg---->|   |  |
edouard@1538
    28
 . . . . . . . . . . . .|. . . . . . . . . . . |---| .|. . . . Sync session .  
edouard@1541
    29
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *|   |* | 
edouard@1538
    30
                        |                      |---|  | 
edouard@1541
    31
 *   ,------------------retrieve_next_sync_msg-|   |* | 
edouard@1538
    32
   ,-v--------,         |                      '---'  | 
edouard@1541
    33
 * | Driver   |         |                           * |
edouard@1538
    34
   '----------'         |                             |
edouard@1541
    35
 *  ||'-event-----,     |                           * |
edouard@1538
    36
    |'--partner--,|     |                             |
edouard@1541
    37
 *  '---extra---,||     |           SYNC THREAD     *<-------------- Start Sync
edouard@1538
    38
            ,---vvv---, |                             |
edouard@1541
    39
 *     ,----|   FSM   | |                           * |
edouard@1538
    40
       |    '---------' |                             |
edouard@1541
    41
 *     |  ,-------,     |                           * |
edouard@1538
    42
       '->|actions|---------messageToSend-------------------> Send mail to self
edouard@1541
    43
 *        '-------'     |                           * |
edouard@1538
    44
              '-------------notifyHandshake-----------------> Ask for handshake
edouard@1541
    45
 *                      |                           * |    display group status
edouard@1538
    46
                        |                             |
edouard@1541
    47
 *  *  *  *  *  *  *  * |*  *  *  *  *  *  *  *  *  * |
edouard@1538
    48
                        |                             |
edouard@1538
    49
edouard@1538
    50
Emails to self
edouard@1538
    51
--------------
edouard@1538
    52
edouard@1538
    53
With e-mail as a transport KeySync message handling is done when an incoming 
edouard@1538
    54
email to self is passed to decrypt_message(), assuming that all incoming email
edouard@1538
    55
messages are passed to decrypt_massage(). 
edouard@1538
    56
edouard@1538
    57
In case of an email containing a KeySync paload, KeySync may consume or ignore
edouard@1538
    58
the message. decrypt_message() signals this to the app with decrypt flags
edouard@1538
    59
PEP_decrypt_flag_consume and PEP_decrypt_flag_ignore.
edouard@1538
    60
edouard@1538
    61
In case of PEP_decrypt_flag_consume, app should delete the message.
edouard@1538
    62
In case of PEP_decrypt_flag_ignore, app should ignore message.
edouard@1538
    63
In both cases, message should be hidden.
edouard@1538
    64
edouard@1538
    65
States, events, actions
edouard@1538
    66
-----------------------
edouard@1538
    67
edouard@1538
    68
In the engine, KeySync is implemented through a finite state machine (FSM) [1].
edouard@1538
    69
KeySync state machine is driven [2] by events, triggering actions [3] and
edouard@1538
    70
transitions to new states.
edouard@1538
    71
edouard@1538
    72
Events happen on :
edouard@1538
    73
edouard@1538
    74
 - decryption of email messages
edouard@1538
    75
edouard@1538
    76
 - key generation
edouard@1538
    77
edouard@1538
    78
 - user interaction through the app 
edouard@1538
    79
edouard@1538
    80
 - timeout when staying too long in some particular states.
edouard@1538
    81
edouard@1538
    82
[1] sync/devicegroup.fsm , src/sync_fsm.c (generated)
edouard@1538
    83
[2] src/sync_driver.c (generated)
edouard@1538
    84
[3] src/sync_actions.c , src/sync_send_actions.c (generated)
edouard@1538
    85
edouard@1538
    86
Sync session, attached sessions
edouard@1538
    87
-------------------------------
vb@1471
    88
vb@1471
    89
To use KeySync, the adapter has to create a session dedicated to handle the
vb@1471
    90
protocol, register some callbacks [4] to the engine, and then call protocol's
edouard@1538
    91
event consumer loop [5] in a dedicated thread. KeySync actions are executed as
edouard@1538
    92
callback invoked from that thread.
vb@1471
    93
edouard@1538
    94
When a session is attached [6] to a KeySync session, decryption of pEp email
edouard@1538
    95
messages in the attached session may trigger operations in KeySync session. In
vb@1471
    96
case of an adapter capable to serve multiple apps, each app is associated to a
vb@1471
    97
different KeySync session, and sessions created for use in that app are
vb@1471
    98
attached to that session.
vb@1471
    99
edouard@1538
   100
Adapters present different approaches regarding session and client abstraction,
edouard@1538
   101
and may not propose to explicitely create or attach session or sync session.
edouard@1538
   102
edouard@1538
   103
[4] register_sync_callbacks()
edouard@1538
   104
[5] do_sync_protocol()
edouard@1538
   105
[6] attach_sync_session()
edouard@1538
   106
edouard@1538
   107
KeySync Messages and queue
edouard@1538
   108
--------------------------
vb@1471
   109
edouard@1538
   110
KeySync messages [7], not to be confused with pEp (email) messages, are either
edouard@1538
   111
directly events to be processed by the state machine, or KeySync payloads
edouard@1538
   112
collected from decrypted messages. 
edouard@1538
   113
edouard@1538
   114
KeySync messages can be emitted by different sessions, and could naturally come
edouard@1538
   115
from different threads. They must be serialized in a locked queue. 
edouard@1538
   116
KeySync messages queue is implemented by adapter, along with thread handling
edouard@1538
   117
KeySync protocol. 
edouard@1538
   118
edouard@1538
   119
Attached sessions inject [8] KeySync messages in the queue. Protocol loop
edouard@1538
   120
retrieves [9] them from the queue. KeySync message is received [10] by the
edouard@1538
   121
state machine, where event, partner and extra parameters are eventually deduced
edouard@1538
   122
from payload.
vb@1471
   123
vb@1471
   124
A state timeout event is a particular case. It doesn't traverse the queue, and
vb@1471
   125
isn't emitted by a session. It is triggered by a timeout on the retrieve
vb@1471
   126
operation. Value of the timeout is determined when entering a new state, and is
vb@1471
   127
passed as a parameter of the call to the blocking queue retrieve operation on 
vb@1471
   128
next protocol loop iteraton.
vb@1471
   129
vb@1471
   130
[7] type sync_msg_t
vb@1471
   131
[8] callback inject_sync_msg
vb@1471
   132
[9] callback retrieve_next_sync_msg
vb@1471
   133
[10] receive_sync_msg() (src/sync_impl.c)
vb@1471
   134
edouard@1538
   135
Application callbacks
edouard@1538
   136
---------------------
edouard@1538
   137
edouard@1538
   138
Some Keysync actions require the application to act, through callbacks :
edouard@1538
   139
edouard@1538
   140
 - messageToSend : send pEp messages through app's transport. 
edouard@1538
   141
   Messages are already encrypted and just need to be passed as-is to
edouard@1538
   142
   transport for transmission, as for messages returned by encrypt_message().
edouard@1538
   143
edouard@1538
   144
 - notifyHandshake : display KeySync status and handshake to the user.
edouard@1538
   145
   notifyHandshake callback receives 2 identities, 'me' and 'partner', together
edouard@1538
   146
   with a sync_handshake_signal enum :
edouard@1538
   147
edouard@1538
   148
    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE :
edouard@1538
   149
        Device (me) is sole, about to enter a group (partner).
edouard@1538
   150
        App displays trustwords, and requests user accept or reject
edouard@1538
   151
        App calls deliverHandshakeResult with user's answer
edouard@1538
   152
edouard@1538
   153
    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE :
edouard@1538
   154
        Device (me) is grouped, another device (partner) wants to join group.
edouard@1538
   155
        App displays trustwords, and requests user accept or reject
edouard@1538
   156
        App calls deliverHandshakeResult with user's answer
edouard@1538
   157
edouard@1538
   158
    SYNC_NOTIFY_INIT_FORM_GROUP :
edouard@1538
   159
        Device (me) is forming a group, including another device (partner)
edouard@1538
   160
        App displays trustwords, and requests user accept or reject
edouard@1538
   161
        App calls deliverHandshakeResult with user's answer
edouard@1538
   162
edouard@1538
   163
    SYNC_NOTIFY_TIMEOUT :
edouard@1538
   164
        KeySync operation timed out.
edouard@1538
   165
        Identities are set reflecting peers involved in aborted operation.
edouard@1538
   166
        App displays error message. No feedback to engine.
edouard@1538
   167
edouard@1538
   168
    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
edouard@1538
   169
        New device was added to group.
edouard@1538
   170
        App displays message. No feedback to engine.
edouard@1538
   171
edouard@1538
   172
    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
edouard@1538
   173
        New group created.
edouard@1538
   174
        App displays message. No feedback to engine.
edouard@1538
   175
edouard@1538
   176
   To deliver handshake result back to engine once user reacted,
edouard@1538
   177
   deliver_handshake_result is used. Result can be :
edouard@1538
   178
edouard@1538
   179
    SYNC_HANDSHAKE_CANCEL
edouard@1538
   180
        Gives no answer. User doesn't know id TrustWord are good or bad.
edouard@1538
   181
        For example in case peering device is away.
edouard@1538
   182
        Handshake will re-appear later.
edouard@1538
   183
edouard@1538
   184
    SYNC_HANDSHAKE_ACCEPTED
edouard@1538
   185
        Trustwords match with other device and user accepts handshake.
edouard@1538
   186
edouard@1538
   187
    SYNC_HANDSHAKE_REJECTED
edouard@1538
   188
        Trustwords do not match with any device and user rejects handshake.
vb@1471
   189
*/
vb@1471
   190
vb@572
   191
#pragma once
vb@572
   192
vb@572
   193
#include "message.h"
vb@690
   194
#include "sync_fsm.h"
vb@572
   195
vb@1470
   196
vb@1470
   197
// this module is for being used WITHOUT the Transport API in transport.h
vb@1470
   198
// DO NOT USE IT WHEN USING Transport API!
vb@1470
   199
vb@1470
   200
vb@572
   201
#ifdef __cplusplus
vb@572
   202
extern "C" {
vb@572
   203
#endif
vb@572
   204
vb@1043
   205
// messageToSend() - send a message
vb@572
   206
//
vb@572
   207
//  parameters:
vb@599
   208
//      obj (in)        object handle (implementation defined)
vb@598
   209
//      msg (in)        message struct with message to send
vb@572
   210
//
vb@572
   211
//  return value:
vb@604
   212
//      PEP_STATUS_OK or any other value on error
vb@991
   213
//
vb@991
   214
//  caveat:
vb@991
   215
//      the ownership of msg goes to the callee
vb@572
   216
vb@991
   217
typedef PEP_STATUS (*messageToSend_t)(void *obj, message *msg);
vb@572
   218
edouard@1477
   219
// TODO add this to generated code.
edouard@1459
   220
typedef enum _sync_handshake_signal {
vb@1473
   221
    SYNC_NOTIFY_UNDEFINED = 0,
vb@1470
   222
vb@1470
   223
    // request show handshake dialog
vb@1473
   224
    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
vb@1473
   225
    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
vb@1473
   226
    SYNC_NOTIFY_INIT_FORM_GROUP,
vb@1470
   227
edouard@1477
   228
    // handshake process timed out
vb@1475
   229
    SYNC_NOTIFY_TIMEOUT,
vb@1470
   230
vb@1470
   231
    // handshake accepted by user
vb@1473
   232
    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
edouard@1477
   233
    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
vb@1470
   234
edouard@1459
   235
} sync_handshake_signal;
vb@572
   236
edouard@1459
   237
// notifyHandshake() - notify UI about sync handshaking process
vb@572
   238
//
vb@572
   239
//  parameters:
vb@599
   240
//      obj (in)        object handle (implementation defined)
vb@1003
   241
//      me (in)         own identity
vb@572
   242
//      partner (in)    identity of partner
edouard@1459
   243
//      signal (in)     reason of the notification
vb@572
   244
//
vb@572
   245
//  return value:
vb@604
   246
//      PEP_STATUS_OK or any other value on error
vb@991
   247
//
vb@991
   248
//  caveat:
vb@991
   249
//      ownership of self and partner go to the callee
vb@572
   250
edouard@1459
   251
typedef PEP_STATUS (*notifyHandshake_t)(
vb@599
   252
        void *obj,
vb@1003
   253
        pEp_identity *me,
edouard@1459
   254
        pEp_identity *partner,
edouard@1459
   255
        sync_handshake_signal signal
vb@609
   256
    );
vb@609
   257
edouard@1459
   258
typedef enum _sync_handshake_result {
edouard@1459
   259
    SYNC_HANDSHAKE_CANCEL = -1,
edouard@1459
   260
    SYNC_HANDSHAKE_ACCEPTED = 0,
edouard@1459
   261
    SYNC_HANDSHAKE_REJECTED = 1
edouard@1459
   262
} sync_handshake_result;
vb@609
   263
vb@609
   264
// deliverHandshakeResult() - give the result of the handshake dialog
vb@609
   265
//
vb@609
   266
//  parameters:
vb@1043
   267
//      session (in)        session handle
vb@1043
   268
//      result (in)         handshake result
vb@609
   269
vb@679
   270
DYNAMIC_API PEP_STATUS deliverHandshakeResult(
vb@609
   271
        PEP_SESSION session,
edouard@1160
   272
        Identity partner,
vb@609
   273
        sync_handshake_result result
vb@572
   274
    );
vb@572
   275
edouard@1172
   276
// sync_msg_t - items queued for serialized handling by protocol engine
edouard@1172
   277
typedef struct _sync_msg_t sync_msg_t;
vb@572
   278
vb@1043
   279
// inject_sync_msg - inject sync protocol message
vb@1043
   280
//
vb@1043
   281
//  parameters:
vb@1043
   282
//      msg (in)            message to inject
vb@1043
   283
//      management (in)     application defined
vb@1043
   284
//
vb@1043
   285
//  return value:
vb@1043
   286
//      0 if msg could be stored successfully or nonzero otherwise
vb@1043
   287
vb@1043
   288
typedef int (*inject_sync_msg_t)(void *msg, void *management);
vb@1043
   289
vb@1043
   290
vb@1470
   291
// retrieve_next_sync_msg - receive next sync message
vb@1043
   292
//
vb@1043
   293
//  parameters:
vb@1043
   294
//      management (in)     application defined
vb@1470
   295
//      timeout (in,out)    do not wait longer than timeout for message
vb@1043
   296
//
vb@1043
   297
//  return value:
edouard@1445
   298
//      next message or :
vb@1471
   299
//      NULL and timeout == 0 for termination
vb@1471
   300
//      NULL and timeout != 0 for timeout occurence
vb@1043
   301
edouard@1445
   302
typedef void *(*retrieve_next_sync_msg_t)(void *management, time_t *timeout);
vb@1043
   303
vb@1043
   304
vb@572
   305
// register_sync_callbacks() - register adapter's callbacks
vb@572
   306
//
vb@572
   307
//  parameters:
vb@599
   308
//      session (in)                session where to store obj handle
edouard@1462
   309
//      management (in)             application defined
vb@599
   310
//      messageToSend (in)          callback for sending message
edouard@1462
   311
//      notifyHandshake (in)        callback for doing the handshake
vb@1043
   312
//      retrieve_next_sync_msg (in) callback for receiving sync messages
vb@572
   313
//
vb@572
   314
//  return value:
vb@572
   315
//      PEP_STATUS_OK or any other value on errror
vb@573
   316
//
vb@573
   317
//  caveat:
vb@573
   318
//      call that BEFORE you're using any other part of the engine
vb@572
   319
vb@572
   320
DYNAMIC_API PEP_STATUS register_sync_callbacks(
vb@599
   321
        PEP_SESSION session,
edouard@1462
   322
        void *management,
vb@597
   323
        messageToSend_t messageToSend,
edouard@1459
   324
        notifyHandshake_t notifyHandshake,
vb@1043
   325
        inject_sync_msg_t inject_sync_msg,
vb@1043
   326
        retrieve_next_sync_msg_t retrieve_next_sync_msg
vb@572
   327
    );
vb@572
   328
edouard@1236
   329
// attach_sync_session() - attach session to a session running keysync state machine 
edouard@1236
   330
//
edouard@1236
   331
//  parameters:
edouard@1236
   332
//      session (in)                session to attach
edouard@1236
   333
//      sync_session (in)           session running keysync
edouard@1236
   334
//
edouard@1236
   335
//  return value:
edouard@1236
   336
//      PEP_STATUS_OK or any other value on errror
edouard@1236
   337
//
edouard@1236
   338
//  caveat:
edouard@1236
   339
//      register_sync_callbacks must have been called on sync_session
edouard@1236
   340
//      call that BEFORE you're using that session in any other part of the engine
edouard@1236
   341
edouard@1236
   342
DYNAMIC_API PEP_STATUS attach_sync_session(
edouard@1236
   343
        PEP_SESSION session,
edouard@1236
   344
        PEP_SESSION sync_session
edouard@1236
   345
    );
edouard@1236
   346
edouard@1236
   347
// detach_sync_session() - detach previously attached sync session
edouard@1236
   348
//
edouard@1236
   349
//  parameters:
edouard@1236
   350
//      session (in)                session to detach 
edouard@1236
   351
edouard@1236
   352
DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session);
vb@572
   353
vb@572
   354
// unregister_sync_callbacks() - unregister adapter's callbacks
vb@602
   355
//
vb@602
   356
//  parameters:
edouard@1236
   357
//      session (in)                session to unregister
vb@572
   358
vb@602
   359
DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session);
vb@572
   360
vb@1116
   361
// do_sync_protocol() - function to be run on an extra thread
vb@1043
   362
//
vb@1043
   363
//  parameters:
vb@1043
   364
//      session                 pEp session to use
vb@1043
   365
//      retrieve_next_sync_msg  pointer to retrieve_next_identity() callback
vb@1043
   366
//                              which returns at least a valid address field in
vb@1043
   367
//                              the identity struct
edouard@1462
   368
//      obj                     application defined sync object
vb@1043
   369
//
vb@1043
   370
//  return value:
vb@1043
   371
//      PEP_STATUS_OK if thread has to terminate successfully or any other
vb@1043
   372
//      value on failure
vb@1043
   373
//
vb@1043
   374
//  caveat:
vb@1043
   375
//      to ensure proper working of this library, a thread has to be started
vb@1043
   376
//      with this function immediately after initialization
vb@1043
   377
vb@1043
   378
DYNAMIC_API PEP_STATUS do_sync_protocol(
vb@1043
   379
        PEP_SESSION session,
edouard@1462
   380
        void *obj
vb@1043
   381
    );
vb@1043
   382
Edouard@1203
   383
// free_sync_msg() - free sync_msg_t struct when not passed to do_sync_protocol  
Edouard@1203
   384
//
Edouard@1203
   385
//  parameters:
roker@1482
   386
//      sync_msg (in)            pointer to sync_msg_t struct to free.
roker@1482
   387
//                               pointer can be NULL.
Edouard@1203
   388
Edouard@1203
   389
DYNAMIC_API void free_sync_msg(sync_msg_t *sync_msg);
vb@1043
   390
vb@1116
   391
// decode_sync_msg() - decode sync message from PER into XER
vb@1116
   392
//
vb@1116
   393
//  parameters:
vb@1116
   394
//      data (in)               PER encoded data
vb@1116
   395
//      size (in)               size of PER encoded data
vb@1116
   396
//      text (out)              XER text of the same sync message
vb@1116
   397
vb@1116
   398
DYNAMIC_API PEP_STATUS decode_sync_msg(
vb@1116
   399
        const char *data,
vb@1116
   400
        size_t size,
vb@1116
   401
        char **text
vb@1116
   402
    );
vb@1116
   403
vb@1116
   404
vb@1128
   405
// encode_sync_msg() - encode sync message from XER into PER
vb@1128
   406
//
vb@1128
   407
//  parameters:
vb@1128
   408
//      text (in)               string with XER text of the sync message
vb@1128
   409
//      data (out)              PER encoded data
vb@1128
   410
//      size (out)              size of PER encoded data
vb@1128
   411
vb@1128
   412
DYNAMIC_API PEP_STATUS encode_sync_msg(
vb@1128
   413
        const char *text,
vb@1128
   414
        char **data,
vb@1128
   415
        size_t *size
vb@1128
   416
    );
vb@1128
   417
vb@1128
   418
vb@572
   419
#ifdef __cplusplus
vb@572
   420
}
vb@572
   421
#endif
vb@572
   422