src/sync.c
author Edouard Tisserant <edouard@pep-project.org>
Sun, 04 Dec 2016 02:51:59 +0100
branchENGINE-133
changeset 1460 66ceb5a7f718
parent 1459 ab329d7db8d7
child 1462 b93663bfc7c6
permissions -rw-r--r--
ENGINE-133 added state 'payload' pointer to data attached to the state, allocated/dealocated on transitions. This state payload allows spontaneous transitions having no context (i.e. timeout) to get some context about the state. It can be used in other cases like checking that received group keys are from the partner we expect (TODO)
     1 #include "pEp_internal.h"
     2 
     3 #include <memory.h>
     4 #include <assert.h>
     5 
     6 #include "asn1_helper.h"
     7 #include "../asn.1/DeviceGroup-Protocol.h"
     8 
     9 // receive_sync_msg is defined in the sync_impl
    10 
    11 PEP_STATUS receive_sync_msg(
    12         PEP_SESSION session,
    13         sync_msg_t *sync_msg,
    14         time_t *timeout
    15     );
    16 
    17 DYNAMIC_API PEP_STATUS register_sync_callbacks(
    18         PEP_SESSION session,
    19         void *obj,
    20         messageToSend_t messageToSend,
    21         notifyHandshake_t notifyHandshake,
    22         inject_sync_msg_t inject_sync_msg,
    23         retrieve_next_sync_msg_t retrieve_next_sync_msg
    24     )
    25 {
    26     assert(session && obj && messageToSend && notifyHandshake && inject_sync_msg && retrieve_next_sync_msg);
    27     if (!(session && obj && messageToSend && notifyHandshake && inject_sync_msg && retrieve_next_sync_msg))
    28         return PEP_ILLEGAL_VALUE;
    29 
    30     pEpUUID uuid;
    31     uuid_generate_random(uuid);
    32     uuid_unparse_upper(uuid, session->sync_uuid);
    33 
    34     session->sync_obj = obj;
    35     session->messageToSend = messageToSend;
    36     session->notifyHandshake = notifyHandshake;
    37     session->inject_sync_msg = inject_sync_msg;
    38     session->retrieve_next_sync_msg = retrieve_next_sync_msg;
    39 
    40     // start state machine
    41     session->sync_state = InitState;
    42     time_t unused = 0;
    43     PEP_STATUS status = fsm_DeviceState_inject(session, Init, NULL, NULL, &unused);
    44     if (status != PEP_STATUS_OK)
    45         unregister_sync_callbacks(session);
    46 
    47     return status;
    48 }
    49 
    50 DYNAMIC_API PEP_STATUS attach_sync_session(
    51         PEP_SESSION session,
    52         PEP_SESSION sync_session
    53     )
    54 {
    55     assert(session && sync_session && sync_session->sync_obj && sync_session->inject_sync_msg );
    56     if (!(session && sync_session && sync_session->sync_obj && sync_session->inject_sync_msg ))
    57         return PEP_ILLEGAL_VALUE;
    58 
    59     memcpy(session->sync_uuid, sync_session->sync_uuid, 37);
    60 
    61     session->sync_obj = sync_session->sync_obj;
    62     session->inject_sync_msg = sync_session->inject_sync_msg;
    63 
    64     return PEP_STATUS_OK;
    65 }
    66 
    67 DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session)
    68 {
    69     assert(session && session->sync_obj && session->inject_sync_msg );
    70     if (!(session && session->sync_obj && session->inject_sync_msg ))
    71         return PEP_ILLEGAL_VALUE;
    72 
    73     memset(session->sync_uuid, 0, 37);
    74 
    75     session->sync_obj = NULL;
    76     session->inject_sync_msg = NULL;
    77 
    78     return PEP_STATUS_OK;
    79 }
    80 
    81 int call_inject_sync_msg(PEP_SESSION session, void *msg)
    82 {
    83     if(session->inject_sync_msg && session->sync_obj)
    84         return session->inject_sync_msg(msg, session->sync_obj);
    85     else
    86        return PEP_SYNC_NO_INJECT_CALLBACK;
    87 }
    88 
    89 DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session) {
    90     // stop state machine
    91     session->sync_state = DeviceState_state_NONE;
    92 
    93     // unregister
    94     session->sync_obj = NULL;
    95     session->messageToSend = NULL;
    96     session->notifyHandshake = NULL;
    97     session->inject_sync_msg = NULL;
    98     session->retrieve_next_sync_msg = NULL;
    99 }
   100 
   101 DYNAMIC_API PEP_STATUS deliverHandshakeResult(
   102         PEP_SESSION session,
   103         Identity partner,
   104         sync_handshake_result result
   105     )
   106 {
   107     assert(session);
   108     if (!session)
   109         return PEP_ILLEGAL_VALUE;
   110 
   111     PEP_STATUS status = PEP_STATUS_OK;
   112 
   113     DeviceState_event event;
   114     bool need_partner = false;
   115 
   116     switch (result) {
   117         case SYNC_HANDSHAKE_CANCEL:
   118             event = Cancel;
   119             break;
   120         case SYNC_HANDSHAKE_ACCEPTED:
   121         {
   122             event = HandshakeAccepted;
   123             need_partner = true;
   124             break;
   125         }
   126         case SYNC_HANDSHAKE_REJECTED:
   127         {
   128             event = HandshakeRejected;
   129             need_partner = true;
   130             break;
   131         }
   132         default:
   133             return PEP_ILLEGAL_VALUE;
   134     }
   135 
   136     pEp_identity *_partner = NULL;
   137     if(need_partner){
   138         _partner = identity_dup(partner);
   139         if (_partner == NULL)
   140             return PEP_OUT_OF_MEMORY;
   141     }
   142     status = inject_DeviceState_event(session, event, _partner, NULL);
   143 
   144     return status;
   145 }
   146 
   147 DYNAMIC_API PEP_STATUS do_sync_protocol(
   148         PEP_SESSION session,
   149         void *management
   150     )
   151 {
   152     sync_msg_t *msg = NULL;
   153     PEP_STATUS status = PEP_STATUS_OK;
   154     time_t timeout = 0;
   155 
   156     assert(session && session->retrieve_next_sync_msg);
   157     assert(management);
   158 
   159     if (!(session && session->retrieve_next_sync_msg) || !management)
   160         return PEP_ILLEGAL_VALUE;
   161 
   162     log_event(session, "sync_protocol thread started", "pEp sync protocol", NULL, NULL);
   163 
   164     while (true) 
   165     {
   166         msg = (sync_msg_t *) session->retrieve_next_sync_msg(management, &timeout);
   167         if(msg == NULL && timeout == 0)
   168             break;
   169         else if(msg == NULL && timeout != 0){
   170             status = fsm_DeviceState_inject(session, Timeout, NULL, NULL, &timeout);
   171             char buffer[MAX_LINELENGTH];
   172             memset(buffer, 0, MAX_LINELENGTH);
   173             snprintf(buffer, MAX_LINELENGTH, "problem with timeout event : %d\n", (int) status);
   174             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   175             continue;
   176         }
   177         else if ((status = receive_sync_msg(session, msg, &timeout) != PEP_STATUS_OK)) {
   178             char buffer[MAX_LINELENGTH];
   179             memset(buffer, 0, MAX_LINELENGTH);
   180             snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
   181             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   182         }
   183     }
   184 
   185     log_event(session, "sync_protocol thread shutdown", "pEp sync protocol", NULL, NULL);
   186 
   187     return PEP_STATUS_OK;
   188 }
   189 
   190 DYNAMIC_API PEP_STATUS decode_sync_msg(
   191         const char *data,
   192         size_t size,
   193         char **text
   194     )
   195 {
   196     PEP_STATUS status = PEP_STATUS_OK;
   197 
   198     assert(data && text);
   199     if (!(data && text))
   200         return PEP_ILLEGAL_VALUE;
   201 
   202     *text = NULL;
   203 
   204     DeviceGroup_Protocol_t *msg = NULL;
   205     uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **) &msg,
   206             data, size);
   207     if (!msg)
   208         return PEP_SYNC_ILLEGAL_MESSAGE;
   209 
   210     growing_buf_t *dst = new_growing_buf();
   211     if (!dst) {
   212         status = PEP_OUT_OF_MEMORY;
   213         goto the_end;
   214     }
   215 
   216     asn_enc_rval_t er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg,
   217             XER_F_BASIC, (asn_app_consume_bytes_f *) consume_bytes, (void *) dst);
   218     if (er.encoded == -1) {
   219         status = PEP_CANNOT_ENCODE;
   220         goto the_end;
   221     }
   222 
   223     *text = dst->data;
   224     dst->data = NULL;
   225 
   226 the_end:
   227     free_growing_buf(dst);
   228     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   229     return status;
   230 }
   231 
   232 DYNAMIC_API PEP_STATUS encode_sync_msg(
   233         const char *text,
   234         char **data,
   235         size_t *size
   236     )
   237 {
   238     PEP_STATUS status = PEP_STATUS_OK;
   239 
   240     assert(text && data && size);
   241     if (!(text && data && size))
   242         return PEP_ILLEGAL_VALUE;
   243 
   244     *data = NULL;
   245     *size = 0;
   246 
   247     DeviceGroup_Protocol_t *msg = NULL;
   248     asn_dec_rval_t dr = xer_decode(NULL, &asn_DEF_DeviceGroup_Protocol,
   249             (void **) &msg, (const void *) text, strlen(text));
   250     if (dr.code != RC_OK) {
   251         status = PEP_SYNC_ILLEGAL_MESSAGE;
   252         goto the_end;
   253     }
   254 
   255     char *payload = NULL;
   256     ssize_t _size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   257             NULL, msg, (void **) &payload);
   258     if (_size == -1) {
   259         status = PEP_CANNOT_ENCODE;
   260         goto the_end;
   261     }
   262 
   263     *data = payload;
   264     *size = (size_t) _size;
   265 
   266 the_end:
   267     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   268     return status;
   269 }
   270