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