src/sync.c
author Edouard Tisserant <edouard@pep-project.org>
Sun, 27 Nov 2016 02:39:02 +0100
branchENGINE-133
changeset 1446 a948c1312c47
parent 1445 5d233bcdde76
child 1447 c5ca494344d9
permissions -rw-r--r--
ENGINE-133 added test in do_sync_protocol to detect when retrieve_next_sync_msg timeout
     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_actions
    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         showHandshake_t showHandshake,
    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 && showHandshake && inject_sync_msg && retrieve_next_sync_msg);
    27     if (!(session && obj && messageToSend && showHandshake && 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->showHandshake = showHandshake;
    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->showHandshake = 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             continue;
   171         else if ((status = receive_sync_msg(session, msg, &timeout) != PEP_STATUS_OK)) {
   172             char buffer[MAX_LINELENGTH];
   173             memset(buffer, 0, MAX_LINELENGTH);
   174             snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
   175             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   176         }
   177     }
   178 
   179     log_event(session, "sync_protocol thread shutdown", "pEp sync protocol", NULL, NULL);
   180 
   181     return PEP_STATUS_OK;
   182 }
   183 
   184 DYNAMIC_API PEP_STATUS decode_sync_msg(
   185         const char *data,
   186         size_t size,
   187         char **text
   188     )
   189 {
   190     PEP_STATUS status = PEP_STATUS_OK;
   191 
   192     assert(data && text);
   193     if (!(data && text))
   194         return PEP_ILLEGAL_VALUE;
   195 
   196     *text = NULL;
   197 
   198     DeviceGroup_Protocol_t *msg = NULL;
   199     uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **) &msg,
   200             data, size);
   201     if (!msg)
   202         return PEP_SYNC_ILLEGAL_MESSAGE;
   203 
   204     growing_buf_t *dst = new_growing_buf();
   205     if (!dst) {
   206         status = PEP_OUT_OF_MEMORY;
   207         goto the_end;
   208     }
   209 
   210     asn_enc_rval_t er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg,
   211             XER_F_BASIC, (asn_app_consume_bytes_f *) consume_bytes, (void *) dst);
   212     if (er.encoded == -1) {
   213         status = PEP_CANNOT_ENCODE;
   214         goto the_end;
   215     }
   216 
   217     *text = dst->data;
   218     dst->data = NULL;
   219 
   220 the_end:
   221     free_growing_buf(dst);
   222     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   223     return status;
   224 }
   225 
   226 DYNAMIC_API PEP_STATUS encode_sync_msg(
   227         const char *text,
   228         char **data,
   229         size_t *size
   230     )
   231 {
   232     PEP_STATUS status = PEP_STATUS_OK;
   233 
   234     assert(text && data && size);
   235     if (!(text && data && size))
   236         return PEP_ILLEGAL_VALUE;
   237 
   238     *data = NULL;
   239     *size = 0;
   240 
   241     DeviceGroup_Protocol_t *msg = NULL;
   242     asn_dec_rval_t dr = xer_decode(NULL, &asn_DEF_DeviceGroup_Protocol,
   243             (void **) &msg, (const void *) text, strlen(text));
   244     if (dr.code != RC_OK) {
   245         status = PEP_SYNC_ILLEGAL_MESSAGE;
   246         goto the_end;
   247     }
   248 
   249     char *payload = NULL;
   250     ssize_t _size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   251             NULL, msg, (void **) &payload);
   252     if (_size == -1) {
   253         status = PEP_CANNOT_ENCODE;
   254         goto the_end;
   255     }
   256 
   257     *data = payload;
   258     *size = (size_t) _size;
   259 
   260 the_end:
   261     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   262     return status;
   263 }
   264