diff options
author | Uros Majstorovic <majstor@majstor.org> | 2022-03-12 13:08:52 +0100 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2022-03-12 13:08:52 +0100 |
commit | 3436ce5d3ffbc2777e785310bac971c830cbb4ff (patch) | |
tree | c3ffb0d18bb992e8b97818e4d0b369844979012d /ecp | |
parent | d359dd9981f4137e8873a7a571e5c54c5b2449c4 (diff) |
new rev compile OK
Diffstat (limited to 'ecp')
35 files changed, 3081 insertions, 2767 deletions
diff --git a/ecp/src/ecp/TODO b/ecp/src/ecp/TODO index 01c2a28..8f633ed 100644 --- a/ecp/src/ecp/TODO +++ b/ecp/src/ecp/TODO @@ -1,9 +1,5 @@ -+ check for nonce -+ check for seq - - memzero keys after usage - implement socket message queue rbuf: - implement _wait variants of open / send -- msgq should subtract ECP_MAX_MTYPE_SYS from mtype (make ECPConnMsgQ smaller) diff --git a/ecp/src/ecp/core.c b/ecp/src/ecp/core.c index 90ee925..d59ea8f 100644 --- a/ecp/src/ecp/core.c +++ b/ecp/src/ecp/core.c @@ -1,4 +1,20 @@ +#include <stdlib.h> +#include <string.h> + +#ifdef ECP_DEBUG +#include <stdio.h> +#endif + #include "core.h" +#include "ext.h" + +#ifdef ECP_WITH_VCONN +#include "vconn/vconn.h" +#endif + +#ifdef ECP_WITH_DIR +#include "dir.h" +#endif #include "cr.h" #include "tr.h" @@ -8,14 +24,17 @@ #include "ht.h" #endif -#include "dir_srv.h" -int ecp_ctx_init(ECPContext *ctx) { +int ecp_ctx_init(ECPContext *ctx, ecp_err_handler_t handle_err, ecp_dir_handler_t handle_dir, ecp_conn_alloc_t conn_alloc, ecp_conn_free_t conn_free) { int rv; if (ctx == NULL) return ECP_ERR; memset(ctx, 0, sizeof(ECPContext)); + ctx->handle_err = handle_err; + ctx->handle_dir = handle_dir; + ctx->conn_alloc = conn_alloc; + ctx->conn_free = conn_free; rv = ecp_tr_init(ctx); if (rv) return rv; @@ -25,10 +44,22 @@ int ecp_ctx_init(ECPContext *ctx) { return ECP_OK; } -int ecp_node_init(ECPNode *node, ecp_dh_public_t *public, void *addr) { +int ecp_ctx_set_handler(ECPContext *ctx, ECPConnHandler *handler, unsigned char ctype) { + if (ctype >= ECP_MAX_CTYPE) return ECP_ERR_CTYPE; + + ctx->handler[ctype] = handler; + return ECP_OK; +} + +int ecp_node_init(ECPNode *node, ecp_ecdh_public_t *public, void *addr) { memset(node, 0, sizeof(ECPNode)); - if (public) memcpy(&node->public, public, sizeof(node->public)); + if (public) { + ECPDHPub *key = &node->key_perma; + + memcpy(&key->public, public, sizeof(key->public)); + key->valid = 1; + } if (addr) { int rv; @@ -40,53 +71,37 @@ int ecp_node_init(ECPNode *node, ecp_dh_public_t *public, void *addr) { return ECP_OK; } -int ecp_seq_item_init(ECPSeqItem *seq_item) { - memset(seq_item, 0, sizeof(ECPSeqItem)); - - return ECP_OK; -} - -int ecp_frag_iter_init(ECPFragIter *iter, unsigned char *buffer, size_t buf_size) { - memset(iter, 0, sizeof(ECPFragIter)); - iter->buffer = buffer; - iter->buf_size = buf_size; - - return ECP_OK; -} - -void ecp_frag_iter_reset(ECPFragIter *iter) { - iter->seq = 0; - iter->frag_cnt = 0; - iter->msg_size = 0; -} - -int ecp_dhkey_gen(ECPContext *ctx, ECPDHKey *key) { +int ecp_dhkey_gen(ECPDHKey *key) { int rv; - if (ctx->rng == NULL) return ECP_ERR_RNG; - - rv = ecp_cr_dh_mkpair(&key->public, &key->private, ctx->rng); + rv = ecp_ecdh_mkpair(&key->public, &key->private); if (rv) return rv; key->valid = 1; return ECP_OK; } -static int ctable_create(ECPSockCTable *conn, ECPContext *ctx) { +static int conn_table_create(ECPConnTable *conn_table) { int rv; - memset(conn, 0, sizeof(ECPSockCTable)); + memset(conn_table, 0, sizeof(ECPConnTable)); #ifdef ECP_WITH_HTABLE - conn->htable = ecp_ht_create(ctx); - if (conn->htable == NULL) return ECP_ERR_ALLOC; + conn_table->keys = ecp_ht_create_keys(); + if (conn_table->keys == NULL) return ECP_ERR_ALLOC; + conn_table->addrs = ecp_ht_create_addrs(); + if (conn_table->addrs == NULL) { + ecp_ht_destroy(conn_table->keys); + return ECP_ERR_ALLOC; + } #endif #ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&conn->mutex, NULL); + rv = pthread_mutex_init(&conn_table->mutex, NULL); if (rv) { #ifdef ECP_WITH_HTABLE - ecp_ht_destroy(conn->htable); + ecp_ht_destroy(conn_table->addrs); + ecp_ht_destroy(conn_table->keys); #endif return ECP_ERR; } @@ -95,97 +110,134 @@ static int ctable_create(ECPSockCTable *conn, ECPContext *ctx) { return ECP_OK; } -static void ctable_destroy(ECPSockCTable *conn, ECPContext *ctx) { +static void conn_table_destroy(ECPConnTable *conn_table) { #ifdef ECP_WITH_PTHREAD - pthread_mutex_destroy(&conn->mutex); + pthread_mutex_destroy(&conn_table->mutex); #endif #ifdef ECP_WITH_HTABLE - ecp_ht_destroy(conn->htable); + ecp_ht_destroy(conn_table->addrs); + ecp_ht_destroy(conn_table->keys); #endif } -static int ctable_insert(ECPConnection *conn) { +static int conn_table_insert(ECPConnection *conn) { ECPSocket *sock = conn->sock; #ifdef ECP_WITH_HTABLE int i, rv = ECP_OK; if (ecp_conn_is_outb(conn)) { + if (!ecp_conn_is_open(conn)) rv = ecp_ht_insert(sock->conn_table.addrs, &conn->remote.addr, conn); + if (rv) return rv; + for (i=0; i<ECP_MAX_CONN_KEY; i++) { - if (conn->key[i].valid) rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[i].public), conn); + if (conn->key[i].valid) rv = ecp_ht_insert(sock->conn_table.keys, &conn->key[i].public, conn); if (rv) { int j; - for (j=0; j<i; j++) if (conn->key[j].valid) ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[j].public)); + + for (j=0; j<i; j++) { + if (conn->key[j].valid) ecp_ht_remove(sock->conn_table.keys, &conn->key[j].public); + } + if (!ecp_conn_is_open(conn)) ecp_ht_remove(sock->conn_table.addrs, &conn->remote.addr); return rv; } } } else { - ECPDHRKeyBucket *remote = &conn->remote; - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - if (remote->key[i].idx != ECP_ECDH_IDX_INV) rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[i].public), conn); + if (conn->rkey[i].valid) rv = ecp_ht_insert(sock->conn_table.keys, &conn->rkey[i].public, conn); if (rv) { int j; - for (j=0; j<i; j++) if (remote->key[j].idx != ECP_ECDH_IDX_INV) ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[j].public)); + + for (j=0; j<i; j++) { + if (conn->rkey[j].valid) ecp_ht_remove(sock->conn_table.keys, &conn->rkey[j].public); + } return rv; } } } #else - if (sock->conn.size == ECP_MAX_SOCK_CONN) return ECP_ERR_MAX_SOCK_CONN; - sock->conn.array[sock->conn.size] = conn; - sock->conn.size++; + if (sock->conn_table.size == ECP_MAX_SOCK_CONN) return ECP_ERR_FULL; + sock->conn_table.arr[sock->conn_table.size] = conn; + sock->conn_table.size++; #endif return ECP_OK; } -static void ctable_remove(ECPConnection *conn) { - int i; +static void conn_table_remove(ECPConnection *conn) { ECPSocket *sock = conn->sock; + int i; #ifdef ECP_WITH_HTABLE if (ecp_conn_is_outb(conn)) { - for (i=0; i<ECP_MAX_CONN_KEY; i++) if (conn->key[i].valid) ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[i].public)); + for (i=0; i<ECP_MAX_CONN_KEY; i++) { + if (conn->key[i].valid) ecp_ht_remove(sock->conn_table.keys, &conn->key[i].public); + } + if (!ecp_conn_is_open(conn)) ecp_ht_remove(sock->conn_table.addrs, &conn->remote.addr); } else { - ECPDHRKeyBucket *remote = &conn->remote; - for (i=0; i<ECP_MAX_NODE_KEY; i++) if (remote->key[i].idx != ECP_ECDH_IDX_INV) ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[i].public)); + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + if (conn->rkey[i].valid) ecp_ht_remove(sock->conn_table.keys, &conn->rkey[i].public); + } } #else - for (i=0; i<sock->conn.size; i++) { - if (conn == sock->conn.array[i]) { - sock->conn.array[i] = sock->conn.array[sock->conn.size-1]; - sock->conn.array[sock->conn.size-1] = NULL; - sock->conn.size--; + for (i=0; i<sock->conn_table.size; i++) { + if (conn == sock->conn_table.arr[i]) { + while (i < (sock->conn_table.size-1)) { + sock->conn_table.arr[i] = sock->conn_table.arr[i+1]; + i++; + } + sock->conn_table.arr[i] = NULL; + sock->conn_table.size--; return; } } #endif } -static ECPConnection *ctable_search(ECPSocket *sock, unsigned char c_idx, unsigned char *c_public, ECPNetAddr *addr) { +static void conn_table_remove_addr(ECPConnection *conn) { + ECPSocket *sock = conn->sock; + +#ifdef ECP_WITH_HTABLE + ecp_ht_remove(sock->conn_table.addrs, &conn->remote.addr); +#endif +} + +static ECPConnection *conn_table_search(ECPSocket *sock, unsigned char c_idx, ecp_ecdh_public_t *c_public, ecp_tr_addr_t *addr) { #ifdef ECP_WITH_HTABLE - return ecp_ht_search(sock->conn.htable, c_public); + if (c_public) { + return ecp_ht_search(sock->conn_table.keys, c_public); + } else if (addr) { + return ecp_ht_search(sock->conn_table.addrs, addr); + } else { + return NULL; + } #else - ECPConnection *conn = NULL; + ECPConnection *conn; int i; if (c_public) { - for (i=0; i<sock->conn.size; i++) { - conn = sock->conn.array[i]; - if (ecp_conn_is_outb(conn)) { - if ((c_idx < ECP_MAX_CONN_KEY) && conn->key[c_idx].valid && ecp_cr_dh_pub_eq(c_public, &conn->key[c_idx].public)) - return conn; - } else { - if ((c_idx < ECP_MAX_SOCK_KEY) && (conn->remote.key_idx_map[c_idx] != ECP_ECDH_IDX_INV) && ecp_cr_dh_pub_eq(c_public, &conn->remote.key[conn->remote.key_idx_map[c_idx]].public)) - return conn; + if (ecp_conn_is_outb(conn)) { + if (c_idx >= ECP_MAX_CONN_KEY) return ECP_ERR_ECDH_IDX; + + for (i=0; i<sock->conn_table.size; i++) { + conn = sock->conn_table.arr[i]; + if (conn->key[c_idx].valid && ecp_ecdh_pub_eq(c_public, &conn->key[c_idx].public)) return conn; + } + } else { + unsigned char *_c_idx; + + if (c_idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; + + _c_idx = c_idx % ECP_MAX_NODE_KEY; + for (i=0; i<sock->conn_table.size; i++) { + conn = sock->conn_table.arr[i]; + if (conn->rkey[_c_idx].valid && ecp_ecdh_pub_eq(c_public, &conn->rkey[_c_idx].public)) return conn; } } } else if (addr) { - /* in case server is not returning client's public key in packet */ - for (i=0; i<sock->conn.size; i++) { - conn = sock->conn.array[i]; - if (ecp_conn_is_outb(conn) && ecp_tr_addr_eq(&conn->node.addr, addr)) return conn; + for (i=0; i<sock->conn_table.size; i++) { + conn = sock->conn_table.arr[i]; + if (ecp_conn_is_outb(conn) && ecp_tr_addr_eq(&conn->remote.addr, addr)) return conn; } } @@ -194,32 +246,26 @@ static ECPConnection *ctable_search(ECPSocket *sock, unsigned char c_idx, unsign } int ecp_sock_init(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key) { - if (sock == NULL) return ECP_ERR; - if (ctx == NULL) return ECP_ERR; - memset(sock, 0, sizeof(ECPSocket)); sock->ctx = ctx; - sock->poll_timeout = ECP_POLL_TIMEOUT; sock->key_curr = 0; if (key) sock->key_perma = *key; - sock->handler[ECP_MTYPE_OPEN] = ecp_sock_handle_open; - sock->handler[ECP_MTYPE_KGET] = ecp_sock_handle_kget; -#ifdef ECP_WITH_DIRSRV - sock->handler[ECP_MTYPE_DIR] = ecp_dir_handle_req; -#endif - return ecp_dhkey_gen(sock->ctx, &sock->key[sock->key_curr]); + return ecp_dhkey_gen(&sock->key[sock->key_curr]); } -int ecp_sock_create(ECPSocket *sock) { +int ecp_sock_create(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key) { int rv; - rv = ctable_create(&sock->conn, sock->ctx); + rv = ecp_sock_init(sock, ctx, key); + if (rv) return rv; + + rv = conn_table_create(&sock->conn_table); if (rv) return rv; rv = ecp_timer_create(&sock->timer); if (rv) { - ctable_destroy(&sock->conn, sock->ctx); + conn_table_destroy(&sock->conn_table); return rv; } @@ -227,28 +273,25 @@ int ecp_sock_create(ECPSocket *sock) { rv = pthread_mutex_init(&sock->mutex, NULL); if (rv) { ecp_timer_destroy(&sock->timer); - ctable_destroy(&sock->conn, sock->ctx); + conn_table_destroy(&sock->conn_table); return ECP_ERR; } #endif + arc4random_buf(&sock->nonce_out, sizeof(sock->nonce_out)); return ECP_OK; } void ecp_sock_destroy(ECPSocket *sock) { ecp_timer_destroy(&sock->timer); - ctable_destroy(&sock->conn, sock->ctx); + conn_table_destroy(&sock->conn_table); + #ifdef ECP_WITH_PTHREAD pthread_mutex_destroy(&sock->mutex); #endif } int ecp_sock_open(ECPSocket *sock, void *myaddr) { - int rv; - - rv = ecp_sock_create(sock); - if (rv) return rv; - return ecp_tr_open(sock, myaddr); } @@ -257,77 +300,158 @@ void ecp_sock_close(ECPSocket *sock) { ecp_tr_close(sock); } -ecp_sock_msg_handler_t ecp_sock_get_msg_handler(ECPSocket *sock, unsigned char mtype) { - return sock->handler[mtype]; +int ecp_sock_dhkey_new(ECPSocket *sock) { + ECPDHKey new_key; + int rv; + + rv = ecp_dhkey_gen(&new_key); + if (rv) return rv; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->mutex); +#endif + + sock->key_curr = (sock->key_curr + 1) % ECP_MAX_SOCK_KEY; + sock->key[sock->key_curr] = new_key; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->mutex); +#endif + + return ECP_OK; +} + +int ecp_sock_dhkey_get(ECPSocket *sock, unsigned char idx, ECPDHKey *key) { + int rv = ECP_OK; + + if (idx == ECP_ECDH_IDX_PERMA) { + *key = sock->key_perma; + } else { + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->mutex); +#endif + + if (idx < ECP_MAX_SOCK_KEY) { + *key = sock->key[idx]; + } else { + rv = ECP_ERR_ECDH_IDX; + } + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->mutex); +#endif + + } + + if (!rv && !key->valid) rv = ECP_ERR_ECDH_IDX; + return rv; } -int ecp_sock_dhkey_get_curr(ECPSocket *sock, unsigned char *idx, unsigned char *public) { +int ecp_sock_dhkey_get_pub(ECPSocket *sock, unsigned char *idx, ecp_ecdh_public_t *public) { + ECPDHKey *key; unsigned char _idx; + int rv = ECP_OK; #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&sock->mutex); #endif _idx = sock->key_curr; - if (_idx != ECP_ECDH_IDX_INV) ecp_cr_dh_pub_to_buf(public, &sock->key[_idx].public); + if (_idx == ECP_ECDH_IDX_INV) rv = ECP_ERR_ECDH_IDX; + + if (!rv) { + key = &sock->key[_idx]; + if (!key->valid) rv = ECP_ERR_ECDH_IDX; + } + if (!rv) memcpy(public, &key->public, sizeof(key->public)); #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&sock->mutex); #endif - if (_idx == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX; + if (rv) return rv; if (idx) *idx = _idx; return ECP_OK; } -int ecp_sock_dhkey_new(ECPSocket *sock) { - ECPDHKey new_key; - int rv; - - rv = ecp_dhkey_gen(sock->ctx, &new_key); - if (rv) return rv; - +void ecp_sock_get_nonce(ECPSocket *sock, ecp_nonce_t *nonce) { #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&sock->mutex); #endif - sock->key_curr = (sock->key_curr + 1) % ECP_MAX_SOCK_KEY; - sock->key[sock->key_curr] = new_key; - sock->key[(sock->key_curr + 1) % ECP_MAX_SOCK_KEY].valid = 0; + + *nonce = sock->nonce_out; + sock->nonce_out++; + #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&sock->mutex); #endif +} - return ECP_OK; +ECPConnection *ecp_sock_keys_search(ECPSocket *sock, ecp_ecdh_public_t *public) { + ECPConnection *conn; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->conn_table.mutex); +#endif + + conn = ecp_ht_search(sock->conn_table.keys, public); + if (conn) ecp_conn_refcount_inc(conn); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->conn_table.mutex); +#endif + + return conn; } -static ECPDHKey *conn_dhkey_get(ECPConnection *conn, unsigned char idx) { - if (conn->key_curr == ECP_ECDH_IDX_INV) { - if (idx < ECP_MAX_SOCK_KEY) return &conn->sock->key[idx]; - } else { - if (idx < ECP_MAX_CONN_KEY) return &conn->key[idx]; - } - return NULL; +int ecp_sock_keys_insert(ECPSocket *sock, ecp_ecdh_public_t *public, ECPConnection *conn) { + int rv; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->conn_table.mutex); +#endif + + rv = ecp_ht_insert(sock->conn_table.keys, public, conn); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->conn_table.mutex); +#endif + + return rv; +} + +void ecp_sock_keys_remove(ECPSocket *sock, ecp_ecdh_public_t *public) { +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->conn_table.mutex); +#endif + + ecp_ht_remove(sock->conn_table.keys, public); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->conn_table.mutex); +#endif } -static int conn_dhkey_new_pair(ECPConnection *conn, ECPDHKey *key) { +static int conn_dhkey_new(ECPConnection *conn, unsigned char idx, ECPDHKey *key) { ECPSocket *sock = conn->sock; - conn->key_curr = conn->key_curr == ECP_ECDH_IDX_INV ? 0 : (conn->key_curr+1) % ECP_MAX_CONN_KEY; + if (idx >= ECP_MAX_CONN_KEY) return ECP_ERR_ECDH_IDX; + #ifdef ECP_WITH_HTABLE - if (ecp_conn_is_outb(conn) && ecp_conn_is_reg(conn) && conn->key[conn->key_curr].valid) { - ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[conn->key_curr].public)); + if (ecp_conn_is_outb(conn) && ecp_conn_is_reg(conn) && conn->key[idx].valid) { + ecp_ht_remove(sock->conn_table.keys, &conn->key[idx].public); } #endif - conn->key[conn->key_curr] = *key; - conn->key_idx_map[conn->key_curr] = ECP_ECDH_IDX_INV; + conn->key[idx] = *key; #ifdef ECP_WITH_HTABLE if (ecp_conn_is_outb(conn) && ecp_conn_is_reg(conn)) { int rv; - rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[conn->key_curr].public), conn); + rv = ecp_ht_insert(sock->conn_table.keys, &conn->key[idx].public, conn); if (rv) return rv; } #endif @@ -335,172 +459,219 @@ static int conn_dhkey_new_pair(ECPConnection *conn, ECPDHKey *key) { return ECP_OK; } -static void conn_dhkey_del_pair(ECPConnection *conn, unsigned char idx) { +static void conn_dhkey_del(ECPConnection *conn, unsigned char idx) { ECPSocket *sock = conn->sock; + if (idx >= ECP_MAX_CONN_KEY) return; + #ifdef ECP_WITH_HTABLE if (ecp_conn_is_outb(conn) && ecp_conn_is_reg(conn) && conn->key[idx].valid) { - ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[idx].public)); + ecp_ht_remove(sock->conn_table.keys, &conn->key[idx].public); } #endif memset(&conn->key[idx], 0, sizeof(conn->key[idx])); - conn->key_idx_map[idx] = ECP_ECDH_IDX_INV; } -/* remote client obtained our key */ -static int conn_dhkey_new_pub_local(ECPConnection *conn, unsigned char idx) { - unsigned char new = conn->key_idx_curr == ECP_ECDH_IDX_INV ? 0 : (conn->key_idx_curr+1) % ECP_MAX_NODE_KEY; +static ECPDHKey *conn_dhkey_get(ECPConnection *conn, unsigned char idx) { + ECPDHKey *key = NULL; + + /* always outbound */ + if (idx < ECP_MAX_CONN_KEY) { + key = &conn->key[idx]; + } + + if (key && key->valid) return key; + return NULL; +} + +static ECPDHPub *conn_dhkey_get_remote(ECPConnection *conn, unsigned char idx) { + ECPDHPub *key = NULL; + + if (ecp_conn_is_outb(conn) && (idx == ECP_ECDH_IDX_PERMA)) { + key = &conn->remote.key_perma; + } else if ((idx & ECP_ECDH_IDX_MASK) == idx) { + key = &conn->rkey[idx % ECP_MAX_NODE_KEY]; + } + + if (key && key->valid) return key; + return NULL; +} + +/* node will send public key */ +static void conn_dhkey_get_pub(ECPConnection *conn, unsigned char idx) { + unsigned char _idx; int i; - if (idx >= ECP_MAX_SOCK_KEY) return ECP_ERR_ECDH_IDX; + _idx = idx % ECP_MAX_NODE_KEY; + if (ecp_conn_is_outb(conn)) { + if (idx == conn->key_curr) return; - if (conn->key_idx[new] != ECP_ECDH_IDX_INV) conn->key_idx_map[conn->key_idx[new]] = ECP_ECDH_IDX_INV; - conn->key_idx_map[idx] = new; - conn->key_idx[new] = idx; - conn->key_idx_curr = new; + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + conn->shkey[i][_idx].valid = 0; + } + } else { + if (idx == conn->rkey_curr) return; - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - conn->shared[new][i].valid = 0; + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + conn->shkey[_idx][i].valid = 0; + } } - return ECP_OK; } -/* this client obtained remote key */ -static int conn_dhkey_new_pub_remote(ECPConnection *conn, unsigned char idx, unsigned char *public) { +/* node received public key */ +static int conn_dhkey_set_pub(ECPConnection *conn, unsigned char idx, ecp_ecdh_public_t *public) { + unsigned char _idx; + ECPDHPub *key; ECPSocket *sock = conn->sock; - ECPDHRKeyBucket *remote = &conn->remote; - unsigned char new = remote->key_curr == ECP_ECDH_IDX_INV ? 0 : (remote->key_curr+1) % ECP_MAX_NODE_KEY; int i; - if (idx >= ECP_MAX_SOCK_KEY) return ECP_ERR_ECDH_IDX; - if ((remote->key_idx_map[idx] != ECP_ECDH_IDX_INV) && ecp_cr_dh_pub_eq(public, &remote->key[remote->key_idx_map[idx]].public)) return ECP_ERR_ECDH_KEY_DUP; + if (idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; + + _idx = idx % ECP_MAX_NODE_KEY; + key = &conn->rkey[_idx]; + if (key->valid && (memcmp(public, &key->public, sizeof(key->public)) == 0)) return ECP_ERR_ECDH_KEY_DUP; #ifdef ECP_WITH_HTABLE - if (ecp_conn_is_inb(conn) && ecp_conn_is_reg(conn) && (remote->key[new].idx != ECP_ECDH_IDX_INV)) { - ecp_ht_remove(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[new].public)); + if (ecp_conn_is_inb(conn) && ecp_conn_is_reg(conn) && (key->valid)) { + ecp_ht_remove(sock->conn_table.keys, &key->public); } #endif - if (remote->key[new].idx != ECP_ECDH_IDX_INV) remote->key_idx_map[remote->key[new].idx] = ECP_ECDH_IDX_INV; - remote->key_idx_map[idx] = new; - ecp_cr_dh_pub_from_buf(&remote->key[new].public, public); - remote->key[new].idx = idx; - remote->key_curr = new; + memcpy(&key->public, public, sizeof(key->public)); + key->valid = 1; #ifdef ECP_WITH_HTABLE if (ecp_conn_is_inb(conn) && ecp_conn_is_reg(conn)) { int rv; - rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[new].public), conn); + rv = ecp_ht_insert(sock->conn_table.keys, &key->public, conn); if (rv) return rv; } #endif - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - conn->shared[i][new].valid = 0; + if (ecp_conn_is_outb(conn)) { + conn->rkey_curr = idx; + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + conn->shkey[_idx][i].valid = 0; + } + } else { + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + conn->shkey[i][_idx].valid = 0; + } } return ECP_OK; } -static int conn_shsec_get(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, ecp_aead_key_t *shsec) { - if (s_idx == ECP_ECDH_IDX_PERMA) { - ECPDHKey *priv = NULL; - ecp_dh_public_t *public_p = NULL; - - if (ecp_conn_is_outb(conn)) { - public_p = &conn->node.public; - priv = conn_dhkey_get(conn, c_idx); - } else { -#if 0 - ECPDHRKey *pub = NULL; +static int conn_shkey_get(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, ecp_aead_key_t *shkey) { + ECPDHPub *pub; + ECPDHKey *priv; + int rv; - if (c_idx >= ECP_MAX_SOCK_KEY) return ECP_ERR_ECDH_IDX; - if (conn->remote.key_idx_map[c_idx] == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX_REMOTE; + if (ecp_conn_is_outb(conn) && (s_idx == ECP_ECDH_IDX_PERMA)) { + pub = conn_dhkey_get_remote(conn, s_idx); + priv = conn_dhkey_get(conn, c_idx); - pub = &conn->remote.key[conn->remote.key_idx_map[c_idx]]; - public_p = pub->idx != ECP_ECDH_IDX_INV ? &pub->public : NULL; - priv = &conn->sock->key_perma; -#endif - } - if (public_p == NULL) return ECP_ERR_ECDH_IDX; - if ((priv == NULL) || !priv->valid) return ECP_ERR_ECDH_IDX; - ecp_cr_dh_shsec(shsec, public_p, &priv->private); + if ((pub == NULL) || (priv == NULL)) return ECP_ERR_ECDH_IDX; + ecp_ecdh_shkey(shkey, &pub->public, &priv->private); } else { - unsigned char l_idx = ecp_conn_is_outb(conn) ? c_idx : s_idx; - unsigned char r_idx = ecp_conn_is_outb(conn) ? s_idx : c_idx; - ECPDHShared *shared = NULL; + ECPDHShkey *_shkey; - if ((l_idx >= ECP_MAX_SOCK_KEY) || (r_idx >= ECP_MAX_SOCK_KEY)) return ECP_ERR_ECDH_IDX; + if (s_idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; + if (c_idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; - if (conn->key_idx_map[l_idx] == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX_LOCAL; - if (conn->remote.key_idx_map[r_idx] == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX_REMOTE; + _shkey = &conn->shkey[s_idx % ECP_MAX_NODE_KEY][c_idx % ECP_MAX_NODE_KEY]; + if (!_shkey->valid) { + if (ecp_conn_is_inb(conn)) { + ECPSocket *sock = conn->sock; + ECPDHKey priv; - shared = &conn->shared[conn->key_idx_map[l_idx]][conn->remote.key_idx_map[r_idx]]; + pub = conn_dhkey_get_remote(conn, c_idx); + if (pub == NULL) return ECP_ERR_ECDH_IDX; - if (!shared->valid) { - ECPDHRKeyBucket *remote = &conn->remote; - ECPDHRKey *pub = &remote->key[conn->remote.key_idx_map[r_idx]]; - ECPDHKey *priv = conn_dhkey_get(conn, l_idx); + rv = ecp_sock_dhkey_get(sock, s_idx, &priv); + if (rv) return rv; - if ((pub == NULL) || (pub->idx == ECP_ECDH_IDX_INV)) return ECP_ERR_ECDH_IDX; - if ((priv == NULL) || !priv->valid) return ECP_ERR_ECDH_IDX; - ecp_cr_dh_shsec(&shared->secret, &pub->public, &priv->private); - shared->valid = 1; - } + ecp_ecdh_shkey(&_shkey->key, &pub->public, &priv.private); + conn->key_curr = s_idx; + conn->rkey_curr = c_idx; + } else { + pub = conn_dhkey_get_remote(conn, s_idx); + priv = conn_dhkey_get(conn, c_idx); - memcpy(shsec, &shared->secret, sizeof(shared->secret)); + if ((pub == NULL) || (priv == NULL)) return ECP_ERR_ECDH_IDX; + ecp_ecdh_shkey(&_shkey->key, &pub->public, &priv->private); + } + _shkey->valid = 1; + } + memcpy(shkey, &_shkey->key, sizeof(_shkey->key)); } return ECP_OK; } -static int conn_shsec_set(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, ecp_aead_key_t *shsec) { - unsigned char l_idx = ecp_conn_is_outb(conn) ? c_idx : s_idx; - unsigned char r_idx = ecp_conn_is_outb(conn) ? s_idx : c_idx; - ECPDHShared *shared = NULL; +static int conn_shkey_set(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, ecp_aead_key_t *shkey) { + ECPDHShkey *_shkey; - if ((l_idx >= ECP_MAX_SOCK_KEY) || (r_idx >= ECP_MAX_SOCK_KEY)) return ECP_ERR_ECDH_IDX; + if (s_idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; + if (c_idx & ~ECP_ECDH_IDX_MASK) return ECP_ERR_ECDH_IDX; - if (conn->key_idx_map[l_idx] == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX_LOCAL; - if (conn->remote.key_idx_map[r_idx] == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX_REMOTE; + _shkey = &conn->shkey[s_idx % ECP_MAX_NODE_KEY][c_idx % ECP_MAX_NODE_KEY]; + memcpy(_shkey->key, shkey, sizeof(_shkey->key)); + _shkey->valid = 1; - shared = &conn->shared[conn->key_idx_map[l_idx]][conn->remote.key_idx_map[r_idx]]; - memcpy(&shared->secret, shsec, sizeof(shared->secret)); - shared->valid = 1; + return ECP_OK; +} +int ecp_conn_alloc(ECPSocket *sock, unsigned char ctype, ECPConnection **_conn) { + ECPContext *ctx = sock->ctx; + ECPConnection *conn; + int rv; + + if (ctx->conn_alloc == NULL) return ECP_ERR_ALLOC; + + conn = ctx->conn_alloc(sock, ctype); + if (conn == NULL) return ECP_ERR_ALLOC; + + *_conn = conn; return ECP_OK; } -int ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { - int i; +void ecp_conn_free(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; - if (conn == NULL) return ECP_ERR; - if (sock == NULL) return ECP_ERR; + if (ctx->conn_free) ctx->conn_free(conn); +} - memset(conn, 0, sizeof(ECPConnection)); +void ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { + int i; - if (ctype >= ECP_MAX_CTYPE) return ECP_ERR_MAX_CTYPE; + memset(conn, 0, sizeof(ECPConnection)); - ecp_conn_set_new(conn); conn->sock = sock; conn->type = ctype; conn->key_curr = ECP_ECDH_IDX_INV; - conn->key_idx_curr = ECP_ECDH_IDX_INV; - conn->remote.key_curr = ECP_ECDH_IDX_INV; - memset(conn->key_idx, ECP_ECDH_IDX_INV, sizeof(conn->key_idx)); - memset(conn->key_idx_map, ECP_ECDH_IDX_INV, sizeof(conn->key_idx_map)); - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - conn->remote.key[i].idx = ECP_ECDH_IDX_INV; - } - memset(conn->remote.key_idx_map, ECP_ECDH_IDX_INV, sizeof(conn->remote.key_idx_map)); + conn->key_next = ECP_ECDH_IDX_INV; + conn->rkey_curr = ECP_ECDH_IDX_INV; + arc4random_buf(&conn->nonce_out, sizeof(conn->nonce_out)); +} - return ECP_OK; +void ecp_conn_reinit(ECPConnection *conn) { + conn->flags = 0; + conn->key_curr = ECP_ECDH_IDX_INV; + conn->key_next = ECP_ECDH_IDX_INV; + conn->rkey_curr = ECP_ECDH_IDX_INV; + memset(&conn->key, 0, sizeof(conn->key)); + memset(&conn->rkey, 0, sizeof(conn->rkey)); + memset(&conn->shkey, 0, sizeof(conn->shkey)); + arc4random_buf(&conn->nonce_out, sizeof(conn->nonce_out)); } -int ecp_conn_create(ECPConnection *conn) { +int ecp_conn_create(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { int rv; + ecp_conn_init(conn, sock, ctype); + #ifdef ECP_WITH_PTHREAD rv = pthread_mutex_init(&conn->mutex, NULL); if (rv) return ECP_ERR; @@ -509,207 +680,223 @@ int ecp_conn_create(ECPConnection *conn) { return ECP_OK; } +int ecp_conn_create_inb(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { + int rv; + + rv = ecp_conn_create(conn, sock, ctype); + if (rv) return rv; + + ecp_conn_set_inb(conn); + +#ifdef ECP_WITH_VCONN + if (conn->parent) { + ecp_conn_refcount_inc(conn->parent); + } +#endif + + return ECP_OK; +} + void ecp_conn_destroy(ECPConnection *conn) { +#ifdef ECP_WITH_VCONN + if (ecp_conn_is_inb(conn) && conn->parent) { + ecp_conn_refcount_dec(conn->parent); + } +#endif + + ecp_ext_conn_destroy(conn); + #ifdef ECP_WITH_PTHREAD pthread_mutex_destroy(&conn->mutex); #endif } -int ecp_conn_create_inb(ECPConnection *conn, ECPConnection *parent, unsigned char c_idx, unsigned char *public) { - ECPContext *ctx = conn->sock->ctx; +void ecp_conn_set_flags(ECPConnection *conn, unsigned char flags) { + flags &= flags & ECP_CONN_FLAG_MASK; + conn->flags_im |= flags; +} + +void ecp_conn_clr_flags(ECPConnection *conn, unsigned char flags) { + flags &= flags & ECP_CONN_FLAG_MASK; + conn->flags_im &= ~flags; +} + +void ecp_conn_set_remote_key(ECPConnection *conn, ECPDHPub *key) { + conn->remote.key_perma = *key; +} + +void ecp_conn_set_remote_addr(ECPConnection *conn, ecp_tr_addr_t *addr) { + conn->remote.addr = *addr; +} + +int ecp_conn_init_inb(ECPConnection *conn, ECPConnection *parent, unsigned char s_idx, unsigned char c_idx, ecp_ecdh_public_t *public, ECPDHPub *remote_key, ecp_aead_key_t *shkey) { + ECPSocket *sock = conn->sock; + unsigned short pcount; int rv; - rv = ecp_conn_create(conn); +#ifdef ECP_WITH_VCONN + pcount = (parent ? parent->pcount + 1 : 0); + if (pcount > ECP_MAX_PARENT) return ECP_ERR_MAX_PARENT; +#endif + + if (ecp_conn_has_vbox(conn) && ((remote_key == NULL) || !remote_key->valid)) return ECP_ERR_VBOX; + + rv = conn_dhkey_set_pub(conn, c_idx, public); if (rv) return rv; - conn->refcount = 1; - conn->parent = parent; - conn->pcount = parent ? parent->pcount+1 : 0; + rv = conn_shkey_set(conn, s_idx, c_idx, shkey); + if (rv) return rv; - rv = ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); - if (!rv) rv = conn_dhkey_new_pub_remote(conn, c_idx, public); +#ifdef ECP_WITH_VCONN + conn->parent = parent; + conn->pcount = pcount; +#endif - if (rv) { - ecp_conn_destroy(conn); - return rv; - } + conn->refcount = 1; + conn->key_curr = s_idx; + conn->rkey_curr = c_idx; + if (remote_key && remote_key->valid) conn->remote.key_perma = *remote_key; return ECP_OK; } -int ecp_conn_create_outb(ECPConnection *conn, ECPNode *node) { - ECPContext *ctx = conn->sock->ctx; +int ecp_conn_init_outb(ECPConnection *conn, ECPNode *node) { ECPDHKey key; int rv; - if (node == NULL) return ECP_ERR; - - rv = ecp_conn_create(conn); + rv = ecp_dhkey_gen(&key); if (rv) return rv; - ecp_conn_set_outb(conn); - conn->node = *node; - rv = ecp_dhkey_gen(ctx, &key); - if (!rv) rv = ctx->rng(conn->nonce, ECP_AEAD_SIZE_NONCE); - if (!rv) rv = ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); - - if (!rv) rv = conn_dhkey_new_pair(conn, &key); - if (!rv) rv = conn_dhkey_new_pub_local(conn, conn->key_curr); + rv = conn_dhkey_new(conn, 0, &key); + if (rv) return rv; - if (rv) { - ecp_conn_destroy(conn); - return rv; - } + if (node) conn->remote = *node; + conn->key_curr = 0; return ECP_OK; } int ecp_conn_insert(ECPConnection *conn) { - ecp_conn_clr_new(conn); - return ecp_conn_register(conn); -} - -int ecp_conn_register(ECPConnection *conn) { ECPSocket *sock = conn->sock; int rv; ecp_conn_set_reg(conn); + #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); + pthread_mutex_lock(&sock->conn_table.mutex); #endif - rv = ctable_insert(conn); + + rv = conn_table_insert(conn); + #ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->conn.mutex); + pthread_mutex_unlock(&sock->conn_table.mutex); #endif + if (rv) ecp_conn_clr_reg(conn); return rv; } -void ecp_conn_unregister(ECPConnection *conn, unsigned short *refcount) { +void ecp_conn_remove(ECPConnection *conn, unsigned short *refcount) { ECPSocket *sock = conn->sock; #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); + pthread_mutex_lock(&sock->conn_table.mutex); pthread_mutex_lock(&conn->mutex); #endif + if (ecp_conn_is_reg(conn)) { - ctable_remove(conn); + conn_table_remove(conn); ecp_conn_clr_reg(conn); } if (refcount) *refcount = conn->refcount; + #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); + pthread_mutex_unlock(&sock->conn_table.mutex); #endif } -int ecp_conn_get_dirlist(ECPConnection *conn, ECPNode *node) { - int rv; - ssize_t _rv; +void ecp_conn_remove_addr(ECPConnection *conn) { + ECPSocket *sock = conn->sock; - rv = ecp_conn_create_outb(conn, node); - if (rv) return rv; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->conn_table.mutex); + pthread_mutex_lock(&conn->mutex); +#endif - rv = ecp_conn_insert(conn); - if (rv) { - ecp_conn_destroy(conn); - return rv; - } + conn_table_remove_addr(conn); - _rv = ecp_conn_send_dir(conn); - if (_rv < 0) { - ecp_conn_close(conn); - return _rv; - } +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->conn_table.mutex); + pthread_mutex_lock(&conn->mutex); +#endif - return ECP_OK; } int ecp_conn_open(ECPConnection *conn, ECPNode *node) { int rv; ssize_t _rv; - rv = ecp_conn_create_outb(conn, node); + rv = ecp_conn_init_outb(conn, node); if (rv) return rv; rv = ecp_conn_insert(conn); - if (rv) { - ecp_conn_destroy(conn); - return rv; - } + if (rv) return rv; - _rv = ecp_conn_send_kget(conn); + _rv = ecp_send_init_req(conn); if (_rv < 0) { - ecp_conn_close(conn); + ecp_timer_remove(conn); + ecp_conn_remove(conn, NULL); return _rv; } return ECP_OK; } -static void conn_close(ECPConnection *conn) { - ECPContext *ctx = conn->sock->ctx; - - if (ecp_conn_is_inb(conn) && conn->parent) { - ecp_conn_refcount_dec(conn->parent); - } - - ecp_conn_destroy(conn); +int ecp_conn_reset(ECPConnection *conn) { + unsigned short refcount = 0; + int i; + int rv; - if (ecp_conn_is_inb(conn) && ctx->conn_free) ctx->conn_free(conn); -} + /* timer holds one reference to this connection */ + ecp_conn_remove(conn, &refcount); + if (refcount > 1) return ECP_ERR_BUSY; -int ecp_conn_close(ECPConnection *conn) { - unsigned short refcount = 0; - ecp_conn_close_t handler; + ecp_conn_reinit(conn); + if (rv) return rv; - ecp_conn_unregister(conn, &refcount); - ecp_timer_remove(conn); - handler = ecp_conn_get_close_handler(conn); - if (handler) handler(conn); + rv = ecp_conn_init_outb(conn, NULL); + if (rv) return rv; - if (refcount) return ECP_ERR_BUSY; + rv = ecp_conn_insert(conn); + if (rv) return rv; - conn_close(conn); return ECP_OK; } -int ecp_conn_reset(ECPConnection *conn) { - ECPDHKey key; - ECPSocket *sock = conn->sock; - ECPContext *ctx = sock->ctx; - int rv; - int i; +void _ecp_conn_close(ECPConnection *conn) { - rv = ecp_dhkey_gen(ctx, &key); - if (rv) return rv; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); - pthread_mutex_lock(&conn->mutex); -#endif + if (ecp_conn_is_open(conn)) { + ecp_close_handler_t handler; - for (i=0; i<ECP_MAX_CONN_KEY; i++) { - conn_dhkey_del_pair(conn, i); + ecp_conn_clr_open(conn); + handler = ecp_get_close_handler(conn); + if (handler) handler(conn); } - conn->key_curr = 0; - rv = conn_dhkey_new_pair(conn, &key); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->conn.mutex); -#endif + ecp_conn_destroy(conn); + if (ecp_conn_is_inb(conn)) ecp_conn_free(conn); +} - if (!rv) rv = conn_dhkey_new_pub_local(conn, conn->key_curr); - if (!rv) rv = ctx->rng(conn->nonce, ECP_AEAD_SIZE_NONCE); - if (!rv) rv = ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); - ecp_conn_clr_open(conn); +int ecp_conn_close(ECPConnection *conn) { + unsigned short refcount = 0; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + ecp_timer_remove(conn); + ecp_conn_remove(conn, &refcount); + if (refcount) return ECP_ERR_BUSY; - return rv; + _ecp_conn_close(conn); + return ECP_OK; } void ecp_conn_refcount_inc(ECPConnection *conn) { @@ -736,1210 +923,1396 @@ void ecp_conn_refcount_dec(ECPConnection *conn) { pthread_mutex_unlock(&conn->mutex); #endif - if (!is_reg && (refcount == 0)) conn_close(conn); -} - -int ecp_conn_handler_init(ECPConnHandler *handler) { - memset(handler, 0, sizeof(ECPConnHandler)); - handler->msg[ECP_MTYPE_OPEN] = ecp_conn_handle_open; - handler->msg[ECP_MTYPE_KGET] = ecp_conn_handle_kget; - handler->msg[ECP_MTYPE_KPUT] = ecp_conn_handle_kput; -#ifdef ECP_WITH_DIRSRV - handler->msg[ECP_MTYPE_DIR] = ecp_dir_handle_update; -#endif -#ifdef ECP_WITH_RBUF - handler->msg[ECP_MTYPE_RBACK] = ecp_rbuf_handle_ack; - handler->msg[ECP_MTYPE_RBFLUSH] = ecp_rbuf_handle_flush; - handler->msg[ECP_MTYPE_RBTIMER] = ecp_rbuf_handle_timer; -#endif - return ECP_OK; + if (!is_reg && (refcount == 0)) _ecp_conn_close(conn); } -ecp_conn_msg_handler_t ecp_conn_get_msg_handler(ECPConnection *conn, unsigned char mtype) { - ECPContext *ctx = conn->sock->ctx; - return ctx->handler[conn->type] ? ctx->handler[conn->type]->msg[mtype] : NULL; -} - -ecp_conn_close_t ecp_conn_get_close_handler(ECPConnection *conn) { - ECPContext *ctx = conn->sock->ctx; - return ctx->handler[conn->type] ? ctx->handler[conn->type]->conn_close : NULL; -} - - int ecp_conn_dhkey_new(ECPConnection *conn) { ECPSocket *sock = conn->sock; ECPDHKey new_key; + unsigned char idx; int rv; ssize_t _rv; - rv = ecp_dhkey_gen(sock->ctx, &new_key); + rv = ecp_dhkey_gen(&new_key); if (rv) return rv; #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); + if (ecp_conn_is_outb(conn)) pthread_mutex_lock(&sock->conn_table.mutex); pthread_mutex_lock(&conn->mutex); #endif - rv = conn_dhkey_new_pair(conn, &new_key); + + idx = conn->key_curr; + if (idx != ECP_ECDH_IDX_INV) { + idx = (idx + 1) % ECP_MAX_CONN_KEY; + rv = conn_dhkey_new(conn, idx, &new_key); + conn->key_next = idx; + } + #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); + if (ecp_conn_is_outb(conn)) pthread_mutex_unlock(&sock->conn_table.mutex); #endif - + if (idx == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX; if (rv) return rv; - _rv = ecp_conn_send_kput(conn); + _rv = ecp_send_keyx_req(conn); if (_rv < 0) return _rv; return ECP_OK; } -int ecp_conn_dhkey_new_pub(ECPConnection *conn, unsigned char idx, unsigned char *public) { +int ecp_conn_dhkey_get(ECPSocket *sock, unsigned char idx, ECPDHKey *key) { + int rv = ECP_OK; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&sock->mutex); +#endif + + if (idx < ECP_MAX_CONN_KEY) { + *key = sock->key[idx]; + } else { + rv = ECP_ERR_ECDH_IDX; + } + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&sock->mutex); +#endif + + if (!rv && !key->valid) rv = ECP_ERR_ECDH_IDX; + return rv; +} + +int ecp_conn_dhkey_get_pub(ECPConnection *conn, unsigned char *idx, ecp_ecdh_public_t *public, int will_send) { + int rv = ECP_OK; + unsigned char _idx; + + if (ecp_conn_is_inb(conn)) { + ECPSocket *sock = conn->sock; + + rv = ecp_sock_dhkey_get_pub(sock, &_idx, public); + if (rv) return rv; + +#ifdef ECP_WITH_PTHREAD + if (will_send) pthread_mutex_lock(&conn->mutex); +#endif + + } else { + ECPDHKey *key; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif + + if (will_send) { + _idx = conn->key_next; + } else { + _idx = conn->key_curr; + } + if (_idx == ECP_ECDH_IDX_INV) rv = ECP_ERR_ECDH_IDX; + + if (!rv) { + key = &conn->key[_idx]; + if (!key->valid) rv = ECP_ERR_ECDH_IDX; + } + if (!rv) memcpy(public, &key->public, sizeof(key->public)); + } + + if (!rv && will_send) conn_dhkey_get_pub(conn, _idx); + +#ifdef ECP_WITH_PTHREAD + if (will_send || ecp_conn_is_outb(conn)) pthread_mutex_unlock(&conn->mutex); +#endif + + if (rv) return rv; + + if (idx) *idx = _idx; + return ECP_OK; +} + +int ecp_conn_dhkey_set_pub(ECPConnection *conn, unsigned char idx, ecp_ecdh_public_t *public) { ECPSocket *sock = conn->sock; int rv; - if (conn == NULL) return ECP_ERR; - if (public == NULL) return ECP_ERR; - #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); + if (ecp_conn_is_inb(conn)) pthread_mutex_lock(&sock->conn_table.mutex); pthread_mutex_lock(&conn->mutex); #endif - rv = conn_dhkey_new_pub_remote(conn, idx, public); + rv = conn_dhkey_set_pub(conn, idx, public); #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); + if (ecp_conn_is_inb(conn)) pthread_mutex_unlock(&sock->conn_table.mutex); #endif if (rv == ECP_ERR_ECDH_KEY_DUP) rv = ECP_OK; return rv; } -int ecp_conn_dhkey_get_curr(ECPConnection *conn, unsigned char *idx, unsigned char *public) { - unsigned char _idx; - ECPSocket *sock = conn->sock; - +void ecp_conn_dhkey_set_curr(ECPConnection *conn) { #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&conn->mutex); #endif - _idx = conn->key_curr; - if (_idx != ECP_ECDH_IDX_INV) ecp_cr_dh_pub_to_buf(public, &conn->key[_idx].public); + if (conn->key_next != ECP_ECDH_IDX_INV) { + conn->key_curr = conn->key_next; + conn->key_next = ECP_ECDH_IDX_INV; + } #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); #endif +} - if (_idx == ECP_ECDH_IDX_INV) return ecp_sock_dhkey_get_curr(sock, idx, public); +void ecp_conn_handler_init(ECPConnHandler *handler, ecp_msg_handler_t handle_msg, ecp_open_handler_t handle_open, ecp_close_handler_t handle_close, ecp_open_send_t send_open) { + memset(handler, 0, sizeof(ECPConnHandler)); + handler->handle_msg = handle_msg; + handler->handle_open = handle_open; + handler->handle_close = handle_close; + handler->send_open = send_open; +} - if (idx) *idx = _idx; - return ECP_OK; +ecp_msg_handler_t ecp_get_msg_handler(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + unsigned char ctype; + + ctype = conn->type; + if (ecp_conn_is_sys(conn)) { + switch (ctype) { +#ifdef ECP_WITH_DIR + case ECP_CTYPE_DIR: + return ecp_dir_handle_msg; +#endif + +#ifdef ECP_WITH_VCONN + case ECP_CTYPE_VCONN: + case ECP_CTYPE_VLINK: + return ecp_vconn_handle_msg; +#endif + + default: + return NULL; + } + } + + if (ctype >= ECP_MAX_CTYPE) return NULL; + return ctx->handler[ctype] ? ctx->handler[ctype]->handle_msg : NULL; } -static ssize_t _conn_send_open(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char *buf; +ecp_open_handler_t ecp_get_open_handler(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + unsigned char ctype; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(1, ECP_MTYPE_OPEN_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(1, ECP_MTYPE_OPEN_REQ, conn); + ctype = conn->type; + if (ecp_conn_is_sys(conn)) { + switch (ctype) { +#ifdef ECP_WITH_DIR + case ECP_CTYPE_DIR: + return ecp_dir_handle_open; +#endif + +#ifdef ECP_WITH_VCONN + case ECP_CTYPE_VCONN: + case ECP_CTYPE_VLINK: + return ecp_vconn_handle_open; +#endif - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_OPEN_REQ); - buf = ecp_pld_get_buf(payload.buffer, payload.size); - buf[0] = conn->type; + default: + return NULL; + } + } - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(1, ECP_MTYPE_OPEN_REQ), 0, ti); + if (ctype >= ECP_MAX_CTYPE) return NULL; + return ctx->handler[ctype] ? ctx->handler[ctype]->handle_open : NULL; } -static ssize_t _conn_send_kget(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; +ecp_close_handler_t ecp_get_close_handler(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + unsigned char ctype; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); + ctype = conn->type; + if (ecp_conn_is_sys(conn)) { + switch (ctype) { +#ifdef ECP_WITH_DIR + case ECP_CTYPE_DIR: + return NULL; +#endif + +#ifdef ECP_WITH_VCONN + case ECP_CTYPE_VCONN: + case ECP_CTYPE_VLINK: + return ecp_vconn_handle_close; +#endif + + default: + return NULL; + } + } - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REQ); - return _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), 0, ti); + if (ctype >= ECP_MAX_CTYPE) return NULL; + return ctx->handler[ctype] ? ctx->handler[ctype]->handle_close : NULL; } -static ssize_t _conn_send_kput(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ, conn)]; - unsigned char *buf; - int rv; +ecp_dir_handler_t ecp_get_dir_handler(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ, conn); + return ctx->handle_dir; +} - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KPUT_REQ); - buf = ecp_pld_get_buf(payload.buffer, payload.size); - rv = ecp_conn_dhkey_get_curr(conn, buf, buf+1); - if (rv) return rv; +void ecp_err_handle(ECPConnection *conn, unsigned char mtype, int err) { + ECPContext *ctx = conn->sock->ctx; + int rv; + + rv = ecp_ext_err_handle(conn, mtype, err); + if (rv != ECP_PASS) return; - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ), 0, ti); + if (ctx->handle_err) ctx->handle_err(conn, mtype, err); } -static ssize_t _conn_send_dir(ECPConnection *conn, ECPTimerItem *ti) { +static ssize_t _send_ireq(ECPConnection *conn, ECPTimerItem *ti) { ECPBuffer packet; ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_DIR_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_DIR_REQ, conn)]; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_INIT_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_INIT_REQ, conn)]; packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_DIR_REQ, conn); + packet.size = sizeof(pkt_buf); payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_DIR_REQ, conn); + payload.size = sizeof(pld_buf); - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_DIR_REQ); - return _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_DIR_REQ), 0, ti); -} + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_INIT_REQ); -ssize_t ecp_conn_send_open(ECPConnection *conn) { - return ecp_timer_send(conn, _conn_send_open, ECP_MTYPE_OPEN_REP, 3, 500); + return _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, NULL, NULL, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_INIT_REQ), 0, ti); } -ssize_t ecp_conn_send_kget(ECPConnection *conn) { - return ecp_timer_send(conn, _conn_send_kget, ECP_MTYPE_KGET_REP, 3, 500); +static ssize_t _retry_ireq(ECPConnection *conn, ECPTimerItem *ti) { + int rv; + + rv = ecp_conn_reset(conn); + if (rv) return rv; + + return _send_ireq(conn, ti); } -ssize_t ecp_conn_send_kput(ECPConnection *conn) { - return ecp_timer_send(conn, _conn_send_kput, ECP_MTYPE_KPUT_REP, 3, 500); +ssize_t ecp_send_init_req(ECPConnection *conn) { + ECPTimerItem ti; + + ecp_timer_item_init(&ti, conn, ECP_MTYPE_OPEN_REP, _retry_ireq, ECP_SEND_TRIES-1, ECP_SEND_TIMEOUT); + + return _send_ireq(conn, &ti); } -ssize_t ecp_conn_send_dir(ECPConnection *conn) { - return ecp_timer_send(conn, _conn_send_dir, ECP_MTYPE_DIR_REP, 3, 500); +ssize_t ecp_handle_init_req(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, unsigned char *public_buf, ecp_aead_key_t *shkey) { + ssize_t rv; + + rv = ecp_send_init_rep(sock, parent, addr, public_buf, shkey); + if (rv < 0) return rv; + + return 0; } -ssize_t _ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b, int *was_open) { +ssize_t ecp_send_init_rep(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, unsigned char *public_buf, ecp_aead_key_t *shkey) { + ECPBuffer packet; + ECPBuffer payload; + ECPPktMeta pkt_meta; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF_IREP(1+ECP_SIZE_ECDH_PUB+ECP_SIZE_COOKIE, ECP_MTYPE_INIT_REP, parent)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF_IREP(1+ECP_SIZE_ECDH_PUB+ECP_SIZE_COOKIE, ECP_MTYPE_INIT_REP, parent)]; + unsigned char cookie[ECP_SIZE_COOKIE]; + unsigned char *msg; + ecp_nonce_t nonce; ssize_t rv; int _rv; - if (mtype & ECP_MTYPE_FLAG_REP) { - int is_open; + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); - if (ecp_conn_is_inb(conn)) return ECP_ERR; + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_INIT_REP); + msg = ecp_pld_get_msg(payload.buffer, payload.size); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - is_open = ecp_conn_is_open(conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + _rv = ecp_cookie_gen(sock, cookie, public_buf); + if (_rv) return _rv; - if (is_open && size == ECP_ERR_TIMEOUT) { - _rv = ecp_conn_reset(conn); - if (_rv) return _rv; - return 0; - } + _rv = ecp_sock_dhkey_get_pub(sock, msg, (ecp_ecdh_public_t *)(msg+1)); + if (_rv) return _rv; + memcpy(msg+1+ECP_SIZE_ECDH_PUB, cookie, ECP_SIZE_COOKIE); + + ecp_sock_get_nonce(sock, &nonce); + pkt_meta.cookie = NULL; + pkt_meta.public = NULL; + pkt_meta.shkey = shkey; + pkt_meta.nonce = &nonce; + pkt_meta.ntype = ECP_NTYPE_INB; + pkt_meta.s_idx = 0xf; + pkt_meta.c_idx = 0xf; + + rv = ecp_pld_send_irep(sock, parent, addr, &packet, &pkt_meta, &payload, ECP_SIZE_PLD(1+ECP_SIZE_ECDH_PUB+ECP_SIZE_COOKIE, ECP_MTYPE_INIT_REP), 0); + return rv; +} - if (size < 0) return size; +ssize_t ecp_handle_init_rep(ECPConnection *conn, unsigned char *msg, size_t msg_size) { + ecp_open_send_t send_open_f; + unsigned char ctype; + unsigned char *cookie; + ssize_t rv; + int _rv; - if (was_open) *was_open = is_open; + if (msg_size < 1+ECP_SIZE_ECDH_PUB+ECP_SIZE_COOKIE) return ECP_ERR_SIZE; - if (!is_open) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - ecp_conn_set_open(conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); + _rv = ecp_conn_dhkey_set_pub(conn, msg[0], (ecp_ecdh_public_t *)(msg+1)); + if (_rv) return _rv; + + ctype = conn->type; + send_open_f = NULL; + cookie = msg+1+ECP_SIZE_ECDH_PUB; + if (ecp_conn_is_sys(conn)) { + switch (ctype) { +#ifdef ECP_WITH_VCONN + case ECP_CTYPE_VCONN: + case ECP_CTYPE_VLINK: + send_open_f = ecp_vconn_send_open_req; + break; #endif - } - rv = 0; + default: + break; + } } else { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_OPEN_REP, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_OPEN_REP, conn)]; - unsigned char ctype; - int is_new; - - if (size < 0) return size; - if (size < 1) return ECP_ERR; - if (ecp_conn_is_outb(conn)) return ECP_ERR; + ECPContext *ctx = conn->sock->ctx; - is_new = ecp_conn_is_new(conn); - if (is_new) { - ecp_conn_set_open(conn); - _rv = ecp_conn_insert(conn); - if (_rv) return rv; - } + if (ctype >= ECP_MAX_CTYPE) return ECP_ERR_CTYPE; + send_open_f = ctx->handler[ctype] ? ctx->handler[ctype]->send_open : NULL; + } + if (send_open_f == NULL) send_open_f = ecp_send_open_req; + + rv = send_open_f(conn, cookie); + if (rv < 0) return rv; - if (was_open) *was_open = !is_new; + return 1+ECP_SIZE_ECDH_PUB+ECP_SIZE_COOKIE; +} - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_OPEN_REP, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_OPEN_REP, conn); +ssize_t ecp_write_open_req(ECPConnection *conn, ECPBuffer *payload) { + unsigned char *msg; + unsigned char vbox; + ssize_t rv; + int _rv; + + if (payload->size < ECP_SIZE_PLD(2, ECP_MTYPE_OPEN_REQ)) return ECP_ERR_SIZE; + + ecp_pld_set_type(payload->buffer, payload->size, ECP_MTYPE_OPEN_REQ); + msg = ecp_pld_get_msg(payload->buffer, payload->size); + *msg = conn->type; + msg++; + + vbox = ecp_conn_has_vbox(conn); + *msg = vbox; + msg++; + + rv = 0; + if (vbox) { + ECPSocket *sock = conn->sock; + ECPDHKey key; + ECPDHPub *remote_key; + ecp_ecdh_public_t public; + ecp_aead_key_t vbox_shkey; + ecp_nonce_t vbox_nonce; + + remote_key = &conn->remote.key_perma; + if (payload->size < ECP_SIZE_PLD(2+ECP_SIZE_VBOX, ECP_MTYPE_OPEN_REQ)) _rv = ECP_ERR_SIZE; + if (!_rv && !remote_key->valid) _rv = ECP_ERR; + if (!_rv) _rv = ecp_sock_dhkey_get(sock, ECP_ECDH_IDX_PERMA, &key); + if (!_rv) _rv = ecp_conn_dhkey_get_pub(conn, NULL, &public, 0); + if (_rv) return _rv; + + memcpy(msg, &key.public, ECP_SIZE_ECDH_PUB); + msg += ECP_SIZE_ECDH_PUB; - ctype = msg[0]; - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_OPEN_REP); - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_OPEN_REP), 0); + arc4random_buf(&vbox_nonce, sizeof(vbox_nonce)); + ecp_nonce2buf(msg, &vbox_nonce); + msg += ECP_SIZE_NONCE; - rv = 1; + ecp_ecdh_shkey(&vbox_shkey, &remote_key->public, &key.private); + rv = ecp_aead_enc(msg, payload->size - (msg - payload->buffer), (unsigned char *)&public, ECP_SIZE_ECDH_PUB, &vbox_shkey, &vbox_nonce, ECP_NTYPE_VBOX); + if (rv < 0) return rv; } - return rv; + return ECP_SIZE_PLD(2+rv, ECP_MTYPE_OPEN_REQ); } -ssize_t ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - return _ecp_conn_handle_open(conn, seq, mtype, msg, size, b, NULL); +ssize_t ecp_send_open_req(ECPConnection *conn, unsigned char *cookie) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF_WCOOKIE(2+ECP_SIZE_VBOX, ECP_MTYPE_OPEN_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(2+ECP_SIZE_VBOX, ECP_MTYPE_OPEN_REQ, conn)]; + ssize_t rv; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + rv = ecp_write_open_req(conn, &payload); + if (rv < 0) return rv; + + rv = ecp_pld_send_wcookie(conn, &packet, &payload, rv, 0, cookie); + return rv; } -ssize_t _ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b, ecp_conn_open_t conn_open) { +ssize_t ecp_handle_open_req(ECPSocket *sock, ECPConnection *parent, unsigned char s_idx, unsigned char c_idx, unsigned char *public_buf, unsigned char *msg, size_t msg_size, ecp_aead_key_t *shkey, ECPConnection **_conn) { + ECPConnection *conn; + ECPDHPub remote_key; + unsigned char ctype; + unsigned char vbox; ssize_t rv; int _rv; - if (mtype & ECP_MTYPE_FLAG_REP) { - ECPContext *ctx = conn->sock->ctx; - int is_open; - - if (ecp_conn_is_inb(conn)) return ECP_ERR; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - is_open = ecp_conn_is_open(conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + if (msg_size < 2) return ECP_ERR_SIZE; + ctype = *msg; + msg++; - if ((size < 0) && !is_open) { - ecp_conn_msg_handler_t handler; + vbox = *msg; + msg++; - handler = ecp_conn_get_msg_handler(conn, ECP_MTYPE_OPEN); - return handler ? handler(conn, seq, mtype, msg, size, b) : size; - } + msg_size -= 2; + remote_key.valid = 0; + if (vbox) { + ECPDHKey key; + ecp_ecdh_public_t public; + ecp_aead_key_t vbox_shkey; + ecp_nonce_t vbox_nonce; - if (size < 0) return size; - if (size < ECP_ECDH_SIZE_KEY+1) return ECP_ERR; + if (msg_size < ECP_SIZE_VBOX) return ECP_ERR_SIZE; - _rv = ecp_conn_dhkey_new_pub(conn, msg[0], msg+1); + _rv = ecp_sock_dhkey_get(sock, ECP_ECDH_IDX_PERMA, &key); if (_rv) return _rv; - if (!is_open && conn_open) { - rv = conn_open(conn); - } - - rv = ECP_ECDH_SIZE_KEY+1; - } else { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, conn)]; - unsigned char *buf; + memcpy(&remote_key.public, msg, ECP_SIZE_ECDH_PUB); + msg+= ECP_SIZE_ECDH_PUB; + msg_size -= ECP_SIZE_ECDH_PUB; - if (ecp_conn_is_outb(conn)) return ECP_ERR; - if (size < 0) return size; + ecp_buf2nonce(&vbox_nonce, msg); + msg+= ECP_SIZE_NONCE; + msg_size -= ECP_SIZE_NONCE; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, conn); + ecp_ecdh_shkey(&vbox_shkey, &remote_key.public, &key.private); + rv = ecp_aead_dec((unsigned char *)&public, ECP_SIZE_ECDH_PUB, msg, msg_size, &vbox_shkey, &vbox_nonce, ECP_NTYPE_VBOX); + if (rv != ECP_SIZE_ECDH_PUB) return ECP_ERR_VBOX; - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REP); - buf= ecp_pld_get_buf(payload.buffer, payload.size); + if (memcmp(&public, public_buf, ECP_SIZE_ECDH_PUB) != 0) return ECP_ERR_VBOX; + remote_key.valid = 1; + } - _rv = ecp_conn_dhkey_get_curr(conn, buf, buf+1); - if (_rv) return _rv; - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP), 0); + _rv = ecp_conn_alloc(sock, ctype, &conn); + if (_rv) return _rv; - rv = 0; + _rv = ecp_conn_init_inb(conn, parent, s_idx, c_idx, (ecp_ecdh_public_t *)public_buf, remote_key.valid ? &remote_key : NULL, shkey); + if (!_rv) _rv = ecp_conn_insert(conn); + if (_rv) { + ecp_conn_destroy(conn); + ecp_conn_free(conn); + return _rv; } - return rv; -} + *_conn = conn; -ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - return _ecp_conn_handle_kget(conn, seq, mtype, msg, size, b, ecp_conn_send_open); + /* handle_open will be called later from msg handler */ + return 2+(vbox ? ECP_SIZE_VBOX : 0); } -ssize_t ecp_conn_handle_kput(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { +ssize_t ecp_send_open_rep(ECPConnection *conn) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_OPEN_REP, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_OPEN_REP, conn)]; ssize_t rv; - int _rv; - if (size < 0) return size; + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); - if (mtype & ECP_MTYPE_FLAG_REP) { - if (ecp_conn_is_inb(conn)) return ECP_ERR; + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_OPEN_REP); + rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_OPEN_REP), 0); + return rv; +} - rv = 0; - } else { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KPUT_REP, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KPUT_REP, conn)]; +ssize_t ecp_handle_open(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { + size_t rsize; + ecp_open_handler_t handler; + int rv = ECP_OK; + if (mtype == ECP_MTYPE_OPEN_REQ) { if (ecp_conn_is_outb(conn)) return ECP_ERR; - if (size < ECP_ECDH_SIZE_KEY+1) return ECP_ERR; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KPUT_REP, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KPUT_REP, conn); + rsize = 2; + if (msg_size < rsize) return ECP_ERR_SIZE; - _rv = ecp_conn_dhkey_new_pub(conn, msg[0], msg+1); - if (_rv) return _rv; + if (msg[1]) rsize += ECP_SIZE_VBOX; + if (msg_size < rsize) return ECP_ERR_SIZE; + } else { + if (ecp_conn_is_inb(conn)) return ECP_ERR; + rsize = 0; + } - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KPUT_REP); - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KPUT_REP), 0); +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif - rv = ECP_ECDH_SIZE_KEY+1; - } + if (ecp_conn_is_open(conn)) rv = ECP_ERR; + if (!rv) rv = ecp_ext_conn_open(conn); + if (!rv) ecp_conn_set_open(conn); - return rv; -} +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); +#endif -ssize_t ecp_conn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { - ecp_conn_msg_handler_t handler; - unsigned char mtype = 0; - unsigned char *content = NULL; - size_t rem_size = msg_size; - ssize_t rv; - int _rv; + if (rv) return rv; - while (rem_size) { - _rv = ecp_msg_get_type(msg, rem_size, &mtype); - if (_rv) return ECP_ERR; - if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; + handler = ecp_get_open_handler(conn); + if (handler) rv = handler(conn, bufs); + if (rv) { +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif - ecp_timer_pop(conn, mtype); + ecp_conn_clr_open(conn); - if (mtype & ECP_MTYPE_FLAG_FRAG) { -#ifdef ECP_WITH_RBUF - ECPFragIter *iter = ecp_rbuf_get_frag_iter(conn); - if (iter) { - _rv = ecp_msg_defrag(iter, seq, mtype, msg, msg_size, &msg, &rem_size); - if (_rv == ECP_ITER_NEXT) break; - if (_rv < 0) return _rv; - } else { - return ECP_ERR_ITER; - } +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); #endif - } - content = ecp_msg_get_content(msg, rem_size); - if (content == NULL) return ECP_ERR; - rem_size -= content - msg; + if (ecp_conn_is_inb(conn)) ecp_conn_close(conn); + return rv; + } - handler = ecp_conn_get_msg_handler(conn, mtype & ECP_MTYPE_MASK); - if (handler) { - rv = handler(conn, seq, mtype, content, rem_size, bufs); - if (rv < 0) return rv; - if (rv > rem_size) return ECP_ERR; - if (mtype & ECP_MTYPE_FLAG_FRAG) break; + if (ecp_conn_is_inb(conn)) { + ssize_t _rv; - rem_size -= rv; - msg = content + rv; - } else { - return msg_size - rem_size - 1; + _rv = ecp_send_open_rep(conn); + if (_rv < 0) { + ecp_conn_close(conn); + return _rv; } + } else { + ecp_conn_remove_addr(conn); } - - return msg_size; + return rsize; } -ssize_t ecp_sock_handle_open(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, ECPConnection **_conn) { - ECPConnection *conn = NULL; - unsigned char c_idx = pkt_meta->c_idx; - unsigned char ctype; - int rv; - - if (msg_size < 0) return msg_size; - if (msg_size < 1) return ECP_ERR; +static ssize_t _send_keyx_req(ECPConnection *conn, ECPTimerItem *ti) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REQ, conn)]; + unsigned char *msg; + ssize_t rv; + int _rv; - ctype = msg[0]; + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); - conn = sock->ctx->conn_alloc ? sock->ctx->conn_alloc(sock, ctype) : NULL; - if (conn == NULL) return ECP_ERR_ALLOC; + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KEYX_REQ); + msg = ecp_pld_get_msg(payload.buffer, payload.size); - rv = ecp_conn_create_inb(conn, parent, c_idx, pkt_meta->public); - if (rv) { - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } + _rv = ecp_conn_dhkey_get_pub(conn, msg, (ecp_ecdh_public_t *)(msg+1), 1); + if (_rv) return _rv; - if (parent) { - ecp_conn_refcount_inc(parent); - } + rv = ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REQ), 0, ti); + return rv; +} - *_conn = conn; - return 1; +ssize_t ecp_send_keyx_req(ECPConnection *conn) { + return ecp_timer_send(conn, _send_keyx_req, ECP_MTYPE_KEYX_REP, ECP_SEND_TRIES, ECP_SEND_TIMEOUT); } -ssize_t ecp_sock_handle_kget(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, ECPConnection **_conn) { +ssize_t ecp_send_keyx_rep(ECPConnection *conn) { ECPBuffer packet; ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent)]; - unsigned char *buf; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REP, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REP, conn)]; + unsigned char *msg; ssize_t rv; int _rv; - if (msg_size < 0) return msg_size; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); + packet.size = sizeof(pkt_buf); payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); + payload.size = sizeof(pld_buf); - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REP); - buf = ecp_pld_get_buf(payload.buffer, payload.size); + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KEYX_REP); + msg = ecp_pld_get_msg(payload.buffer, payload.size); - _rv = ecp_sock_dhkey_get_curr(sock, buf, buf+1); + _rv = ecp_conn_dhkey_get_pub(conn, msg, (ecp_ecdh_public_t *)(msg+1), 1); if (_rv) return _rv; - rv = ecp_pld_send_tr(sock, addr, parent, &packet, pkt_meta, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP), 0); - if (rv < 0) return rv; - - return msg_size; + rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(1+ECP_SIZE_ECDH_PUB, ECP_MTYPE_KEYX_REP), 0); + return rv; } -ssize_t _ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, ECPPktMeta *pkt_meta, unsigned char *payload, size_t pld_size) { +ssize_t ecp_handle_keyx(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size) { ssize_t rv; - unsigned char s_idx, c_idx; + int _rv; - if (pkt_size < ECP_SIZE_PKT_HDR) return ECP_ERR; + if (msg_size < 1+ECP_SIZE_ECDH_PUB) return ECP_ERR_SIZE; - // ECP_SIZE_PROTO - packet[0] = 0; - packet[1] = 0; - s_idx = pkt_meta->s_idx & 0x0F; - c_idx = pkt_meta->c_idx & 0x0F; - packet[ECP_SIZE_PROTO] = (s_idx << 4) | c_idx; - memcpy(packet+ECP_SIZE_PROTO+1, pkt_meta->public, ECP_ECDH_SIZE_KEY); - memcpy(packet+ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY, pkt_meta->nonce, ECP_AEAD_SIZE_NONCE); - - payload[0] = (pkt_meta->seq & 0xFF000000) >> 24; - payload[1] = (pkt_meta->seq & 0x00FF0000) >> 16; - payload[2] = (pkt_meta->seq & 0x0000FF00) >> 8; - payload[3] = (pkt_meta->seq & 0x000000FF); - rv = ecp_cr_aead_enc(packet+ECP_SIZE_PKT_HDR, pkt_size-ECP_SIZE_PKT_HDR, payload, pld_size, &pkt_meta->shsec, pkt_meta->nonce); - if (rv < 0) return ECP_ERR_ENCRYPT; + _rv = ecp_conn_dhkey_set_pub(conn, msg[0], (ecp_ecdh_public_t *)(msg+1)); + if (_rv) return _rv; - memcpy(pkt_meta->nonce, packet+ECP_SIZE_PKT_HDR, ECP_AEAD_SIZE_NONCE); + if (mtype == ECP_MTYPE_KEYX_REP) { + if (ecp_conn_is_inb(conn)) return ECP_ERR; - return rv+ECP_SIZE_PKT_HDR; -} + ecp_conn_dhkey_set_curr(conn); + } else { + if (ecp_conn_is_outb(conn)) return ECP_ERR; -#ifndef ECP_WITH_VCONN -ssize_t ecp_pack(ECPContext *ctx, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; + rv = ecp_send_keyx_rep(conn); + if (rv < 0) return rv; + } - return _ecp_pack(ctx, packet->buffer, packet->size, pkt_meta, payload->buffer, pld_size); + return 1+ECP_SIZE_ECDH_PUB; } -#endif -ssize_t _ecp_pack_conn(ECPConnection *conn, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si) { - ECPPktMeta pkt_meta; - int rv; - ssize_t _rv; +ssize_t ecp_msg_handle(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { + if (mtype & ECP_MTYPE_FLAG_SYS) { + switch (mtype) { + case ECP_MTYPE_OPEN_REQ: + case ECP_MTYPE_OPEN_REP: + return ecp_handle_open(conn, mtype, msg, msg_size, bufs); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif + case ECP_MTYPE_KEYX_REQ: + case ECP_MTYPE_KEYX_REP: + return ecp_handle_keyx(conn, mtype, msg, msg_size); - if (s_idx == ECP_ECDH_IDX_INV) { - if (ecp_conn_is_outb(conn)) { - if (conn->remote.key_curr != ECP_ECDH_IDX_INV) s_idx = conn->remote.key[conn->remote.key_curr].idx; - } else { - if (conn->key_idx_curr != ECP_ECDH_IDX_INV) s_idx = conn->key_idx[conn->key_idx_curr]; - } - } - if (c_idx == ECP_ECDH_IDX_INV) { - if (ecp_conn_is_outb(conn)) { - if (conn->key_idx_curr != ECP_ECDH_IDX_INV) c_idx = conn->key_idx[conn->key_idx_curr]; - } else { - if (conn->remote.key_curr != ECP_ECDH_IDX_INV) c_idx = conn->remote.key[conn->remote.key_curr].idx; + default: + return ecp_ext_msg_handle(conn, seq, mtype, msg, msg_size, bufs); } - } - rv = conn_shsec_get(conn, s_idx, c_idx, &pkt_meta.shsec); - if (!rv) memcpy(pkt_meta.nonce, conn->nonce, sizeof(pkt_meta.nonce)); - if (!rv) { - if (ecp_conn_is_outb(conn)) { - ECPDHKey *key = conn_dhkey_get(conn, c_idx); + } else { + ecp_msg_handler_t handler; - if ((key == NULL) || !key->valid) rv = ECP_ERR_ECDH_IDX; - if (!rv) memcpy(&pkt_meta.public, &key->public, sizeof(pkt_meta.public)); + handler = ecp_get_msg_handler(conn); + if (handler) { + return handler(conn, seq, mtype, msg, msg_size, bufs); } else { - memcpy(&pkt_meta.public, &conn->remote.key[conn->remote.key_curr].public, sizeof(pkt_meta.public)); + return ECP_ERR_HANDLER; } } - if (!rv) { - if (si) { - if (si->seq_w) { - pkt_meta.seq = si->seq; - } else { - pkt_meta.seq = conn->seq_out + 1; - si->seq = pkt_meta.seq; - } - -#ifdef ECP_WITH_RBUF - if (conn->rbuf.send) { - rv = ecp_rbuf_set_seq(conn, si, payload, pld_size); - } -#endif +} - if (!rv && !si->seq_w) conn->seq_out = pkt_meta.seq; - } else { - pkt_meta.seq = conn->seq_out + 1; - conn->seq_out = pkt_meta.seq; - } - if (!rv && addr) *addr = conn->node.addr; - } +ssize_t ecp_pld_handle_one(ECPConnection *conn, ecp_seq_t seq, unsigned char *payload, size_t pld_size, ECP2Buffer *bufs) { + unsigned char mtype; + unsigned char *msg; + size_t hdr_size, msg_size; + ssize_t rv; + int _rv; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + _rv = ecp_pld_get_type(payload, pld_size, &mtype); + if (_rv) return _rv; - if (rv) return rv; + ecp_timer_pop(conn, mtype); - pkt_meta.s_idx = s_idx; - pkt_meta.c_idx = c_idx; - _rv = _ecp_pack(conn->sock->ctx, packet, pkt_size, &pkt_meta, payload, pld_size); - if (_rv < 0) return _rv; + msg = ecp_pld_get_msg(payload, pld_size); + if (msg == NULL) return ECP_ERR; + hdr_size = msg - payload; + msg_size = pld_size - hdr_size; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - memcpy(conn->nonce, pkt_meta.nonce, sizeof(conn->nonce)); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + rv = ecp_msg_handle(conn, seq, mtype, msg, msg_size, bufs); + if (rv < 0) return rv; - return _rv; + rv += hdr_size; + if (rv > pld_size) return ECP_ERR_SIZE; + return rv; } -#ifndef ECP_WITH_VCONN -ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; +ssize_t ecp_pld_handle(ECPConnection *conn, ecp_seq_t seq, unsigned char *payload, size_t _pld_size, ECP2Buffer *bufs) { + size_t pld_size = _pld_size; + ssize_t rv; + + rv = ecp_ext_pld_handle(conn, seq, payload, pld_size, bufs); + if (rv < 0) return rv; + + payload += rv; + pld_size -= rv; + + while (pld_size) { + rv = ecp_pld_handle_one(conn, seq, payload, pld_size, bufs); + if (rv == ECP_ERR_HANDLER) return _pld_size - pld_size; + if (rv < 0) return rv; + + payload += rv; + pld_size -= rv; + } - return _ecp_pack_conn(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, addr, si); + return _pld_size; } -#endif -ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size, ECPConnection **_conn, ecp_seq_t *_seq) { +ssize_t ecp_unpack(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECP2Buffer *bufs, size_t _pkt_size, ECPConnection **_conn, unsigned char **_payload, ecp_seq_t *_seq) { + ECPConnection *conn = NULL; + unsigned char idx; unsigned char s_idx; unsigned char c_idx; - unsigned char l_idx = ECP_ECDH_IDX_INV; - unsigned char *payload = bufs->payload->buffer; - unsigned char *packet = bufs->packet->buffer; - size_t pld_size = bufs->payload->size; - ssize_t dec_size; - ecp_aead_key_t shsec; - ecp_dh_public_t public; - ecp_dh_private_t private; - unsigned char *public_buf; - unsigned char *nonce; - unsigned char nonce_next[ECP_AEAD_SIZE_NONCE]; - ECPConnection *conn = NULL; - ECPDHKey *key = NULL; - unsigned char mtype; + unsigned char *payload; + unsigned char *packet; + ssize_t pld_size; + size_t pkt_size = _pkt_size; + ecp_aead_key_t shkey; + unsigned char *public_buf = NULL; + unsigned char *nonce_buf = NULL; unsigned char is_open = 0; - unsigned char seq_check; - unsigned char seq_reset; - ecp_seq_t seq_pkt, seq_conn, seq_last; - ecp_ack_t seq_map; - int rv = ECP_OK; + unsigned char is_inb = 0; + ecp_nonce_t nonce_pkt, nonce_conn, nonce_in; + ecp_ack_t nonce_map; + ssize_t rv; + int _rv = ECP_OK; + + if (pkt_size < ECP_MIN_PKT) return ECP_ERR_SIZE; *_conn = NULL; + *_payload = NULL; *_seq = 0; - s_idx = (packet[ECP_SIZE_PROTO] & 0xF0) >> 4; - c_idx = (packet[ECP_SIZE_PROTO] & 0x0F); - - public_buf = packet+ECP_SIZE_PROTO+1; - nonce = packet+ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY; + packet = bufs->packet->buffer; + idx = packet[ECP_SIZE_PROTO]; + s_idx = (idx & 0xF0) >> 4; + c_idx = (idx & 0x0F); + if (idx != ECP_ECDH_IDX_INV) { + public_buf = packet+ECP_SIZE_PROTO+1; + } #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); + pthread_mutex_lock(&sock->conn_table.mutex); #endif - conn = ctable_search(sock, c_idx, public_buf, NULL); - if (conn && ecp_conn_is_inb(conn) && (s_idx == ECP_ECDH_IDX_PERMA)) conn = NULL; + conn = conn_table_search(sock, c_idx, (ecp_ecdh_public_t *)public_buf, addr); #ifdef ECP_WITH_PTHREAD if (conn) pthread_mutex_lock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); + pthread_mutex_unlock(&sock->conn_table.mutex); #endif if (conn) { - rv = conn_shsec_get(conn, s_idx, c_idx, &shsec); - if (rv == ECP_ERR_ECDH_IDX_LOCAL) { - rv = ECP_OK; - l_idx = ecp_conn_is_outb(conn) ? c_idx : s_idx; - key = conn_dhkey_get(conn, l_idx); - if ((key == NULL) || !key->valid) rv = ECP_ERR_ECDH_IDX; - } - } else { - if (s_idx == ECP_ECDH_IDX_PERMA) { - key = &sock->key_perma; - } else { - l_idx = s_idx; - if (l_idx < ECP_MAX_SOCK_KEY) key = &sock->key[l_idx]; - } - if ((key == NULL) || !key->valid) rv = ECP_ERR_ECDH_IDX; - } - - if (!rv && key) memcpy(&private, &key->private, sizeof(private)); - - if (!rv && conn) { - conn->refcount++; + is_inb = ecp_conn_is_inb(conn); is_open = ecp_conn_is_open(conn); + if (is_open) { - seq_conn = conn->seq_in; - seq_map = conn->seq_in_map; + nonce_buf = packet+ECP_SIZE_PROTO+1+ECP_SIZE_ECDH_PUB; + packet += ECP_SIZE_PKT_HDR; + pkt_size -= ECP_SIZE_PKT_HDR; + + nonce_conn = conn->nonce_in; + nonce_map = conn->nonce_map; + } else if (!is_inb && (idx == ECP_ECDH_IDX_INV)) { + nonce_buf = packet+ECP_SIZE_PROTO+1; + packet += ECP_SIZE_PROTO+1+ECP_SIZE_NONCE; + pkt_size -= ECP_SIZE_PROTO+1+ECP_SIZE_NONCE; + + s_idx = ECP_ECDH_IDX_PERMA; + c_idx = conn->key_curr; + } else { + _rv = ECP_ERR; } - } + if (!_rv) _rv = conn_shkey_get(conn, s_idx, c_idx, &shkey); + if (!_rv) conn->refcount++; #ifdef ECP_WITH_PTHREAD - if (conn) pthread_mutex_unlock(&conn->mutex); + pthread_mutex_unlock(&conn->mutex); #endif - if (rv) return rv; + if (_rv) return _rv; + } else { + ECPDHKey key; - if (key) { - ecp_cr_dh_pub_from_buf(&public, public_buf); - ecp_cr_dh_shsec(&shsec, &public, &private); - memset(&private, 0, sizeof(private)); - } + is_inb = 1; + public_buf = packet+ECP_SIZE_PROTO+1; - dec_size = ecp_cr_aead_dec(payload, pld_size, packet+ECP_SIZE_PKT_HDR, pkt_size-ECP_SIZE_PKT_HDR, &shsec, nonce); - if (dec_size < ECP_SIZE_PLD_HDR+1) rv = ECP_ERR_DECRYPT; - if (rv) goto ecp_unpack_err; + if (s_idx == ECP_ECDH_IDX_PERMA) { + nonce_buf = public_buf+ECP_SIZE_ECDH_PUB; + packet += ECP_SIZE_PKT_HDR; + pkt_size -= ECP_SIZE_PKT_HDR; - seq_pkt = \ - (payload[0] << 24) | \ - (payload[1] << 16) | \ - (payload[2] << 8) | \ - (payload[3]); + _rv = ecp_sock_dhkey_get(sock, s_idx, &key); + if (_rv) return _rv; - mtype = payload[ECP_SIZE_PLD_HDR]; - memcpy(nonce_next, packet+ECP_SIZE_PKT_HDR, sizeof(nonce_next)); - // XXX! - // if ((mtype & ECP_MTYPE_MASK) < ECP_MAX_MTYPE_SYS) ecp_tr_release(bufs->packet, 1); - if (conn == NULL) { - ECPPktMeta pkt_meta; - unsigned char *msg = payload+ECP_SIZE_PLD_HDR+1; - size_t msg_size = dec_size-ECP_SIZE_PLD_HDR-1; - ecp_sock_msg_handler_t handler; - - if (key == NULL) return ECP_ERR; - if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE_SOCK) return ECP_ERR_MAX_MTYPE; - if (mtype & ECP_MTYPE_FLAG_REP) return ECP_ERR; - - memcpy(pkt_meta.public, public_buf, sizeof(pkt_meta.public)); - memcpy(pkt_meta.nonce, nonce_next, sizeof(pkt_meta.nonce)); - memcpy(&pkt_meta.shsec, &shsec, sizeof(pkt_meta.shsec)); - pkt_meta.seq = seq_pkt; - pkt_meta.s_idx = s_idx; - pkt_meta.c_idx = c_idx; - - handler = ecp_sock_get_msg_handler(sock, mtype & ECP_MTYPE_MASK); - if (handler) { - ssize_t _rv; + ecp_ecdh_shkey(&shkey, (ecp_ecdh_public_t *)public_buf, &key.private); + } else if (pkt_size >= (ECP_MIN_PKT+ECP_SIZE_COOKIE)) { + unsigned char *cookie_buf; + + cookie_buf = public_buf+ECP_SIZE_ECDH_PUB; + nonce_buf = cookie_buf+ECP_SIZE_COOKIE; + packet += ECP_SIZE_PKT_HDR+ECP_SIZE_COOKIE; + pkt_size -= ECP_SIZE_PKT_HDR+ECP_SIZE_COOKIE; + + _rv = ecp_cookie_verify(sock, cookie_buf, public_buf); + if (_rv) return _rv; - _rv = handler(sock, addr, parent, msg, msg_size, &pkt_meta, bufs, &conn); - if (_rv < 0) return _rv; + _rv = ecp_sock_dhkey_get(sock, s_idx, &key); + if (_rv) return _rv; + + ecp_ecdh_shkey(&shkey, (ecp_ecdh_public_t *)public_buf, &key.private); + } else { + return ECP_ERR; } } - if (conn == NULL) return dec_size; + ecp_buf2nonce(&nonce_pkt, nonce_buf); + if (conn && is_open) { + if (ECP_NONCE_LTE(nonce_pkt, nonce_conn)) { + ecp_nonce_t nonce_offset = nonce_conn - nonce_pkt; - seq_check = 1; - seq_reset = 0; + if (nonce_offset < ECP_SIZE_ACKB) { + ecp_ack_t nonce_mask = ((ecp_ack_t)1 << nonce_offset); - if (is_open) { -#ifdef ECP_WITH_RBUF - if (ecp_rbuf_handle_seq(conn, mtype)) seq_check = 0; -#endif + if (nonce_mask & nonce_map) _rv = ECP_ERR_SEQ; + if (!_rv) nonce_in = nonce_conn; + } else { + _rv = ECP_ERR_SEQ; + } + } else { + ecp_nonce_t nonce_offset = nonce_pkt - nonce_conn; - if (seq_check) { - if (ECP_SEQ_LTE(seq_pkt, seq_conn)) { - ecp_seq_t seq_offset = seq_conn - seq_pkt; - if (seq_offset < ECP_SIZE_ACKB) { - ecp_ack_t ack_mask = ((ecp_ack_t)1 << seq_offset); - if (ack_mask & seq_map) rv = ECP_ERR_SEQ; - if (!rv) seq_last = seq_conn; + if (nonce_offset < ECP_MAX_SEQ_FWD) { + if (nonce_offset < ECP_SIZE_ACKB) { + nonce_map = nonce_map << nonce_offset; } else { - rv = ECP_ERR_SEQ; + nonce_map = 0; } + nonce_map |= 1; + nonce_in = nonce_pkt; } else { - ecp_seq_t seq_offset = seq_pkt - seq_conn; - if (seq_offset < ECP_MAX_SEQ_FWD) { - if (seq_offset < ECP_SIZE_ACKB) { - seq_map = seq_map << seq_offset; - } else { - seq_map = 0; - } - seq_map |= 1; - seq_last = seq_pkt; - } else { - rv = ECP_ERR_SEQ; - } + _rv = ECP_ERR_SEQ; + } + } + if (_rv) { + rv = _rv; + goto unpack_err; + } + } + + payload = bufs->payload->buffer; + rv = ecp_aead_dec(payload, bufs->payload->size, packet, pkt_size, &shkey, &nonce_pkt, is_inb ? ECP_NTYPE_INB : ECP_NTYPE_OUTB); + if (rv < 0) goto unpack_err; + + pld_size = rv; + if (pld_size < ECP_MIN_PLD) { + rv = ECP_ERR_SIZE; + goto unpack_err; + } + + if (conn == NULL) { + unsigned char mtype; + unsigned char *msg; + size_t hdr_size, msg_size; + + _rv = ecp_pld_get_type(payload, pld_size, &mtype); + if (_rv) return _rv; + + msg = ecp_pld_get_msg(payload, pld_size); + if (msg == NULL) return ECP_ERR; + hdr_size = msg - payload; + msg_size = pld_size - hdr_size; + + switch (mtype) { + case ECP_MTYPE_INIT_REQ: { + rv = ecp_handle_init_req(sock, parent, addr, public_buf, &shkey); + if (rv < 0) return rv; + + rv += hdr_size; + break; } - if ((rv == ECP_ERR_SEQ) && (mtype == ECP_MTYPE_OPEN_REQ) && key) { - rv = ECP_OK; - seq_reset = 1; + case ECP_MTYPE_OPEN_REQ: { + rv = ecp_handle_open_req(sock, parent, s_idx, c_idx, public_buf, msg, msg_size, &shkey, &conn); + if (rv < 0) return rv; + + /* pass to payload handler */ + nonce_in = nonce_pkt; + nonce_map = ECP_ACK_FULL; + is_open = 1; + rv = 0; + break; } - if (rv) goto ecp_unpack_err; + + default: + return ECP_ERR_MTYPE; } - } - if (!is_open || seq_reset) { - seq_last = seq_pkt; - seq_map = 1; + payload += rv; + pld_size -= rv; + } else if (!is_open) { + unsigned char mtype; + unsigned char *msg; + size_t hdr_size, msg_size; + + _rv = ecp_pld_get_type(payload, pld_size, &mtype); + if (_rv) { + rv = _rv; + goto unpack_err; + } -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv) { - rv = ecp_rbuf_recv_start(conn, seq_pkt); - if (rv) goto ecp_unpack_err; + msg = ecp_pld_get_msg(payload, pld_size); + if (msg == NULL) { + rv = ECP_ERR; + goto unpack_err; } -#endif + hdr_size = msg - payload; + msg_size = pld_size - hdr_size; + + switch (mtype) { + case ECP_MTYPE_INIT_REP: { + rv = ecp_handle_init_rep(conn, msg, msg_size); + if (rv < 0) goto unpack_err; + + rv += hdr_size; + break; + } + + case ECP_MTYPE_OPEN_REP: { + /* pass to payload handler */ + nonce_in = nonce_pkt; + nonce_map = ECP_ACK_FULL; + is_open = 1; + rv = 0; + break; + } + + default: + rv = ECP_ERR_MTYPE; + goto unpack_err; + } + + payload += rv; + pld_size -= rv; } + if (conn && is_open) { #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); + pthread_mutex_lock(&conn->mutex); #endif - memcpy(conn->nonce, nonce_next, sizeof(conn->nonce)); - if (addr) conn->node.addr = *addr; - if (seq_check) { - conn->seq_in = seq_last; - conn->seq_in_map = seq_map; - } - if (key) { - if (!rv) rv = conn_dhkey_new_pub_local(conn, l_idx); - if (!rv) rv = conn_shsec_set(conn, s_idx, c_idx, &shsec); - } + + conn->nonce_in = nonce_in; + conn->nonce_map = nonce_map; + if (is_inb && addr) conn->remote.addr = *addr; + #ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); + pthread_mutex_unlock(&conn->mutex); #endif - if (rv) goto ecp_unpack_err; + *_conn = conn; + *_payload = payload; + *_seq = (ecp_seq_t)nonce_pkt; + } - *_conn = conn; - *_seq = seq_pkt; - return dec_size; + return _pkt_size - pld_size; -ecp_unpack_err: - if (conn == NULL) return rv; - ecp_conn_refcount_dec(conn); +unpack_err: + if (conn) ecp_conn_refcount_dec(conn); return rv; } -ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size) { - ECPConnection *conn; +ssize_t ecp_pkt_handle(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECP2Buffer *bufs, size_t pkt_size) { + ECPConnection *conn = NULL; + unsigned char *payload; ecp_seq_t seq; - ssize_t pld_size; - ssize_t rv = 0; + size_t pld_size; + ssize_t rv; - pld_size = ecp_unpack(sock, addr, parent, bufs, pkt_size, &conn, &seq); - if (pld_size < 0) return pld_size; - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; + rv = ecp_unpack(sock, parent, addr, bufs, pkt_size, &conn, &payload, &seq); + if (rv < 0) return rv; - if (conn) { -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv) { - rv = ecp_rbuf_store(conn, seq, bufs->payload->buffer+ECP_SIZE_PLD_HDR, pld_size-ECP_SIZE_PLD_HDR, bufs); - } -#endif - if (rv == 0) rv = ecp_conn_handle_msg(conn, seq, bufs->payload->buffer+ECP_SIZE_PLD_HDR, pld_size-ECP_SIZE_PLD_HDR, bufs); - ecp_conn_refcount_dec(conn); - } else { - rv = pld_size-ECP_SIZE_PLD_HDR; + pld_size = pkt_size - rv; + if (conn == NULL) { + if (pld_size) return ECP_ERR; + return pkt_size; } - if (rv < 0) return rv; - return ECP_SIZE_PKT_HDR+ECP_AEAD_SIZE_TAG+ECP_SIZE_PLD_HDR+rv; -} + if (pld_size) { + rv = ecp_ext_pld_store(conn, seq, payload, pld_size, bufs); + if (rv < 0) goto pkt_handle_fin; -ssize_t ecp_pkt_send(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t pkt_size, unsigned char flags) { - ssize_t rv; + payload += rv; + pld_size -= rv; + } - rv = ecp_tr_send(sock, packet, pkt_size, addr, flags); - if (rv < 0) return rv; - if (rv < ECP_MIN_PKT) return ECP_ERR_SEND; + if (pld_size) { + rv = ecp_pld_handle(conn, seq, payload, pld_size, bufs); + if (rv < 0) goto pkt_handle_fin; - return rv; -} + payload += rv; + pld_size -= rv; + } -int ecp_msg_get_type(unsigned char *msg, size_t msg_size, unsigned char *mtype) { - if (msg_size == 0) ECP_ERR; + rv = pkt_size - pld_size; - *mtype = msg[0]; - return ECP_OK; +pkt_handle_fin: + ecp_conn_refcount_dec(conn); + return rv; } -int ecp_msg_set_type(unsigned char *msg, size_t msg_size, unsigned char type) { - if (msg_size == 0) ECP_ERR; +ssize_t ecp_pkt_send(ECPSocket *sock, ECPBuffer *packet, size_t pkt_size, unsigned char flags, ECPTimerItem *ti, ecp_tr_addr_t *addr) { + ssize_t rv; - msg[0] = type; - return ECP_OK; -} + if (ti) { + int _rv; -int ecp_msg_get_frag(unsigned char *msg, size_t msg_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size) { - if (msg_size < 3) return ECP_ERR; - if (!(msg[0] & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; - if (msg[2] == 0) return ECP_ERR; + _rv = ecp_timer_push(ti); + if (_rv) return _rv; + } - *frag_cnt = msg[1]; - *frag_tot = msg[2]; - *frag_size = \ - (msg[3] << 8) | \ - (msg[4]); + rv = ecp_tr_send(sock, packet, pkt_size, addr, flags); + if (rv < 0) return rv; - return ECP_OK; + return rv; } -int ecp_msg_set_frag(unsigned char *msg, size_t msg_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size) { - if (msg_size < 3) return ECP_ERR; - if (!(msg[0] & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; - - msg[1] = frag_cnt; - msg[2] = frag_tot; - msg[3] = (frag_size & 0xFF00) >> 8; - msg[4] = (frag_size & 0x00FF); - - return ECP_OK; +void ecp_nonce2buf(unsigned char *b, ecp_nonce_t *n) { + b[0] = *n >> 56; + b[1] = *n >> 48; + b[2] = *n >> 40; + b[3] = *n >> 32; + b[4] = *n >> 24; + b[5] = *n >> 16; + b[6] = *n >> 8; + b[7] = *n; } -int ecp_msg_get_pts(unsigned char *msg, size_t msg_size, ecp_pts_t *pts) { - unsigned char mtype; - size_t offset; - - if (msg_size == 0) ECP_ERR; - - mtype = msg[0]; - if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; - - offset = 1 + ECP_SIZE_MT_FRAG(mtype); - if (msg_size < offset + sizeof(ecp_pts_t)) return ECP_ERR; - - *pts = \ - (msg[offset] << 24) | \ - (msg[offset + 1] << 16) | \ - (msg[offset + 2] << 8) | \ - (msg[offset + 3]); - - return ECP_OK; +void ecp_buf2nonce(ecp_nonce_t *n, unsigned char *b) { + *n = (ecp_nonce_t)b[0] << 56; + *n |= (ecp_nonce_t)b[1] << 48; + *n |= (ecp_nonce_t)b[2] << 40; + *n |= (ecp_nonce_t)b[3] << 32; + *n |= (ecp_nonce_t)b[4] << 24; + *n |= (ecp_nonce_t)b[5] << 16; + *n |= (ecp_nonce_t)b[6] << 8; + *n |= (ecp_nonce_t)b[7]; } -int ecp_msg_set_pts(unsigned char *msg, size_t msg_size, ecp_pts_t pts) { - unsigned char mtype; - size_t offset; - - if (msg_size == 0) ECP_ERR; - - mtype = msg[0]; - if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; +int ecp_pkt_get_seq(unsigned char *pkt, size_t pkt_size, ecp_seq_t *s) { + *s = 0; - offset = 1 + ECP_SIZE_MT_FRAG(mtype); - if (msg_size < offset + sizeof(ecp_pts_t)) return ECP_ERR; + if (pkt_size < ECP_MIN_PKT) return ECP_ERR_SIZE; - msg[offset] = (pts & 0xFF000000) >> 24; - msg[offset + 1] = (pts & 0x00FF0000) >> 16; - msg[offset + 2] = (pts & 0x0000FF00) >> 8; - msg[offset + 3] = (pts & 0x000000FF); + pkt += ECP_SIZE_PROTO+1+ECP_SIZE_ECDH_PUB; + *s |= (ecp_seq_t)pkt[4] << 24; + *s |= (ecp_seq_t)pkt[5] << 16; + *s |= (ecp_seq_t)pkt[6] << 8; + *s |= (ecp_seq_t)pkt[7]; return ECP_OK; } -unsigned char *ecp_msg_get_content(unsigned char *msg, size_t msg_size) { - unsigned char mtype; - size_t offset; +static ssize_t _pack(ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size) { + ssize_t rv; + unsigned char s_idx, c_idx; + unsigned char *pkt_buf; + size_t pkt_size; + size_t hdr_size; - if (msg_size == 0) ECP_ERR; + pkt_size = ECP_MIN_PKT; + if (pkt_meta->public == NULL) pkt_size -= ECP_SIZE_ECDH_PUB; + if (pkt_meta->cookie) pkt_size += ECP_SIZE_COOKIE; - mtype = msg[0]; - offset = 1 + ECP_SIZE_MT_FLAG(mtype); - if (msg_size < offset) return NULL; + if (packet->size < pkt_size) return ECP_ERR_SIZE; - return msg + offset; -} + pkt_buf = packet->buffer; + pkt_size = packet->size; -int ecp_msg_defrag(ECPFragIter *iter, ecp_seq_t seq, unsigned char mtype, unsigned char *msg_in, size_t msg_in_size, unsigned char **msg_out, size_t *msg_out_size) { - unsigned char *content; - unsigned char frag_cnt, frag_tot; - uint16_t frag_size; - size_t msg_size; - size_t buf_offset; - int rv; + // ECP_SIZE_PROTO + pkt_buf[0] = 0; + pkt_buf[1] = 0; + pkt_buf[ECP_SIZE_PROTO] = (pkt_meta->s_idx << 4) | pkt_meta->c_idx; + pkt_buf += 3; + + if (pkt_meta->public) { + memcpy(pkt_buf, &pkt_meta->public, ECP_SIZE_ECDH_PUB); + pkt_buf += ECP_SIZE_ECDH_PUB; + } + if (pkt_meta->cookie) { + memcpy(pkt_buf, pkt_meta->cookie, ECP_SIZE_COOKIE); + pkt_buf += ECP_SIZE_COOKIE; + } + ecp_nonce2buf(pkt_buf, pkt_meta->nonce); + pkt_buf += ECP_SIZE_NONCE; - rv = ecp_msg_get_frag(msg_in, msg_in_size, &frag_cnt, &frag_tot, &frag_size); - if (rv) return ECP_ERR; + hdr_size = pkt_buf - packet->buffer; + rv = ecp_aead_enc(pkt_buf, packet->size-hdr_size, payload->buffer, pld_size, pkt_meta->shkey, pkt_meta->nonce, pkt_meta->ntype); + if (rv < 0) return rv; - content = ecp_msg_get_content(msg_in, msg_in_size); - if (content == NULL) return ECP_ERR; + return rv+hdr_size; +} - msg_size = msg_in_size - (content - msg_in); - if (msg_size == 0) return ECP_ERR; +static ssize_t _pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, unsigned char *cookie, ecp_nonce_t *_nonce, ECPBuffer *payload, size_t pld_size, ecp_tr_addr_t *addr) { + ECPPktMeta pkt_meta; + ecp_ecdh_public_t public; + ecp_aead_key_t shkey; + ecp_nonce_t nonce; + int rv = ECP_OK; - if (iter->msg_size && (iter->seq + frag_cnt != seq)) ecp_frag_iter_reset(iter); +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif - if (iter->msg_size == 0) { - iter->seq = seq - frag_cnt; - iter->frag_cnt = 0; + if (s_idx == ECP_ECDH_IDX_INV) { + if (ecp_conn_is_inb(conn)) { + s_idx = conn->key_curr; + } else { + s_idx = conn->rkey_curr; + } + } + if (c_idx == ECP_ECDH_IDX_INV) { + if (ecp_conn_is_outb(conn)) { + c_idx = conn->key_curr; + } else { + c_idx = conn->rkey_curr; + } } + rv = conn_shkey_get(conn, s_idx, c_idx, &shkey); + if (rv) goto pack_conn_fin; - mtype &= (~ECP_MTYPE_FLAG_FRAG); - buf_offset = 1 + ECP_SIZE_MT_FLAG(mtype) + frag_size * frag_cnt; - if (buf_offset + msg_size > iter->buf_size) return ECP_ERR_SIZE; - memcpy(iter->buffer + buf_offset, content, msg_size); + if (ecp_conn_is_outb(conn)) { + ECPDHKey *key = conn_dhkey_get(conn, c_idx); - if (frag_cnt == 0) { - if (1 + ECP_SIZE_MT_FLAG(mtype) > iter->buf_size) return ECP_ERR_SIZE; + if (key) { + memcpy(&public, &key->public, sizeof(public)); + } else { + rv = ECP_ERR_ECDH_IDX; + } + } else { + ECPDHPub *key = conn_dhkey_get_remote(conn, c_idx); - iter->buffer[0] = mtype; - if (ECP_SIZE_MT_FLAG(mtype)) { - memcpy(iter->buffer + 1, msg_in + 1, ECP_SIZE_MT_FLAG(mtype)); + if (key) { + memcpy(&public, &key->public, sizeof(public)); + } else { + rv = ECP_ERR_ECDH_IDX; } - msg_size += 1 + ECP_SIZE_MT_FLAG(mtype); + memcpy(&public, &key->public, sizeof(public)); } + if (rv) goto pack_conn_fin; - iter->frag_cnt++; - iter->msg_size += msg_size; - if (iter->frag_cnt == frag_tot) { - *msg_out = iter->buffer; - *msg_out_size = iter->msg_size; - return ECP_OK; + if (_nonce) { + nonce = *_nonce; } else { - return ECP_ITER_NEXT; + nonce = conn->nonce_out; + conn->nonce_out++; } -} +#ifdef ECP_WITH_VCONN + if ((conn->parent == NULL) && addr) *addr = conn->remote.addr; +#else + if (addr) *addr = conn->remote.addr; +#endif -int ecp_pld_get_type(unsigned char *payload, size_t pld_size, unsigned char *mtype) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +pack_conn_fin: - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); +#endif + if (rv) return rv; - return ecp_msg_get_type(payload, pld_size, mtype); + pkt_meta.cookie = cookie; + pkt_meta.public = &public; + pkt_meta.shkey = &shkey; + pkt_meta.nonce = &nonce; + pkt_meta.ntype = (ecp_conn_is_inb(conn) ? ECP_NTYPE_INB : ECP_NTYPE_OUTB); + pkt_meta.s_idx = s_idx; + pkt_meta.c_idx = c_idx; + return _pack(packet, &pkt_meta, payload, pld_size); } -int ecp_pld_set_type(unsigned char *payload, size_t pld_size, unsigned char mtype) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +ssize_t ecp_pack(ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ecp_tr_addr_t *addr) { + ssize_t rv; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; + rv = _pack(packet, pkt_meta, payload, pld_size); + if (rv < 0) return rv; - return ecp_msg_set_type(payload, pld_size, mtype); +#ifdef ECP_WITH_VCONN + if (parent) { + rv = ecp_vconn_pack_parent(parent, packet, payload, rv, addr); + } +#endif + + return rv; } -int ecp_pld_get_frag(unsigned char *payload, size_t pld_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, unsigned char *cookie, ecp_nonce_t *nonce, ECPBuffer *payload, size_t pld_size, ecp_tr_addr_t *addr) { + ssize_t rv; + + rv = _pack_conn(conn, packet, s_idx, c_idx, cookie, nonce, payload, pld_size, addr); + if (rv < 0) return rv; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; +#ifdef ECP_WITH_VCONN + if (conn->parent) { + rv = ecp_vconn_pack_parent(conn->parent, packet, payload, rv, addr); + } +#endif - return ecp_msg_get_frag(payload, pld_size, frag_cnt, frag_tot, frag_size); + return rv; } -int ecp_pld_set_frag(unsigned char *payload, size_t pld_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +int ecp_pld_get_type(unsigned char *pld, size_t pld_size, unsigned char *mtype) { + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; - - return ecp_msg_set_frag(payload, pld_size, frag_cnt, frag_tot, frag_size); + *mtype = pld[0]; + return ECP_OK; } -int ecp_pld_get_pts(unsigned char *payload, size_t pld_size, ecp_pts_t *pts) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +int ecp_pld_set_type(unsigned char *pld, size_t pld_size, unsigned char mtype) { + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; - - return ecp_msg_get_pts(payload, pld_size, pts); + pld[0] = mtype; + return ECP_OK; } -int ecp_pld_set_pts(unsigned char *payload, size_t pld_size, ecp_pts_t pts) { - if (pld_size < ECP_SIZE_PLD_HDR) return ECP_ERR; +int ecp_pld_get_frag(unsigned char *pld, size_t pld_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size) { + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; + if (!(pld[0] & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; + if (pld_size < (ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]))) return ECP_ERR_SIZE; + if (pld[2] == 0) return ECP_ERR; - return ecp_msg_set_pts(payload, pld_size, pts); + *frag_cnt = pld[1]; + *frag_tot = pld[2]; + *frag_size = \ + (pld[3] << 8) | \ + (pld[4]); + + return ECP_OK; } -unsigned char *ecp_pld_get_buf(unsigned char *payload, size_t pld_size) { - if (pld_size < ECP_SIZE_PLD_HDR) return NULL; +int ecp_pld_set_frag(unsigned char *pld, size_t pld_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size) { + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - payload += ECP_SIZE_PLD_HDR; - pld_size -= ECP_SIZE_PLD_HDR; + if (!(pld[0] & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; + if (pld_size < (ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]))) return ECP_ERR_SIZE; - return ecp_msg_get_content(payload, pld_size); -} + pld[1] = frag_cnt; + pld[2] = frag_tot; + pld[3] = frag_size >> 8; + pld[4] = frag_size; -ssize_t __ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti, ECPSeqItem *si) { - ECPSocket *sock = conn->sock; - ECPNetAddr addr; - ssize_t rv; + return ECP_OK; +} - rv = ecp_pack_conn(conn, packet, s_idx, c_idx, payload, pld_size, &addr, si); - if (rv < 0) return rv; +int ecp_pld_get_pts(unsigned char *pld, size_t pld_size, ecp_pts_t *pts) { + size_t offset; -#ifdef ECP_WITH_RBUF - if (conn->rbuf.send) { - return ecp_rbuf_pkt_send(conn, conn->sock, &addr, packet, rv, flags, ti, si); - } -#endif + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - if (ti) { - int _rv; + if (!(pld[0] & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; + if (pld_size < (ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]))) return ECP_ERR_SIZE; - _rv = ecp_timer_push(ti); - if (_rv) return _rv; - } + offset = ECP_SIZE_MTYPE + ECP_SIZE_MT_FRAG(pld[0]); + *pts = \ + ((ecp_pts_t)pld[offset] << 24) | \ + ((ecp_pts_t)pld[offset + 1] << 16) | \ + ((ecp_pts_t)pld[offset + 2] << 8) | \ + ((ecp_pts_t)pld[offset + 3]); - return ecp_pkt_send(sock, &addr, packet, rv, flags); + return ECP_OK; } -#ifdef ECP_WITH_RBUF +int ecp_pld_set_pts(unsigned char *pld, size_t pld_size, ecp_pts_t pts) { + size_t offset; -ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { - if (conn->rbuf.send) { - ECPSeqItem seq_item; - int rv; + if (pld_size < ECP_SIZE_MTYPE) return ECP_ERR_SIZE; - rv = ecp_seq_item_init(&seq_item); - if (rv) return rv; + if (!(pld[0] & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; + if (pld_size < (ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]))) return ECP_ERR_SIZE; - return __ecp_pld_send(conn, packet, s_idx, c_idx, payload, pld_size, flags, ti, &seq_item); - } + offset = ECP_SIZE_MTYPE + ECP_SIZE_MT_FRAG(pld[0]); + pld[offset] = pts >> 24; + pld[offset + 1] = pts >> 16; + pld[offset + 2] = pts >> 8; + pld[offset + 3] = pts; - return __ecp_pld_send(conn, packet, s_idx, c_idx, payload, pld_size, flags, ti, NULL); + return ECP_OK; } -#else +unsigned char *ecp_pld_get_msg(unsigned char *pld, size_t pld_size) { + size_t offset; -ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { - return __ecp_pld_send(conn, packet, s_idx, c_idx, payload, pld_size, flags, ti, NULL); + if (pld_size < ECP_SIZE_MTYPE) return NULL; + if (pld_size < (ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]))) return NULL; + + return pld + ECP_SIZE_MTYPE + ECP_SIZE_MT_FLAG(pld[0]); } -#endif +ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, unsigned char *cookie, ecp_nonce_t *n, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { + ecp_tr_addr_t addr; + size_t pkt_size; + ssize_t rv; + + rv = ecp_pack_conn(conn, packet, s_idx, c_idx, cookie, n, payload, pld_size, &addr); + if (rv < 0) return rv; + + pkt_size = rv; + rv = ecp_ext_pld_send(conn, payload, pld_size, packet, pkt_size, flags, ti, &addr); + if (rv) return rv; + + rv = ecp_pkt_send(conn->sock, packet, pkt_size, flags, ti, &addr); + if (rv < 0) return rv; + + return pld_size; +} ssize_t ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags) { - return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, pld_size, flags, NULL); + return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, NULL, NULL, payload, pld_size, flags, NULL); } ssize_t ecp_pld_send_wtimer(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { - return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, pld_size, flags, ti); + return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, NULL, NULL, payload, pld_size, flags, ti); } -ssize_t ecp_pld_send_tr(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, unsigned char flags) { - ECPNetAddr _addr; +ssize_t ecp_pld_send_wcookie(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, unsigned char *cookie) { + return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, cookie, NULL, payload, pld_size, flags, NULL); +} + +ssize_t ecp_pld_send_wnonce(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, ecp_nonce_t *nonce) { + return _ecp_pld_send(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, NULL, nonce, payload, pld_size, flags, NULL); +} + +ssize_t ecp_pld_send_irep(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, unsigned char flags) { + ecp_tr_addr_t _addr; ssize_t rv; - rv = ecp_pack(sock->ctx, parent, packet, pkt_meta, payload, pld_size, addr ? NULL : &_addr); + rv = ecp_pack(parent, packet, pkt_meta, payload, pld_size, addr ? NULL : &_addr); if (rv < 0) return rv; - return ecp_pkt_send(sock, addr ? addr : &_addr, packet, rv, flags); + rv = ecp_pkt_send(sock, packet, rv, flags, NULL, addr ? addr : &_addr); + if (rv < 0) return rv; + + return pld_size; } -ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *content, size_t content_size) { +ssize_t ecp_msg_send(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size) { ECPBuffer packet; ECPBuffer payload; unsigned char pkt_buf[ECP_MAX_PKT]; unsigned char pld_buf[ECP_MAX_PLD]; - unsigned char *content_buf; - ssize_t rv = 0; - int pkt_cnt = 0; - int vc_cnt = conn->pcount; - size_t pld_max = ECP_MAX_PKT - (ECP_SIZE_PKT_HDR + ECP_AEAD_SIZE_TAG + ECP_SIZE_PLD_HDR + 1) * vc_cnt - (ECP_SIZE_PKT_HDR + ECP_AEAD_SIZE_TAG); + unsigned char *msg_buf; + ssize_t rv; packet.buffer = pkt_buf; packet.size = ECP_MAX_PKT; payload.buffer = pld_buf; payload.size = ECP_MAX_PLD; - if (ECP_SIZE_PLD(content_size, mtype) > pld_max) { - size_t frag_size, frag_size_final; - ecp_seq_t seq_start; - ECPSeqItem seq_item; - int i; - int _rv; - - _rv = ecp_seq_item_init(&seq_item); - if (_rv) return _rv; - - mtype |= ECP_MTYPE_FLAG_FRAG; - frag_size = pld_max - ECP_SIZE_PLD(0, mtype); - pkt_cnt = content_size / frag_size; - frag_size_final = content_size - frag_size * pkt_cnt; - if (frag_size_final) pkt_cnt++; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - - seq_start = conn->seq_out + 1; - conn->seq_out += pkt_cnt; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - seq_item.seq_w = 1; - for (i=0; i<pkt_cnt; i++) { - ssize_t _rv; - - ecp_pld_set_type(pld_buf, ECP_MAX_PLD, mtype); - ecp_pld_set_frag(pld_buf, ECP_MAX_PLD, i, pkt_cnt, frag_size); - content_buf = ecp_pld_get_buf(pld_buf, ECP_MAX_PLD); - - if ((i == pkt_cnt - 1) && frag_size_final) frag_size = frag_size_final; - memcpy(content_buf, content, frag_size); - content += frag_size; - seq_item.seq = seq_start + i; - - _rv = __ecp_pld_send(conn, &packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(frag_size, mtype), 0, NULL, &seq_item); - if (_rv < 0) return _rv; + rv = ecp_ext_msg_send(conn, mtype, msg, msg_size, &packet, &payload); + if (rv) return rv; - rv += _rv; - } - } else { + if (ECP_SIZE_PKT_BUF(msg_size, mtype, conn) <= ECP_MAX_PKT) { ecp_pld_set_type(pld_buf, ECP_MAX_PLD, mtype); - content_buf = ecp_pld_get_buf(pld_buf, ECP_MAX_PLD); + msg_buf = ecp_pld_get_msg(pld_buf, ECP_MAX_PLD); - memcpy(content_buf, content, content_size); - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(content_size, mtype), 0); + memcpy(msg_buf, msg, msg_size); + rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(msg_size, mtype), 0); + if (rv < 0) return rv; + } else { + return ECP_ERR_SIZE; } - return rv; -} -#if defined(ECP_WITH_RBUF) && defined(ECP_WITH_MSGQ) -ssize_t ecp_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout) { - ssize_t rv; - - pthread_mutex_lock(&conn->rbuf.recv->msgq.mutex); - rv = ecp_conn_msgq_pop(conn, mtype, msg, msg_size, timeout); - pthread_mutex_unlock(&conn->rbuf.recv->msgq.mutex); - - return rv; -} -#else -ssize_t ecp_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout) { - return ECP_ERR_NOT_IMPLEMENTED; + return msg_size; } -#endif -static int recv_p(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t size) { +static int recv_p(ECPSocket *sock, ecp_tr_addr_t *addr, ECPBuffer *packet, size_t size) { ECP2Buffer bufs; ECPBuffer payload; unsigned char pld_buf[ECP_MAX_PLD]; @@ -1951,17 +2324,17 @@ static int recv_p(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t s payload.buffer = pld_buf; payload.size = ECP_MAX_PLD; - rv = ecp_pkt_handle(sock, addr, NULL, &bufs, size); + rv = ecp_pkt_handle(sock, NULL, addr, &bufs, size); if (rv < 0) return rv; return ECP_OK; } int ecp_receiver(ECPSocket *sock) { - ECPNetAddr addr; + ecp_tr_addr_t addr; ECPBuffer packet; unsigned char pkt_buf[ECP_MAX_PKT]; - ecp_cts_t next = 0; + ecp_sts_t next = 0; ssize_t rv; int _rv; @@ -1970,12 +2343,12 @@ int ecp_receiver(ECPSocket *sock) { packet.buffer = pkt_buf; packet.size = ECP_MAX_PKT; - rv = ecp_tr_recv(sock, &packet, &addr, next ? next : sock->poll_timeout); + rv = ecp_tr_recv(sock, &packet, &addr, next ? next : ECP_POLL_TIMEOUT); if (rv > 0) { _rv = recv_p(sock, &addr, &packet, rv); #ifdef ECP_DEBUG if (_rv) { - printf("RECEIVER ERR:%d\n", _rv); + printf("RCV ERR:%d\n", _rv); } #endif } @@ -2007,12 +2380,4 @@ int ecp_stop_receiver(ECPSocket *sock) { if (rv) return ECP_ERR; return ECP_OK; } -#else -int ecp_start_receiver(ECPSocket *sock) { - return ECP_ERR_NOT_IMPLEMENTED; -} - -int ecp_stop_receiver(ECPSocket *sock) { - return ECP_ERR_NOT_IMPLEMENTED; -} #endif diff --git a/ecp/src/ecp/core.h b/ecp/src/ecp/core.h index b126430..b5c260f 100644 --- a/ecp/src/ecp/core.h +++ b/ecp/src/ecp/core.h @@ -1,16 +1,13 @@ #include <sys/types.h> #include <stddef.h> #include <stdint.h> -#include <string.h> #ifdef ECP_WITH_PTHREAD #include <pthread.h> #endif -#define ECP_MEM_TINY 1 - #define ECP_OK 0 -#define ECP_ITER_NEXT 1 +#define ECP_PASS 1 #define ECP_ERR -1 #define ECP_ERR_TIMEOUT -2 @@ -20,104 +17,138 @@ #define ECP_ERR_BUSY -6 #define ECP_ERR_EMPTY -7 #define ECP_ERR_FULL -8 +#define ECP_ERR_MTYPE -9 +#define ECP_ERR_CTYPE -10 +#define ECP_ERR_HANDLER -11 -#define ECP_ERR_MAX_SOCK_CONN -10 -#define ECP_ERR_MAX_CTYPE -11 -#define ECP_ERR_MAX_MTYPE -12 -#define ECP_ERR_NET_ADDR -13 +#define ECP_ERR_NET_ADDR -12 +#define ECP_ERR_MAX_PARENT -13 #define ECP_ERR_ECDH_KEY_DUP -21 #define ECP_ERR_ECDH_IDX -22 -#define ECP_ERR_ECDH_IDX_LOCAL -23 -#define ECP_ERR_ECDH_IDX_REMOTE -24 -#define ECP_ERR_RNG -25 #define ECP_ERR_ENCRYPT -26 #define ECP_ERR_DECRYPT -27 -#define ECP_ERR_SEND -28 -#define ECP_ERR_RECV -29 -#define ECP_ERR_SEQ -30 -#define ECP_ERR_CLOSED -31 -#define ECP_ERR_NOT_IMPLEMENTED -99 - -#define ECP_SIZE_PROTO 2 -#define ECP_SIZE_SEQ 4 - -#define ECP_MAX_SOCK_CONN 16 -#define ECP_MAX_SOCK_KEY 8 +#define ECP_ERR_SIGN -28 +#define ECP_ERR_VERIFY -29 +#define ECP_ERR_SEND -30 +#define ECP_ERR_RECV -31 +#define ECP_ERR_SEQ -32 +#define ECP_ERR_VBOX -33 +#define ECP_ERR_CLOSED -34 + +#define ECP_MAX_SOCK_CONN 4 +#define ECP_MAX_SOCK_KEY 2 #define ECP_MAX_CONN_KEY 2 #define ECP_MAX_NODE_KEY 2 #define ECP_MAX_CTYPE 8 #define ECP_MAX_MTYPE 16 -#define ECP_MAX_MTYPE_SYS 4 -#define ECP_MAX_MTYPE_SOCK ECP_MAX_MTYPE_SYS +#define ECP_MAX_PARENT 3 #define ECP_MAX_SEQ_FWD 1024 -#define ECP_SIZE_PKT_HDR (ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY+ECP_AEAD_SIZE_NONCE) -#define ECP_SIZE_PLD_HDR (ECP_SIZE_SEQ) +#define ECP_SIZE_PROTO 2 +#define ECP_SIZE_NONCE 8 +#define ECP_SIZE_MTYPE 1 +#define ECP_SIZE_COOKIE (ECP_SIZE_ECDH_PUB) + +#define ECP_SIZE_PKT_HDR (ECP_SIZE_PROTO+1+ECP_SIZE_ECDH_PUB+ECP_SIZE_NONCE) #define ECP_MAX_PKT 1412 -#define ECP_MAX_PLD (ECP_MAX_PKT-ECP_SIZE_PKT_HDR-ECP_AEAD_SIZE_TAG) -#define ECP_MAX_MSG (ECP_MAX_PLD-ECP_SIZE_PLD_HDR-1) +#define ECP_MAX_PLD (ECP_MAX_PKT-ECP_SIZE_PKT_HDR-ECP_SIZE_AEAD_TAG) +#define ECP_MAX_MSG (ECP_MAX_PLD-ECP_SIZE_MTYPE) + +#define ECP_MIN_PKT (ECP_SIZE_PKT_HDR+ECP_SIZE_MTYPE+ECP_SIZE_AEAD_TAG) +#define ECP_MIN_PLD (ECP_SIZE_MTYPE) + +#define ECP_SIZE_VBOX (ECP_SIZE_ECDH_PUB+ECP_SIZE_NONCE+ECP_SIZE_ECDH_PUB+ECP_SIZE_AEAD_TAG) + +#define ECP_SIZE_MT_FRAG(T) ((T) & ECP_MTYPE_FLAG_FRAG ? 2 + sizeof(uint16_t) : 0) +#define ECP_SIZE_MT_PTS(T) ((T) & ECP_MTYPE_FLAG_PTS ? sizeof(ecp_pts_t) : 0) +#define ECP_SIZE_MT_FLAG(T) (ECP_SIZE_MT_FRAG(T)+ECP_SIZE_MT_PTS(T)) +#define ECP_SIZE_PLD(X,T) ((X)+ECP_SIZE_MTYPE+ECP_SIZE_MT_FLAG(T)) +#define ECP_SIZE_PKT(X,T) (ECP_SIZE_PKT_HDR+ECP_SIZE_PLD(X,T)+ECP_SIZE_AEAD_TAG) -#define ECP_MIN_PKT (ECP_SIZE_PKT_HDR+ECP_SIZE_PLD_HDR+1+ECP_AEAD_SIZE_TAG) +#ifdef ECP_WITH_VCONN +#define ECP_SIZE_PLD_BUF(X,T,C) (ECP_SIZE_PLD(X,T)+(C)->pcount*(ECP_SIZE_PKT_HDR+ECP_SIZE_MTYPE+ECP_SIZE_AEAD_TAG)) +#else +#define ECP_SIZE_PLD_BUF(X,T,C) (ECP_SIZE_PLD(X,T)) +#endif + +#define ECP_SIZE_PKT_BUF(X,T,C) (ECP_SIZE_PLD_BUF(X,T,C)+ECP_SIZE_PKT_HDR+ECP_SIZE_AEAD_TAG) +#define ECP_SIZE_PKT_BUF_WCOOKIE(X,T,C) (ECP_SIZE_PKT_BUF(X,T,C)+ECP_SIZE_COOKIE) +#ifdef ECP_WITH_VCONN +#define ECP_SIZE_PLD_BUF_IREP(X,T,P) (ECP_SIZE_PLD(X,T)+((P) ? ((P)->pcount+1)*(ECP_SIZE_PKT_HDR+ECP_SIZE_MTYPE+ECP_SIZE_AEAD_TAG) : 0)) +#else +#define ECP_SIZE_PLD_BUF_IREP(X,T,P) (ECP_SIZE_PLD(X,T)) +#endif + +#define ECP_SIZE_PKT_BUF_IREP(X,T,P) (ECP_SIZE_PLD_BUF_IREP(X,T,P)+ECP_SIZE_PKT_HDR-ECP_SIZE_ECDH_PUB+ECP_SIZE_AEAD_TAG) + +#define ECP_SEND_TRIES 3 +#define ECP_SEND_TIMEOUT 500 #define ECP_POLL_TIMEOUT 500 + #define ECP_ECDH_IDX_INV 0xFF #define ECP_ECDH_IDX_PERMA 0x0F +#define ECP_ECDH_IDX_MASK 0x07 + +#define ECP_NTYPE_INB 1 +#define ECP_NTYPE_OUTB 2 +#define ECP_NTYPE_VBOX 3 -#define ECP_MTYPE_FLAG_FRAG 0x80 -#define ECP_MTYPE_FLAG_PTS 0x40 -#define ECP_MTYPE_FLAG_REP 0x20 -#define ECP_MTYPE_MASK 0x1f - -#define ECP_MTYPE_OPEN 0x00 -#define ECP_MTYPE_KGET 0x01 -#define ECP_MTYPE_KPUT 0x02 -#define ECP_MTYPE_DIR 0x03 - -#define ECP_MTYPE_OPEN_REQ (ECP_MTYPE_OPEN) -#define ECP_MTYPE_OPEN_REP (ECP_MTYPE_OPEN | ECP_MTYPE_FLAG_REP) -#define ECP_MTYPE_KGET_REQ (ECP_MTYPE_KGET) -#define ECP_MTYPE_KGET_REP (ECP_MTYPE_KGET | ECP_MTYPE_FLAG_REP) -#define ECP_MTYPE_KPUT_REQ (ECP_MTYPE_KPUT) -#define ECP_MTYPE_KPUT_REP (ECP_MTYPE_KPUT | ECP_MTYPE_FLAG_REP) -#define ECP_MTYPE_DIR_REQ (ECP_MTYPE_DIR) -#define ECP_MTYPE_DIR_REP (ECP_MTYPE_DIR | ECP_MTYPE_FLAG_REP) - -#define ECP_CONN_FLAG_OUTB 0x01 -#define ECP_CONN_FLAG_NEW 0x02 +#define ECP_MTYPE_FLAG_SYS 0x80 +#define ECP_MTYPE_FLAG_FRAG 0x40 +#define ECP_MTYPE_FLAG_PTS 0x20 +#define ECP_MTYPE_MASK 0x1F + +#define ECP_MTYPE_INIT_REQ (0x00 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_INIT_REP (0x01 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_OPEN_REQ (0x02 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_OPEN_REP (0x03 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_KEYX_REQ (0x04 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_KEYX_REP (0x05 | ECP_MTYPE_FLAG_SYS) + +#define ECP_CTYPE_FLAG_SYS 0x80 +#define ECP_CTYPE_MASK 0x7F + +/* immutable flags */ +#define ECP_CONN_FLAG_INB 0x80 +#define ECP_CONN_FLAG_VBOX 0x01 +#define ECP_CONN_FLAG_RBUF 0x02 + +#define ECP_CONN_FLAG_MASK 0x7F + +/* mutable flags */ #define ECP_CONN_FLAG_REG 0x04 #define ECP_CONN_FLAG_OPEN 0x08 #define ECP_SEND_FLAG_REPLY 0x01 #define ECP_SEND_FLAG_MORE 0x02 -#define ecp_conn_is_inb(conn) (!((conn)->flags_im & ECP_CONN_FLAG_OUTB)) -#define ecp_conn_is_outb(conn) ((conn)->flags_im & ECP_CONN_FLAG_OUTB) -#define ecp_conn_is_new(conn) ((conn)->flags_im & ECP_CONN_FLAG_NEW) +#define ecp_conn_has_vbox(conn) ((conn)->flags_im & ECP_CONN_FLAG_VBOX) +#define ecp_conn_has_rbuf(conn) ((conn)->flags_im & ECP_CONN_FLAG_RBUF) +#define ecp_conn_is_inb(conn) ((conn)->flags_im & ECP_CONN_FLAG_INB) +#define ecp_conn_is_outb(conn) (!((conn)->flags_im & ECP_CONN_FLAG_INB)) #define ecp_conn_is_reg(conn) ((conn)->flags & ECP_CONN_FLAG_REG) #define ecp_conn_is_open(conn) ((conn)->flags & ECP_CONN_FLAG_OPEN) +#define ecp_conn_is_sys(conn) ((conn)->type & ECP_CTYPE_FLAG_SYS) -#define ecp_conn_set_outb(conn) ((conn)->flags_im |= ECP_CONN_FLAG_OUTB) -#define ecp_conn_set_new(conn) ((conn)->flags_im |= ECP_CONN_FLAG_NEW) -#define ecp_conn_set_reg(conn) ((conn)->flags |= ECP_CONN_FLAG_REG) -#define ecp_conn_set_open(conn) ((conn)->flags |= ECP_CONN_FLAG_OPEN) +#define ecp_conn_set_inb(conn) ((conn)->flags_im |= ECP_CONN_FLAG_INB) +#define ecp_conn_set_outb(conn) ((conn)->flags_im &= ~ECP_CONN_FLAG_INB) +#define ecp_conn_set_reg(conn) ((conn)->flags |= ECP_CONN_FLAG_REG) +#define ecp_conn_set_open(conn) ((conn)->flags |= ECP_CONN_FLAG_OPEN) -#define ecp_conn_clr_outb(conn) ((conn)->flags_im &= ~ECP_CONN_FLAG_OUTB) -#define ecp_conn_clr_new(conn) ((conn)->flags_im &= ~ECP_CONN_FLAG_NEW) #define ecp_conn_clr_reg(conn) ((conn)->flags &= ~ECP_CONN_FLAG_REG) #define ecp_conn_clr_open(conn) ((conn)->flags &= ~ECP_CONN_FLAG_OPEN) -// typedef long ssize_t; - typedef uint32_t ecp_ack_t; #define ECP_SIZE_ACKB (sizeof(ecp_ack_t)*8) -#define ECP_ACK_FULL (~(ecp_ack_t)0) +#define ECP_ACK_FULL (~((ecp_ack_t)0)) -typedef uint32_t ecp_cts_t; -#define ECP_CTS_HALF ((ecp_cts_t)1 << (sizeof(ecp_cts_t) * 8 - 1)) -#define ECP_CTS_LT(a,b) ((ecp_cts_t)((ecp_cts_t)(a) - (ecp_cts_t)(b)) > ECP_CTS_HALF) -#define ECP_CTS_LTE(a,b) ((ecp_cts_t)((ecp_cts_t)(b) - (ecp_cts_t)(a)) < ECP_CTS_HALF) +typedef uint32_t ecp_sts_t; +#define ECP_STS_HALF ((ecp_sts_t)1 << (sizeof(ecp_sts_t) * 8 - 1)) +#define ECP_STS_LT(a,b) ((ecp_sts_t)((ecp_sts_t)(a) - (ecp_sts_t)(b)) > ECP_STS_HALF) +#define ECP_STS_LTE(a,b) ((ecp_sts_t)((ecp_sts_t)(b) - (ecp_sts_t)(a)) < ECP_STS_HALF) typedef uint32_t ecp_pts_t; #define ECP_PTS_HALF ((ecp_pts_t)1 << (sizeof(ecp_pts_t) * 8 - 1)) @@ -129,51 +160,32 @@ typedef uint32_t ecp_seq_t; #define ECP_SEQ_LT(a,b) ((ecp_seq_t)((ecp_seq_t)(a) - (ecp_seq_t)(b)) > ECP_SEQ_HALF) #define ECP_SEQ_LTE(a,b) ((ecp_seq_t)((ecp_seq_t)(b) - (ecp_seq_t)(a)) < ECP_SEQ_HALF) +typedef uint64_t ecp_nonce_t; +#define ECP_NONCE_HALF ((ecp_nonce_t)1 << (sizeof(ecp_nonce_t) * 8 - 1)) +#define ECP_NONCE_LT(a,b) ((ecp_nonce_t)((ecp_nonce_t)(a) - (ecp_nonce_t)(b)) > ECP_NONCE_HALF) +#define ECP_NONCE_LTE(a,b) ((ecp_nonce_t)((ecp_nonce_t)(b) - (ecp_nonce_t)(a)) < ECP_NONCE_HALF) -#define ECP_SIZE_MT_FRAG(F) ((F) & ECP_MTYPE_FLAG_FRAG ? 2 + sizeof(uint16_t) : 0) -#define ECP_SIZE_MT_PTS(F) ((F) & ECP_MTYPE_FLAG_PTS ? sizeof(ecp_pts_t) : 0) -#define ECP_SIZE_MT_FLAG(F) (ECP_SIZE_MT_FRAG(F)+ECP_SIZE_MT_PTS(F)) -#define ECP_SIZE_PLD(X,F) ((X) + ECP_SIZE_PLD_HDR+1+ECP_SIZE_MT_FLAG(F)) -#define ECP_SIZE_PKT(X,F) (ECP_SIZE_PKT_HDR+ECP_SIZE_PLD(X,F)+ECP_AEAD_SIZE_TAG) - -#define ECP_SIZE_MSG_BUF(T,P) ((P) && ecp_conn_is_outb(P) && (((T) == ECP_MTYPE_OPEN_REQ) || ((T) == ECP_MTYPE_KGET_REQ)) ? ECP_SIZE_PLD_HDR+3+2*ECP_ECDH_SIZE_KEY : ECP_SIZE_PLD_HDR+1) - -#define ECP_SIZE_PLD_BUF(X,T,C) (ECP_SIZE_PLD(X,T)+(C)->pcount*(ECP_SIZE_PKT_HDR+ECP_SIZE_MSG_BUF(T,(C)->parent)+ECP_AEAD_SIZE_TAG)) -#define ECP_SIZE_PKT_BUF(X,T,C) (ECP_SIZE_PLD_BUF(X,T,C)+ECP_SIZE_PKT_HDR+ECP_AEAD_SIZE_TAG) - -#define ECP_SIZE_PLD_BUF_TR(X,T,P) (ECP_SIZE_PLD(X,T)+((P) ? ((P)->pcount+1)*(ECP_SIZE_PKT_HDR+ECP_SIZE_MSG_BUF(T,P)+ECP_AEAD_SIZE_TAG) : 0)) -#define ECP_SIZE_PKT_BUF_TR(X,T,P) (ECP_SIZE_PLD_BUF_TR(X,T,P)+ECP_SIZE_PKT_HDR+ECP_AEAD_SIZE_TAG) - -#ifdef ECP_DEBUG -#include <stdio.h> -#endif - -struct ECPBuffer; struct ECP2Buffer; -struct ECPContext; struct ECPSocket; struct ECPConnection; -struct ECPSeqItem; -struct ECPPktMeta; + +#ifdef ECP_WITH_DIRSRV struct ECPDirList; +#endif #include "crypto/crypto.h" #include "transport.h" #include "timer.h" -#ifdef ECP_WITH_RBUF -#include "rbuf.h" -#endif - -typedef int (*ecp_rng_t) (void *, size_t); +typedef void (*ecp_err_handler_t) (struct ECPConnection *conn, unsigned char mtype, int err); +typedef ssize_t (*ecp_dir_handler_t) (struct ECPConnection *conn, unsigned char *msg, size_t msg_size, struct ECP2Buffer *b); +typedef struct ECPConnection * (*ecp_conn_alloc_t) (struct ECPSocket *sock, unsigned char type); +typedef void (*ecp_conn_free_t) (struct ECPConnection *conn); -typedef ssize_t (*ecp_sock_msg_handler_t) (struct ECPSocket *s, ECPNetAddr *a, struct ECPConnection *p, unsigned char *msg, size_t sz, struct ECPPktMeta *m, struct ECP2Buffer *b, struct ECPConnection **c); -typedef ssize_t (*ecp_conn_msg_handler_t) (struct ECPConnection *c, ecp_seq_t s, unsigned char t, unsigned char *msg, ssize_t sz, struct ECP2Buffer *b); - -typedef struct ECPConnection * (*ecp_conn_alloc_t) (struct ECPSocket *s, unsigned char t); -typedef void (*ecp_conn_free_t) (struct ECPConnection *c); -typedef ssize_t (*ecp_conn_open_t) (struct ECPConnection *c); -typedef void (*ecp_conn_close_t) (struct ECPConnection *c); +typedef ssize_t (*ecp_msg_handler_t) (struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, struct ECP2Buffer *b); +typedef int (*ecp_open_handler_t) (struct ECPConnection *conn, struct ECP2Buffer *b); +typedef void (*ecp_close_handler_t) (struct ECPConnection *conn); +typedef ssize_t (*ecp_open_send_t) (struct ECPConnection *conn, unsigned char *cookie); typedef struct ECPBuffer { unsigned char *buffer; @@ -186,78 +198,46 @@ typedef struct ECP2Buffer { } ECP2Buffer; typedef struct ECPDHKey { - ecp_dh_public_t public; - ecp_dh_private_t private; + ecp_ecdh_public_t public; + ecp_ecdh_private_t private; unsigned char valid; } ECPDHKey; -typedef struct ECPDHRKey { - unsigned char idx; - ecp_dh_public_t public; -} ECPDHRKey; - -typedef struct ECPDHShared { - ecp_aead_key_t secret; +typedef struct ECPDHPub { + ecp_ecdh_public_t public; unsigned char valid; -} ECPDHShared; - -typedef struct ECPDHRKeyBucket { - ECPDHRKey key[ECP_MAX_NODE_KEY]; - unsigned char key_curr; - unsigned char key_idx_map[ECP_MAX_SOCK_KEY]; -} ECPDHRKeyBucket; +} ECPDHPub; typedef struct ECPNode { - ECPNetAddr addr; - ecp_dh_public_t public; + ecp_tr_addr_t addr; + ECPDHPub key_perma; } ECPNode; -typedef struct ECPSeqItem { - ecp_seq_t seq; - unsigned char seq_w; -#ifdef ECP_WITH_RBUF - unsigned char rb_pass; - unsigned char rb_mtype; - unsigned short rb_idx; -#endif -} ECPSeqItem; - -typedef struct ECPFragIter { - ecp_seq_t seq; - unsigned char frag_cnt; - unsigned char *buffer; - size_t buf_size; - size_t msg_size; -} ECPFragIter; +typedef struct ECPDHShkey { + ecp_aead_key_t key; + unsigned char valid; +} ECPDHShkey; typedef struct ECPPktMeta { - ecp_aead_key_t shsec; - ecp_seq_t seq; - unsigned char public[ECP_ECDH_SIZE_KEY]; - unsigned char nonce[ECP_AEAD_SIZE_NONCE]; + unsigned char *cookie; + ecp_ecdh_public_t *public; + ecp_aead_key_t *shkey; + ecp_nonce_t *nonce; + unsigned char ntype; unsigned char s_idx; unsigned char c_idx; } ECPPktMeta; typedef struct ECPConnHandler { - ecp_conn_msg_handler_t msg[ECP_MAX_MTYPE]; - ecp_conn_close_t conn_close; + ecp_msg_handler_t handle_msg; + ecp_open_handler_t handle_open; + ecp_close_handler_t handle_close; + ecp_open_send_t send_open; } ECPConnHandler; -typedef struct ECPSockCTable { -#ifdef ECP_WITH_HTABLE - void *htable; -#else - struct ECPConnection *array[ECP_MAX_SOCK_CONN]; - unsigned short size; -#endif -#ifdef ECP_WITH_PTHREAD - pthread_mutex_t mutex; -#endif -} ECPSockCTable; - typedef struct ECPContext { - ecp_rng_t rng; + ecp_err_handler_t handle_err; + ecp_dir_handler_t handle_dir; ecp_conn_alloc_t conn_alloc; ecp_conn_free_t conn_free; ECPConnHandler *handler[ECP_MAX_CTYPE]; @@ -267,17 +247,29 @@ typedef struct ECPContext { #endif } ECPContext; +typedef struct ECPConnTable { +#ifdef ECP_WITH_HTABLE + void *keys; + void *addrs; +#else + struct ECPConnection *arr[ECP_MAX_SOCK_CONN]; + unsigned short size; +#endif +#ifdef ECP_WITH_PTHREAD + pthread_mutex_t mutex; +#endif +} ECPConnTable; + typedef struct ECPSocket { ECPContext *ctx; unsigned char running; - int poll_timeout; - ECPNetSock sock; + ecp_tr_sock_t sock; + ecp_nonce_t nonce_out; ECPDHKey key_perma; ECPDHKey key[ECP_MAX_SOCK_KEY]; unsigned char key_curr; - ECPSockCTable conn; + ECPConnTable conn_table; ECPTimer timer; - ecp_sock_msg_handler_t handler[ECP_MAX_MTYPE_SOCK]; #ifdef ECP_WITH_PTHREAD pthread_t rcvr_thd; pthread_mutex_t mutex; @@ -289,120 +281,133 @@ typedef struct ECPConnection { unsigned char flags; unsigned char flags_im; unsigned short refcount; - ecp_seq_t seq_out; - ecp_seq_t seq_in; - ecp_ack_t seq_in_map; + ecp_nonce_t nonce_out; + ecp_nonce_t nonce_in; + ecp_ack_t nonce_map; ECPSocket *sock; - ECPNode node; - ECPDHRKeyBucket remote; + ECPNode remote; ECPDHKey key[ECP_MAX_CONN_KEY]; + ECPDHPub rkey[ECP_MAX_NODE_KEY]; unsigned char key_curr; - unsigned char key_idx[ECP_MAX_NODE_KEY]; - unsigned char key_idx_curr; - unsigned char key_idx_map[ECP_MAX_SOCK_KEY]; - ECPDHShared shared[ECP_MAX_NODE_KEY][ECP_MAX_NODE_KEY]; - unsigned char nonce[ECP_AEAD_SIZE_NONCE]; -#ifdef ECP_WITH_RBUF - ECPConnRBuffer rbuf; -#endif + unsigned char key_next; + unsigned char rkey_curr; + ECPDHShkey shkey[ECP_MAX_NODE_KEY][ECP_MAX_NODE_KEY]; #ifdef ECP_WITH_PTHREAD pthread_mutex_t mutex; #endif +#ifdef ECP_WITH_VCONN struct ECPConnection *parent; + struct ECPConnection *next; unsigned short pcount; - void *conn_data; +#endif } ECPConnection; int ecp_init(ECPContext *ctx); -int ecp_ctx_init(ECPContext *ctx); -int ecp_node_init(ECPNode *node, ecp_dh_public_t *public, void *addr); -int ecp_seq_item_init(ECPSeqItem *seq_item); -int ecp_frag_iter_init(ECPFragIter *iter, unsigned char *buffer, size_t buf_size); -void ecp_frag_iter_reset(ECPFragIter *iter); -int ecp_dhkey_gen(ECPContext *ctx, ECPDHKey *key); +int ecp_ctx_init(ECPContext *ctx, ecp_err_handler_t handle_err, ecp_dir_handler_t handle_dir, ecp_conn_alloc_t conn_alloc, ecp_conn_free_t conn_free); +int ecp_ctx_set_handler(ECPContext *ctx, ECPConnHandler *handler, unsigned char ctype); +int ecp_node_init(ECPNode *node, ecp_ecdh_public_t *public, void *addr); +int ecp_dhkey_gen(ECPDHKey *key); int ecp_sock_init(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key); -int ecp_sock_create(ECPSocket *sock); +int ecp_sock_create(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key); void ecp_sock_destroy(ECPSocket *sock); int ecp_sock_open(ECPSocket *sock, void *myaddr); void ecp_sock_close(ECPSocket *sock); -ecp_sock_msg_handler_t ecp_sock_get_msg_handler(ECPSocket *sock, unsigned char mtype); -int ecp_sock_dhkey_get_curr(ECPSocket *sock, unsigned char *idx, unsigned char *public); int ecp_sock_dhkey_new(ECPSocket *sock); +int ecp_sock_dhkey_get(ECPSocket *sock, unsigned char idx, ECPDHKey *key); +int ecp_sock_dhkey_get_pub(ECPSocket *sock, unsigned char *idx, ecp_ecdh_public_t *public); +void ecp_sock_get_nonce(ECPSocket *sock, ecp_nonce_t *nonce); -int ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype); -int ecp_conn_create(ECPConnection *conn); +ECPConnection *ecp_sock_keys_search(ECPSocket *sock, ecp_ecdh_public_t *public); +int ecp_sock_keys_insert(ECPSocket *sock, ecp_ecdh_public_t *public, ECPConnection *conn); +void ecp_sock_keys_remove(ECPSocket *sock, ecp_ecdh_public_t *public); + +int ecp_conn_alloc(ECPSocket *sock, unsigned char ctype, ECPConnection **_conn); +void ecp_conn_free(ECPConnection *conn); + +void ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype); +void ecp_conn_reinit(ECPConnection *conn); +int ecp_conn_create(ECPConnection *conn, ECPSocket *sock, unsigned char ctype); +int ecp_conn_create_inb(ECPConnection *conn, ECPSocket *sock, unsigned char ctype); void ecp_conn_destroy(ECPConnection *conn); -int ecp_conn_create_inb(ECPConnection *conn, ECPConnection *parent, unsigned char c_idx, unsigned char *public); -int ecp_conn_create_outb(ECPConnection *conn, ECPNode *node); + +void ecp_conn_set_flags(ECPConnection *conn, unsigned char flags); +void ecp_conn_clr_flags(ECPConnection *conn, unsigned char flags); +void ecp_conn_set_remote_key(ECPConnection *conn, ECPDHPub *key); +void ecp_conn_set_remote_addr(ECPConnection *conn, ecp_tr_addr_t *addr); + +int ecp_conn_init_inb(ECPConnection *conn, ECPConnection *parent, unsigned char s_idx, unsigned char c_idx, ecp_ecdh_public_t *public, ECPDHPub *remote_key, ecp_aead_key_t *shkey); +int ecp_conn_init_outb(ECPConnection *conn, ECPNode *node); + int ecp_conn_insert(ECPConnection *conn); -int ecp_conn_register(ECPConnection *conn); -void ecp_conn_unregister(ECPConnection *conn, unsigned short *refcount); +void ecp_conn_remove(ECPConnection *conn, unsigned short *refcount); +void ecp_conn_remove_addr(ECPConnection *conn); -int ecp_conn_get_dirlist(ECPConnection *conn, ECPNode *node); int ecp_conn_open(ECPConnection *conn, ECPNode *node); -int ecp_conn_close(ECPConnection *conn); int ecp_conn_reset(ECPConnection *conn); +void _ecp_conn_close(ECPConnection *conn); +int ecp_conn_close(ECPConnection *conn); void ecp_conn_refcount_inc(ECPConnection *conn); void ecp_conn_refcount_dec(ECPConnection *conn); -int ecp_conn_handler_init(ECPConnHandler *handler); -ecp_conn_msg_handler_t ecp_conn_get_msg_handler(ECPConnection *conn, unsigned char mtype); -ecp_conn_close_t ecp_conn_get_close_handler(ECPConnection *conn); int ecp_conn_dhkey_new(ECPConnection *conn); -int ecp_conn_dhkey_new_pub(ECPConnection *conn, unsigned char idx, unsigned char *public); -int ecp_conn_dhkey_get_curr(ECPConnection *conn, unsigned char *idx, unsigned char *public); - -ssize_t ecp_conn_send_open(ECPConnection *conn); -ssize_t ecp_conn_send_kget(ECPConnection *conn); -ssize_t ecp_conn_send_kput(ECPConnection *conn); -ssize_t ecp_conn_send_dir(ECPConnection *conn); - -ssize_t _ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b, int *was_open); -ssize_t ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b); -ssize_t _ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b, ecp_conn_open_t conn_open); -ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b); -ssize_t ecp_conn_handle_kput(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b); -ssize_t ecp_conn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs); -ssize_t ecp_sock_handle_open(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, ECPConnection **_conn); -ssize_t ecp_sock_handle_kget(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, ECPConnection **_conn); - -ssize_t _ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, ECPPktMeta *pkt_meta, unsigned char *payload, size_t pld_size); -ssize_t ecp_pack(ECPContext *ctx, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) ; - -ssize_t _ecp_pack_conn(ECPConnection *conn, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si); -ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si); - -ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size, ECPConnection **_conn, ecp_seq_t *_seq); -ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size); -ssize_t ecp_pkt_send(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t pkt_size, unsigned char flags); - -int ecp_msg_get_type(unsigned char *msg, size_t msg_size, unsigned char *mtype); -int ecp_msg_set_type(unsigned char *msg, size_t msg_size, unsigned char mtype); -int ecp_msg_get_frag(unsigned char *msg, size_t msg_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size); -int ecp_msg_set_frag(unsigned char *msg, size_t msg_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size); -int ecp_msg_get_pts(unsigned char *msg, size_t msg_size, ecp_pts_t *pts); -int ecp_msg_set_pts(unsigned char *msg, size_t msg_size, ecp_pts_t pts); -unsigned char *ecp_msg_get_content(unsigned char *msg, size_t msg_size); -int ecp_msg_defrag(ECPFragIter *iter, ecp_seq_t seq, unsigned char mtype, unsigned char *msg_in, size_t msg_in_size, unsigned char **msg_out, size_t *msg_out_size); - -int ecp_pld_get_type(unsigned char *payload, size_t pld_size, unsigned char *mtype); -int ecp_pld_set_type(unsigned char *payload, size_t pld_size, unsigned char mtype); -int ecp_pld_get_frag(unsigned char *payload, size_t pld_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size); -int ecp_pld_set_frag(unsigned char *payload, size_t pld_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size); -int ecp_pld_get_pts(unsigned char *payload, size_t pld_size, ecp_pts_t *pts); -int ecp_pld_set_pts(unsigned char *payload, size_t pld_size, ecp_pts_t pts); -unsigned char *ecp_pld_get_buf(unsigned char *payload, size_t pld_size); - -ssize_t __ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti, ECPSeqItem *si); -ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti); +int ecp_conn_dhkey_get(ECPSocket *sock, unsigned char idx, ECPDHKey *key); +int ecp_conn_dhkey_get_pub(ECPConnection *conn, unsigned char *idx, ecp_ecdh_public_t *public, int will_send); +int ecp_conn_dhkey_set_pub(ECPConnection *conn, unsigned char idx, ecp_ecdh_public_t *public); +void ecp_conn_dhkey_set_curr(ECPConnection *conn); + +void ecp_conn_handler_init(ECPConnHandler *handler, ecp_msg_handler_t handle_msg, ecp_open_handler_t handle_open, ecp_close_handler_t handle_close, ecp_open_send_t send_open); +ecp_msg_handler_t ecp_get_msg_handler(ECPConnection *conn); +ecp_open_handler_t ecp_get_open_handler(ECPConnection *conn); +ecp_close_handler_t ecp_get_close_handler(ECPConnection *conn); +ecp_dir_handler_t ecp_get_dir_handler(ECPConnection *conn); +void ecp_err_handle(ECPConnection *conn, unsigned char mtype, int err); + +ssize_t ecp_send_init_req(ECPConnection *conn); +ssize_t ecp_handle_init_req(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, unsigned char *public_buf, ecp_aead_key_t *shkey); +ssize_t ecp_send_init_rep(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, unsigned char *public_buf, ecp_aead_key_t *shkey); +ssize_t ecp_handle_init_rep(ECPConnection *conn, unsigned char *msg, size_t msg_size); +ssize_t ecp_write_open_req(ECPConnection *conn, ECPBuffer *payload); +ssize_t ecp_send_open_req(ECPConnection *conn, unsigned char *cookie); +ssize_t ecp_handle_open_req(ECPSocket *sock, ECPConnection *parent, unsigned char s_idx, unsigned char c_idx, unsigned char *public_buf, unsigned char *msg, size_t msg_size, ecp_aead_key_t *shkey, ECPConnection **_conn); +ssize_t ecp_send_open_rep(ECPConnection *conn); +ssize_t ecp_handle_open(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs); + +ssize_t ecp_send_keyx_req(ECPConnection *conn); +ssize_t ecp_send_keyx_rep(ECPConnection *conn); +ssize_t ecp_handle_keyx(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size); + +ssize_t ecp_msg_handle(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs); +ssize_t ecp_pld_handle_one(ECPConnection *conn, ecp_seq_t seq, unsigned char *payload, size_t pld_size, ECP2Buffer *bufs); +ssize_t ecp_pld_handle(ECPConnection *conn, ecp_seq_t seq, unsigned char *payload, size_t _pld_size, ECP2Buffer *bufs); + +ssize_t ecp_unpack(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECP2Buffer *bufs, size_t _pkt_size, ECPConnection **_conn, unsigned char **_payload, ecp_seq_t *_seq); +ssize_t ecp_pkt_handle(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECP2Buffer *bufs, size_t pkt_size); + +ssize_t ecp_pkt_send(ECPSocket *sock, ECPBuffer *packet, size_t pkt_size, unsigned char flags, ECPTimerItem *ti, ecp_tr_addr_t *addr); + +void ecp_nonce2buf(unsigned char *b, ecp_nonce_t *n); +void ecp_buf2nonce(ecp_nonce_t *n, unsigned char *b); +int ecp_pkt_get_seq(unsigned char *pkt, size_t pkt_size, ecp_seq_t *s); +ssize_t ecp_pack(ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ecp_tr_addr_t *addr); +ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, unsigned char *cookie, ecp_nonce_t *nonce, ECPBuffer *payload, size_t pld_size, ecp_tr_addr_t *addr); + +int ecp_pld_get_type(unsigned char *pld, size_t pld_size, unsigned char *mtype); +int ecp_pld_set_type(unsigned char *pld, size_t pld_size, unsigned char mtype); +int ecp_pld_get_frag(unsigned char *pld, size_t pld_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size); +int ecp_pld_set_frag(unsigned char *pld, size_t pld_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size); +int ecp_pld_get_pts(unsigned char *pld, size_t pld_size, ecp_pts_t *pts); +int ecp_pld_set_pts(unsigned char *pld, size_t pld_size, ecp_pts_t pts); +unsigned char *ecp_pld_get_msg(unsigned char *pld, size_t pld_size); + +ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, unsigned char *cookie, ecp_nonce_t *n, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti); ssize_t ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags); ssize_t ecp_pld_send_wtimer(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti); -ssize_t ecp_pld_send_tr(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, unsigned char flags); - -ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *content, size_t content_size); -ssize_t ecp_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout); +ssize_t ecp_pld_send_wcookie(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, unsigned char *cookie); +ssize_t ecp_pld_send_wnonce(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, ecp_nonce_t *nonce); +ssize_t ecp_pld_send_irep(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, unsigned char flags); +ssize_t ecp_msg_send(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size); int ecp_receiver(ECPSocket *sock); int ecp_start_receiver(ECPSocket *sock); int ecp_stop_receiver(ECPSocket *sock); diff --git a/ecp/src/ecp/cr.h b/ecp/src/ecp/cr.h index a8d0dea..bcca318 100644 --- a/ecp/src/ecp/cr.h +++ b/ecp/src/ecp/cr.h @@ -1,13 +1,16 @@ -int ecp_cr_dh_mkpair(ecp_dh_public_t *pub, ecp_dh_private_t *priv, ecp_rng_t rand_buf); -int ecp_cr_dh_shsec(ecp_aead_key_t *shared, ecp_dh_public_t *pub, ecp_dh_private_t *priv); -unsigned char *ecp_cr_dh_pub_get_buf(ecp_dh_public_t *p); -void ecp_cr_dh_pub_to_buf(unsigned char *b, ecp_dh_public_t *p); -void ecp_cr_dh_pub_from_buf(ecp_dh_public_t *p, unsigned char *b) ; -int ecp_cr_dh_pub_eq(unsigned char *p1, ecp_dh_public_t *p2) ; -unsigned int ecp_cr_dh_pub_hash_fn(unsigned char *p); -int ecp_cr_dh_pub_hash_eq(unsigned char *p1, unsigned char *p2); -ssize_t ecp_cr_aead_enc(unsigned char *ct, size_t cl, unsigned char *pt, size_t pl, ecp_aead_key_t *k, unsigned char *n); -ssize_t ecp_cr_aead_dec(unsigned char *pt, size_t pl, unsigned char *ct, size_t cl, ecp_aead_key_t *k, unsigned char *n) ; -int ecp_cr_dsa_mkpair(ecp_dsa_public_t *pub, ecp_dsa_private_t *priv, ecp_rng_t rand_buf); -int ecp_cr_dsa_sign(unsigned char *sig, unsigned char *m, size_t ml, ecp_dsa_public_t *p, ecp_dsa_private_t *s) ; -int ecp_cr_dsa_verify(unsigned char *m, size_t ml, unsigned char *sig, ecp_dsa_public_t *p); +uint32_t arc4random(void); +void arc4random_buf(void *_buf, size_t n); +uint32_t arc4random_uniform(uint32_t upper_bound); + +int ecp_ecdh_mkpair(ecp_ecdh_public_t *pub, ecp_ecdh_private_t *priv); +int ecp_ecdh_shkey(ecp_aead_key_t *shared, ecp_ecdh_public_t *pub, ecp_ecdh_private_t *priv); + +unsigned int ecp_ecdh_pub_hash(ecp_ecdh_public_t *p); +int ecp_ecdh_pub_eq(ecp_ecdh_public_t *p1, ecp_ecdh_public_t *p2); + +ssize_t ecp_aead_enc(unsigned char *ct, size_t cl, unsigned char *pt, size_t pl, ecp_aead_key_t *k, ecp_nonce_t *n, unsigned char nt); +ssize_t ecp_aead_dec(unsigned char *pt, size_t pl, unsigned char *ct, size_t cl, ecp_aead_key_t *k, ecp_nonce_t *n, unsigned char nt); + +int ecp_ecdsa_mkpair(ecp_ecdsa_public_t *pub, ecp_ecdsa_private_t *priv); +int ecp_ecdsa_sign(ecp_ecdsa_signature_t *sig, unsigned char *m, size_t ml, ecp_ecdsa_private_t *k); +int ecp_ecdsa_verify(unsigned char *m, size_t ml, ecp_ecdsa_signature_t *sig, ecp_ecdsa_public_t *p); diff --git a/ecp/src/ecp/crypto/crypto.c b/ecp/src/ecp/crypto/crypto.c index e1d06b3..66ce524 100644 --- a/ecp/src/ecp/crypto/crypto.c +++ b/ecp/src/ecp/crypto/crypto.c @@ -1,14 +1,17 @@ +#include <stdlib.h> +#include <string.h> + #include <core.h> #include <cr.h> #include <openssl/curve25519.h> -int ecp_cr_dh_mkpair(ecp_dh_public_t *pub, ecp_dh_private_t *priv, ecp_rng_t rand_buf) { +int ecp_ecdh_mkpair(ecp_ecdh_public_t *pub, ecp_ecdh_private_t *priv) { X25519_keypair(*pub, *priv); return ECP_OK; } -int ecp_cr_dh_shsec(ecp_aead_key_t *shared, ecp_dh_public_t *pub, ecp_dh_private_t *priv) { +int ecp_ecdh_shkey(ecp_aead_key_t *shared, ecp_ecdh_public_t *pub, ecp_ecdh_private_t *priv) { int rv; rv = X25519(*shared, *priv, *pub); @@ -16,78 +19,87 @@ int ecp_cr_dh_shsec(ecp_aead_key_t *shared, ecp_dh_public_t *pub, ecp_dh_private return ECP_OK; } -unsigned char *ecp_cr_dh_pub_get_buf(ecp_dh_public_t *p) { - return (unsigned char *)p; +unsigned int ecp_ecdh_pub_hash(ecp_ecdh_public_t *p) { + return *((unsigned int *)p); } -void ecp_cr_dh_pub_to_buf(unsigned char *b, ecp_dh_public_t *p) { - memcpy(b, p, ECP_ECDH_SIZE_KEY); +int ecp_ecdh_pub_eq(ecp_ecdh_public_t *p1, ecp_ecdh_public_t *p2) { + return !memcmp(p1, p2, sizeof(ecp_ecdh_public_t)); } -void ecp_cr_dh_pub_from_buf(ecp_dh_public_t *p, unsigned char *b) { - memcpy(p, b, ECP_ECDH_SIZE_KEY); -} +ssize_t ecp_aead_enc(unsigned char *ct, size_t cl, unsigned char *pt, size_t pl, ecp_aead_key_t *k, ecp_nonce_t *n, unsigned char nt) { + ecp_aead_nonce_t nonce; + size_t ol; + int rv; -int ecp_cr_dh_pub_eq(unsigned char *p1, ecp_dh_public_t *p2) { - return !memcmp(p1, p2, ECP_ECDH_SIZE_KEY); -} + switch (nt) { + case ECP_NTYPE_INB: + memcpy(&nonce, "SRVR", 4); + break; -unsigned int ecp_cr_dh_pub_hash_fn(unsigned char *p) { - return *((unsigned int *)p); -} + case ECP_NTYPE_OUTB: + memcpy(&nonce, "CLNT", 4); + break; -int ecp_cr_dh_pub_hash_eq(unsigned char *p1, unsigned char *p2) { - return !memcmp(p1, p2, ECP_ECDH_SIZE_KEY); -} + case ECP_NTYPE_VBOX: + memcpy(&nonce, "VBOX", 4); + break; -ssize_t ecp_cr_aead_enc(unsigned char *ct, size_t cl, unsigned char *pt, size_t pl, ecp_aead_key_t *k, unsigned char *n) { - uint8_t _n[ECP_AEAD_SIZE_NONCE + 4]; - size_t ol; - int rv; + default: + return ECP_ERR_ENCRYPT; + } + ecp_nonce2buf((unsigned char *)&nonce + 4, n); - memset(_n, 0, 4); - memcpy(_n + 4, n, ECP_AEAD_SIZE_NONCE); - rv = aead_chacha20_poly1305_seal(*k, ECP_AEAD_SIZE_TAG, ct, &ol, cl, _n, ECP_AEAD_SIZE_NONCE + 4, pt, pl, NULL, 0); - if (!rv) return ECP_ERR; + rv = aead_chacha20_poly1305_seal(*k, ECP_SIZE_AEAD_TAG, ct, &ol, cl, (const unsigned char *)&nonce, sizeof(nonce), pt, pl, NULL, 0); + if (!rv) return ECP_ERR_ENCRYPT; return ol; } -ssize_t ecp_cr_aead_dec(unsigned char *pt, size_t pl, unsigned char *ct, size_t cl, ecp_aead_key_t *k, unsigned char *n) { - uint8_t _n[ECP_AEAD_SIZE_NONCE + 4]; +ssize_t ecp_aead_dec(unsigned char *pt, size_t pl, unsigned char *ct, size_t cl, ecp_aead_key_t *k, ecp_nonce_t *n, unsigned char nt) { + ecp_aead_nonce_t nonce; size_t ol; int rv; - memset(_n, 0, 4); - memcpy(_n + 4, n, ECP_AEAD_SIZE_NONCE); - rv = aead_chacha20_poly1305_open(*k, ECP_AEAD_SIZE_TAG, pt, &ol, pl, _n, ECP_AEAD_SIZE_NONCE + 4, ct, cl, NULL, 0); - if (!rv) return ECP_ERR; + switch (nt) { + case ECP_NTYPE_INB: + memcpy(&nonce, "CLNT", 4); + break; + + case ECP_NTYPE_OUTB: + memcpy(&nonce, "SRVR", 4); + break; + + case ECP_NTYPE_VBOX: + memcpy(&nonce, "VBOX", 4); + break; + + default: + return ECP_ERR_DECRYPT; + } + ecp_nonce2buf((unsigned char *)&nonce + 4, n); + + rv = aead_chacha20_poly1305_open(*k, ECP_SIZE_AEAD_TAG, pt, &ol, pl, (const unsigned char *)&nonce, sizeof(nonce), ct, cl, NULL, 0); + if (!rv) return ECP_ERR_DECRYPT; return ol; } -int ecp_cr_dsa_mkpair(ecp_dsa_public_t *pub, ecp_dsa_private_t *priv, ecp_rng_t rand_buf) { - unsigned char key[2*ECP_DSA_SIZE_KEY]; - - ED25519_keypair(*pub, key); - memcpy(priv, key, ECP_DSA_SIZE_KEY); +int ecp_ecdsa_mkpair(ecp_ecdsa_public_t *pub, ecp_ecdsa_private_t *priv) { + ED25519_keypair(*pub, *priv); return ECP_OK; } -int ecp_cr_dsa_sign(unsigned char *sig, unsigned char *m, size_t ml, ecp_dsa_public_t *p, ecp_dsa_private_t *s) { - unsigned char key[2*ECP_DSA_SIZE_KEY]; +int ecp_ecdsa_sign(ecp_ecdsa_signature_t *sig, unsigned char *m, size_t ml, ecp_ecdsa_private_t *k) { int rv; - memcpy(key, s, ECP_DSA_SIZE_KEY); - memcpy(key+ECP_DSA_SIZE_KEY, p, ECP_DSA_SIZE_KEY); - - rv = ED25519_sign(sig, m, ml, key); - if (!rv) return ECP_ERR; + rv = ED25519_sign(*sig, m, ml, *k); + if (!rv) return ECP_ERR_SIGN; return ECP_OK; } -int ecp_cr_dsa_verify(unsigned char *m, size_t ml, unsigned char *sig, ecp_dsa_public_t *p) { +int ecp_ecdsa_verify(unsigned char *m, size_t ml, ecp_ecdsa_signature_t *sig, ecp_ecdsa_public_t *p) { int rv; - rv = ED25519_verify(m, ml, sig, *p); + rv = ED25519_verify(m, ml, *sig, *p); if (rv == 1) return ECP_OK; - return ECP_ERR; + return ECP_ERR_VERIFY; } diff --git a/ecp/src/ecp/crypto/crypto.h b/ecp/src/ecp/crypto/crypto.h index 378500c..863b25b 100644 --- a/ecp/src/ecp/crypto/crypto.h +++ b/ecp/src/ecp/crypto/crypto.h @@ -1,21 +1,25 @@ #define CURVE25519_SIZE_KEY 32 #define CHACHA20_SIZE_KEY 32 #define POLY1305_SIZE_TAG 16 -#define CHACHA20_SIZE_NONCE 8 +#define CHACHA20_SIZE_NONCE 12 -#define ECP_ECDH_SIZE_KEY 32 -#define ECP_AEAD_SIZE_KEY 32 -#define ECP_AEAD_SIZE_TAG 16 -#define ECP_AEAD_SIZE_NONCE 8 +#define ECP_SIZE_ECDH_PUB 32 +#define ECP_SIZE_ECDH_SEC 32 +#define ECP_SIZE_AEAD_KEY 32 +#define ECP_SIZE_AEAD_TAG 16 +#define ECP_SIZE_AEAD_NONCE 12 -#define ECP_DSA_SIZE_KEY 32 -#define ECP_DSA_SIZE_SIGNATURE 32 +#define ECP_SIZE_ECDSA_PUB 32 +#define ECP_SIZE_ECDSA_SEC 64 +#define ECP_SIZE_ECDSA_SIG 32 -typedef uint8_t ecp_dh_public_t[ECP_ECDH_SIZE_KEY]; -typedef uint8_t ecp_dh_private_t[ECP_ECDH_SIZE_KEY]; -typedef uint8_t ecp_aead_key_t[ECP_AEAD_SIZE_KEY]; -typedef uint8_t ecp_dsa_public_t[ECP_DSA_SIZE_KEY]; -typedef uint8_t ecp_dsa_private_t[ECP_DSA_SIZE_KEY]; +typedef uint8_t ecp_ecdh_public_t[ECP_SIZE_ECDH_PUB]; +typedef uint8_t ecp_ecdh_private_t[ECP_SIZE_ECDH_SEC]; +typedef uint8_t ecp_aead_key_t[ECP_SIZE_AEAD_KEY]; +typedef uint8_t ecp_aead_nonce_t[ECP_SIZE_AEAD_NONCE]; +typedef uint8_t ecp_ecdsa_public_t[ECP_SIZE_ECDSA_PUB]; +typedef uint8_t ecp_ecdsa_private_t[ECP_SIZE_ECDSA_SEC]; +typedef uint8_t ecp_ecdsa_signature_t[ECP_SIZE_ECDSA_SIG]; int aead_chacha20_poly1305_seal(unsigned char key[32], unsigned char tag_len, diff --git a/ecp/src/ecp/dir.c b/ecp/src/ecp/dir.c index 46d152e..0e07486 100644 --- a/ecp/src/ecp/dir.c +++ b/ecp/src/ecp/dir.c @@ -1,3 +1,6 @@ +#include <stdlib.h> +#include <string.h> + #include "core.h" #include "cr.h" @@ -8,7 +11,7 @@ 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) { + if (memcmp(&list->item[i].node.key_perma.public, &item->node.key_perma.public, sizeof(item->node.key_perma.public)) == 0) { return ECP_OK; } } @@ -23,45 +26,65 @@ static int dir_update(ECPDirList *list, ECPDirItem *item) { ssize_t ecp_dir_parse(ECPDirList *list, unsigned char *buf, size_t buf_size) { ECPDirItem item; - size_t size; + size_t rsize; + uint16_t count; + int i; int rv; - size = buf_size; - while (size >= ECP_SIZE_DIR_ITEM) { + if (buf_size < sizeof(uint16_t)) return ECP_ERR_SIZE; + + count = \ + (buf[0] << 8) | \ + (buf[1]); + + rsize = sizeof(uint16_t) + count * ECP_SIZE_DIR_ITEM; + if (buf_size < rsize) return ECP_ERR_SIZE; + + buf += sizeof(uint16_t); + for (i=0; i<count; i++) { 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; + return rsize; } -int ecp_dir_serialize(ECPDirList *list, unsigned char *buf, size_t buf_size) { +ssize_t ecp_dir_serialize(ECPDirList *list, unsigned char *buf, size_t buf_size) { + size_t rsize; int i; - for (i=0; i<list->count; i++) { - if (buf_size < ECP_SIZE_DIR_ITEM) return ECP_ERR_SIZE; + rsize = sizeof(uint16_t) + list->count * ECP_SIZE_DIR_ITEM; + if (buf_size < rsize) return ECP_ERR_SIZE; + buf[0] = (list->count & 0xFF00) >> 8; + buf[1] = (list->count & 0x00FF); + buf += sizeof(uint16_t); + for (i=0; i<list->count; i++) { ecp_dir_item_serialize(&list->item[i], buf); buf += ECP_SIZE_DIR_ITEM; - buf_size -= ECP_SIZE_DIR_ITEM; } - return ECP_OK; + return rsize; } 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; + ECPDHPub *key; + ecp_tr_addr_t *addr; - memcpy(&item->node.addr.host, buf, sizeof(item->node.addr)); - buf += ECP_IPv4_ADDR_SIZE; + key = &item->node.key_perma; + addr = &item->node.addr; - item->node.addr.port = \ + memcpy(&key->public, buf, sizeof(key->public)); + buf += sizeof(key->public); + + memcpy(&addr->host, buf, sizeof(addr->host)); + buf += sizeof(addr->host); + + addr->port = \ (buf[0] << 8) | \ (buf[1]); buf += sizeof(uint16_t); @@ -73,17 +96,108 @@ void ecp_dir_item_parse(ECPDirItem *item, unsigned char *buf) { } 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; + ECPDHPub *key; + ecp_tr_addr_t *addr; + + key = &item->node.key_perma; + addr = &item->node.addr; - memcpy(buf, &item->node.addr.host, sizeof(item->node.addr)); - buf += ECP_IPv4_ADDR_SIZE; + memcpy(buf, &key->public, sizeof(key->public)); + buf += sizeof(key->public); - buf[0] = (item->node.addr.port & 0xFF00) >> 8; - buf[1] = (item->node.addr.port & 0x00FF); + memcpy(buf, &addr->host, sizeof(addr->host)); + buf += sizeof(addr->host); + + buf[0] = (addr->port & 0xFF00) >> 8; + buf[1] = (addr->port & 0x00FF); buf += sizeof(uint16_t); buf[0] = (item->capabilities & 0xFF00) >> 8; buf[1] = (item->capabilities & 0x00FF); buf += sizeof(uint16_t); } + +ssize_t ecp_dir_handle(ECPConnection *conn, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + ecp_dir_handler_t handler; + + handler = ecp_get_dir_handler(conn); + if (handler) { + return handler(conn, msg, msg_size, b); + } else { + return ECP_ERR_HANDLER; + } +} + +int ecp_dir_handle_open(ECPConnection *conn, ECP2Buffer *b) { + ssize_t rv; + + if (ecp_conn_is_inb(conn)) return ECP_OK; + +#ifdef ECP_WITH_DIRSRV + rv = ecp_dir_send_upd(conn); +#else + rv = ecp_dir_send_req(conn); +#endif + if (rv < 0) return rv; + + return ECP_OK; +} + +ssize_t ecp_dir_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + switch (mtype) { +#ifdef ECP_WITH_DIRSRV + case ECP_MTYPE_DIR_UPD: { + return ecp_dir_handle_upd(conn, msg, msg_size); + } + + case ECP_MTYPE_DIR_REQ: { + return ecp_dir_handle_req(conn, msg, msg_size); + } +#endif + + case ECP_MTYPE_DIR_REP: { +#ifdef ECP_WITH_DIRSRV + return ecp_dir_handle_rep(conn, msg, msg_size); +#else + return ecp_dir_handle(conn, msg, msg_size, b); +#endif + } + + default: + return ECP_ERR_MTYPE; + } +} + +// iterator for client + +static ssize_t _dir_send_req(ECPConnection *conn, ECPTimerItem *ti) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_DIR_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_DIR_REQ, conn)]; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_DIR_REQ); + return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_DIR_REQ), 0, ti); +} + +ssize_t ecp_dir_send_req(ECPConnection *conn) { + return ecp_timer_send(conn, _dir_send_req, ECP_MTYPE_DIR_REP, ECP_SEND_TRIES, ECP_SEND_TIMEOUT); +} + +int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ECPNode *node) { + int rv; + ssize_t _rv; + + rv = ecp_conn_create(conn, sock, ECP_CTYPE_DIR); + if (rv) return rv; + + rv = ecp_conn_open(conn, node); + if (rv) return rv; + + return ECP_OK; +} diff --git a/ecp/src/ecp/dir.h b/ecp/src/ecp/dir.h index 2fcc50f..e9f8e1e 100644 --- a/ecp/src/ecp/dir.h +++ b/ecp/src/ecp/dir.h @@ -1,5 +1,11 @@ -#define ECP_MAX_DIR_ITEM 30 -#define ECP_SIZE_DIR_ITEM 40 +#define ECP_MAX_DIR_ITEM 30 +#define ECP_SIZE_DIR_ITEM 40 + +#define ECP_MTYPE_DIR_UPD 0x00 +#define ECP_MTYPE_DIR_REQ 0x01 +#define ECP_MTYPE_DIR_REP 0x02 + +#define ECP_CTYPE_DIR (0x00 | ECP_CTYPE_FLAG_SYS) typedef struct ECPDirItem { ECPNode node; @@ -12,7 +18,15 @@ typedef struct ECPDirList { } ECPDirList; ssize_t ecp_dir_parse(ECPDirList *list, unsigned char *buf, size_t buf_size); -int ecp_dir_serialize(ECPDirList *list, unsigned char *buf, size_t buf_size); +ssize_t ecp_dir_serialize(ECPDirList *list, unsigned char *buf, size_t buf_size); void ecp_dir_item_parse(ECPDirItem *item, unsigned char *buf); void ecp_dir_item_serialize(ECPDirItem *item, unsigned char *buf); + +ssize_t ecp_dir_handle(ECPConnection *conn, unsigned char *msg, size_t msg_size, ECP2Buffer *b); + +int ecp_dir_handle_open(ECPConnection *conn, ECP2Buffer *b); +ssize_t ecp_dir_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *b); + +ssize_t ecp_dir_send_req(ECPConnection *conn); +int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ECPNode *node);
\ No newline at end of file diff --git a/ecp/src/ecp/dir_srv.c b/ecp/src/ecp/dir_srv.c index 563326d..952d393 100644 --- a/ecp/src/ecp/dir_srv.c +++ b/ecp/src/ecp/dir_srv.c @@ -1,11 +1,11 @@ +#include <stdlib.h> + #include "core.h" #include "cr.h" #include "dir.h" #include "dir_srv.h" -#ifdef ECP_WITH_DIRSRV - int ecp_dir_init(ECPContext *ctx, ECPDirList *dir_online, ECPDirList *dir_shadow) { ctx->dir_online = dir_online; ctx->dir_shadow = dir_shadow; @@ -13,38 +13,76 @@ int ecp_dir_init(ECPContext *ctx, ECPDirList *dir_online, ECPDirList *dir_shadow return ECP_OK; } -ssize_t ecp_dir_handle_update(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { +ssize_t ecp_dir_send_list(ECPConnection *conn, unsigned char mtype, ECPDirList *list) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_MAX_PKT]; + unsigned char pld_buf[ECP_MAX_PLD]; + unsigned char *msg; + size_t hdr_size; + size_t msg_size; + ssize_t rv; + + packet.buffer = pkt_buf; + packet.size = ECP_MAX_PKT; + payload.buffer = pld_buf; + payload.size = ECP_MAX_PLD; + + ecp_pld_set_type(payload.buffer, payload.size, mtype); + msg = ecp_pld_get_msg(payload.buffer, payload.size); + hdr_size = msg - payload.buffer; + msg_size = payload.size - hdr_size; + + rv = ecp_dir_serialize(list, msg, msg_size); + if (rv < 0) return rv; + + rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(rv, mtype), 0); + return rv; +} + +ssize_t ecp_dir_send_upd(ECPConnection *conn) { ECPContext *ctx = conn->sock->ctx; - ECPDirList *dir_shadow = ctx->dir_shadow; + ssize_t rv; - if (mtype == ECP_MTYPE_DIR_REQ) { - return ecp_dir_parse(dir_shadow, msg, size); - } else { - return ECP_ERR; - } + rv = ecp_dir_send_list(conn, ECP_MTYPE_DIR_UPD, ctx->dir_shadow); + return rv; } -ssize_t ecp_dir_handle_req(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, ECPConnection **_conn) { - ECPContext *ctx = sock->ctx; - ECPBuffer *packet = bufs->packet; - ECPBuffer *payload = bufs->payload; - ECPDirList *dir_online = ctx->dir_online; +ssize_t ecp_dir_handle_upd(ECPConnection *conn, unsigned char *msg, size_t msg_size) { + ECPContext *ctx = conn->sock->ctx; + ssize_t rsize; ssize_t rv; - int _rv; - if (msg_size < 0) return msg_size; + rsize = ecp_dir_parse(ctx->dir_shadow, msg, msg_size); + if (rsize < 0) return rsize; - ecp_pld_set_type(payload->buffer, payload->size, ECP_MTYPE_DIR_REP); - msg = ecp_pld_get_buf(payload->buffer, payload->size); - msg_size = payload->size - (msg - payload->buffer); + rv = ecp_dir_send_list(conn, ECP_MTYPE_DIR_REP, ctx->dir_shadow); + if (rv < 0) return rv; + + return rsize; +} - _rv = ecp_dir_serialize(dir_online, msg, msg_size); - if (_rv) return _rv; +ssize_t ecp_dir_handle_req(ECPConnection *conn, unsigned char *msg, size_t msg_size) { + ssize_t rv; - rv = ecp_pld_send_tr(sock, addr, parent, packet, pkt_meta, payload, ECP_SIZE_PLD(dir_online->count * ECP_SIZE_DIR_ITEM, ECP_MTYPE_DIR_REP), 0); + rv = ecp_dir_send_rep(conn); if (rv < 0) return rv; - return msg_size; + return 0; +} + +ssize_t ecp_dir_send_rep(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + ssize_t rv; + + rv = ecp_dir_send_list(conn, ECP_MTYPE_DIR_REP, ctx->dir_online); + return rv; } -#endif /* ECP_WITH_DIRSRV */
\ No newline at end of file +ssize_t ecp_dir_handle_rep(ECPConnection *conn, unsigned char *msg, size_t msg_size) { + ECPContext *ctx = conn->sock->ctx; + ssize_t rv; + + rv = ecp_dir_parse(ctx->dir_shadow, msg, msg_size); + return rv; +}
\ No newline at end of file diff --git a/ecp/src/ecp/dir_srv.h b/ecp/src/ecp/dir_srv.h index 3fc14ee..85606c8 100644 --- a/ecp/src/ecp/dir_srv.h +++ b/ecp/src/ecp/dir_srv.h @@ -1,7 +1,10 @@ -#ifdef ECP_WITH_DIRSRV +int ecp_dir_init(ECPContext *ctx, ECPDirList *dir_online, ECPDirList *dir_shadow); +ssize_t ecp_dir_send_list(ECPConnection *conn, unsigned char mtype, ECPDirList *list); -int ecp_dir_init(struct ECPContext *ctx, struct ECPDirList *dir_online, struct ECPDirList *dir_shadow); -ssize_t ecp_dir_handle_update(struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, struct ECP2Buffer *b); -ssize_t ecp_dir_handle_req(struct ECPSocket *sock, struct ECPNetAddr *addr, struct ECPConnection *parent, unsigned char *msg, size_t msg_size, struct ECPPktMeta *pkt_meta, struct ECP2Buffer *bufs, struct ECPConnection **_conn); +ssize_t ecp_dir_send_upd(ECPConnection *conn); +ssize_t ecp_dir_handle_upd(ECPConnection *conn, unsigned char *msg, size_t msg_size); -#endif /* ECP_WITH_DIRSRV */
\ No newline at end of file +ssize_t ecp_dir_handle_req(ECPConnection *conn, unsigned char *msg, size_t msg_size); + +ssize_t ecp_dir_send_rep(ECPConnection *conn); +ssize_t ecp_dir_handle_rep(ECPConnection *conn, unsigned char *msg, size_t msg_size); diff --git a/ecp/src/ecp/ht.h b/ecp/src/ecp/ht.h index 13bf1d7..cf33454 100644 --- a/ecp/src/ecp/ht.h +++ b/ecp/src/ecp/ht.h @@ -1,5 +1,7 @@ -void *ecp_ht_create(ECPContext *ctx); +void *ecp_ht_create_keys(void); +void *ecp_ht_create_addrs(void); + void ecp_ht_destroy(void *h); -int ecp_ht_insert(void *h, unsigned char *k, ECPConnection *v); -ECPConnection *ecp_ht_remove(void *h, unsigned char *k); -ECPConnection *ecp_ht_search(void *h, unsigned char *k); +int ecp_ht_insert(void *h, void *k, ECPConnection *v); +ECPConnection *ecp_ht_remove(void *h, void *k); +ECPConnection *ecp_ht_search(void *h, void *k); diff --git a/ecp/src/ecp/htable/htable.c b/ecp/src/ecp/htable/htable.c index 104d2aa..bd8ab2d 100644 --- a/ecp/src/ecp/htable/htable.c +++ b/ecp/src/ecp/htable/htable.c @@ -1,28 +1,34 @@ +#include <stdlib.h> + #include <core.h> -#include <ht.h> #include <cr.h> +#include <tr.h> +#include <ht.h> #include "hashtable.h" -void *ecp_ht_create(ECPContext *ctx) { - return hashtable_create(1000, (unsigned int (*)(void *))ecp_cr_dh_pub_hash_fn, (int (*)(void *, void *))ecp_cr_dh_pub_hash_eq); +void *ecp_ht_create_keys(void) { + return hashtable_create(1000, (unsigned int (*)(void *))ecp_ecdh_pub_hash, (int (*)(void *, void *))ecp_ecdh_pub_eq); +} + +void *ecp_ht_create_addrs(void) { + return hashtable_create(1000, (unsigned int (*)(void *))ecp_tr_addr_hash, (int (*)(void *, void *))ecp_tr_addr_eq); } void ecp_ht_destroy(void *h) { hashtable_destroy(h, 0); } -int ecp_ht_insert(void *h, unsigned char *k, ECPConnection *v) { +int ecp_ht_insert(void *h, void *k, ECPConnection *v) { int rv = hashtable_insert(h, k, v); if (!rv) return ECP_ERR; return ECP_OK; } -ECPConnection *ecp_ht_remove(void *h, unsigned char *k) { +ECPConnection *ecp_ht_remove(void *h, void *k) { return hashtable_remove(h, k); } -ECPConnection *ecp_ht_search(void *h, unsigned char *k) { +ECPConnection *ecp_ht_search(void *h, void *k) { return hashtable_search(h, k); } - diff --git a/ecp/src/ecp/msgq.c b/ecp/src/ecp/msgq.c index 8f81d8a..8a5408b 100644 --- a/ecp/src/ecp/msgq.c +++ b/ecp/src/ecp/msgq.c @@ -1,12 +1,14 @@ -#include "core.h" - -#ifdef ECP_WITH_MSGQ - #include <sys/time.h> +#include <stdlib.h> +#include <string.h> -#define MSG_IDX_MASK(idx) ((idx) & ((ECP_MSGQ_MAX_MSG) - 1)) +#include "core.h" +#include "rbuf.h" +#include "msgq.h" -static struct timespec *abstime_ts(struct timespec *ts, ecp_cts_t msec) { +#define MSGQ_IDX_MASK(idx) ((idx) & ((ECP_MSGQ_MAX_MSG) - 1)) + +static struct timespec *abstime_ts(struct timespec *ts, ecp_sts_t msec) { struct timeval tv; uint64_t us_start; @@ -18,16 +20,15 @@ static struct timespec *abstime_ts(struct timespec *ts, ecp_cts_t msec) { return ts; } -int ecp_conn_msgq_create(ECPConnMsgQ *msgq) { +int ecp_msgq_create(ECPRBConn *conn, ECPMsgQ *msgq) { int i; int rv; - memset(msgq, 0, sizeof(ECPConnMsgQ)); + if (conn->recv == NULL) return ECP_ERR; - rv = pthread_mutex_init(&msgq->mutex, NULL); - if (rv) return ECP_ERR; + memset(msgq, 0, sizeof(ECPMsgQ)); - for (i=0; i<ECP_MAX_MTYPE; i++) { + for (i=0; i<ECP_MSGQ_MAX_MTYPE; i++) { rv = pthread_cond_init(&msgq->cond[i], NULL); if (rv) { int j; @@ -35,40 +36,42 @@ int ecp_conn_msgq_create(ECPConnMsgQ *msgq) { for (j=0; j<i; j++) { pthread_cond_destroy(&msgq->cond[j]); } - pthread_mutex_destroy(&msgq->mutex); return ECP_ERR; } } + conn->recv->msgq = msgq; return ECP_OK; } -void ecp_conn_msgq_destroy(ECPConnMsgQ *msgq) { +void ecp_msgq_destroy(ECPRBConn *conn) { + ECPMsgQ *msgq = conn->recv->msgq; int i; - for (i=0; i<ECP_MAX_MTYPE; i++) { + for (i=0; i<ECP_MSGQ_MAX_MTYPE; i++) { pthread_cond_destroy(&msgq->cond[i]); } - pthread_mutex_destroy(&msgq->mutex); + + conn->recv->msgq = NULL; } -int ecp_conn_msgq_start(ECPConnMsgQ *msgq, ecp_seq_t seq) { +void ecp_msgq_start(ECPRBConn *conn, ecp_seq_t seq) { + ECPMsgQ *msgq = conn->recv->msgq; + msgq->seq_max = seq; msgq->seq_start = seq + 1; - - return ECP_OK; } -int ecp_conn_msgq_push(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype) { - ECPRBRecv *buf = conn->rbuf.recv; - ECPConnMsgQ *msgq = &buf->msgq; +int ecp_msgq_push(ECPRBConn *conn, ecp_seq_t seq, unsigned char mtype) { + ECPRBRecv *buf = conn->recv; + ECPMsgQ *msgq = buf->msgq; - if (mtype >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; + if (mtype >= ECP_MSGQ_MAX_MTYPE) return ECP_ERR_MTYPE; if ((unsigned short)(msgq->idx_w[mtype] - msgq->idx_r[mtype]) == ECP_MSGQ_MAX_MSG) return ECP_ERR_FULL; if (msgq->idx_w[mtype] == msgq->idx_r[mtype]) pthread_cond_signal(&msgq->cond[mtype]); - msgq->seq_msg[mtype][MSG_IDX_MASK(msgq->idx_w[mtype])] = seq; + msgq->seq_msg[mtype][MSGQ_IDX_MASK(msgq->idx_w[mtype])] = seq; msgq->idx_w[mtype]++; if (ECP_SEQ_LT(msgq->seq_max, seq)) msgq->seq_max = seq; @@ -76,68 +79,72 @@ int ecp_conn_msgq_push(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype) return ECP_OK; } -ssize_t ecp_conn_msgq_pop(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout) { - ECPRBRecv *buf = conn->rbuf.recv; - ECPConnMsgQ *msgq = &buf->msgq; +ssize_t ecp_msgq_pop(ECPRBConn *conn, unsigned char mtype, unsigned char *msg, size_t _msg_size, ecp_sts_t timeout) { + ECPRBRecv *buf = conn->recv; + ECPMsgQ *msgq = buf->msgq; ECPRBuffer *rbuf = &buf->rbuf; - ecp_seq_t seq; + unsigned char *pld_buf; unsigned char *msg_buf; - unsigned char *content; + size_t pld_size, hdr_size, msg_size; + ecp_seq_t seq; unsigned short idx; - int _rv; - ssize_t rv; + int rv; - if (mtype >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; + if (mtype >= ECP_MSGQ_MAX_MTYPE) return ECP_ERR_MTYPE; if (msgq->idx_r[mtype] == msgq->idx_w[mtype]) { if (timeout == -1) { - pthread_cond_wait(&msgq->cond[mtype], &msgq->mutex); + pthread_cond_wait(&msgq->cond[mtype], &buf->mutex); } else { struct timespec ts; - _rv = pthread_cond_timedwait(&msgq->cond[mtype], &msgq->mutex, abstime_ts(&ts, timeout)); - if (_rv) return ECP_ERR_TIMEOUT; + rv = pthread_cond_timedwait(&msgq->cond[mtype], &buf->mutex, abstime_ts(&ts, timeout)); + if (rv) return ECP_ERR_TIMEOUT; } } - seq = msgq->seq_msg[mtype][MSG_IDX_MASK(msgq->idx_r[mtype])]; - - _rv = _ecp_rbuf_msg_idx(rbuf, seq, &idx); - if (_rv) return ECP_ERR; + seq = msgq->seq_msg[mtype][MSGQ_IDX_MASK(msgq->idx_r[mtype])]; - msg_buf = rbuf->arr.msg[idx].buf; - rv = rbuf->arr.msg[idx].size; - - content = ecp_msg_get_content(msg_buf, rv); - if (content == NULL) { - rv = ECP_ERR; - goto msgq_pop_fin; - } + rv = _ecp_rbuf_msg_idx(rbuf, seq, &idx); + if (rv) return ECP_ERR; - rv -= content - msg_buf; - if (msg_size < rv) { - rv = ECP_ERR_FULL; - goto msgq_pop_fin; - } + pld_buf = rbuf->arr.pld[idx].buf; + pld_size = rbuf->arr.pld[idx].size; - memcpy(msg, content, rv); + msg_buf = ecp_pld_get_msg(pld_buf, pld_size); + if (msg_buf == NULL) return ECP_ERR; + hdr_size = msg_buf - pld_buf; + msg_size = pld_size - hdr_size; - rbuf->arr.msg[idx].flags &= ~ECP_RBUF_FLAG_IN_MSGQ; - // if (rbuf->arr.msg[idx].flags == 0); + rbuf->arr.pld[idx].flags &= ~ECP_RBUF_FLAG_IN_MSGQ; + // if (rbuf->arr.pld[idx].flags == 0); -msgq_pop_fin: msgq->idx_r[mtype]++; if (msgq->seq_start == seq) { int i; unsigned short msg_cnt = msgq->seq_max - msgq->seq_start + 1; for (i=0; i<msg_cnt; i++) { - if (rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_IN_MSGQ) break; + if (rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_IN_MSGQ) break; idx = ECP_RBUF_IDX_MASK(idx + 1, rbuf->arr_size); } msgq->seq_start += i; } - return rv; + if (_msg_size < msg_size) return ECP_ERR_FULL; + if (msg_size) memcpy(msg, msg_buf, msg_size); + return msg_size; } -#endif /* ECP_WITH_MSGQ */
\ No newline at end of file +ssize_t ecp_msg_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_sts_t timeout) { + ECPRBConn *_conn; + ssize_t rv; + + _conn = ecp_rbuf_get_rbconn(conn); + if (_conn == NULL) return ECP_ERR; + + pthread_mutex_lock(&_conn->recv->mutex); + rv = ecp_msgq_pop(_conn, mtype, msg, msg_size, timeout); + pthread_mutex_unlock(&_conn->recv->mutex); + + return rv; +} diff --git a/ecp/src/ecp/msgq.h b/ecp/src/ecp/msgq.h index 394209f..dddb6e7 100644 --- a/ecp/src/ecp/msgq.h +++ b/ecp/src/ecp/msgq.h @@ -1,22 +1,19 @@ -#ifdef ECP_WITH_MSGQ - #define ECP_MSGQ_MAX_MSG 32 -typedef struct ECPConnMsgQ { - unsigned short idx_w[ECP_MAX_MTYPE]; - unsigned short idx_r[ECP_MAX_MTYPE]; +#define ECP_MSGQ_MAX_MTYPE (ECP_MAX_MTYPE) + +typedef struct ECPMsgQ { + unsigned short idx_w[ECP_MSGQ_MAX_MTYPE]; + unsigned short idx_r[ECP_MSGQ_MAX_MTYPE]; ecp_seq_t seq_start; ecp_seq_t seq_max; - ecp_seq_t seq_msg[ECP_MAX_MTYPE][ECP_MSGQ_MAX_MSG]; - pthread_cond_t cond[ECP_MAX_MTYPE]; - pthread_mutex_t mutex; -} ECPConnMsgQ; - -int ecp_conn_msgq_create(ECPConnMsgQ *msgq); -void ecp_conn_msgq_destroy(ECPConnMsgQ *msgq); -int ecp_conn_msgq_start(ECPConnMsgQ *msgq, ecp_seq_t seq); - -int ecp_conn_msgq_push(struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype); -ssize_t ecp_conn_msgq_pop(struct ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout); + ecp_seq_t seq_msg[ECP_MSGQ_MAX_MTYPE][ECP_MSGQ_MAX_MSG]; + pthread_cond_t cond[ECP_MSGQ_MAX_MTYPE]; +} ECPMsgQ; -#endif /* ECP_WITH_MSGQ */
\ No newline at end of file +int ecp_msgq_create(ECPRBConn *conn, ECPMsgQ *msgq); +void ecp_msgq_destroy(ECPRBConn *conn); +void ecp_msgq_start(ECPRBConn *conn, ecp_seq_t seq); +int ecp_msgq_push(ECPRBConn *conn, ecp_seq_t seq, unsigned char mtype); +ssize_t ecp_msgq_pop(ECPRBConn *conn, unsigned char mtype, unsigned char *msg, size_t _msg_size, ecp_sts_t timeout); +ssize_t ecp_msg_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_sts_t timeout);
\ No newline at end of file diff --git a/ecp/src/ecp/rbuf.c b/ecp/src/ecp/rbuf.c index be8e9f3..d2e6e28 100644 --- a/ecp/src/ecp/rbuf.c +++ b/ecp/src/ecp/rbuf.c @@ -1,10 +1,20 @@ +#include <stdlib.h> + #include "core.h" +#include "rbuf.h" + +ECPRBConn *ecp_rbuf_get_rbconn(ECPConnection *conn) { + if (ecp_conn_has_rbuf(conn)) return (ECPRBConn *)conn; + return NULL; +} -int _ecp_rbuf_start(ECPRBuffer *rbuf, ecp_seq_t seq) { +ECPConnection *ecp_rbuf_get_conn(ECPRBConn *conn) { + return &conn->b; +} + +void _ecp_rbuf_start(ECPRBuffer *rbuf, ecp_seq_t seq) { rbuf->seq_max = seq; rbuf->seq_start = seq + 1; - - return ECP_OK; } int _ecp_rbuf_msg_idx(ECPRBuffer *rbuf, ecp_seq_t seq, unsigned short *idx) { @@ -13,198 +23,90 @@ int _ecp_rbuf_msg_idx(ECPRBuffer *rbuf, ecp_seq_t seq, unsigned short *idx) { /* This also checks for seq_start <= seq if seq type range >> rbuf->arr_size */ if (seq_offset >= rbuf->arr_size) return ECP_ERR_FULL; - *idx = ECP_RBUF_IDX_MASK(rbuf->idx_start + seq_offset, rbuf->arr_size); + if (idx) *idx = ECP_RBUF_IDX_MASK(rbuf->idx_start + seq_offset, rbuf->arr_size); return ECP_OK; } -int ecp_rbuf_create(ECPConnection *conn, ECPRBSend *buf_s, ECPRBPacket *msg_s, unsigned int msg_s_size, ECPRBRecv *buf_r, ECPRBMessage *msg_r, unsigned int msg_r_size) { - int rv; +void ecp_rbuf_conn_init(ECPRBConn *conn) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); - if (buf_s) { - rv = ecp_rbuf_send_create(conn, buf_s, msg_s, msg_s_size); - if (rv) return rv; + ecp_conn_set_flags(_conn, ECP_CONN_FLAG_RBUF); + conn->send = NULL; + conn->recv = NULL; + conn->iter = NULL; +} - rv = ecp_rbuf_send_start(conn); - if (rv) { - ecp_rbuf_send_destroy(conn); - return rv; - } - } +int ecp_rbuf_conn_create(ECPRBConn *conn, ECPSocket *sock, unsigned char type) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + int rv; - if (buf_r) { - rv = ecp_rbuf_recv_create(conn, buf_r, msg_r, msg_r_size); - if (rv) { - if (buf_s) ecp_rbuf_send_destroy(conn); - return rv; - } - } + rv = ecp_conn_create(_conn, sock, type); + if (rv) return rv; + ecp_rbuf_conn_init(conn); return ECP_OK; } -void ecp_rbuf_destroy(ECPConnection *conn) { - ecp_rbuf_send_destroy(conn); - ecp_rbuf_recv_destroy(conn); -} - -int ecp_rbuf_handle_seq(ECPConnection *conn, unsigned char mtype) { - if (conn->rbuf.recv || (mtype == ECP_MTYPE_RBACK) || (mtype == ECP_MTYPE_RBFLUSH)) return 1; - return 0; -} - -int ecp_rbuf_set_seq(ECPConnection *conn, ECPSeqItem *si, unsigned char *payload, size_t pld_size) { - ECPRBSend *buf = conn->rbuf.send; - ECPRBuffer *rbuf = &buf->rbuf; - unsigned char mtype; - unsigned short idx; +int ecp_rbuf_conn_create_inb(ECPRBConn *conn, ECPSocket *sock, unsigned char type) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); int rv; - if (si->rb_pass) return ECP_OK; - - buf = conn->rbuf.send; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&buf->mutex); -#endif - rv = _ecp_rbuf_msg_idx(rbuf, si->seq, &idx); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&buf->mutex); -#endif + rv = ecp_conn_create_inb(_conn, sock, type); if (rv) return rv; - rv = ecp_pld_get_type(payload, pld_size, &mtype); - if (rv) return rv; - - si->rb_mtype = mtype; - si->rb_idx = idx; - rbuf->arr.pkt[idx].size = 0; - rbuf->arr.pkt[idx].flags = 0; - + ecp_rbuf_conn_init(conn); return ECP_OK; } -ssize_t ecp_rbuf_pld_send(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags, ecp_seq_t seq) { - ECPSocket *sock = conn->sock; - ECPContext *ctx = sock->ctx; - ECPNetAddr addr; - ECPSeqItem seq_item; - int _rv; - ssize_t rv; +void ecp_rbuf_destroy(ECPRBConn *conn) { + if (conn->send) ecp_rbsend_destroy(conn); + if (conn->recv) ecp_rbrecv_destroy(conn); + conn->iter = NULL; +} - _rv = ecp_seq_item_init(&seq_item); - if (_rv) return _rv; +void ecp_rbuf_start(ECPRBConn *conn) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); - seq_item.seq = seq; - seq_item.seq_w = 1; - seq_item.rb_pass = 1; + if (conn->send) { + ecp_seq_t seq_out; - rv = ecp_pack_conn(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, pld_size, &addr, &seq_item); - if (rv < 0) return rv; + seq_out = (ecp_seq_t)(_conn->nonce_out); + ecp_rbsend_start(conn, seq_out); + } - rv = ecp_pkt_send(sock, &addr, packet, rv, flags); - if (rv < 0) return rv; + if (conn->recv) { + ecp_seq_t seq_in; - return rv; + seq_in = (ecp_seq_t)(_conn->nonce_in); + ecp_rbrecv_start(conn, seq_in); + } } -ssize_t ecp_rbuf_pkt_send(ECPConnection *conn, ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t pkt_size, unsigned char flags, ECPTimerItem *ti, ECPSeqItem *si) { - ECPRBSend *buf = conn->rbuf.send; - ECPRBuffer *rbuf = &buf->rbuf; - ecp_seq_t seq = si->seq; - unsigned short idx = si->rb_idx; - unsigned char mtype = si->rb_mtype & ECP_MTYPE_MASK; - unsigned char _flags; - int rb_rel; - int rb_cc; - int do_send; - int do_skip; - int _rv = ECP_OK; - ssize_t rv = 0; - - if (pkt_size == 0) return ECP_ERR; - - do_send = 1; - do_skip = ecp_rbuf_skip(mtype); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&buf->mutex); -#endif - - rb_rel = (buf->flags & ECP_RBUF_FLAG_RELIABLE); - rb_cc = ((buf->flags & ECP_RBUF_FLAG_CCONTROL) && (buf->cnt_cc || (buf->in_transit >= buf->win_size))); - - if (rb_rel || rb_cc) { - ECPRBTimer *rb_timer = NULL; - ECPRBTimerItem *rb_ti = NULL; - - _flags = ECP_RBUF_FLAG_IN_RBUF; - if (do_skip) { - _flags |= ECP_RBUF_FLAG_SKIP; - } else { - do_send = 0; - } - - if (rbuf->arr.pkt[idx].flags) _rv = ECP_ERR_RBUF_DUP; - - if (!_rv && !do_send && ti) { - rb_timer = buf->timer; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&rb_timer->mutex); -#endif - - rb_ti = &rb_timer->item[rb_timer->idx_w]; - if (rb_ti->empty) { - rb_ti->empty = 0; - rb_ti->item = *ti; - rb_timer->idx_w = (rb_timer->idx_w + 1) % ECP_MAX_TIMER; - } else { - _rv = ECP_ERR_MAX_TIMER; - } - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&rb_timer->mutex); -#endif - } - - if (_rv) { - rv = _rv; - goto pkt_send_fin; - } - - if (!do_send) { - memcpy(rbuf->arr.pkt[idx].buf, packet->buffer, pkt_size); - rbuf->arr.pkt[idx].size = pkt_size; - rbuf->arr.pkt[idx].timer = rb_ti; - rv = pkt_size; - } - rbuf->arr.pkt[idx].flags = _flags; - - if (ECP_SEQ_LT(rbuf->seq_max, seq)) rbuf->seq_max = seq; - - if (rb_cc && !do_send) { - if (buf->cnt_cc == 0) buf->seq_cc = seq; - buf->cnt_cc++; - } - } +ssize_t ecp_rbuf_msg_handle(ECPRBConn *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { + switch (mtype) { + case ECP_MTYPE_RBACK: + if (conn->send) return ecp_rbuf_handle_ack(conn, msg, msg_size); + break; - if ((buf->flags & ECP_RBUF_FLAG_CCONTROL) && !do_skip && do_send) { - buf->in_transit++; - } + case ECP_MTYPE_RBNOP: + if (conn->recv) return ecp_rbuf_handle_nop(conn, msg, msg_size); + break; -pkt_send_fin: + case ECP_MTYPE_RBFLUSH: + if (conn->recv) return ecp_rbuf_handle_flush(conn); + break; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&buf->mutex); -#endif + default: + break; + } - if (rv < 0) return rv; + return ECP_ERR_MTYPE; +} - if (do_send) { - if (ti) { - _rv = ecp_timer_push(ti); - if (_rv) return _rv; - } - rv = ecp_pkt_send(sock, addr, packet, pkt_size, flags); +int ecp_rbuf_err_handle(ECPRBConn *conn, unsigned char mtype, int err) { + if (conn->recv && (mtype == ECP_MTYPE_RBTIMER)) { + ecp_rbuf_handle_timer(conn); + return ECP_OK; } - return rv; + return ECP_PASS; } diff --git a/ecp/src/ecp/rbuf.h b/ecp/src/ecp/rbuf.h index 31aeb39..36ff963 100644 --- a/ecp/src/ecp/rbuf.h +++ b/ecp/src/ecp/rbuf.h @@ -5,49 +5,36 @@ #define ECP_RBUF_FLAG_CCONTROL 0x01 #define ECP_RBUF_FLAG_RELIABLE 0x02 -#define ECP_RBUF_FLAG_MSGQ 0x04 -#define ECP_MTYPE_RBACK 0x04 -#define ECP_MTYPE_RBFLUSH 0x05 -#define ECP_MTYPE_RBTIMER 0x06 -#define ECP_MTYPE_NOP 0x07 + +#define ECP_MTYPE_RBNOP (0x08 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_RBACK (0x09 | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_RBFLUSH (0x0a | ECP_MTYPE_FLAG_SYS) +#define ECP_MTYPE_RBTIMER (0x0b | ECP_MTYPE_FLAG_SYS) #define ECP_ERR_RBUF_DUP -100 +#define ECP_ERR_RBUF_TIMER -101 -typedef uint32_t ecp_win_t; +#define ecp_rbuf_skip(mtype) (mtype & ECP_MTYPE_FLAG_SYS) /* size must be power of 2 */ #define ECP_RBUF_IDX_MASK(idx, size) ((idx) & ((size) - 1)) -#define ecp_rbuf_skip(mtype) ((mtype & ECP_MTYPE_MASK) < ECP_MTYPE_NOP ? 1 : 0) -#ifdef ECP_WITH_MSGQ -#include "msgq.h" -#endif +typedef uint32_t ecp_win_t; -typedef struct ECPRBTimerItem { - ECPTimerItem item; - unsigned char empty; -} ECPRBTimerItem; +struct ECPMsgQ; +struct ECPFragIter; -typedef struct ECPRBTimer { - ECPRBTimerItem item[ECP_MAX_TIMER]; - unsigned short idx_w; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_t mutex; -#endif -} ECPRBTimer; - -typedef struct ECPRBMessage { - unsigned char buf[ECP_MAX_MSG]; +typedef struct ECPRBPayload { + unsigned char buf[ECP_MAX_PLD]; size_t size; unsigned char flags; -} ECPRBMessage; +} ECPRBPayload; typedef struct ECPRBPacket { unsigned char buf[ECP_MAX_PKT]; size_t size; unsigned char flags; - ECPRBTimerItem *timer; } ECPRBPacket; typedef struct ECPRBuffer { @@ -56,27 +43,31 @@ typedef struct ECPRBuffer { unsigned short arr_size; unsigned short idx_start; union { - ECPRBMessage *msg; + ECPRBPayload *pld; ECPRBPacket *pkt; } arr; } ECPRBuffer; typedef struct ECPRBRecv { + unsigned char start; unsigned char flags; - ecp_cts_t deliver_delay; + ecp_sts_t deliver_delay; unsigned short hole_max; unsigned short ack_rate; unsigned short ack_pkt; ecp_seq_t seq_ack; ecp_ack_t ack_map; ECPRBuffer rbuf; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_t mutex; +#endif #ifdef ECP_WITH_MSGQ - ECPConnMsgQ msgq; + struct ECPMsgQ *msgq; #endif - struct ECPFragIter *frag_iter; } ECPRBRecv; typedef struct ECPRBSend { + unsigned char start; unsigned char flags; ecp_win_t win_size; ecp_win_t in_transit; @@ -87,42 +78,46 @@ typedef struct ECPRBSend { unsigned char flush; unsigned int nack_rate; ECPRBuffer rbuf; - ECPRBTimer *timer; #ifdef ECP_WITH_PTHREAD pthread_mutex_t mutex; #endif } ECPRBSend; -typedef struct ECPConnRBuffer { +typedef struct ECPRBConn { + ECPConnection b; ECPRBRecv *recv; ECPRBSend *send; -} ECPConnRBuffer; + struct ECPFragIter *iter; +} ECPRBConn; -int _ecp_rbuf_start(ECPRBuffer *rbuf, ecp_seq_t seq); +ECPRBConn *ecp_rbuf_get_rbconn(ECPConnection *conn); +ECPConnection *ecp_rbuf_get_conn(ECPRBConn *conn); +void _ecp_rbuf_start(ECPRBuffer *rbuf, ecp_seq_t seq); int _ecp_rbuf_msg_idx(ECPRBuffer *rbuf, ecp_seq_t seq, unsigned short *idx); - -int ecp_rbuf_create(struct ECPConnection *conn, ECPRBSend *buf_s, ECPRBPacket *msg_s, unsigned int msg_s_size, ECPRBRecv *buf_r, ECPRBMessage *msg_r, unsigned int msg_r_size); -void ecp_rbuf_destroy(struct ECPConnection *conn); -ssize_t ecp_rbuf_pld_send(struct ECPConnection *conn, struct ECPBuffer *packet, struct ECPBuffer *payload, size_t pld_size, unsigned char flags, ecp_seq_t seq); -int ecp_rbuf_handle_seq(struct ECPConnection *conn, unsigned char mtype); -int ecp_rbuf_set_seq(struct ECPConnection *conn, struct ECPSeqItem *si, unsigned char *payload, size_t pld_size); -ssize_t ecp_rbuf_pkt_send(struct ECPConnection *conn, struct ECPSocket *sock, ECPNetAddr *addr, struct ECPBuffer *packet, size_t pkt_size, unsigned char flags, ECPTimerItem *ti, struct ECPSeqItem *si); - -int ecp_rbuf_recv_create(struct ECPConnection *conn, ECPRBRecv *buf, ECPRBMessage *msg, unsigned short msg_size); -void ecp_rbuf_recv_destroy(struct ECPConnection *conn); -int ecp_rbuf_recv_start(struct ECPConnection *conn, ecp_seq_t seq); -int ecp_rbuf_set_hole(struct ECPConnection *conn, unsigned short hole_max); -int ecp_rbuf_set_delay(struct ECPConnection *conn, ecp_cts_t delay); - -ssize_t ecp_rbuf_store(struct ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, struct ECP2Buffer *b); -struct ECPFragIter *ecp_rbuf_get_frag_iter(struct ECPConnection *conn); - -int ecp_rbuf_send_create(struct ECPConnection *conn, ECPRBSend *buf, ECPRBPacket *msg, unsigned short msg_size); -void ecp_rbuf_send_destroy(struct ECPConnection *conn); -int ecp_rbuf_send_start(struct ECPConnection *conn); -int ecp_rbuf_flush(struct ECPConnection *conn); -int ecp_rbuf_set_wsize(struct ECPConnection *conn, ecp_win_t size); - -ssize_t ecp_rbuf_handle_ack(struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, struct ECP2Buffer *b); -ssize_t ecp_rbuf_handle_flush(struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, struct ECP2Buffer *b); -ssize_t ecp_rbuf_handle_timer(struct ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, struct ECP2Buffer *b); +void ecp_rbuf_conn_init(ECPRBConn *conn); +int ecp_rbuf_conn_create(ECPRBConn *conn, ECPSocket *sock, unsigned char type); +int ecp_rbuf_conn_create_inb(ECPRBConn *conn, ECPSocket *sock, unsigned char type); +void ecp_rbuf_destroy(ECPRBConn *conn); +void ecp_rbuf_start(ECPRBConn *conn); +ssize_t ecp_rbuf_msg_handle(ECPRBConn *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs); +int ecp_rbuf_err_handle(ECPRBConn *conn, unsigned char mtype, int err); + +/* send */ +ssize_t ecp_rbuf_send_flush(ECPRBConn *conn); +ssize_t ecp_rbuf_handle_ack(ECPRBConn *conn, unsigned char *msg, size_t msg_size); +int ecp_rbsend_create(ECPRBConn *conn, ECPRBSend *buf, ECPRBPacket *pkt, unsigned short pkt_size); +void ecp_rbsend_destroy(ECPRBConn *conn); +void ecp_rbsend_start(ECPRBConn *conn, ecp_seq_t seq); +int ecp_rbuf_set_wsize(ECPRBConn *conn, ecp_win_t size); +int ecp_rbuf_flush(ECPRBConn *conn); +ssize_t ecp_rbuf_pld_send(ECPRBConn *conn, ECPBuffer *payload, size_t pld_size, ECPBuffer *packet, size_t pkt_size, ECPTimerItem *ti); + +ssize_t ecp_rbuf_handle_nop(ECPRBConn *conn, unsigned char *msg, size_t msg_size); +ssize_t ecp_rbuf_handle_flush(ECPRBConn *conn); +void ecp_rbuf_handle_timer(ECPRBConn *conn) ; +int ecp_rbrecv_create(ECPRBConn *conn, ECPRBRecv *buf, ECPRBPayload *pld, unsigned short pld_size); +void ecp_rbrecv_destroy(ECPRBConn *conn); +void ecp_rbrecv_start(ECPRBConn *conn, ecp_seq_t seq); +int ecp_rbuf_set_hole(ECPRBConn *conn, unsigned short hole_max); +int ecp_rbuf_set_delay(ECPRBConn *conn, ecp_sts_t delay); +ssize_t ecp_rbuf_store(ECPRBConn *conn, ecp_seq_t seq, unsigned char *pld, size_t pld_size); diff --git a/ecp/src/ecp/rbuf_recv.c b/ecp/src/ecp/rbuf_recv.c index a3f2345..1d50494 100644 --- a/ecp/src/ecp/rbuf_recv.c +++ b/ecp/src/ecp/rbuf_recv.c @@ -1,12 +1,21 @@ +#include <stdlib.h> +#include <string.h> + #include "core.h" -#include "tr.h" #include "tm.h" +#include "rbuf.h" + +#ifdef ECP_WITH_MSGQ +#include "msgq.h" +#endif + #define ACK_RATE 8 #define ACK_MASK_FIRST ((ecp_ack_t)1 << (ECP_SIZE_ACKB - 1)) -static ssize_t msg_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, unsigned char mtype) { - ECPRBRecv *buf = conn->rbuf.recv; +static ssize_t msg_store(ECPRBConn *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *pld, size_t pld_size) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBRecv *buf = conn->recv; ECPRBuffer *rbuf = &buf->rbuf; unsigned short idx; unsigned char flags; @@ -16,18 +25,22 @@ static ssize_t msg_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, rv = _ecp_rbuf_msg_idx(rbuf, seq, &idx); if (rv) return rv; - if (rbuf->arr.msg[idx].flags) return ECP_ERR_RBUF_DUP; + if (rbuf->arr.pld[idx].flags) return ECP_ERR_RBUF_DUP; #ifdef ECP_WITH_MSGQ - if (buf->flags & ECP_RBUF_FLAG_MSGQ) { + if (buf->msgq) { ecp_seq_t seq_offset; - pthread_mutex_lock(&buf->msgq.mutex); +#ifndef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif - seq_offset = seq - buf->msgq.seq_start; + seq_offset = seq - buf->msgq->seq_start; if (seq_offset >= rbuf->arr_size) rv = ECP_ERR_FULL; - pthread_mutex_unlock(&buf->msgq.mutex); +#ifndef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif if (rv) return rv; } @@ -36,75 +49,80 @@ static ssize_t msg_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, skip = ecp_rbuf_skip(mtype); flags = ECP_RBUF_FLAG_IN_RBUF; if (skip) flags |= ECP_RBUF_FLAG_SKIP; - rbuf->arr.msg[idx].flags = flags; + rbuf->arr.pld[idx].flags = flags; - if (skip) return 0; + if ((mtype == ECP_MTYPE_RBNOP) && pld) { + return ecp_pld_handle_one(_conn, seq, pld, pld_size, NULL); + } else if (skip) { + return 0; + } - memcpy(rbuf->arr.msg[idx].buf, msg, msg_size); - rbuf->arr.msg[idx].size = msg_size; + if (pld && pld_size) memcpy(rbuf->arr.pld[idx].buf, pld, pld_size); + rbuf->arr.pld[idx].size = pld_size; if (ECP_SEQ_LT(rbuf->seq_max, seq)) rbuf->seq_max = seq; - return msg_size; + return pld_size; } -static void msg_flush(ECPConnection *conn, ECP2Buffer *b) { - ECPRBRecv *buf = conn->rbuf.recv; +static void msg_flush(ECPRBConn *conn) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBRecv *buf = conn->recv; ECPRBuffer *rbuf = &buf->rbuf; ecp_seq_t seq; unsigned short idx; int i; #ifdef ECP_WITH_MSGQ - if (buf->flags & ECP_RBUF_FLAG_MSGQ) pthread_mutex_lock(&buf->msgq.mutex); +#ifndef ECP_WITH_RTHD + if (buf->msgq) pthread_mutex_lock(&buf->mutex); +#endif #endif seq = rbuf->seq_start; idx = rbuf->idx_start; - unsigned short msg_cnt = rbuf->seq_max - rbuf->seq_start + 1; - while (ECP_SEQ_LTE(seq, rbuf->seq_max)) { - if (rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_IN_RBUF) { - if (!(rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_SKIP)) { + if (rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_IN_RBUF) { + if (!(rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_SKIP)) { ecp_pts_t msg_pts; int rv; - rv = ecp_msg_get_pts(rbuf->arr.msg[idx].buf, rbuf->arr.msg[idx].size, &msg_pts); + rv = ecp_pld_get_pts(rbuf->arr.pld[idx].buf, rbuf->arr.pld[idx].size, &msg_pts); if (!rv && buf->deliver_delay) { - ecp_cts_t now = ecp_tm_abstime_ms(0); + ecp_sts_t now = ecp_tm_abstime_ms(0); msg_pts += buf->deliver_delay; if (ECP_PTS_LT(now, msg_pts)) { - if (!(rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_IN_TIMER)) { + if (!(rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_IN_TIMER)) { ECPTimerItem ti; - rv = ecp_timer_item_init(&ti, conn, ECP_MTYPE_RBTIMER, 0, msg_pts - now); - if (!rv) rv = ecp_timer_push(&ti); - if (!rv) rbuf->arr.msg[idx].flags |= ECP_RBUF_FLAG_IN_TIMER; + ecp_timer_item_init(&ti, _conn, ECP_MTYPE_RBTIMER, NULL, 0, msg_pts - now); + rv = ecp_timer_push(&ti); + if (!rv) rbuf->arr.pld[idx].flags |= ECP_RBUF_FLAG_IN_TIMER; } break; - } else if (rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_IN_TIMER) { - rbuf->arr.msg[idx].flags &= ~ECP_RBUF_FLAG_IN_TIMER; + } else if (rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_IN_TIMER) { + rbuf->arr.pld[idx].flags &= ~ECP_RBUF_FLAG_IN_TIMER; } } #ifdef ECP_WITH_MSGQ - if (buf->flags & ECP_RBUF_FLAG_MSGQ) { + if (buf->msgq) { unsigned char mtype; - rv = ecp_msg_get_type(rbuf->arr.msg[idx].buf, rbuf->arr.msg[idx].size, &mtype); - if (!rv) rv = ecp_conn_msgq_push(conn, seq, mtype & ECP_MTYPE_MASK); + rv = ecp_pld_get_type(rbuf->arr.pld[idx].buf, rbuf->arr.pld[idx].size, &mtype); + if (!rv) rv = ecp_msgq_push(conn, seq, mtype & ECP_MTYPE_MASK); if (rv) break; - rbuf->arr.msg[idx].flags |= ECP_RBUF_FLAG_IN_MSGQ; + rbuf->arr.pld[idx].flags |= ECP_RBUF_FLAG_IN_MSGQ; } else #endif - ecp_conn_handle_msg(conn, seq, rbuf->arr.msg[idx].buf, rbuf->arr.msg[idx].size, b); + ecp_pld_handle(_conn, seq, rbuf->arr.pld[idx].buf, rbuf->arr.pld[idx].size, NULL); } else { - rbuf->arr.msg[idx].flags &= ~ECP_RBUF_FLAG_SKIP; + rbuf->arr.pld[idx].flags &= ~ECP_RBUF_FLAG_SKIP; } - rbuf->arr.msg[idx].flags &= ~ECP_RBUF_FLAG_IN_RBUF; - // if (rbuf->arr.msg[idx].flags == 0); + rbuf->arr.pld[idx].flags &= ~ECP_RBUF_FLAG_IN_RBUF; + // if (rbuf->arr.pld[idx].flags == 0); } else { if (buf->flags & ECP_RBUF_FLAG_RELIABLE) break; if (!ECP_SEQ_LT(seq, rbuf->seq_max - buf->hole_max)) break; @@ -116,45 +134,14 @@ static void msg_flush(ECPConnection *conn, ECP2Buffer *b) { rbuf->idx_start = idx; #ifdef ECP_WITH_MSGQ - if (buf->flags & ECP_RBUF_FLAG_MSGQ) pthread_mutex_unlock(&buf->msgq.mutex); +#ifndef ECP_WITH_RTHD + if (buf->msgq) pthread_mutex_unlock(&buf->mutex); +#endif #endif - -} - -static int ack_send(ECPConnection *conn, ecp_seq_t seq_ack, ecp_seq_t ack_map) { - ECPRBRecv *buf = conn->rbuf.recv; - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, conn)]; - unsigned char *_buf; - ssize_t rv; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, conn); - - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_RBACK); - _buf = ecp_pld_get_buf(payload.buffer, payload.size); - _buf[0] = (seq_ack & 0xFF000000) >> 24; - _buf[1] = (seq_ack & 0x00FF0000) >> 16; - _buf[2] = (seq_ack & 0x0000FF00) >> 8; - _buf[3] = (seq_ack & 0x000000FF); - _buf[4] = (ack_map & 0xFF000000) >> 24; - _buf[5] = (ack_map & 0x00FF0000) >> 16; - _buf[6] = (ack_map & 0x0000FF00) >> 8; - _buf[7] = (ack_map & 0x000000FF); - - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK), 0); - if (rv < 0) return rv; - - buf->ack_pkt = 0; - - return ECP_OK; } -static int ack_shift(ECPRBRecv *buf) { +static int ack_shift(ECPRBConn *conn) { + ECPRBRecv *buf = conn->recv; ECPRBuffer *rbuf = &buf->rbuf; unsigned short idx; int do_ack = 0; @@ -168,7 +155,7 @@ static int ack_shift(ECPRBRecv *buf) { buf->seq_ack++; rv = _ecp_rbuf_msg_idx(rbuf, buf->seq_ack, &idx); if (!rv) { - in_rbuf = rbuf->arr.msg[idx].flags & ECP_RBUF_FLAG_IN_RBUF; + in_rbuf = rbuf->arr.pld[idx].flags & ECP_RBUF_FLAG_IN_RBUF; } else { in_rbuf = 1; } @@ -190,100 +177,194 @@ static int ack_shift(ECPRBRecv *buf) { return do_ack; } -ssize_t ecp_rbuf_handle_flush(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPRBRecv *buf = conn->rbuf.recv; +static int ack_send(ECPRBConn *conn, ecp_seq_t seq_ack, ecp_seq_t ack_map) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBRecv *buf = conn->recv; + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, _conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK, _conn)]; + unsigned char *_buf; + ssize_t rv; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_RBACK); + _buf = ecp_pld_get_msg(payload.buffer, payload.size); + _buf[0] = seq_ack >> 24; + _buf[1] = seq_ack >> 16; + _buf[2] = seq_ack >> 8; + _buf[3] = seq_ack; + _buf[4] = ack_map >> 24; + _buf[5] = ack_map >> 16; + _buf[6] = ack_map >> 8; + _buf[7] = ack_map; + + rv = ecp_pld_send(_conn, &packet, &payload, ECP_SIZE_PLD(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBACK), 0); + if (rv < 0) return rv; + + buf->ack_pkt = 0; + + return ECP_OK; +} + +ssize_t ecp_rbuf_handle_nop(ECPRBConn *conn, unsigned char *msg, size_t msg_size) { + ECPRBRecv *buf = conn->recv; + ECPRBuffer *rbuf = &buf->rbuf; + ecp_seq_t seq_ack; + ecp_ack_t ack_map; + ecp_ack_t ack_mask = (ecp_ack_t)1 << (ECP_SIZE_ACKB - 1); + size_t rsize = sizeof(ecp_seq_t) + sizeof(ecp_ack_t); + int i; - if (buf == NULL) return ECP_ERR; - if (size < 0) return size; + if (msg_size < rsize) return ECP_ERR_SIZE; + + seq_ack = \ + ((ecp_seq_t)msg[0] << 24) | \ + ((ecp_seq_t)msg[1] << 16) | \ + ((ecp_seq_t)msg[2] << 8) | \ + ((ecp_seq_t)msg[3]); + ack_map = \ + ((ecp_ack_t)msg[4] << 24) | \ + ((ecp_ack_t)msg[5] << 16) | \ + ((ecp_ack_t)msg[6] << 8) | \ + ((ecp_ack_t)msg[7]); + + seq_ack -= (ECP_SIZE_ACKB - 1); + for (i=0; i<ECP_SIZE_ACKB; i++) { + if (ack_map & ack_mask) { + msg_store(conn, seq_ack, ECP_MTYPE_RBNOP, NULL, 0); + } + seq_ack++; + ack_mask = ack_mask >> 1; + } + + return rsize; +} + +ssize_t ecp_rbuf_handle_flush(ECPRBConn *conn) { + ECPRBRecv *buf = conn->recv; + +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif - ecp_tr_release(b->packet, 1); ack_send(conn, buf->seq_ack, buf->ack_map); + +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif + return 0; } -ssize_t ecp_rbuf_handle_timer(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPRBRecv *buf = conn->rbuf.recv; +void ecp_rbuf_handle_timer(ECPRBConn *conn) { + ECPRBRecv *buf = conn->recv; + +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif - if (buf == NULL) return ECP_ERR; + msg_flush(conn); - msg_flush(conn, b); - return 0; +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif } -int ecp_rbuf_recv_create(ECPConnection *conn, ECPRBRecv *buf, ECPRBMessage *msg, unsigned short msg_size) { +int ecp_rbrecv_create(ECPRBConn *conn, ECPRBRecv *buf, ECPRBPayload *pld, unsigned short pld_size) { ECPRBuffer *rbuf = &buf->rbuf; int rv; - if (msg == NULL) return ECP_ERR; - memset(buf, 0, sizeof(ECPRBRecv)); - memset(msg, 0, sizeof(ECPRBMessage) * msg_size); + memset(pld, 0, sizeof(ECPRBPayload) * pld_size); buf->ack_map = ECP_ACK_FULL; buf->ack_rate = ACK_RATE; - rbuf->arr.msg = msg; - rbuf->arr_size = msg_size; + rbuf->arr.pld = pld; + rbuf->arr_size = pld_size; -#ifdef ECP_WITH_MSGQ - rv = ecp_conn_msgq_create(&buf->msgq); - if (rv) return rv; +#ifdef ECP_WITH_PTHREAD + rv = pthread_mutex_init(&buf->mutex, NULL); + if (rv) return ECP_ERR; #endif - conn->rbuf.recv = buf; + conn->recv = buf; return ECP_OK; } -void ecp_rbuf_recv_destroy(ECPConnection *conn) { - ECPRBRecv *buf = conn->rbuf.recv; +void ecp_rbrecv_destroy(ECPRBConn *conn) { + ECPRBRecv *buf = conn->recv; - if (buf == NULL) return; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_destroy(&buf->mutex); +#endif #ifdef ECP_WITH_MSGQ - ecp_conn_msgq_destroy(&buf->msgq); + if (buf->msgq) ecp_msgq_destroy(conn); #endif - conn->rbuf.recv = NULL; + + conn->recv = NULL; } -int ecp_rbuf_recv_start(ECPConnection *conn, ecp_seq_t seq) { - ECPRBRecv *buf = conn->rbuf.recv; +void ecp_rbrecv_start(ECPRBConn *conn, ecp_seq_t seq) { + ECPRBRecv *buf = conn->recv; ECPRBuffer *rbuf = &buf->rbuf; - int rv; - if (buf == NULL) return ECP_ERR; +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif - seq--; + buf->start = 1; buf->seq_ack = seq; - rv = _ecp_rbuf_start(rbuf, seq); - if (rv) return rv; + _ecp_rbuf_start(rbuf, seq); #ifdef ECP_WITH_MSGQ - if (buf->flags & ECP_RBUF_FLAG_MSGQ) { - rv = ecp_conn_msgq_start(&buf->msgq, seq); - if (rv) return rv; - } + if (buf->msgq) ecp_msgq_start(conn, seq); #endif - return ECP_OK; +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif } -int ecp_rbuf_set_hole(ECPConnection *conn, unsigned short hole_max) { - ECPRBRecv *buf = conn->rbuf.recv; +int ecp_rbuf_set_hole(ECPRBConn *conn, unsigned short hole_max) { + ECPRBRecv *buf = conn->recv; + +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif buf->hole_max = hole_max; +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif + return ECP_OK; } -int ecp_rbuf_set_delay(ECPConnection *conn, ecp_cts_t delay) { - ECPRBRecv *buf = conn->rbuf.recv; +int ecp_rbuf_set_delay(ECPRBConn *conn, ecp_sts_t delay) { + ECPRBRecv *buf = conn->recv; + +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif buf->deliver_delay = delay; +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif + return ECP_OK; } -ssize_t ecp_rbuf_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { - ECPRBRecv *buf = conn->rbuf.recv; +ssize_t ecp_rbuf_store(ECPRBConn *conn, ecp_seq_t seq, unsigned char *pld, size_t pld_size) { + ECPRBRecv *buf = conn->recv; ECPRBuffer *rbuf = &buf->rbuf; unsigned char mtype; unsigned short ack_pkt = 0; @@ -291,9 +372,18 @@ ssize_t ecp_rbuf_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, s int _rv; ssize_t rv; - _rv = ecp_msg_get_type(msg, msg_size, &mtype); + _rv = ecp_pld_get_type(pld, pld_size, &mtype); if (_rv) return _rv; +#ifdef ECP_WITH_RTHD + pthread_mutex_lock(&buf->mutex); +#endif + + if (!buf->start) { + rv = 0; + goto rbuf_store_fin; + } + if (ECP_SEQ_LT(rbuf->seq_max, seq)) { ack_pkt = seq - rbuf->seq_max; } @@ -302,42 +392,51 @@ ssize_t ecp_rbuf_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, s if (seq_offset < ECP_SIZE_ACKB) { ecp_ack_t ack_bit = ((ecp_ack_t)1 << seq_offset); - if (ack_bit & buf->ack_map) return ECP_ERR_RBUF_DUP; + if (ack_bit & buf->ack_map) { + rv = ECP_ERR_RBUF_DUP; + goto rbuf_store_fin; + } - rv = msg_store(conn, seq, msg, msg_size, mtype); - if (rv < 0) return rv; + rv = msg_store(conn, seq, mtype, pld, pld_size); + if (rv < 0) goto rbuf_store_fin; buf->ack_map |= ack_bit; /* reliable transport can prevent seq_ack from reaching seq_max */ if (ECP_SEQ_LT(buf->seq_ack, rbuf->seq_max)) { - do_ack = ack_shift(buf); + do_ack = ack_shift(conn); } } else { - return ECP_ERR_RBUF_DUP; + rv = ECP_ERR_RBUF_DUP; + goto rbuf_store_fin; } } else { unsigned short msg_cnt = rbuf->seq_max - rbuf->seq_start + 1; if ((msg_cnt == 0) && (seq == (ecp_seq_t)(buf->seq_ack + 1))) { - if ((buf->flags & ECP_RBUF_FLAG_MSGQ) || buf->deliver_delay) { - rv = msg_store(conn, seq, msg, msg_size, mtype); - if (rv < 0) return rv; - } else { + int deliver = 1; +#ifdef ECP_WITH_MSGQ + if (buf->msgq) deliver = 0; +#endif + if (buf->deliver_delay) deliver = 0; + if (deliver) { /* receive buffer is empty, so no need for msgq mutex lock */ rv = 0; rbuf->seq_max++; rbuf->seq_start++; rbuf->idx_start = ECP_RBUF_IDX_MASK(rbuf->idx_start + 1, rbuf->arr_size); + } else { + rv = msg_store(conn, seq, mtype, pld, pld_size); + if (rv < 0) goto rbuf_store_fin; } buf->seq_ack++; } else { - rv = msg_store(conn, seq, msg, msg_size, mtype); - if (rv < 0) return rv; + rv = msg_store(conn, seq, mtype, pld, pld_size); + if (rv < 0) goto rbuf_store_fin; - do_ack = ack_shift(buf); + do_ack = ack_shift(conn); } } - msg_flush(conn, b); + msg_flush(conn); if (ack_pkt) { buf->ack_pkt += ack_pkt; if (!do_ack && (buf->ack_pkt > buf->ack_rate)) do_ack = 1; @@ -358,13 +457,17 @@ ssize_t ecp_rbuf_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, s } } _rv = ack_send(conn, seq_ack, ack_map); - if (_rv) return _rv; + if (_rv) { + rv = _rv; + goto rbuf_store_fin; + } } - return rv; -} +rbuf_store_fin: -ECPFragIter *ecp_rbuf_get_frag_iter(ECPConnection *conn) { - if (conn->rbuf.recv) return conn->rbuf.recv->frag_iter; - return NULL; +#ifdef ECP_WITH_RTHD + pthread_mutex_unlock(&buf->mutex); +#endif + + return rv; } diff --git a/ecp/src/ecp/rbuf_send.c b/ecp/src/ecp/rbuf_send.c index 9f29010..4a7cb2c 100644 --- a/ecp/src/ecp/rbuf_send.c +++ b/ecp/src/ecp/rbuf_send.c @@ -1,39 +1,17 @@ +#include <stdlib.h> +#include <string.h> + #include "core.h" -#include "tr.h" +#include "rbuf.h" #define NACK_RATE_UNIT 10000 #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) -static ssize_t flush_send(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_RBFLUSH, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_RBFLUSH, conn)]; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_RBFLUSH, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_RBFLUSH, conn); - - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_RBFLUSH); - if (ti == NULL) { - ECPTimerItem _ti; - int rv; - - rv = ecp_timer_item_init(&_ti, conn, ECP_MTYPE_RBACK, 3, 500); - if (rv) return rv; - - _ti.retry = flush_send; - rv = ecp_timer_push(&_ti); - if (rv) return rv; - } - return ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_RBFLUSH), 0); -} - -static void cc_flush(ECPConnection *conn, unsigned char flags) { - ECPRBSend *buf = conn->rbuf.send; +static void cc_flush(ECPRBConn *conn, unsigned char flags) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBSend *buf = conn->send; ECPRBuffer *rbuf = &buf->rbuf; unsigned short idx; int rv; @@ -42,7 +20,6 @@ static void cc_flush(ECPConnection *conn, unsigned char flags) { if (rv) return; while (ECP_SEQ_LTE(buf->seq_cc, rbuf->seq_max)) { - ECPRBTimerItem *ti; ECPBuffer packet; if ((buf->cnt_cc == 0) || (buf->in_transit >= buf->win_size)) break; @@ -52,26 +29,14 @@ static void cc_flush(ECPConnection *conn, unsigned char flags) { pthread_mutex_unlock(&buf->mutex); #endif - ti = rbuf->arr.pkt[idx].timer; - if (ti) ecp_timer_push(&ti->item); packet.buffer = rbuf->arr.pkt[idx].buf; packet.size = ECP_MAX_PKT; - ecp_pkt_send(conn->sock, &conn->node.addr, &packet, rbuf->arr.pkt[idx].size, flags); + ecp_pkt_send(_conn->sock, &packet, rbuf->arr.pkt[idx].size, flags, NULL, &_conn->remote.addr); #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&buf->mutex); #endif - if (ti) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&buf->timer->mutex); -#endif - ti->empty = 1; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&buf->timer->mutex); -#endif - } - buf->cnt_cc--; buf->in_transit++; } @@ -88,39 +53,55 @@ static void cc_flush(ECPConnection *conn, unsigned char flags) { } } -ssize_t ecp_rbuf_handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPRBSend *buf; - ECPRBuffer *rbuf; - ssize_t rsize = sizeof(ecp_seq_t)+sizeof(ecp_ack_t); - ecp_seq_t seq_ack = 0; - ecp_ack_t ack_map = 0; +static ssize_t _rbuf_send_flush(ECPConnection *_conn, ECPTimerItem *ti) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_RBFLUSH, _conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_RBFLUSH, _conn)]; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_RBFLUSH); + + return ecp_pld_send_wtimer(_conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_RBFLUSH), 0, ti); +} + +ssize_t ecp_rbuf_send_flush(ECPRBConn *conn) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + + return ecp_timer_send(_conn, _rbuf_send_flush, ECP_MTYPE_RBACK, 3, 500); +} + +ssize_t ecp_rbuf_handle_ack(ECPRBConn *conn, unsigned char *msg, size_t msg_size) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBSend *buf = conn->send; + ECPRBuffer *rbuf = &buf->rbuf; + ssize_t rsize = sizeof(ecp_seq_t) + sizeof(ecp_ack_t); ecp_seq_t seq_start; ecp_seq_t seq_max; + ecp_seq_t seq_ack; + ecp_ack_t ack_map; unsigned short idx; unsigned short msg_cnt; int do_flush = 0; int i; int rv; - buf = conn->rbuf.send; - if (buf == NULL) return size; - - rbuf = &buf->rbuf; - if (size < 0) return size; - if (size < rsize) return ECP_ERR; + if (msg_size < rsize) return ECP_ERR_SIZE; seq_ack = \ - (msg[0] << 24) | \ - (msg[1] << 16) | \ - (msg[2] << 8) | \ - (msg[3]); + ((ecp_seq_t)msg[0] << 24) | \ + ((ecp_seq_t)msg[1] << 16) | \ + ((ecp_seq_t)msg[2] << 8) | \ + ((ecp_seq_t)msg[3]); ack_map = \ - (msg[4] << 24) | \ - (msg[5] << 16) | \ - (msg[6] << 8) | \ - (msg[7]); - - ecp_tr_release(b->packet, 1); + ((ecp_ack_t)msg[4] << 24) | \ + ((ecp_ack_t)msg[5] << 16) | \ + ((ecp_ack_t)msg[6] << 8) | \ + ((ecp_ack_t)msg[7]); #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&buf->mutex); @@ -130,7 +111,7 @@ ssize_t ecp_rbuf_handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mt if (ECP_SEQ_LT(seq_max, seq_ack)) return ECP_ERR; if (buf->flags & ECP_RBUF_FLAG_RELIABLE) { - rv = _ecp_rbuf_msg_idx(rbuf, seq_ack, &idx); + rv = _ecp_rbuf_msg_idx(rbuf, seq_ack, NULL); if (rv) goto handle_ack_fin; } @@ -140,6 +121,7 @@ ssize_t ecp_rbuf_handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mt if (ack_map != ECP_ACK_FULL) { ecp_ack_t ack_mask = (ecp_ack_t)1 << (ECP_SIZE_ACKB - 1); + ecp_ack_t ack_map_nop = 0; unsigned short nack_cnt = 0; int nack_first = 0; @@ -162,24 +144,13 @@ ssize_t ecp_rbuf_handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mt if (buf->flags & ECP_RBUF_FLAG_RELIABLE) { if (!(rbuf->arr.pkt[idx].flags & ECP_RBUF_FLAG_IN_RBUF) || (rbuf->arr.pkt[idx].flags & ECP_RBUF_FLAG_SKIP)) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_NOP, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_NOP, conn)]; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_NOP, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_NOP, conn); - - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_NOP); - ecp_rbuf_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_NOP), ECP_SEND_FLAG_MORE, seq_ack); + ack_map_nop |= ack_mask; } else { ECPBuffer packet; packet.buffer = rbuf->arr.pkt[idx].buf; packet.size = ECP_MAX_PKT; - ecp_pkt_send(conn->sock, &conn->node.addr, &packet, rbuf->arr.pkt[idx].size, ECP_SEND_FLAG_MORE); + ecp_pkt_send(_conn->sock, &packet, rbuf->arr.pkt[idx].size, ECP_SEND_FLAG_MORE, NULL, &_conn->remote.addr); if (buf->flags & ECP_RBUF_FLAG_CCONTROL) { buf->in_transit++; } @@ -195,6 +166,34 @@ ssize_t ecp_rbuf_handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mt if (buf->flags & ECP_RBUF_FLAG_RELIABLE) idx = ECP_RBUF_IDX_MASK(idx + 1, rbuf->arr_size); } + if ((buf->flags & ECP_RBUF_FLAG_RELIABLE) && ack_map_nop) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBNOP, _conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBNOP, _conn)]; + unsigned char *_buf; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_RBNOP); + _buf = ecp_pld_get_msg(payload.buffer, payload.size); + + seq_ack--; + _buf[0] = seq_ack >> 24; + _buf[1] = seq_ack >> 16; + _buf[2] = seq_ack >> 8; + _buf[3] = seq_ack; + _buf[4] = ack_map_nop >> 24; + _buf[5] = ack_map_nop >> 16; + _buf[6] = ack_map_nop >> 8; + _buf[7] = ack_map_nop; + + ecp_pld_send(_conn, &packet, &payload, ECP_SIZE_PLD(sizeof(ecp_seq_t) + sizeof(ecp_ack_t), ECP_MTYPE_RBNOP), ECP_SEND_FLAG_MORE); + } + #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&buf->mutex); #endif @@ -231,24 +230,18 @@ handle_ack_fin: if (!rv && do_flush) { ssize_t _rv; - _rv = flush_send(conn, NULL); + _rv = ecp_rbuf_send_flush(conn); if (_rv < 0) rv = _rv; - } else { - // ecp_tr_nomore(); } - ecp_tr_release(b->packet, 0); - if (rv) return rv; return rsize; } -int ecp_rbuf_send_create(ECPConnection *conn, ECPRBSend *buf, ECPRBPacket *pkt, unsigned short pkt_size) { +int ecp_rbsend_create(ECPRBConn *conn, ECPRBSend *buf, ECPRBPacket *pkt, unsigned short pkt_size) { ECPRBuffer *rbuf = &buf->rbuf; int rv; - if (pkt == NULL) return ECP_ERR; - memset(buf, 0, sizeof(ECPRBRecv)); memset(pkt, 0, sizeof(ECPRBPacket) * pkt_size); @@ -260,36 +253,39 @@ int ecp_rbuf_send_create(ECPConnection *conn, ECPRBSend *buf, ECPRBPacket *pkt, if (rv) return ECP_ERR; #endif - conn->rbuf.send = buf; + conn->send = buf; return ECP_OK; } -void ecp_rbuf_send_destroy(ECPConnection *conn) { - ECPRBSend *buf = conn->rbuf.send; - - if (buf == NULL) return; +void ecp_rbsend_destroy(ECPRBConn *conn) { + ECPRBSend *buf = conn->send; #ifdef ECP_WITH_PTHREAD pthread_mutex_destroy(&buf->mutex); #endif - conn->rbuf.send = NULL; + conn->send = NULL; } -int ecp_rbuf_send_start(ECPConnection *conn) { - ECPRBSend *buf = conn->rbuf.send; +void ecp_rbsend_start(ECPRBConn *conn, ecp_seq_t seq) { + ECPRBSend *buf = conn->send; ECPRBuffer *rbuf = &buf->rbuf; - if (buf == NULL) return ECP_ERR; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&buf->mutex); +#endif - buf->seq_nack = conn->seq_out; - return _ecp_rbuf_start(rbuf, conn->seq_out); -} + buf->start = 1; + buf->seq_nack = seq; + _ecp_rbuf_start(rbuf, seq); -int ecp_rbuf_set_wsize(ECPConnection *conn, ecp_win_t size) { - ECPRBSend *buf = conn->rbuf.send; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&buf->mutex); +#endif +} - if (buf == NULL) return ECP_ERR; +int ecp_rbuf_set_wsize(ECPRBConn *conn, ecp_win_t size) { + ECPRBSend *buf = conn->send; #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&buf->mutex); @@ -305,19 +301,18 @@ int ecp_rbuf_set_wsize(ECPConnection *conn, ecp_win_t size) { return ECP_OK; } -int ecp_rbuf_flush(ECPConnection *conn) { - ECPRBSend *buf = conn->rbuf.send; +int ecp_rbuf_flush(ECPRBConn *conn) { + ECPConnection *_conn = ecp_rbuf_get_conn(conn); + ECPRBSend *buf = conn->send; ecp_seq_t seq; ssize_t rv; - if (buf == NULL) return ECP_ERR; - #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); + pthread_mutex_lock(&_conn->mutex); #endif - seq = conn->seq_out; + seq = (ecp_seq_t)(_conn->nonce_out) - 1; #ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); + pthread_mutex_unlock(&_conn->mutex); #endif #ifdef ECP_WITH_PTHREAD @@ -335,8 +330,89 @@ int ecp_rbuf_flush(ECPConnection *conn) { pthread_mutex_unlock(&buf->mutex); #endif - rv = flush_send(conn, NULL); + rv = ecp_rbuf_send_flush(conn); if (rv < 0) return rv; return ECP_OK; } + +ssize_t ecp_rbuf_pld_send(ECPRBConn *conn, ECPBuffer *payload, size_t pld_size, ECPBuffer *packet, size_t pkt_size, ECPTimerItem *ti) { + ECPRBSend *buf = conn->send; + ECPRBuffer *rbuf = &buf->rbuf; + unsigned char mtype; + int rb_rel; + int rb_cc; + int do_send; + int do_skip; + int _rv = ECP_OK; + ssize_t rv = 0; + + _rv = ecp_pld_get_type(payload->buffer, pld_size, &mtype); + if (_rv) return _rv; + + do_send = 1; + do_skip = ecp_rbuf_skip(mtype); + if (ti && !do_skip) return ECP_ERR_RBUF_TIMER; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&buf->mutex); +#endif + + if (!buf->start) { + rv = 0; + goto pld_send_fin; + } + + rb_rel = (buf->flags & ECP_RBUF_FLAG_RELIABLE); + rb_cc = ((buf->flags & ECP_RBUF_FLAG_CCONTROL) && (buf->cnt_cc || (buf->in_transit >= buf->win_size))); + + if (rb_rel || rb_cc) { + ecp_seq_t seq; + unsigned short idx; + unsigned char _flags; + + _rv = ecp_pkt_get_seq(packet->buffer, pkt_size, &seq); + if (_rv) { + rv = _rv; + goto pld_send_fin; + } + + _rv = _ecp_rbuf_msg_idx(rbuf, seq, &idx); + if (_rv) rv = ECP_ERR_RBUF_DUP; + if (!rv && rbuf->arr.pkt[idx].flags) rv = ECP_ERR_RBUF_DUP; + if (rv) goto pld_send_fin; + + _flags = ECP_RBUF_FLAG_IN_RBUF; + if (do_skip) { + _flags |= ECP_RBUF_FLAG_SKIP; + } else { + do_send = 0; + } + + rbuf->arr.pkt[idx].flags = _flags; + if (!do_send) { + memcpy(rbuf->arr.pkt[idx].buf, packet->buffer, pkt_size); + rbuf->arr.pkt[idx].size = pkt_size; + rv = pld_size; + } + + if (ECP_SEQ_LT(rbuf->seq_max, seq)) rbuf->seq_max = seq; + + if (rb_cc && !do_send) { + if (buf->cnt_cc == 0) buf->seq_cc = seq; + buf->cnt_cc++; + } + } + + if ((buf->flags & ECP_RBUF_FLAG_CCONTROL) && !do_skip && do_send) { + buf->in_transit++; + } + +pld_send_fin: + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&buf->mutex); +#endif + + return rv; +} diff --git a/ecp/src/ecp/timer.c b/ecp/src/ecp/timer.c index 28d4cb1..445c343 100644 --- a/ecp/src/ecp/timer.c +++ b/ecp/src/ecp/timer.c @@ -1,3 +1,6 @@ +#include <stdlib.h> +#include <string.h> + #include "core.h" #include "tm.h" @@ -20,20 +23,13 @@ void ecp_timer_destroy(ECPTimer *timer) { #endif } -int ecp_timer_item_init(ECPTimerItem *ti, ECPConnection *conn, unsigned char mtype, short cnt, ecp_cts_t timeout) { - if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; - - if (ti == NULL) return ECP_ERR; - if (conn == NULL) return ECP_ERR; - +void ecp_timer_item_init(ECPTimerItem *ti, ECPConnection *conn, unsigned char mtype, ecp_timer_retry_t retry_f, unsigned short cnt, ecp_sts_t timeout) { ti->conn = conn; ti->mtype = mtype; - ti->cnt = cnt-1; + ti->retry = retry_f; + ti->cnt = cnt; ti->timeout = timeout; ti->abstime = 0; - ti->retry = NULL; - - return ECP_OK; } int ecp_timer_push(ECPTimerItem *ti) { @@ -58,7 +54,7 @@ int ecp_timer_push(ECPTimerItem *ti) { if (!rv) { for (i=timer->head; i>=0; i--) { - if (ECP_CTS_LTE(ti->abstime, timer->item[i].abstime)) { + if (ECP_STS_LTE(ti->abstime, timer->item[i].abstime)) { if (i != timer->head) memmove(timer->item+i+2, timer->item+i+1, sizeof(ECPTimerItem) * (timer->head-i)); timer->item[i+1] = *ti; timer->head++; @@ -106,7 +102,6 @@ void ecp_timer_pop(ECPConnection *conn, unsigned char mtype) { #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&timer->mutex); #endif - } void ecp_timer_remove(ECPConnection *conn) { @@ -134,25 +129,24 @@ void ecp_timer_remove(ECPConnection *conn) { #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&timer->mutex); #endif - } -ecp_cts_t ecp_timer_exe(ECPSocket *sock) { +ecp_sts_t ecp_timer_exe(ECPSocket *sock) { int i; - ecp_cts_t ret = 0; + ecp_sts_t ret = 0; ECPTimer *timer = &sock->timer; ECPTimerItem to_exec[ECP_MAX_TIMER]; int to_exec_size = 0; - ecp_cts_t now = ecp_tm_abstime_ms(0); + ecp_sts_t now = ecp_tm_abstime_ms(0); #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&timer->mutex); #endif for (i=timer->head; i>=0; i--) { - ecp_cts_t abstime = timer->item[i].abstime; + ecp_sts_t abstime = timer->item[i].abstime; - if (ECP_CTS_LT(now, abstime)) { + if (ECP_STS_LT(now, abstime)) { ret = abstime - now; break; } @@ -172,7 +166,6 @@ ecp_cts_t ecp_timer_exe(ECPSocket *sock) { ECPConnection *conn = to_exec[i].conn; unsigned char mtype = to_exec[i].mtype; ecp_timer_retry_t retry = to_exec[i].retry; - ecp_conn_msg_handler_t handler = ecp_conn_get_msg_handler(conn, mtype & ECP_MTYPE_MASK); int rv = ECP_OK; if (to_exec[i].cnt > 0) { @@ -183,9 +176,9 @@ ecp_cts_t ecp_timer_exe(ECPSocket *sock) { _rv = retry(conn, to_exec+i); if (_rv < 0) rv = _rv; } - if (rv && (rv != ECP_ERR_CLOSED) && handler) handler(conn, 0, mtype, NULL, rv, NULL); - } else if (handler) { - handler(conn, 0, mtype, NULL, ECP_ERR_TIMEOUT, NULL); + if (rv && (rv != ECP_ERR_CLOSED)) ecp_err_handle(conn, mtype, rv); + } else { + ecp_err_handle(conn, mtype, ECP_ERR_TIMEOUT); } ecp_conn_refcount_dec(conn); } @@ -193,13 +186,12 @@ ecp_cts_t ecp_timer_exe(ECPSocket *sock) { return ret; } -ssize_t ecp_timer_send(ECPConnection *conn, ecp_timer_retry_t send_f, unsigned char mtype, short cnt, ecp_cts_t timeout) { +ssize_t ecp_timer_send(ECPConnection *conn, ecp_timer_retry_t send_f, unsigned char mtype, unsigned short cnt, ecp_sts_t timeout) { ECPTimerItem ti; - int rv; - rv = ecp_timer_item_init(&ti, conn, mtype, cnt, timeout); - if (rv) return rv; + if (cnt == 0) return ECP_ERR; + + ecp_timer_item_init(&ti, conn, mtype, send_f, cnt-1, timeout); - ti.retry = send_f; return send_f(conn, &ti); } diff --git a/ecp/src/ecp/timer.h b/ecp/src/ecp/timer.h index 5bccff1..9079a5e 100644 --- a/ecp/src/ecp/timer.h +++ b/ecp/src/ecp/timer.h @@ -9,9 +9,9 @@ typedef ssize_t (*ecp_timer_retry_t) (struct ECPConnection *, struct ECPTimerIte typedef struct ECPTimerItem { struct ECPConnection *conn; unsigned char mtype; - short cnt; - ecp_cts_t abstime; - ecp_cts_t timeout; + unsigned short cnt; + ecp_sts_t abstime; + ecp_sts_t timeout; ecp_timer_retry_t retry; } ECPTimerItem; @@ -25,9 +25,9 @@ typedef struct ECPTimer { int ecp_timer_create(ECPTimer *timer); void ecp_timer_destroy(ECPTimer *timer); -int ecp_timer_item_init(ECPTimerItem *ti, struct ECPConnection *conn, unsigned char mtype, short cnt, ecp_cts_t timeout); +void ecp_timer_item_init(ECPTimerItem *ti, struct ECPConnection *conn, unsigned char mtype, ecp_timer_retry_t retry_f, unsigned short cnt, ecp_sts_t timeout); int ecp_timer_push(ECPTimerItem *ti); void ecp_timer_pop(struct ECPConnection *conn, unsigned char mtype); void ecp_timer_remove(struct ECPConnection *conn); -ecp_cts_t ecp_timer_exe(struct ECPSocket *sock); -ssize_t ecp_timer_send(struct ECPConnection *conn, ecp_timer_retry_t send_f, unsigned char mtype, short cnt, ecp_cts_t timeout); +ecp_sts_t ecp_timer_exe(struct ECPSocket *sock); +ssize_t ecp_timer_send(struct ECPConnection *conn, ecp_timer_retry_t send_f, unsigned char mtype, unsigned short cnt, ecp_sts_t timeout); diff --git a/ecp/src/ecp/tm.h b/ecp/src/ecp/tm.h index 00c6fad..af84b66 100644 --- a/ecp/src/ecp/tm.h +++ b/ecp/src/ecp/tm.h @@ -1,4 +1,4 @@ int ecp_tm_init(ECPContext *ctx); -ecp_cts_t ecp_tm_abstime_ms(ecp_cts_t msec); -void ecp_tm_sleep_ms(ecp_cts_t msec); -void ecp_tm_timer_set(ecp_cts_t next); +ecp_sts_t ecp_tm_abstime_ms(ecp_sts_t msec); +void ecp_tm_sleep_ms(ecp_sts_t msec); +void ecp_tm_timer_set(ecp_sts_t next); diff --git a/ecp/src/ecp/tr.h b/ecp/src/ecp/tr.h index 116590b..5037b07 100644 --- a/ecp/src/ecp/tr.h +++ b/ecp/src/ecp/tr.h @@ -1,10 +1,11 @@ int ecp_tr_init(ECPContext *ctx); -int ecp_tr_addr_eq(ECPNetAddr *addr1, ECPNetAddr *addr2); -int ecp_tr_addr_set(ECPNetAddr *addr, void *addr_s); +unsigned int ecp_tr_addr_hash(ecp_tr_addr_t *addr); +int ecp_tr_addr_eq(ecp_tr_addr_t *addr1, ecp_tr_addr_t *addr2); +int ecp_tr_addr_set(ecp_tr_addr_t *addr, void *addr_s); int ecp_tr_open(ECPSocket *sock, void *addr_s); void ecp_tr_close(ECPSocket *sock); -ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ECPNetAddr *addr, unsigned char flags); -ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ECPNetAddr *addr, int timeout); +ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ecp_tr_addr_t *addr, unsigned char flags); +ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ecp_tr_addr_t *addr, int timeout); void ecp_tr_release(ECPBuffer *packet, unsigned char more); void ecp_tr_flag_set(unsigned char flags); void ecp_tr_flag_clear(unsigned char flags); diff --git a/ecp/src/ecp/vconn/vconn.c b/ecp/src/ecp/vconn/vconn.c index d3eec44..bbed3c3 100644 --- a/ecp/src/ecp/vconn/vconn.c +++ b/ecp/src/ecp/vconn/vconn.c @@ -1,620 +1,313 @@ -#include <core.h> +#include <stdlib.h> +#include <string.h> -#ifdef ECP_WITH_HTABLE -#include <ht.h> -#endif -#include <cr.h> +#include <core.h> #include "vconn.h" -#ifdef ECP_WITH_HTABLE -static void *key_perma_table; -static void *key_next_table; -#ifdef ECP_WITH_PTHREAD -static pthread_mutex_t key_perma_mutex; -static pthread_mutex_t key_next_mutex; -#endif -#endif - -static ECPConnHandler handler_vc; -static ECPConnHandler handler_vl; +ssize_t ecp_vconn_send_open_req(ECPConnection *conn, unsigned char *cookie) { + if (conn->type == ECP_CTYPE_VCONN) { + ECPDHPub *key; + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF_WCOOKIE(2+ECP_SIZE_VBOX, ECP_MTYPE_OPEN_REQ, conn)+ECP_SIZE_PLD(ECP_SIZE_ECDH_PUB, ECP_MTYPE_NEXT)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(2+ECP_SIZE_VBOX, ECP_MTYPE_OPEN_REQ, conn)+ECP_SIZE_PLD(ECP_SIZE_ECDH_PUB, ECP_MTYPE_NEXT)]; + unsigned char *msg; + unsigned char *_pld_buf; + size_t _pld_size; + ssize_t rv; + + if (conn->next == NULL) return ECP_ERR; + + key = &conn->next->remote.key_perma; + if (!key->valid) return ECP_ERR; + + packet.buffer = pkt_buf; + packet.size = sizeof(pkt_buf); + payload.buffer = pld_buf; + payload.size = sizeof(pld_buf); + + rv = ecp_write_open_req(conn, &payload); + if (rv < 0) return rv; -#ifdef ECP_WITH_HTABLE + _pld_buf = payload.buffer + rv; + _pld_size = payload.size - rv; -static int key_is_null(unsigned char *key) { - int i; + ecp_pld_set_type(_pld_buf, _pld_size, ECP_MTYPE_NEXT); + msg = ecp_pld_get_msg(_pld_buf, _pld_size); + memcpy(msg, &key->public, ECP_SIZE_ECDH_PUB); - for (i=0; i<ECP_ECDH_SIZE_KEY; i++) { - if (key[i] != 0) return 0; + rv = ecp_pld_send_wcookie(conn, &packet, &payload, rv+ECP_SIZE_PLD(ECP_SIZE_ECDH_PUB, ECP_MTYPE_NEXT), 0, cookie); + return rv; + } else { + return ecp_send_open_req(conn, cookie); } - return 1; } -static void vconn_remove(ECPConnection *conn) { - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - int i; +static void insert_key_next(ECPConnection *conn, unsigned char idx, ecp_ecdh_public_t *public) { + ECPVConn *_conn = (ECPVConn *)conn; + ecp_ecdh_public_t to_remove; + unsigned char c_idx; + int do_insert = 0, do_remove = 0; + + if (idx == ECP_ECDH_IDX_INV) return; - if (conn->type != ECP_CTYPE_VCONN) return; - if (ecp_conn_is_outb(conn)) return; + c_idx = (idx & 0x0F); + if (c_idx & ~ECP_ECDH_IDX_MASK) return; #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); pthread_mutex_lock(&conn->mutex); #endif - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - if (!key_is_null(conn_v->key_next[i])) ecp_ht_remove(key_next_table, conn_v->key_next[i]); - } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&key_next_mutex); -#endif -} - -#endif /* ECP_WITH_HTABLE */ - -static ssize_t _vconn_send_open(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); + if (c_idx != _conn->key_next_curr) { + ECPDHPub *key; + unsigned char _c_idx; - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REQ); - return _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), 0, ti); -} + _c_idx = c_idx % ECP_MAX_NODE_KEY; + key = &_conn->key_next[_c_idx]; -static ssize_t vconn_send_open(ECPConnection *conn) { - ECPTimerItem ti; - ECPVConnOut *conn_v = (ECPVConnOut *)conn; - ECPConnection *conn_next; - ssize_t rv; - - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - if (ecp_conn_is_inb(conn)) return ECP_ERR; - - conn_next = conn_v->next; - if (conn_next == NULL) return ECP_ERR; - - rv = ecp_timer_send(conn_next, _vconn_send_open, ECP_MTYPE_KGET_REP, 3, 1000); - if (rv < 0) return rv; - - return rv; -} - -static ssize_t vconn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - return _ecp_conn_handle_kget(conn, seq, mtype, msg, size, b, vconn_send_open); -} - -static ssize_t vconn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ssize_t rv; - int _rv; - - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - - if (mtype & ECP_MTYPE_FLAG_REP) { - if (ecp_conn_is_inb(conn)) return ECP_ERR; - if (size < 0) { - ecp_conn_msg_handler_t handler; - while (conn && (conn->type == ECP_CTYPE_VCONN)) { - ECPVConnOut *conn_v = (ECPVConnOut *)conn; - conn = conn_v->next; + if (!key->valid || (memcmp(public, &key->public, sizeof(key->public)) != 0)) { + if (key->valid) { + memcpy(&to_remove, &key->public, sizeof(key->public)); + do_remove = 1; } - if (conn) handler = ecp_conn_get_msg_handler(conn, ECP_MTYPE_OPEN); - return handler ? handler(conn, seq, mtype, msg, size, b) : size; - } - - rv = ecp_conn_handle_open(conn, seq, mtype, msg, size, b); - } else { + memcpy(&key->public, public, sizeof(key->public)); + key->valid = 1; -#ifdef ECP_WITH_HTABLE - - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - unsigned char ctype; - int is_new, do_ins; - - if (ecp_conn_is_outb(conn)) return ECP_ERR; - if (size < 0) return size; - if (size < 1+2*ECP_ECDH_SIZE_KEY) return ECP_ERR; - - ctype = msg[0]; - msg++; - - is_new = ecp_conn_is_new(conn); - do_ins = 0; - if (is_new) { - conn_v->key_next_curr = 0; - memset(conn_v->key_next, 0, sizeof(conn_v->key_next)); - memset(conn_v->key_out, 0, sizeof(conn_v->key_out)); - memcpy(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY); - memcpy(conn_v->key_out, msg+ECP_ECDH_SIZE_KEY, ECP_ECDH_SIZE_KEY); - do_ins = 1; - - _rv = ecp_conn_insert(conn); - if (_rv) return rv; + _conn->key_next_curr = c_idx; + do_insert = 1; } + } #ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); - pthread_mutex_lock(&conn->mutex); + pthread_mutex_unlock(&conn->mutex); #endif - _rv = ECP_OK; - if (!is_new && memcmp(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY)) { - conn_v->key_next_curr = (conn_v->key_next_curr + 1) % ECP_MAX_NODE_KEY; - if (!key_is_null(conn_v->key_next[conn_v->key_next_curr])) ecp_ht_remove(key_next_table, conn_v->key_next[conn_v->key_next_curr]); - memcpy(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY); - do_ins = 1; - } - if (do_ins) _rv = ecp_ht_insert(key_next_table, conn_v->key_next[conn_v->key_next_curr], conn); - if (!_rv && !ecp_conn_is_open(conn)) ecp_conn_set_open(conn); + if (do_remove) ecp_sock_keys_remove(conn->sock, &to_remove); + if (do_insert) ecp_sock_keys_insert(conn->sock, public, conn); +} -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&key_next_mutex); -#endif +static ssize_t handle_next(ECPConnection *conn, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + ECPConnection *conn_next; - if (_rv) { - ecp_conn_close(conn); - return _rv; - } + if (msg_size < ECP_SIZE_ECDH_PUB) return ECP_ERR_SIZE; - rv = 1+2*ECP_ECDH_SIZE_KEY; + conn_next = ecp_sock_keys_search(conn->sock, (ecp_ecdh_public_t *)msg); + if (conn_next == NULL) return ECP_ERR; -#else /* ECP_WITH_HTABLE */ + conn->next = conn_next; - ecp_conn_close(conn); - rv = ECP_ERR_NOT_IMPLEMENTED; + return ECP_SIZE_ECDH_PUB; +} -#endif /* ECP_WITH_HTABLE */ +static ssize_t handle_exec(ECPConnection *conn, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + ECPBuffer *packet; - } + if (b == NULL) return ECP_ERR; - return rv; + packet = b->packet; + if (packet->size < msg_size) return ECP_ERR_SIZE; + + memcpy(packet->buffer, msg, msg_size); + return ecp_pkt_handle(conn->sock, conn, NULL, b, msg_size); } -#ifdef ECP_WITH_HTABLE -static ssize_t vconn_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { +static ssize_t handle_relay(ECPConnection *conn, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { ECPBuffer payload; - ECPConnection *conn_out = NULL; - ECPVConnIn *conn_v = (ECPVConnIn *)conn; + ECPConnection *conn_next; ssize_t rv; - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - if (ecp_conn_is_outb(conn)) return ECP_ERR; - if (b == NULL) return ECP_ERR; - - if (size < 0) return size; - if (size < ECP_MIN_PKT) return ECP_ERR; + if (msg_size < ECP_MIN_PKT) return ECP_ERR_SIZE; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif - conn_out = ecp_ht_search(key_perma_table, conn_v->key_out); - if (conn_out) { - ecp_conn_refcount_inc(conn_out); + if (conn->type == ECP_CTYPE_VCONN) { + if (ecp_conn_is_outb(conn)) return ECP_ERR; + conn_next = conn->next; + insert_key_next(conn, msg[ECP_SIZE_PROTO], (ecp_ecdh_public_t *)(msg+ECP_SIZE_PROTO+1)); + } else if (conn->type == ECP_CTYPE_VLINK) { + conn_next = ecp_sock_keys_search(conn->sock, (ecp_ecdh_public_t *)(msg+ECP_SIZE_PROTO+1)); } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif - if (conn_out == NULL) return ECP_ERR; + if (conn_next == NULL) return ECP_ERR; - payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; + payload.buffer = msg - ECP_SIZE_MTYPE; payload.size = b->payload->size - (payload.buffer - b->payload->buffer); ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_EXEC); - rv = ecp_pld_send(conn_out, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size, ECP_SEND_FLAG_REPLY); + rv = ecp_pld_send(conn_next, b->packet, &payload, ECP_SIZE_MTYPE + msg_size, ECP_SEND_FLAG_REPLY); - ecp_conn_refcount_dec(conn_out); + if (conn->type == ECP_CTYPE_VLINK) { + ecp_conn_refcount_dec(conn_next); + } if (rv < 0) return rv; - return size; + return msg_size; } -static int vlink_insert(ECPConnection *conn) { +ssize_t ecp_vconn_pack_parent(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pkt_size, ecp_tr_addr_t *addr) { + unsigned char *msg; + size_t hdr_size; int rv; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif - rv = ecp_ht_insert(key_perma_table, ecp_cr_dh_pub_get_buf(&conn->node.public), conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif - - return rv; -} - -static void vlink_remove(ECPConnection *conn) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif - ecp_ht_remove(key_perma_table, ecp_cr_dh_pub_get_buf(&conn->node.public)); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif -} - -#endif /* ECP_WITH_HTABLE */ + rv = ecp_pld_set_type(payload->buffer, payload->size, ECP_MTYPE_RELAY); + if (rv) return rv; -static ssize_t _vlink_send_open(ECPConnection *conn, ECPTimerItem *ti) { - ECPSocket *sock = conn->sock; - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char *buf; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); - - // XXX server should verify perma_key - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_OPEN_REQ); - buf = ecp_pld_get_buf(payload.buffer, payload.size); - buf[0] = conn->type; - memcpy(buf+1, ecp_cr_dh_pub_get_buf(&sock->key_perma.public), ECP_ECDH_SIZE_KEY); - - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ), 0, ti); -} + msg = ecp_pld_get_msg(payload->buffer, payload->size); + if (msg == NULL) return ECP_ERR; -static ssize_t vlink_send_open(ECPConnection *conn) { - return ecp_timer_send(conn, _vlink_send_open, ECP_MTYPE_OPEN_REP, 3, 500); -} + hdr_size = msg - payload->buffer; + if (payload->size < pkt_size+hdr_size) return ECP_ERR_SIZE; -static ssize_t vlink_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - return _ecp_conn_handle_kget(conn, seq, mtype, msg, size, b, vlink_send_open); + memcpy(msg, packet->buffer, pkt_size); + return ecp_pack_conn(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, NULL, NULL, payload, pkt_size+hdr_size, addr); } -static ssize_t vlink_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ssize_t rv; - int _rv; - int is_open; +int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *b) { + if (conn->type == ECP_CTYPE_VCONN) { + if (ecp_conn_is_outb(conn)) { + if (conn->next) { + int rv; - if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; + rv = ecp_conn_open(conn->next, NULL); + if (rv) ecp_err_handle(conn->next, ECP_MTYPE_INIT_REQ, rv); + } + } + } else if (conn->type == ECP_CTYPE_VLINK) { + ECPDHPub *key = &conn->remote.key_perma; - if (size < 0) return size; + if (key->valid) { + int rv; - if (ecp_conn_is_new(conn) && (size >= 1+ECP_ECDH_SIZE_KEY)) { - // XXX we should verify perma_key - ecp_cr_dh_pub_from_buf(&conn->node.public, msg+1); + rv = ecp_sock_keys_insert(conn->sock, &key->public, conn); + if (rv) return rv; + } } - rv = _ecp_conn_handle_open(conn, seq, mtype, msg, size, b, &is_open); - if (rv < 0) return rv; - - if (mtype & ECP_MTYPE_FLAG_REP) { - -#ifdef ECP_WITH_HTABLE + return ECP_OK; +} - if (!is_open) { - _rv = vlink_insert(conn); - if (_rv) return _rv; +void ecp_vconn_handle_close(ECPConnection *conn) { + if (conn->type == ECP_CTYPE_VCONN) { + if (ecp_conn_is_inb(conn)) { + ecp_vconn_destroy_inb((ECPVConn *)conn); } + } else if (conn->type == ECP_CTYPE_VLINK) { + ECPDHPub *key = &conn->remote.key_perma; -#endif /* ECP_WITH_HTABLE */ - - } else { - if (size < rv+ECP_ECDH_SIZE_KEY) return ECP_ERR; - -#ifdef ECP_WITH_HTABLE - - msg += rv; - - if (!is_open) { - _rv = vlink_insert(conn); - if (_rv) { - ecp_conn_close(conn); - return _rv; - } + if (key->valid) { + ecp_sock_keys_remove(conn->sock, &key->public); } - - rv = rv+ECP_ECDH_SIZE_KEY; - -#else /* ECP_WITH_HTABLE */ - - ecp_conn_close(conn); - rv = ECP_ERR_NOT_IMPLEMENTED; - -#endif /* ECP_WITH_HTABLE */ - } - - return rv; } -#ifdef ECP_WITH_HTABLE -static ssize_t vlink_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPBuffer payload; - ssize_t rv; +ssize_t ecp_vconn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + switch (mtype) { + case ECP_MTYPE_NEXT: + return handle_next(conn, msg, msg_size, b); - if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; - if (b == NULL) return ECP_ERR; + case ECP_MTYPE_EXEC: + return handle_exec(conn, msg, msg_size, b); - if (size < 0) return size; - if (size < ECP_MIN_PKT) return ECP_ERR; + case ECP_MTYPE_RELAY: + return handle_relay(conn, msg, msg_size, b); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); -#endif - conn = ecp_ht_search(key_next_table, msg+ECP_SIZE_PROTO+1); - if (conn) { - ecp_conn_refcount_inc(conn); + default: + return ECP_ERR_MTYPE; } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_next_mutex); -#endif - - if (conn == NULL) return ECP_ERR; - - payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; - payload.size = b->payload->size - (payload.buffer - b->payload->buffer); - - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_EXEC); - rv = ecp_pld_send(conn, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size, ECP_SEND_FLAG_REPLY); - - ecp_conn_refcount_dec(conn); - - if (rv < 0) return rv; - return size; } -#endif /* ECP_WITH_HTABLE */ - -#ifdef ECP_MEM_TINY -/* Memory limited version */ - -static ssize_t vconn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (size < 0) return size; - if (b == NULL) return ECP_ERR; - if (b->packet->buffer == NULL) return ECP_ERR; - memcpy(b->packet->buffer, msg, size); - return ecp_pkt_handle(conn->sock, NULL, conn, b, size); -} - -#else - -static ssize_t vconn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (size < 0) return size; - if (b == NULL) return ECP_ERR; - - ECP2Buffer b2; - ECPBuffer packet; - ECPBuffer payload; - unsigned char pld_buf[ECP_MAX_PLD]; +int ecp_vconn_create_inb(ECPVConn *conn, ECPSocket *sock) { + ECPConnection *_conn = &conn->b; + int rv; - b2.packet = &packet; - b2.payload = &payload; + rv = ecp_conn_create_inb(_conn, sock, ECP_CTYPE_VCONN); + if (rv) return rv; - packet.buffer = msg; - packet.size = b->payload->size - (msg - b->payload->buffer); - payload.buffer = pld_buf; - payload.size = ECP_MAX_PLD; + memset(conn->key_next, 0, sizeof(conn->key_next)); + conn->key_next_curr = ECP_ECDH_IDX_INV; - return ecp_pkt_handle(conn->sock, NULL, conn, &b2, size); + return ECP_OK; } -#endif - -static ssize_t vconn_set_msg(ECPConnection *conn, ECPBuffer *payload, unsigned char mtype) { - if (ecp_conn_is_outb(conn) && (conn->type == ECP_CTYPE_VCONN) && ((mtype == ECP_MTYPE_OPEN_REQ) || (mtype == ECP_MTYPE_KGET_REQ))) { - ECPVConnOut *conn_v = (ECPVConnOut *)conn; - ECPConnection *conn_next = conn_v->next; - unsigned char *buf = NULL; - int rv; - - if (payload->size < ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY) return ECP_ERR; - if (conn_next == NULL) return ECP_ERR; - - ecp_pld_set_type(payload->buffer, payload->size, ECP_MTYPE_OPEN_REQ); - buf = ecp_pld_get_buf(payload->buffer, payload->size); - - buf[0] = ECP_CTYPE_VCONN; - rv = ecp_conn_dhkey_get_curr(conn_next, NULL, buf+1); - if (rv) return rv; - - memcpy(buf+1+ECP_ECDH_SIZE_KEY, ecp_cr_dh_pub_get_buf(&conn_next->node.public), ECP_ECDH_SIZE_KEY); - buf[1+2*ECP_ECDH_SIZE_KEY] = ECP_MTYPE_RELAY; - - return ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY; - } else { - if (payload->size < ECP_SIZE_PLD_HDR + 1) return ECP_ERR; +void ecp_vconn_destroy_inb(ECPVConn *conn) { + ECPConnection *_conn = &conn->b; + int i; - ecp_pld_set_type(payload->buffer, payload->size, ECP_MTYPE_RELAY); + for (i=0; i<ECP_MAX_NODE_KEY; i++) { + ECPDHPub *key; - return ECP_SIZE_PLD_HDR + 1; + key = &conn->key_next[i]; + if (key->valid) { + ecp_sock_keys_remove(_conn->sock, &key->public); + } } - + if (_conn->next) ecp_conn_refcount_dec(_conn->next); } -#ifdef ECP_MEM_TINY -/* Memory limited version */ - -ssize_t ecp_pack(ECPContext *ctx, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; - - if (parent) { - unsigned char mtype; - ssize_t rv, hdr_size; - int _rv; - - _rv = ecp_pld_get_type(payload->buffer, payload->size, &mtype); - if (_rv) return _rv; - - hdr_size = vconn_set_msg(parent, packet, mtype); - if (hdr_size < 0) return hdr_size; - - rv = _ecp_pack(ctx, packet->buffer+hdr_size, packet->size-hdr_size, pkt_meta, payload->buffer, pld_size); - if (rv < 0) return rv; - - if (payload->size < rv+hdr_size) return ECP_ERR; - memcpy(payload->buffer, packet->buffer, rv+hdr_size); +static int vconn_create(ECPConnection vconn[], ecp_ecdh_public_t keys[], size_t vconn_size, ECPSocket *sock) { + ECPDHPub key; + int i, j; + int rv; - return ecp_pack_conn(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, addr, NULL); - } else { - return _ecp_pack(ctx, packet->buffer, packet->size, pkt_meta, payload->buffer, pld_size); + key.valid = 1; + for (i=0; i<vconn_size; j++) { + rv = ecp_conn_create(&vconn[i], sock, ECP_CTYPE_VCONN); + if (rv) { + for (j=0; j<i; j++) { + ecp_conn_destroy(&vconn[j]); + } + return rv; + } + memcpy(&key.public, &keys[i], sizeof(keys[i])); + ecp_conn_set_remote_key(&vconn[i], &key); } -} - -#else - -ssize_t ecp_pack(ECPContext *ctx, ECPConnection *parent, ECPBuffer *packet, ECPPktMeta *pkt_meta, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; - - if (parent) { - ECPBuffer _payload; - unsigned char pld_buf[ECP_MAX_PLD]; - unsigned char mtype; - ssize_t rv, hdr_size; - int _rv; - - _payload.buffer = pld_buf; - _payload.size = ECP_MAX_PLD; - - _rv = ecp_pld_get_type(payload->buffer, payload->size, &mtype); - if (_rv) return _rv; - hdr_size = vconn_set_msg(parent, &_payload, mtype); - if (hdr_size < 0) return hdr_size; - - rv = _ecp_pack(ctx, _payload.buffer+hdr_size, _payload.size-hdr_size, pkt_meta, payload->buffer, pld_size); - if (rv < 0) return rv; - - return ecp_pack_conn(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &_payload, rv+hdr_size, addr, NULL); - } else { - return _ecp_pack(ctx, packet->buffer, packet->size, pkt_meta, payload->buffer, pld_size); - } + return ECP_OK; } -#endif - -#ifdef ECP_MEM_TINY -/* Memory limited version */ - -ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; - - if (conn->parent) { - unsigned char mtype; - ssize_t rv, hdr_size; - int _rv; +int ecp_vconn_create(ECPConnection vconn[], ecp_ecdh_public_t keys[], size_t vconn_size, ECPConnection *conn) { + ECPConnection *_conn; + unsigned short pcount; + int rv; - _rv = ecp_pld_get_type(payload->buffer, payload->size, &mtype); - if (_rv) return _rv; + _conn = conn; + pcount = vconn_size; - hdr_size = vconn_set_msg(conn->parent, packet, mtype); - if (hdr_size < 0) return hdr_size; + if (pcount >= ECP_MAX_PARENT) return ECP_ERR_MAX_PARENT; - rv = _ecp_pack_conn(conn, packet->buffer+hdr_size, packet->size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, NULL, si); - if (rv < 0) return rv; + rv = vconn_create(vconn, keys, vconn_size, conn->sock); + if (rv) return rv; - if (payload->size < rv+hdr_size) return ECP_ERR; - memcpy(payload->buffer, packet->buffer, rv+hdr_size); + while (pcount) { + _conn->parent = &vconn[pcount-1]; + _conn->parent->next = _conn; + _conn->pcount = pcount; - return ecp_pack_conn(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, addr, NULL); - } else { - return _ecp_pack_conn(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, addr, si); + _conn = _conn->parent; + pcount--; } -} - -#else - -ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr, ECPSeqItem *si) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; - - if (conn->parent) { - ECPBuffer _payload; - unsigned char pld_buf[ECP_MAX_PLD]; - unsigned char mtype; - ssize_t rv, hdr_size; - int _rv; - - _payload.buffer = pld_buf; - _payload.size = ECP_MAX_PLD; - - _rv = ecp_pld_get_type(payload->buffer, payload->size, &mtype); - if (_rv) return _rv; - hdr_size = vconn_set_msg(conn->parent, &_payload, mtype); - if (hdr_size < 0) return hdr_size; - - rv = _ecp_pack_conn(conn, _payload.buffer+hdr_size, _payload.size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, NULL, si); - if (rv < 0) return rv; - - return ecp_pack_conn(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &_payload, rv+hdr_size, addr, NULL); - } else { - return _ecp_pack_conn(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, addr, si); - } + return ECP_OK; } -#endif - -int ecp_vconn_ctx_init(ECPContext *ctx) { +int ecp_vconn_open(ECPConnection *conn, ECPNode *node) { + ECPConnection *vconn0; int rv; - rv = ecp_conn_handler_init(&handler_vc); - if (rv) return rv; - - handler_vc.msg[ECP_MTYPE_OPEN] = vconn_handle_open; - handler_vc.msg[ECP_MTYPE_KGET] = vconn_handle_kget; - handler_vc.msg[ECP_MTYPE_EXEC] = vconn_handle_exec; -#ifdef ECP_WITH_HTABLE - handler_vc.msg[ECP_MTYPE_RELAY] = vconn_handle_relay; - handler_vc.conn_close = vconn_remove; -#endif /* ECP_WITH_HTABLE */ - ctx->handler[ECP_CTYPE_VCONN] = &handler_vc; - - rv = ecp_conn_handler_init(&handler_vl); - if (rv) return rv; - - handler_vl.msg[ECP_MTYPE_OPEN] = vlink_handle_open; - handler_vl.msg[ECP_MTYPE_KGET] = vlink_handle_kget; - handler_vl.msg[ECP_MTYPE_EXEC] = vconn_handle_exec; -#ifdef ECP_WITH_HTABLE - handler_vl.msg[ECP_MTYPE_RELAY] = vlink_handle_relay; - handler_vl.conn_close = vlink_remove; -#endif /* ECP_WITH_HTABLE */ - ctx->handler[ECP_CTYPE_VLINK] = &handler_vl; - -#ifdef ECP_WITH_HTABLE - key_perma_table = ecp_ht_create(ctx); - if (key_perma_table == NULL) { - return ECP_ERR; - } - key_next_table = ecp_ht_create(ctx); - if (key_next_table == NULL) { - ecp_ht_destroy(key_perma_table); - return ECP_ERR; + vconn0 = conn; + while (vconn0->parent) { + vconn0 = vconn0->parent; } -#ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&key_perma_mutex, NULL); - if (rv) { - ecp_ht_destroy(key_next_table); - ecp_ht_destroy(key_perma_table); - return ECP_ERR; - } - rv = pthread_mutex_init(&key_next_mutex, NULL); - if (rv) { - pthread_mutex_destroy(&key_perma_mutex); - ecp_ht_destroy(key_next_table); - ecp_ht_destroy(key_perma_table); - return ECP_ERR; + + if (node) { + ecp_conn_set_remote_key(conn, &node->key_perma); + ecp_conn_set_remote_addr(vconn0, &node->addr); } -#endif /* ECP_WITH_PTHREAD */ -#endif /* ECP_WITH_HTABLE */ - return ECP_OK; + rv = ecp_conn_open(vconn0, NULL); + return rv; } +/* int ecp_vconn_create_parent(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut vconn[], ECPNode vconn_node[], int size) { ECPSocket *sock = conn->sock; int i, j, rv; @@ -650,21 +343,6 @@ int ecp_vconn_create_parent(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut return ECP_OK; } -static ssize_t _vconn_send_kget(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); - - ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REQ); - return _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), 0, ti); -} - int ecp_vconn_open(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut vconn[], ECPNode vconn_node[], int size) { int rv; ssize_t _rv; @@ -688,4 +366,5 @@ int ecp_vconn_open(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut vconn[], if (_rv < 0) return _rv; return ECP_OK; -}
\ No newline at end of file +} +*/
\ No newline at end of file diff --git a/ecp/src/ecp/vconn/vconn.h b/ecp/src/ecp/vconn/vconn.h index 73d9fd6..eec13d4 100644 --- a/ecp/src/ecp/vconn/vconn.h +++ b/ecp/src/ecp/vconn/vconn.h @@ -1,22 +1,25 @@ -#define ECP_CTYPE_VCONN 1 -#define ECP_CTYPE_VLINK 2 +#define ECP_CTYPE_VCONN (0x01 | ECP_CTYPE_FLAG_SYS) +#define ECP_CTYPE_VLINK (0x02 | ECP_CTYPE_FLAG_SYS) -#define ECP_MTYPE_RELAY 0x08 -#define ECP_MTYPE_EXEC 0x09 +#define ECP_MTYPE_NEXT 0x00 +#define ECP_MTYPE_EXEC 0x02 +#define ECP_MTYPE_RELAY 0x01 -typedef struct ECPVConnOut { +/* inbound only */ +typedef struct ECPVConn { ECPConnection b; - ECPConnection *next; -} ECPVConnOut; - -typedef struct ECPVConnIn { - ECPConnection b; - unsigned char key_next[ECP_MAX_NODE_KEY][ECP_ECDH_SIZE_KEY]; + ECPDHPub key_next[ECP_MAX_NODE_KEY]; unsigned char key_next_curr; - unsigned char key_out[ECP_ECDH_SIZE_KEY]; -} ECPVConnIn; +} ECPVConn; + +ssize_t ecp_vconn_send_open_req(ECPConnection *conn, unsigned char *cookie); +ssize_t ecp_vconn_pack_parent(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pkt_size, ecp_tr_addr_t *addr); +int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *b); +void ecp_vconn_handle_close(ECPConnection *conn); +ssize_t ecp_vconn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *b); + +int ecp_vconn_create_inb(ECPVConn *conn, ECPSocket *sock); +void ecp_vconn_destroy_inb(ECPVConn *conn); -ssize_t ecp_vconn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b); -int ecp_vconn_ctx_init(ECPContext *ctx); -int ecp_vconn_create_parent(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut vconn[], ECPNode vconn_node[], int size); -int ecp_vconn_open(ECPConnection *conn, ECPNode *conn_node, ECPVConnOut vconn[], ECPNode vconn_node[], int size); +int ecp_vconn_create(ECPConnection vconn[], ecp_ecdh_public_t keys[], size_t vconn_size, ECPConnection *conn); +int ecp_vconn_open(ECPConnection *conn, ECPNode *node); diff --git a/ecp/src/platform/fe310/time.c b/ecp/src/platform/fe310/time.c index 3c74933..1e5eb17 100644 --- a/ecp/src/platform/fe310/time.c +++ b/ecp/src/platform/fe310/time.c @@ -1,3 +1,5 @@ +#include <stdlib.h> + #include <core.h> #include <tr.h> @@ -9,7 +11,7 @@ extern ECPSocket *_ecp_tr_sock; static void timer_handler(unsigned char type) { - ecp_cts_t next = ecp_timer_exe(_ecp_tr_sock); + ecp_sts_t next = ecp_timer_exe(_ecp_tr_sock); if (next) { eos_timer_set(next, EOS_TIMER_ETYPE_ECP); } @@ -21,15 +23,15 @@ int ecp_tm_init(ECPContext *ctx) { return ECP_OK; } -ecp_cts_t ecp_tm_abstime_ms(ecp_cts_t msec) { +ecp_sts_t ecp_tm_abstime_ms(ecp_sts_t msec) { return eos_time_get_tick() * 1000 / EOS_TIMER_RTC_FREQ + msec; } -void ecp_tm_sleep_ms(ecp_cts_t msec) { +void ecp_tm_sleep_ms(ecp_sts_t msec) { eos_time_sleep(msec); } -void ecp_tm_timer_set(ecp_cts_t next) { +void ecp_tm_timer_set(ecp_sts_t next) { uint32_t _next = eos_timer_get(EOS_TIMER_ETYPE_ECP); if ((_next == EOS_TIMER_NONE) || (next < _next)) eos_timer_set(next, EOS_TIMER_ETYPE_ECP); } diff --git a/ecp/src/platform/fe310/transport.c b/ecp/src/platform/fe310/transport.c index 777a956..b551c51 100644 --- a/ecp/src/platform/fe310/transport.c +++ b/ecp/src/platform/fe310/transport.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <string.h> #include <core.h> #include <tr.h> @@ -11,7 +12,7 @@ static unsigned char _flags = 0; ECPSocket *_ecp_tr_sock = NULL; static void packet_handler(unsigned char type, unsigned char *buffer, uint16_t len) { - ECPNetAddr addr; + ecp_tr_addr_t addr; ECP2Buffer bufs; ECPBuffer packet; @@ -49,13 +50,18 @@ int ecp_tr_init(ECPContext *ctx) { return ECP_OK; } -int ecp_tr_addr_eq(ECPNetAddr *addr1, ECPNetAddr *addr2) { +unsigned int ecp_tr_addr_hash(ecp_tr_addr_t *addr) { + unsigned int ret = *((unsigned int *)addr->host); + return ret ^ ((unsigned int)addr->port << 16); +} + +int ecp_tr_addr_eq(ecp_tr_addr_t *addr1, ecp_tr_addr_t *addr2) { if (addr1->port != addr2->port) return 0; if (memcmp(addr1->host, addr2->host, sizeof(addr1->host)) != 0) return 0; return 1; } -int ecp_tr_addr_set(ECPNetAddr *addr, void *addr_s) { +int ecp_tr_addr_set(ecp_tr_addr_t *addr, void *addr_s) { return ECP_ERR; } @@ -74,7 +80,7 @@ void ecp_tr_close(ECPSocket *sock) { _ecp_tr_sock = NULL; } -ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ECPNetAddr *addr, unsigned char flags) { +ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ecp_tr_addr_t *addr, unsigned char flags) { unsigned char *buf = NULL; int rv; @@ -94,7 +100,7 @@ ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ECPNetA return msg_size; } -ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ECPNetAddr *addr, int timeout) { +ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ecp_tr_addr_t *addr, int timeout) { return ECP_ERR; } diff --git a/ecp/src/platform/fe310/transport.h b/ecp/src/platform/fe310/transport.h index 47ad482..213ca11 100644 --- a/ecp/src/platform/fe310/transport.h +++ b/ecp/src/platform/fe310/transport.h @@ -1,7 +1,4 @@ #include <eos/sock.h> -#define ECP_IPv4_ADDR_SIZE 4 - -typedef EOSNetAddr ECPNetAddr; -typedef int ECPNetSock; - +typedef EOSNetAddr ecp_tr_addr_t; +typedef int ecp_tr_sock_t; diff --git a/ecp/src/platform/posix/platform.mk b/ecp/src/platform/posix/platform.mk index 0370c58..9dcfe37 100644 --- a/ecp/src/platform/posix/platform.mk +++ b/ecp/src/platform/posix/platform.mk @@ -1,2 +1,2 @@ -CFLAGS += -O3 -DECP_WITH_PTHREAD=1 -DECP_WITH_HTABLE=1 -DECP_WITH_RBUF=1 -DECP_WITH_MSGQ=1 -DECP_WITH_VCONN=1 -DECP_WITH_DIRSRV -DECP_DEBUG=1 +CFLAGS += -O3 -DECP_WITH_PTHREAD=1 -DECP_WITH_HTABLE=1 -DECP_WITH_VCONN=1 -DECP_WITH_DIR -DECP_WITH_DIRSRV -DECP_WITH_MSGQ=1 -DECP_DEBUG=1 LDFLAGS += -lm -pthread diff --git a/ecp/src/platform/posix/platform_obj.mk b/ecp/src/platform/posix/platform_obj.mk index 6ca3b8d..4157ff4 100644 --- a/ecp/src/platform/posix/platform_obj.mk +++ b/ecp/src/platform/posix/platform_obj.mk @@ -1,2 +1,2 @@ -obj += rbuf.o rbuf_send.o rbuf_recv.o msgq.o +obj += ext.o frag.o rbuf.o rbuf_send.o rbuf_recv.o msgq.o subdirs += htable vconn diff --git a/ecp/src/platform/posix/time.c b/ecp/src/platform/posix/time.c index 111e598..efee4f8 100644 --- a/ecp/src/platform/posix/time.c +++ b/ecp/src/platform/posix/time.c @@ -1,3 +1,4 @@ +#include <stdlib.h> #include <unistd.h> #include <sys/time.h> @@ -8,17 +9,17 @@ int ecp_tm_init(ECPContext *ctx) { return ECP_OK; } -ecp_cts_t ecp_tm_abstime_ms(ecp_cts_t msec) { +ecp_sts_t ecp_tm_abstime_ms(ecp_sts_t msec) { struct timeval tv; - ecp_cts_t ms_now; + ecp_sts_t ms_now; gettimeofday(&tv, NULL); ms_now = tv.tv_sec * 1000 + tv.tv_usec / 1000; return ms_now + msec; } -void ecp_tm_sleep_ms(ecp_cts_t msec) { +void ecp_tm_sleep_ms(ecp_sts_t msec) { usleep(msec*1000); } -void ecp_tm_timer_set(ecp_cts_t next) {}
\ No newline at end of file +void ecp_tm_timer_set(ecp_sts_t next) {} diff --git a/ecp/src/platform/posix/transport.c b/ecp/src/platform/posix/transport.c index c41f0df..30822b6 100644 --- a/ecp/src/platform/posix/transport.c +++ b/ecp/src/platform/posix/transport.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> @@ -14,13 +15,18 @@ int ecp_tr_init(ECPContext *ctx) { return ECP_OK; } -int ecp_tr_addr_eq(ECPNetAddr *addr1, ECPNetAddr *addr2) { +unsigned int ecp_tr_addr_hash(ecp_tr_addr_t *addr) { + unsigned int ret = *((unsigned int *)addr->host); + return ret ^ ((unsigned int)addr->port << 16); +} + +int ecp_tr_addr_eq(ecp_tr_addr_t *addr1, ecp_tr_addr_t *addr2) { if (addr1->port != addr2->port) return 0; if (memcmp(addr1->host, addr2->host, sizeof(addr1->host)) != 0) return 0; return 1; } -int ecp_tr_addr_set(ECPNetAddr *addr, void *addr_s) { +int ecp_tr_addr_set(ecp_tr_addr_t *addr, void *addr_s) { int rv; char addr_c[ADDR_S_MAX]; char *colon = NULL; @@ -49,7 +55,7 @@ int ecp_tr_open(ECPSocket *sock, void *addr_s) { memset((char *)&_myaddr, 0, sizeof(_myaddr)); _myaddr.sin_family = AF_INET; if (addr_s) { - ECPNetAddr addr; + ecp_tr_addr_t addr; int rv = ecp_tr_addr_set(&addr, addr_s); if (rv) return rv; @@ -75,7 +81,7 @@ void ecp_tr_close(ECPSocket *sock) { close(sock->sock); } -ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ECPNetAddr *addr, unsigned char flags) { +ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ecp_tr_addr_t *addr, unsigned char flags) { struct sockaddr_in servaddr; memset((void *)&servaddr, 0, sizeof(servaddr)); @@ -85,7 +91,7 @@ ssize_t ecp_tr_send(ECPSocket *sock, ECPBuffer *packet, size_t msg_size, ECPNetA return sendto(sock->sock, packet->buffer, msg_size, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); } -ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ECPNetAddr *addr, int timeout) { +ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ecp_tr_addr_t *addr, int timeout) { struct sockaddr_in servaddr; socklen_t addrlen = sizeof(servaddr); struct pollfd fds[] = { @@ -111,4 +117,3 @@ ssize_t ecp_tr_recv(ECPSocket *sock, ECPBuffer *packet, ECPNetAddr *addr, int ti void ecp_tr_release(ECPBuffer *packet, unsigned char more) {} void ecp_tr_flag_set(unsigned char flags) {} void ecp_tr_flag_clear(unsigned char flags) {} - diff --git a/ecp/src/platform/posix/transport.h b/ecp/src/platform/posix/transport.h index 155bd9c..736dbc1 100644 --- a/ecp/src/platform/posix/transport.h +++ b/ecp/src/platform/posix/transport.h @@ -1,7 +1,9 @@ #define ECP_IPv4_ADDR_SIZE 4 -typedef int ECPNetSock; -typedef struct ECPNetAddr { +struct ECPNetAddr { unsigned char host[ECP_IPv4_ADDR_SIZE]; uint16_t port; -} ECPNetAddr; +}; + +typedef struct ECPNetAddr ecp_tr_addr_t; +typedef int ecp_tr_sock_t; diff --git a/ecp/util/mknode.c b/ecp/util/mknode.c index 0c262fe..885a4c0 100644 --- a/ecp/util/mknode.c +++ b/ecp/util/mknode.c @@ -12,26 +12,15 @@ static char fn_key[FN_LEN]; static char fn_node[FN_LEN]; -static int v_rng(void *buf, size_t bufsize) { - int fd; - - if((fd = open("/dev/urandom", O_RDONLY)) < 0) return -1; - size_t nb = read(fd, buf, bufsize); - close(fd); - if (nb != bufsize) return -1; - return 0; -} - static void usage(char *arg) { fprintf(stderr, "Usage: %s <name> [address]\n", arg); exit(1); } int main(int argc, char *argv[]) { - int rv; - ECPContext ctx; ECPDHKey key; ECPNode node; + int rv; if ((argc < 2) || (argc > 3)) usage(argv[0]); @@ -41,20 +30,16 @@ int main(int argc, char *argv[]) { strcat(fn_key, ".priv"); strcat(fn_node, ".pub"); - rv = ecp_ctx_init(&ctx); - if (rv) goto err; - ctx.rng = v_rng; - - rv = ecp_dhkey_gen(&ctx, &key); + rv = ecp_dhkey_gen(&key); if (rv) goto err; rv = ecp_node_init(&node, &key.public, (argc == 3) ? argv[2] : NULL); if (rv) goto err; - rv = ecp_util_key_save(&ctx, &key, fn_key); + rv = ecp_util_key_save(&key, fn_key); if (rv) goto err; - rv = ecp_util_node_save(&ctx, &node, fn_node); + rv = ecp_util_node_save(&node, fn_node); if (rv) goto err; return 0; diff --git a/ecp/util/util.c b/ecp/util/util.c index 7ce8da5..ee51c73 100644 --- a/ecp/util/util.c +++ b/ecp/util/util.c @@ -7,13 +7,15 @@ #include "cr.h" #include "util.h" -int ecp_util_key_save(ECPContext *ctx, ECPDHKey *key, char *filename) { +int ecp_util_key_save(ECPDHKey *key, char *filename) { int fd; ssize_t rv; + if (!key->valid) return ECP_ERR; + if ((fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) return ECP_ERR; - rv = write(fd, ecp_cr_dh_pub_get_buf(&key->public), ECP_ECDH_SIZE_KEY); - if (rv != ECP_ECDH_SIZE_KEY) { + rv = write(fd, &key->public, sizeof(key->public)); + if (rv != sizeof(key->public)) { close(fd); return ECP_ERR; } @@ -26,14 +28,13 @@ int ecp_util_key_save(ECPContext *ctx, ECPDHKey *key, char *filename) { return ECP_OK; } -int ecp_util_key_load(ECPContext *ctx, ECPDHKey *key, char *filename) { +int ecp_util_key_load(ECPDHKey *key, char *filename) { int fd; ssize_t rv; - unsigned char buf[ECP_ECDH_SIZE_KEY]; if ((fd = open(filename, O_RDONLY)) < 0) return ECP_ERR; - rv = read(fd, buf, ECP_ECDH_SIZE_KEY); - if (rv != ECP_ECDH_SIZE_KEY) { + rv = read(fd, &key->public, sizeof(key->public)); + if (rv != sizeof(key->public)) { close(fd); return ECP_ERR; } @@ -44,19 +45,19 @@ int ecp_util_key_load(ECPContext *ctx, ECPDHKey *key, char *filename) { } close(fd); - ecp_cr_dh_pub_from_buf(&key->public, buf); - key->valid = 1; return ECP_OK; } -int ecp_util_node_save(ECPContext *ctx, ECPNode *node, char *filename) { +int ecp_util_node_save(ECPNode *node, char *filename) { int fd; ssize_t rv; + if (!node->key_perma.valid) return ECP_ERR; + if ((fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) return ECP_ERR; - rv = write(fd, ecp_cr_dh_pub_get_buf(&node->public), ECP_ECDH_SIZE_KEY); - if (rv != ECP_ECDH_SIZE_KEY) { + rv = write(fd, &node->key_perma.public, sizeof(node->key_perma.public)); + if (rv != sizeof(node->key_perma.public)) { close(fd); return ECP_ERR; } @@ -69,14 +70,13 @@ int ecp_util_node_save(ECPContext *ctx, ECPNode *node, char *filename) { return ECP_OK; } -int ecp_util_node_load(ECPContext *ctx, ECPNode *node, char *filename) { +int ecp_util_node_load(ECPNode *node, char *filename) { int fd; ssize_t rv; - unsigned char buf[ECP_ECDH_SIZE_KEY]; if ((fd = open(filename, O_RDONLY)) < 0) return ECP_ERR; - rv = read(fd, buf, ECP_ECDH_SIZE_KEY); - if (rv != ECP_ECDH_SIZE_KEY) { + rv = read(fd, &node->key_perma.public, sizeof(node->key_perma.public)); + if (rv != sizeof(node->key_perma.public)) { close(fd); return ECP_ERR; } @@ -87,7 +87,6 @@ int ecp_util_node_load(ECPContext *ctx, ECPNode *node, char *filename) { } close(fd); - ecp_cr_dh_pub_from_buf(&node->public, buf); - + node->key_perma.valid = 1; return ECP_OK; }
\ No newline at end of file diff --git a/ecp/util/util.h b/ecp/util/util.h index 3d07588..631a808 100644 --- a/ecp/util/util.h +++ b/ecp/util/util.h @@ -1,5 +1,5 @@ -int ecp_util_key_save(ECPContext *ctx, ECPDHKey *key, char *filename); -int ecp_util_key_load(ECPContext *ctx, ECPDHKey *key, char *filename); +int ecp_util_key_save(ECPDHKey *key, char *filename); +int ecp_util_key_load(ECPDHKey *key, char *filename); -int ecp_util_node_save(ECPContext *ctx, ECPNode *node, char *filename); -int ecp_util_node_load(ECPContext *ctx, ECPNode *node, char *filename);
\ No newline at end of file +int ecp_util_node_save(ECPNode *node, char *filename); +int ecp_util_node_load(ECPNode *node, char *filename);
\ No newline at end of file |