src/sync.h
author Krista Grothoff <krista@pep-project.org>
Mon, 13 Feb 2017 22:13:48 +0100
branchenigmail-color-tests
changeset 1582 7dd855780eef
parent 1547 6c7051a7f0d5
child 1586 599deda50386
permissions -rw-r--r--
closing branch
     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_TIMEOUT :
   164         KeySync operation timed out.
   165         Identities are set reflecting peers involved in aborted operation.
   166         App displays error message. No feedback to engine.
   167 
   168     SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
   169         New device was added to group.
   170         App displays message. No feedback to engine.
   171 
   172     SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   173         New group created.
   174         App displays message. No feedback to engine.
   175 
   176    To deliver handshake result back to engine once user reacted,
   177    deliver_handshake_result is used. Result can be :
   178 
   179     SYNC_HANDSHAKE_CANCEL
   180         Gives no answer. User doesn't know id TrustWord are good or bad.
   181         For example in case peering device is away.
   182         Handshake will re-appear later.
   183 
   184     SYNC_HANDSHAKE_ACCEPTED
   185         Trustwords match with other device and user accepts handshake.
   186 
   187     SYNC_HANDSHAKE_REJECTED
   188         Trustwords do not match with any device and user rejects handshake.
   189 */
   190 
   191 #pragma once
   192 
   193 #include "message.h"
   194 #include "sync_fsm.h"
   195 
   196 
   197 // this module is for being used WITHOUT the Transport API in transport.h
   198 // DO NOT USE IT WHEN USING Transport API!
   199 
   200 
   201 #ifdef __cplusplus
   202 extern "C" {
   203 #endif
   204 
   205 // messageToSend() - send a message
   206 //
   207 //  parameters:
   208 //      obj (in)        object handle (implementation defined)
   209 //      msg (in)        message struct with message to send
   210 //
   211 //  return value:
   212 //      PEP_STATUS_OK or any other value on error
   213 //
   214 //  caveat:
   215 //      the ownership of msg goes to the callee
   216 
   217 typedef PEP_STATUS (*messageToSend_t)(void *obj, message *msg);
   218 
   219 // TODO add this to generated code.
   220 typedef enum _sync_handshake_signal {
   221     SYNC_NOTIFY_UNDEFINED = 0,
   222 
   223     // request show handshake dialog
   224     SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
   225     SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
   226     SYNC_NOTIFY_INIT_FORM_GROUP,
   227 
   228     // handshake process timed out
   229     SYNC_NOTIFY_TIMEOUT,
   230 
   231     // handshake accepted by user
   232     SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
   233     SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   234 
   235 } sync_handshake_signal;
   236 
   237 // notifyHandshake() - notify UI about sync handshaking process
   238 //
   239 //  parameters:
   240 //      obj (in)        object handle (implementation defined)
   241 //      me (in)         own identity
   242 //      partner (in)    identity of partner
   243 //      signal (in)     reason of the notification
   244 //
   245 //  return value:
   246 //      PEP_STATUS_OK or any other value on error
   247 //
   248 //  caveat:
   249 //      ownership of self and partner go to the callee
   250 
   251 typedef PEP_STATUS (*notifyHandshake_t)(
   252         void *obj,
   253         pEp_identity *me,
   254         pEp_identity *partner,
   255         sync_handshake_signal signal
   256     );
   257 
   258 typedef enum _sync_handshake_result {
   259     SYNC_HANDSHAKE_CANCEL = -1,
   260     SYNC_HANDSHAKE_ACCEPTED = 0,
   261     SYNC_HANDSHAKE_REJECTED = 1
   262 } sync_handshake_result;
   263 
   264 // deliverHandshakeResult() - give the result of the handshake dialog
   265 //
   266 //  parameters:
   267 //      session (in)        session handle
   268 //      result (in)         handshake result
   269 
   270 DYNAMIC_API PEP_STATUS deliverHandshakeResult(
   271         PEP_SESSION session,
   272         Identity partner,
   273         sync_handshake_result result
   274     );
   275 
   276 // sync_msg_t - items queued for serialized handling by protocol engine
   277 typedef struct _sync_msg_t sync_msg_t;
   278 
   279 // inject_sync_msg - inject sync protocol message
   280 //
   281 //  parameters:
   282 //      msg (in)            message to inject
   283 //      management (in)     application defined
   284 //
   285 //  *** BEWARE: msg is 1st parameter, obj is second!!! ***
   286 //  return value:
   287 //      0 if msg could be stored successfully or nonzero otherwise
   288 
   289 typedef int (*inject_sync_msg_t)(void *msg, void *management);
   290 
   291 
   292 // retrieve_next_sync_msg - receive next sync message
   293 //
   294 //  parameters:
   295 //      management (in)     application defined
   296 //      timeout (in,out)    do not wait longer than timeout for message
   297 //
   298 //  return value:
   299 //      next message or :
   300 //      NULL and timeout == 0 for termination
   301 //      NULL and timeout != 0 for timeout occurence
   302 
   303 typedef void *(*retrieve_next_sync_msg_t)(void *management, time_t *timeout);
   304 
   305 
   306 // register_sync_callbacks() - register adapter's callbacks
   307 //
   308 //  parameters:
   309 //      session (in)                session where to store obj handle
   310 //      management (in)             application defined
   311 //      messageToSend (in)          callback for sending message
   312 //      notifyHandshake (in)        callback for doing the handshake
   313 //      retrieve_next_sync_msg (in) callback for receiving sync messages
   314 //
   315 //  return value:
   316 //      PEP_STATUS_OK or any other value on errror
   317 //
   318 //  caveat:
   319 //      call that BEFORE you're using any other part of the engine
   320 
   321 DYNAMIC_API PEP_STATUS register_sync_callbacks(
   322         PEP_SESSION session,
   323         void *management,
   324         messageToSend_t messageToSend,
   325         notifyHandshake_t notifyHandshake,
   326         inject_sync_msg_t inject_sync_msg,
   327         retrieve_next_sync_msg_t retrieve_next_sync_msg
   328     );
   329 
   330 // attach_sync_session() - attach session to a session running keysync state machine 
   331 //
   332 //  parameters:
   333 //      session (in)                session to attach
   334 //      sync_session (in)           session running keysync
   335 //
   336 //  return value:
   337 //      PEP_STATUS_OK or any other value on errror
   338 //
   339 //  caveat:
   340 //      register_sync_callbacks must have been called on sync_session
   341 //      call that BEFORE you're using that session in any other part of the engine
   342 
   343 DYNAMIC_API PEP_STATUS attach_sync_session(
   344         PEP_SESSION session,
   345         PEP_SESSION sync_session
   346     );
   347 
   348 // detach_sync_session() - detach previously attached sync session
   349 //
   350 //  parameters:
   351 //      session (in)                session to detach 
   352 
   353 DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session);
   354 
   355 // unregister_sync_callbacks() - unregister adapter's callbacks
   356 //
   357 //  parameters:
   358 //      session (in)                session to unregister
   359 
   360 DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session);
   361 
   362 // do_sync_protocol() - function to be run on an extra thread
   363 //
   364 //  parameters:
   365 //      session                 pEp session to use
   366 //      retrieve_next_sync_msg  pointer to retrieve_next_identity() callback
   367 //                              which returns at least a valid address field in
   368 //                              the identity struct
   369 //      obj                     application defined sync object
   370 //
   371 //  return value:
   372 //      PEP_STATUS_OK if thread has to terminate successfully or any other
   373 //      value on failure
   374 //
   375 //  caveat:
   376 //      to ensure proper working of this library, a thread has to be started
   377 //      with this function immediately after initialization
   378 
   379 DYNAMIC_API PEP_STATUS do_sync_protocol(
   380         PEP_SESSION session,
   381         void *obj
   382     );
   383 
   384 // free_sync_msg() - free sync_msg_t struct when not passed to do_sync_protocol  
   385 //
   386 //  parameters:
   387 //      sync_msg (in)            pointer to sync_msg_t struct to free.
   388 //                               pointer can be NULL.
   389 
   390 DYNAMIC_API void free_sync_msg(sync_msg_t *sync_msg);
   391 
   392 // decode_sync_msg() - decode sync message from PER into XER
   393 //
   394 //  parameters:
   395 //      data (in)               PER encoded data
   396 //      size (in)               size of PER encoded data
   397 //      text (out)              XER text of the same sync message
   398 
   399 DYNAMIC_API PEP_STATUS decode_sync_msg(
   400         const char *data,
   401         size_t size,
   402         char **text
   403     );
   404 
   405 
   406 // encode_sync_msg() - encode sync message from XER into PER
   407 //
   408 //  parameters:
   409 //      text (in)               string with XER text of the sync message
   410 //      data (out)              PER encoded data
   411 //      size (out)              size of PER encoded data
   412 
   413 DYNAMIC_API PEP_STATUS encode_sync_msg(
   414         const char *text,
   415         char **data,
   416         size_t *size
   417     );
   418 
   419 
   420 #ifdef __cplusplus
   421 }
   422 #endif
   423