src/sync.c
author Edouard Tisserant <edouard@pep-project.org>
Wed, 07 Dec 2016 15:39:06 +0100
branchENGINE-133
changeset 1462 b93663bfc7c6
parent 1460 66ceb5a7f718
child 1494 27ded4922ae2
permissions -rw-r--r--
sync: distinguish management pointer (for queuing sync_messages, i.e. sync job 'management') from obj pointer (for sending email messages, notifying user, alias sync 'object'), thus following original design convention
     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 *management,
    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 && management && messageToSend && notifyHandshake && inject_sync_msg && retrieve_next_sync_msg);
    27     if (!(session && management && 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_management = management;
    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_management && sync_session->inject_sync_msg );
    56     if (!(session && sync_session && sync_session->sync_management && 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_management = sync_session->sync_management;
    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_management && session->inject_sync_msg );
    70     if (!(session && session->sync_management && session->inject_sync_msg ))
    71         return PEP_ILLEGAL_VALUE;
    72 
    73     memset(session->sync_uuid, 0, 37);
    74 
    75     session->sync_management = 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_management)
    84         return session->inject_sync_msg(msg, session->sync_management);
    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_management = 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 *obj
   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(obj);
   158 
   159     if (!(session && session->retrieve_next_sync_msg) || !obj)
   160         return PEP_ILLEGAL_VALUE;
   161 
   162     log_event(session, "sync_protocol thread started", "pEp sync protocol", NULL, NULL);
   163 
   164     session->sync_obj = obj;
   165 
   166     while (true) 
   167     {
   168         msg = (sync_msg_t *) session->retrieve_next_sync_msg(session->sync_management, &timeout);
   169         if(msg == NULL && timeout == 0)
   170             break;
   171         else if(msg == NULL && timeout != 0){
   172             status = fsm_DeviceState_inject(session, Timeout, NULL, NULL, &timeout);
   173             char buffer[MAX_LINELENGTH];
   174             memset(buffer, 0, MAX_LINELENGTH);
   175             snprintf(buffer, MAX_LINELENGTH, "problem with timeout event : %d\n", (int) status);
   176             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   177             continue;
   178         }
   179         else if ((status = receive_sync_msg(session, msg, &timeout) != PEP_STATUS_OK)) {
   180             char buffer[MAX_LINELENGTH];
   181             memset(buffer, 0, MAX_LINELENGTH);
   182             snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
   183             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   184         }
   185     }
   186 
   187     log_event(session, "sync_protocol thread shutdown", "pEp sync protocol", NULL, NULL);
   188 
   189     session->sync_obj = NULL;
   190 
   191     return PEP_STATUS_OK;
   192 }
   193 
   194 DYNAMIC_API PEP_STATUS decode_sync_msg(
   195         const char *data,
   196         size_t size,
   197         char **text
   198     )
   199 {
   200     PEP_STATUS status = PEP_STATUS_OK;
   201 
   202     assert(data && text);
   203     if (!(data && text))
   204         return PEP_ILLEGAL_VALUE;
   205 
   206     *text = NULL;
   207 
   208     DeviceGroup_Protocol_t *msg = NULL;
   209     uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **) &msg,
   210             data, size);
   211     if (!msg)
   212         return PEP_SYNC_ILLEGAL_MESSAGE;
   213 
   214     growing_buf_t *dst = new_growing_buf();
   215     if (!dst) {
   216         status = PEP_OUT_OF_MEMORY;
   217         goto the_end;
   218     }
   219 
   220     asn_enc_rval_t er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg,
   221             XER_F_BASIC, (asn_app_consume_bytes_f *) consume_bytes, (void *) dst);
   222     if (er.encoded == -1) {
   223         status = PEP_CANNOT_ENCODE;
   224         goto the_end;
   225     }
   226 
   227     *text = dst->data;
   228     dst->data = NULL;
   229 
   230 the_end:
   231     free_growing_buf(dst);
   232     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   233     return status;
   234 }
   235 
   236 DYNAMIC_API PEP_STATUS encode_sync_msg(
   237         const char *text,
   238         char **data,
   239         size_t *size
   240     )
   241 {
   242     PEP_STATUS status = PEP_STATUS_OK;
   243 
   244     assert(text && data && size);
   245     if (!(text && data && size))
   246         return PEP_ILLEGAL_VALUE;
   247 
   248     *data = NULL;
   249     *size = 0;
   250 
   251     DeviceGroup_Protocol_t *msg = NULL;
   252     asn_dec_rval_t dr = xer_decode(NULL, &asn_DEF_DeviceGroup_Protocol,
   253             (void **) &msg, (const void *) text, strlen(text));
   254     if (dr.code != RC_OK) {
   255         status = PEP_SYNC_ILLEGAL_MESSAGE;
   256         goto the_end;
   257     }
   258 
   259     char *payload = NULL;
   260     ssize_t _size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   261             NULL, msg, (void **) &payload);
   262     if (_size == -1) {
   263         status = PEP_CANNOT_ENCODE;
   264         goto the_end;
   265     }
   266 
   267     *data = payload;
   268     *size = (size_t) _size;
   269 
   270 the_end:
   271     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   272     return status;
   273 }
   274