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