summaryrefslogtreecommitdiff
path: root/ecp/src/dir.c
blob: 8bc7a94601823dacc73b3ed4dcdcd67ad1d40076 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "core.h"
#include "cr.h"

#include "dir.h"

static int dir_update(ECPDirList *list, ECPDirItem *item) {
    int i;

    for (i=0; i<list->count; i++) {
        if (memcmp(ecp_cr_dh_pub_get_buf(&list->item[i].node.public), ecp_cr_dh_pub_get_buf(&item->node.public), ECP_ECDH_SIZE_KEY) == 0) {
            return ECP_OK;
        }
    }

    if (list->count == ECP_MAX_DIR_ITEM) return ECP_ERR_SIZE;

    list->item[list->count] = *item;
    list->count++;

    return ECP_OK;
}

ssize_t ecp_dir_parse(ECPDirList *list, unsigned char *buf, size_t buf_size) {
    ECPDirItem item;
    size_t size;
    int rv;

    size = buf_size;
    while (size >= ECP_SIZE_DIR_ITEM) {
        ecp_dir_item_parse(&item, buf);

        rv = dir_update(list, &item);
        if (rv) return rv;

        buf += ECP_SIZE_DIR_ITEM;
        size -= ECP_SIZE_DIR_ITEM;
    };

    return buf_size - size;
}

int ecp_dir_serialize(ECPDirList *list, unsigned char *buf, size_t buf_size) {
    int i;

    for (i=0; i<list->count; i++) {
        if (buf_size < ECP_SIZE_DIR_ITEM) return ECP_ERR_SIZE;

        ecp_dir_item_serialize(&list->item[i], buf);
        buf += ECP_SIZE_DIR_ITEM;
        buf_size -= ECP_SIZE_DIR_ITEM;
    }

    return ECP_OK;
}

void ecp_dir_item_parse(ECPDirItem *item, unsigned char *buf) {
    ecp_cr_dh_pub_from_buf(&item->node.public, buf);
    buf += ECP_ECDH_SIZE_KEY;

    memcpy(&item->node.addr.host, buf, sizeof(item->node.addr));
    buf += ECP_IPv4_ADDR_SIZE;

    item->node.addr.port =  \
        (buf[0] << 8) |     \
        (buf[1]);
    buf += sizeof(uint16_t);

    item->capabilities =    \
        (buf[0] << 8) |     \
        (buf[1]);
    buf += sizeof(uint16_t);
}

void ecp_dir_item_serialize(ECPDirItem *item, unsigned char *buf) {
    ecp_cr_dh_pub_to_buf(buf, &item->node.public);
    buf += ECP_ECDH_SIZE_KEY;

    memcpy(buf, &item->node.addr.host, sizeof(item->node.addr));
    buf += ECP_IPv4_ADDR_SIZE;

    buf[0] = (item->node.addr.port & 0xFF00) >> 8;
    buf[1] = (item->node.addr.port & 0x00FF);
    buf += sizeof(uint16_t);

    buf[0] = (item->capabilities & 0xFF00) >> 8;
    buf[1] = (item->capabilities & 0x00FF);
    buf += sizeof(uint16_t);
}