diff options
Diffstat (limited to 'ecp/src/ecp/core.c')
-rw-r--r-- | ecp/src/ecp/core.c | 2727 |
1 files changed, 1546 insertions, 1181 deletions
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 |