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