src/sync.c
author Volker Birk <vb@pep.foundation>
Tue, 27 Dec 2016 21:13:41 +0100
changeset 1513 e7f7e42385b5
parent 1494 27ded4922ae2
child 1603 f954f77387f1
permissions -rw-r--r--
adding license info to each file
     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     memcpy(session->sync_uuid, sync_session->sync_uuid, 37);
    63 
    64     session->sync_management = sync_session->sync_management;
    65     session->inject_sync_msg = sync_session->inject_sync_msg;
    66 
    67     return PEP_STATUS_OK;
    68 }
    69 
    70 DYNAMIC_API PEP_STATUS detach_sync_session(PEP_SESSION session)
    71 {
    72     assert(session && session->sync_management && session->inject_sync_msg );
    73     if (!(session && session->sync_management && session->inject_sync_msg ))
    74         return PEP_ILLEGAL_VALUE;
    75 
    76     memset(session->sync_uuid, 0, 37);
    77 
    78     session->sync_management = NULL;
    79     session->inject_sync_msg = NULL;
    80 
    81     return PEP_STATUS_OK;
    82 }
    83 
    84 int call_inject_sync_msg(PEP_SESSION session, void *msg)
    85 {
    86     if(session->inject_sync_msg && session->sync_management)
    87         return session->inject_sync_msg(msg, session->sync_management);
    88     else
    89        return PEP_SYNC_NO_INJECT_CALLBACK;
    90 }
    91 
    92 DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session) {
    93     // stop state machine
    94     session->sync_state = DeviceState_state_NONE;
    95 
    96     // unregister
    97     session->sync_management = NULL;
    98     session->messageToSend = NULL;
    99     session->notifyHandshake = NULL;
   100     session->inject_sync_msg = NULL;
   101     session->retrieve_next_sync_msg = NULL;
   102 }
   103 
   104 DYNAMIC_API PEP_STATUS deliverHandshakeResult(
   105         PEP_SESSION session,
   106         Identity partner,
   107         sync_handshake_result result
   108     )
   109 {
   110     assert(session);
   111     if (!session)
   112         return PEP_ILLEGAL_VALUE;
   113 
   114     PEP_STATUS status = PEP_STATUS_OK;
   115 
   116     DeviceState_event event;
   117     bool need_partner = false;
   118 
   119     switch (result) {
   120         case SYNC_HANDSHAKE_CANCEL:
   121             event = Cancel;
   122             break;
   123         case SYNC_HANDSHAKE_ACCEPTED:
   124         {
   125             event = HandshakeAccepted;
   126             need_partner = true;
   127             break;
   128         }
   129         case SYNC_HANDSHAKE_REJECTED:
   130         {
   131             event = HandshakeRejected;
   132             need_partner = true;
   133             break;
   134         }
   135         default:
   136             return PEP_ILLEGAL_VALUE;
   137     }
   138 
   139     pEp_identity *_partner = NULL;
   140     if(need_partner){
   141         _partner = identity_dup(partner);
   142         if (_partner == NULL)
   143             return PEP_OUT_OF_MEMORY;
   144     }
   145     status = inject_DeviceState_event(session, event, _partner, NULL);
   146 
   147     return status;
   148 }
   149 
   150 DYNAMIC_API PEP_STATUS do_sync_protocol(
   151         PEP_SESSION session,
   152         void *obj
   153     )
   154 {
   155     sync_msg_t *msg = NULL;
   156     PEP_STATUS status = PEP_STATUS_OK;
   157     time_t timeout = 0;
   158 
   159     assert(session && session->retrieve_next_sync_msg);
   160     assert(obj);
   161 
   162     if (!(session && session->retrieve_next_sync_msg) || !obj)
   163         return PEP_ILLEGAL_VALUE;
   164 
   165     log_event(session, "sync_protocol thread started", "pEp sync protocol", NULL, NULL);
   166 
   167     session->sync_obj = obj;
   168 
   169     while (true) 
   170     {
   171         msg = (sync_msg_t *) session->retrieve_next_sync_msg(session->sync_management, &timeout);
   172         if(msg == NULL && timeout == 0)
   173             break;
   174         else if(msg == NULL && timeout != 0){
   175             status = fsm_DeviceState_inject(session, Timeout, NULL, NULL, &timeout);
   176 #ifndef NDEBUG
   177             char buffer[MAX_LINELENGTH];
   178             memset(buffer, 0, MAX_LINELENGTH);
   179             snprintf(buffer, MAX_LINELENGTH, "problem with timeout event : %d\n", (int) status);
   180             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   181             continue;
   182 #endif
   183         }
   184         else if ((status = receive_sync_msg(session, msg, &timeout) != PEP_STATUS_OK)) {
   185 #ifndef NDEBUG
   186             char buffer[MAX_LINELENGTH];
   187             memset(buffer, 0, MAX_LINELENGTH);
   188             snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
   189             log_event(session, buffer, "pEp sync protocol", NULL, NULL);
   190 #endif
   191         }
   192     }
   193 
   194     log_event(session, "sync_protocol thread shutdown", "pEp sync protocol", NULL, NULL);
   195 
   196     session->sync_obj = NULL;
   197 
   198     return PEP_STATUS_OK;
   199 }
   200 
   201 DYNAMIC_API PEP_STATUS decode_sync_msg(
   202         const char *data,
   203         size_t size,
   204         char **text
   205     )
   206 {
   207     PEP_STATUS status = PEP_STATUS_OK;
   208 
   209     assert(data && text);
   210     if (!(data && text))
   211         return PEP_ILLEGAL_VALUE;
   212 
   213     *text = NULL;
   214 
   215     DeviceGroup_Protocol_t *msg = NULL;
   216     uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **) &msg,
   217             data, size);
   218     if (!msg)
   219         return PEP_SYNC_ILLEGAL_MESSAGE;
   220 
   221     growing_buf_t *dst = new_growing_buf();
   222     if (!dst) {
   223         status = PEP_OUT_OF_MEMORY;
   224         goto the_end;
   225     }
   226 
   227     asn_enc_rval_t er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg,
   228             XER_F_BASIC, (asn_app_consume_bytes_f *) consume_bytes, (void *) dst);
   229     if (er.encoded == -1) {
   230         status = PEP_CANNOT_ENCODE;
   231         goto the_end;
   232     }
   233 
   234     *text = dst->data;
   235     dst->data = NULL;
   236 
   237 the_end:
   238     free_growing_buf(dst);
   239     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   240     return status;
   241 }
   242 
   243 DYNAMIC_API PEP_STATUS encode_sync_msg(
   244         const char *text,
   245         char **data,
   246         size_t *size
   247     )
   248 {
   249     PEP_STATUS status = PEP_STATUS_OK;
   250 
   251     assert(text && data && size);
   252     if (!(text && data && size))
   253         return PEP_ILLEGAL_VALUE;
   254 
   255     *data = NULL;
   256     *size = 0;
   257 
   258     DeviceGroup_Protocol_t *msg = NULL;
   259     asn_dec_rval_t dr = xer_decode(NULL, &asn_DEF_DeviceGroup_Protocol,
   260             (void **) &msg, (const void *) text, strlen(text));
   261     if (dr.code != RC_OK) {
   262         status = PEP_SYNC_ILLEGAL_MESSAGE;
   263         goto the_end;
   264     }
   265 
   266     char *payload = NULL;
   267     ssize_t _size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
   268             NULL, msg, (void **) &payload);
   269     if (_size == -1) {
   270         status = PEP_CANNOT_ENCODE;
   271         goto the_end;
   272     }
   273 
   274     *data = payload;
   275     *size = (size_t) _size;
   276 
   277 the_end:
   278     ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   279     return status;
   280 }
   281