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