diff options
author | Uros Majstorovic <majstor@majstor.org> | 2020-08-05 03:38:22 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2020-08-05 03:38:22 +0200 |
commit | 5cd610a07468137066ea4daa5176c3e7045113b0 (patch) | |
tree | a6a5b572572f8f37ec2cb87332fa46e9bcc53aa7 /code/ecp/core.c | |
parent | 2473a7d5c51806ab8651cd3c4e07a15b62084eb5 (diff) |
ecp moved to root; fixed utils and tests
Diffstat (limited to 'code/ecp/core.c')
-rw-r--r-- | code/ecp/core.c | 1809 |
1 files changed, 0 insertions, 1809 deletions
diff --git a/code/ecp/core.c b/code/ecp/core.c deleted file mode 100644 index ae5eca1..0000000 --- a/code/ecp/core.c +++ /dev/null @@ -1,1809 +0,0 @@ -#include "core.h" - -#include "cr.h" -#include "tr.h" -#include "tm.h" - -#ifdef ECP_WITH_HTABLE -#include "ht.h" -#endif - -int ecp_dhkey_generate(ECPContext *ctx, ECPDHKey *key) { - int rv; - - if (ctx->rng == NULL) return ECP_ERR_RNG; - - rv = ecp_cr_dh_mkpair(&key->public, &key->private, ctx->rng); - if (rv) return rv; - - key->valid = 1; - return ECP_OK; -} - -int ecp_node_init(ECPNode *node, ecp_dh_public_t *public, void *addr) { - int rv = ECP_OK; - - memset(node, 0, sizeof(ECPNode)); - - if (public) memcpy(&node->public, public, sizeof(node->public)); - - if (addr) rv = ecp_tr_addr_set(&node->addr, addr); - if (rv) return ECP_ERR_NET_ADDR; - - return ECP_OK; -} - -int ecp_ctx_create(ECPContext *ctx) { - int rv; - - if (ctx == NULL) return ECP_ERR; - - memset(ctx, 0, sizeof(ECPContext)); - - rv = ecp_tr_init(ctx); - if (rv) return rv; - rv = ecp_tm_init(ctx); - if (rv) return rv; - - return ECP_OK; -} - -int ecp_ctx_destroy(ECPContext *ctx) { - return ECP_OK; -} - -static int ctable_create(ECPSockCTable *conn, ECPContext *ctx) { - int rv = ECP_OK; - - memset(conn, 0, sizeof(ECPSockCTable)); - -#ifdef ECP_WITH_HTABLE - conn->htable = ecp_ht_create(ctx); - if (conn->htable == NULL) return ECP_ERR_ALLOC; -#endif - -#ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&conn->mutex, NULL); - if (rv) { -#ifdef ECP_WITH_HTABLE - ecp_ht_destroy(conn->htable); -#endif - return ECP_ERR; - } -#endif - - return ECP_OK; -} - -static void ctable_destroy(ECPSockCTable *conn, ECPContext *ctx) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_destroy(&conn->mutex); -#endif -#ifdef ECP_WITH_HTABLE - ecp_ht_destroy(conn->htable); -#endif -} - -static int ctable_insert(ECPConnection *conn) { - int with_htable = 0; - ECPSocket *sock = conn->sock; - -#ifdef ECP_WITH_HTABLE - with_htable = 1; -#endif - - if (with_htable) { -#ifdef ECP_WITH_HTABLE - int i, rv = ECP_OK; - if (conn->out) { - 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 (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)); - 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 (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)); - return rv; - } - } - } -#endif - } else { -#ifndef ECP_WITH_HTABLE - if (sock->conn.size == ECP_MAX_SOCK_CONN) return ECP_ERR_MAX_SOCK_CONN; - sock->conn.array[sock->conn.size] = conn; - sock->conn.size++; -#endif - } - - return ECP_OK; -} - -static void ctable_remove(ECPConnection *conn) { - int i, with_htable = 0; - ECPSocket *sock = conn->sock; - -#ifdef ECP_WITH_HTABLE - with_htable = 1; -#endif - - if (with_htable) { -#ifdef ECP_WITH_HTABLE - if (conn->out) { - 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)); - } 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)); - } -#endif - } else { -#ifndef ECP_WITH_HTABLE - 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--; - return; - } - } -#endif - } -} - -static ECPConnection *ctable_search(ECPSocket *sock, unsigned char c_idx, unsigned char *c_public, ECPNetAddr *addr) { - int i, with_htable = 0; - ECPConnection *conn = NULL; - -#ifdef ECP_WITH_HTABLE - with_htable = 1; -#endif - - if (with_htable) { -#ifdef ECP_WITH_HTABLE - return ecp_ht_search(sock->conn.htable, c_public); -#endif - } else { -#ifndef ECP_WITH_HTABLE - if (c_public) { - for (i=0; i<sock->conn.size; i++) { - conn = sock->conn.array[i]; - if (conn->out) { - 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; - } - } - } 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 (conn->out && ecp_tr_addr_eq(&conn->node.addr, addr)) return conn; - } - } -#endif - } - - return NULL; -} - -int ecp_sock_create(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key) { - int rv = ECP_OK; - - 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->conn_new = ecp_conn_handle_new; - - rv = ecp_dhkey_generate(sock->ctx, &sock->key[sock->key_curr]); - if (!rv) rv = ctable_create(&sock->conn, sock->ctx); - - if (rv) return rv; - - rv = ecp_timer_create(&sock->timer); - if (rv) { - ctable_destroy(&sock->conn, sock->ctx); - return rv; - } - -#ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&sock->mutex, NULL); - if (rv) { - ecp_timer_destroy(&sock->timer); - ctable_destroy(&sock->conn, sock->ctx); - return ECP_ERR; - } -#endif - - return ECP_OK; -} - -void ecp_sock_destroy(ECPSocket *sock) { - ecp_timer_destroy(&sock->timer); - ctable_destroy(&sock->conn, sock->ctx); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_destroy(&sock->mutex); -#endif -} - -int ecp_sock_open(ECPSocket *sock, void *myaddr) { - return ecp_tr_open(sock, myaddr); -} - -void ecp_sock_close(ECPSocket *sock) { - ecp_tr_close(sock); -} - -int ecp_sock_dhkey_get_curr(ECPSocket *sock, unsigned char *idx, unsigned char *public) { - unsigned char _idx; - -#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); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->mutex); -#endif - - if (_idx == ECP_ECDH_IDX_INV) return ECP_ERR_ECDH_IDX; - - if (idx) *idx = _idx; - return ECP_OK; -} - -int ecp_sock_dhkey_new(ECPSocket *sock) { - ECPDHKey new_key; - int rv = ecp_dhkey_generate(sock->ctx, &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; - sock->key[(sock->key_curr + 1) % ECP_MAX_SOCK_KEY].valid = 0; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->mutex); -#endif - - return ECP_OK; -} - -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; -} - -static int conn_dhkey_new_pair(ECPConnection *conn, ECPDHKey *key) { - /* called when client makes new key pair */ - ECPSocket *sock = conn->sock; - - conn->key_curr = conn->key_curr == ECP_ECDH_IDX_INV ? 0 : (conn->key_curr+1) % ECP_MAX_CONN_KEY; -#ifdef ECP_WITH_HTABLE - if (conn->out && 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)); - } -#endif - - conn->key[conn->key_curr] = *key; - conn->key_idx_map[conn->key_curr] = ECP_ECDH_IDX_INV; - -#ifdef ECP_WITH_HTABLE - if (conn->out && ecp_conn_is_reg(conn)) { - int rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&conn->key[conn->key_curr].public), conn); - if (rv) return rv; - } -#endif - - return ECP_OK; -} - -static void conn_dhkey_del_pair(ECPConnection *conn, unsigned char idx) { - ECPSocket *sock = conn->sock; - -#ifdef ECP_WITH_HTABLE - if (conn->out && 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)); - } -#endif - - memset(&conn->key[idx], 0, sizeof(conn->key[idx])); - conn->key_idx_map[idx] = ECP_ECDH_IDX_INV; -} - -static int conn_dhkey_new_pub_local(ECPConnection *conn, unsigned char idx) { - // Remote obtained our key - unsigned char new = conn->key_idx_curr == ECP_ECDH_IDX_INV ? 0 : (conn->key_idx_curr+1) % ECP_MAX_NODE_KEY; - int i; - - if (idx >= ECP_MAX_SOCK_KEY) return ECP_ERR_ECDH_IDX; - - 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->shared[new][i].valid = 0; - } - return ECP_OK; -} - - -static int conn_dhkey_new_pub_remote(ECPConnection *conn, unsigned char idx, unsigned char *public) { - // We obtained remote 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; - -#ifdef ECP_WITH_HTABLE - if (!conn->out && 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)); - } -#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; - -#ifdef ECP_WITH_HTABLE - if (!conn->out && ecp_conn_is_reg(conn)) { - int rv = ecp_ht_insert(sock->conn.htable, ecp_cr_dh_pub_get_buf(&remote->key[new].public), conn); - if (rv) return rv; - } -#endif - - for (i=0; i<ECP_MAX_NODE_KEY; i++) { - conn->shared[i][new].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 (conn->out) { - public_p = &conn->node.public; - priv = conn_dhkey_get(conn, c_idx); - } else { - ECPDHRKey *pub = NULL; - - 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; - - 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; - } - 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); - } else { - unsigned char l_idx = conn->out ? c_idx : s_idx; - unsigned char r_idx = conn->out ? s_idx : c_idx; - ECPDHShared *shared = NULL; - - if ((l_idx >= ECP_MAX_SOCK_KEY) || (r_idx >= ECP_MAX_SOCK_KEY)) 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; - - shared = &conn->shared[conn->key_idx_map[l_idx]][conn->remote.key_idx_map[r_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); - - 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; - } - - memcpy(shsec, &shared->secret, sizeof(shared->secret)); - } - - 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 = conn->out ? c_idx : s_idx; - unsigned char r_idx = conn->out ? s_idx : c_idx; - ECPDHShared *shared = NULL; - - if ((l_idx >= ECP_MAX_SOCK_KEY) || (r_idx >= ECP_MAX_SOCK_KEY)) 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; - - 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_create(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { - int i, rv = ECP_OK; - - if (conn == NULL) return ECP_ERR; - if (sock == NULL) return ECP_ERR; - - memset(conn, 0, sizeof(ECPConnection)); - - if (ctype >= ECP_MAX_CTYPE) return ECP_ERR_MAX_CTYPE; - - 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->sock = sock; - -#ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&conn->mutex, NULL); - if (rv) return ECP_ERR; -#endif - - return ECP_OK; -} - -void ecp_conn_destroy(ECPConnection *conn) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_destroy(&conn->mutex); -#endif -} - -int ecp_conn_register(ECPConnection *conn) { - ECPSocket *sock = conn->sock; - - conn->flags |= ECP_CONN_FLAG_REG; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); -#endif - int rv = ctable_insert(conn); - if (rv) conn->flags &= ~ECP_CONN_FLAG_REG; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->conn.mutex); -#endif - - return rv; -} - -void ecp_conn_unregister(ECPConnection *conn) { - ECPSocket *sock = conn->sock; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); - pthread_mutex_lock(&conn->mutex); -#endif - if (ecp_conn_is_reg(conn)) { - ctable_remove(conn); - conn->flags &= ~ECP_CONN_FLAG_REG; - } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); -#endif -} - -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)]; - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); - - ecp_pld_set_type(pld_buf, ECP_MTYPE_KGET_REQ); - return ecp_pld_send_ll(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), 0, ti); -} - -int ecp_conn_init(ECPConnection *conn, ECPNode *node) { - ECPDHKey key; - ECPContext *ctx = conn->sock->ctx; - int rv = ECP_OK; - - if (node == NULL) return ECP_ERR; - - conn->out = 1; - conn->node = *node; - rv = ecp_dhkey_generate(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); - if (!rv) rv = ecp_conn_register(conn); - return rv; -} - -int ecp_conn_open(ECPConnection *conn, ECPNode *node) { - int rv = ecp_conn_init(conn, node); - if (rv) return rv; - - ssize_t _rv = ecp_timer_send(conn, _conn_send_kget, ECP_MTYPE_KGET_REP, 3, 500); - if (_rv < 0) { - ecp_conn_unregister(conn); - return _rv; - } - - return ECP_OK; -} - -int ecp_conn_close(ECPConnection *conn, ecp_cts_t timeout) { - ECPSocket *sock = conn->sock; - int refcount = 0; - - ecp_conn_unregister(conn); - ecp_timer_remove(conn); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); - refcount = conn->refcount; - pthread_mutex_unlock(&conn->mutex); - - if (timeout && refcount) { - ecp_tm_sleep_ms(timeout); - pthread_mutex_lock(&conn->mutex); - refcount = conn->refcount; - pthread_mutex_unlock(&conn->mutex); - } - - if (refcount) return ECP_ERR_TIMEOUT; -#endif - - if (conn->out) { - ecp_conn_close_t handler = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->conn_close : NULL; - if (handler) handler(conn); - } else { - ecp_conn_destroy_t handler = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->conn_destroy : NULL; - if (handler) handler(conn); - if (conn->parent) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->parent->mutex); -#endif - conn->parent->refcount--; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->parent->mutex); -#endif - } - ecp_conn_destroy(conn); - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - } - - return ECP_OK; -} - -int ecp_conn_reset(ECPConnection *conn) { - ECPDHKey key; - ECPSocket *sock = conn->sock; - ECPContext *ctx = sock->ctx; - int rv = ECP_OK; - int i; - - rv = ecp_dhkey_generate(ctx, &key); - if (rv) return rv; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); - pthread_mutex_lock(&conn->mutex); -#endif - - for (i=0; i<ECP_MAX_CONN_KEY; i++) { - conn_dhkey_del_pair(conn, i); - } - conn->key_curr = 0; - rv = conn_dhkey_new_pair(conn, &key); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&sock->conn.mutex); -#endif - - 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)); - conn->flags &= ~ECP_CONN_FLAG_OPEN; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - return rv; -} - -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_RBUF - handler->msg[ECP_MTYPE_RBACK] = ecp_rbuf_handle_ack; - handler->msg[ECP_MTYPE_RBFLUSH] = ecp_rbuf_handle_flush; - handler->msg[ECP_MTYPE_RBFLUSH_PTS] = ecp_rbuf_handle_flush_pts; -#endif - handler->conn_open = ecp_conn_send_open; - return ECP_OK; -} - -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_pld_get_buf(pld_buf, ECP_MTYPE_OPEN_REQ); - - 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); - - ecp_pld_set_type(pld_buf, ECP_MTYPE_OPEN_REQ); - buf[0] = conn->type; - - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(1, ECP_MTYPE_OPEN_REQ), 0, ti); -} - -ssize_t ecp_conn_send_open(ECPConnection *conn) { - return ecp_timer_send(conn, _conn_send_open, ECP_MTYPE_OPEN_REP, 3, 500); -} - -int ecp_conn_handle_new(ECPSocket *sock, ECPConnection *parent, unsigned char *payload, size_t payload_size, ECPConnection **_conn) { - ECPConnection *conn = NULL; - int rv = ECP_OK; - unsigned char ctype = 0; - ecp_conn_create_t handle_create = NULL; - ecp_conn_destroy_t handle_destroy = NULL; - - if (payload_size < 1) return ECP_ERR; - - ctype = payload[0]; - - conn = sock->ctx->conn_alloc ? sock->ctx->conn_alloc(ctype) : NULL; - if (conn == NULL) return ECP_ERR_ALLOC; - - rv = ecp_conn_create(conn, sock, ctype); - if (!rv) rv = sock->ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); - if (rv) { - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } - - conn->refcount = 1; - conn->parent = parent; - conn->pcount = parent ? parent->pcount+1 : 0; - handle_create = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->conn_create : NULL; - handle_destroy = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->conn_destroy : NULL; - - if (handle_create) rv = handle_create(conn, payload+1, payload_size-1); - if (rv) { - ecp_conn_destroy(conn); - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } - - rv = ecp_conn_register(conn); - if (rv) { - if (handle_destroy) handle_destroy(conn); - ecp_conn_destroy(conn); - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } - - if (parent) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&parent->mutex); -#endif - parent->refcount++; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&parent->mutex); -#endif - } - - *_conn = conn; - return rv; -} - -ssize_t ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - int is_open = ecp_conn_is_open(conn); - if (!is_open && (size >= 0)) conn->flags |= ECP_CONN_FLAG_OPEN; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - if (mtype & ECP_MTYPE_FLAG_REP) { - if (!conn->out) return ECP_ERR; - - if (is_open && size == ECP_ERR_TIMEOUT) { - int rv = ecp_conn_reset(conn); - if (rv) return rv; - - return 0; - } - - if (size < 0) return size; - return 0; - } else { - if (conn->out) return ECP_ERR; - if (size < 0) return size; - if (size < 1) return ECP_ERR; - - 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 = 0; - - 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); - - ctype = msg[0]; - ecp_pld_set_type(pld_buf, ECP_MTYPE_OPEN_REP); - ssize_t _rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_OPEN_REP), 0); - - return 1; - } - return ECP_ERR; -} - -ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (mtype & ECP_MTYPE_FLAG_REP) { - ECPContext *ctx = conn->sock->ctx; - - if (!conn->out) return ECP_ERR; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - int is_open = ecp_conn_is_open(conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - if ((size < 0) && !is_open) { - ecp_conn_handler_msg_t handler = ctx->handler[conn->type] ? ctx->handler[conn->type]->msg[ECP_MTYPE_OPEN] : NULL; - return handler ? handler(conn, seq, mtype, msg, size, b) : size; - } - - if (size < 0) return size; - if (size < ECP_ECDH_SIZE_KEY+1) return ECP_ERR; - - int rv = ecp_conn_dhkey_new_pub(conn, msg[0], msg+1); - if (!rv && !is_open) { - ecp_conn_open_t conn_open = ctx->handler[conn->type] ? ctx->handler[conn->type]->conn_open : NULL; - if (conn_open) { - ssize_t _rv = conn_open(conn); - if (_rv < 0) rv = _rv; - } - } - if (rv) return rv; - - return ECP_ECDH_SIZE_KEY+1; - } else { - if (conn->out) return ECP_ERR; - if (size < 0) return size; - - 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 = ecp_pld_get_buf(pld_buf, 0); - - 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_pld_set_type(pld_buf, ECP_MTYPE_KGET_REP); - int rv = ecp_conn_dhkey_get_curr(conn, buf, buf+1); - if (rv) return rv; - ssize_t _rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP), 0); - - return 0; - } - return ECP_ERR; -} - -ssize_t ecp_conn_handle_kput(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (size < 0) return size; - - if (mtype & ECP_MTYPE_FLAG_REP) { - if (!conn->out) return ECP_ERR; - return 0; - } else { - if (conn->out) return ECP_ERR; - if (size < ECP_ECDH_SIZE_KEY+1) return ECP_ERR; - - 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)]; - - 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); - - int rv = ecp_conn_dhkey_new_pub(conn, msg[0], msg+1); - if (rv) return rv; - - ecp_pld_set_type(pld_buf, ECP_MTYPE_KPUT_REP); - ssize_t _rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KPUT_REP), 0); - - return ECP_ECDH_SIZE_KEY+1; - } - return ECP_ERR; -} - -/* Memory limited version: */ -ssize_t ecp_conn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (size < 0) return size; - if (b == NULL) return ECP_ERR; - if (b->packet->buffer == NULL) return ECP_ERR; - - memcpy(b->packet->buffer, msg, size); - return ecp_pkt_handle(conn->sock, NULL, conn, b, size); -} - -/* Non memory limited version: */ -/* -ssize_t ecp_conn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (size < 0) return size; - if (b == NULL) return ECP_ERR; - - ECP2Buffer b2; - ECPBuffer packet; - ECPBuffer payload; - unsigned char pld_buf[ECP_MAX_PLD]; - - b2.packet = &packet; - b2.payload = &payload; - - packet.buffer = msg; - packet.size = b->payload->size - (msg - b->payload->buffer); - payload.buffer = pld_buf; - payload.size = ECP_MAX_PLD; - - return ecp_pkt_handle(conn->sock, NULL, conn, &b2, size); -} -*/ - -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 = ecp_pld_get_buf(pld_buf, ECP_MTYPE_KPUT_REQ); - int rv = ECP_OK; - - 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); - - ecp_pld_set_type(pld_buf, ECP_MTYPE_KPUT_REQ); - rv = ecp_conn_dhkey_get_curr(conn, buf, buf+1); - if (rv) return rv; - - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ), 0, ti); -} - -int ecp_conn_dhkey_new(ECPConnection *conn) { - ECPSocket *sock = conn->sock; - ECPDHKey new_key; - int rv; - ssize_t _rv; - - rv = ecp_dhkey_generate(sock->ctx, &new_key); - if (rv) return rv; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); - pthread_mutex_lock(&conn->mutex); -#endif - rv = conn_dhkey_new_pair(conn, &new_key); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); -#endif - - if (rv) return rv; - - _rv = ecp_timer_send(conn, _conn_send_kput, ECP_MTYPE_KPUT_REP, 3, 500); - if (_rv < 0) return _rv; - - return ECP_OK; -} - -int ecp_conn_dhkey_new_pub(ECPConnection *conn, unsigned char idx, unsigned char *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); - pthread_mutex_lock(&conn->mutex); -#endif - rv = conn_dhkey_new_pub_remote(conn, idx, public); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.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; - -#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); - -#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); - - if (idx) *idx = _idx; - return ECP_OK; -} - -ssize_t ecp_pkt_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t pld_size) { - ssize_t rv; - - if (pkt_size < ECP_SIZE_PKT_HDR) return ECP_ERR; - - // ECP_SIZE_PROTO - packet[0] = 0; - packet[1] = 0; - s_idx = s_idx & 0x0F; - c_idx = c_idx & 0x0F; - packet[ECP_SIZE_PROTO] = (s_idx << 4) | c_idx; - ecp_cr_dh_pub_to_buf(packet+ECP_SIZE_PROTO+1, public); - memcpy(packet+ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY, nonce, ECP_AEAD_SIZE_NONCE); - - payload[0] = (seq & 0xFF000000) >> 24; - payload[1] = (seq & 0x00FF0000) >> 16; - payload[2] = (seq & 0x0000FF00) >> 8; - payload[3] = (seq & 0x000000FF); - rv = ecp_cr_aead_enc(packet+ECP_SIZE_PKT_HDR, pkt_size-ECP_SIZE_PKT_HDR, payload, pld_size, shsec, nonce); - if (rv < 0) return ECP_ERR_ENCRYPT; - - memcpy(nonce, packet+ECP_SIZE_PKT_HDR, ECP_AEAD_SIZE_NONCE); - - return rv+ECP_SIZE_PKT_HDR; -} - -ssize_t ecp_pkt_pack_raw(ECPSocket *sock, ECPConnection *parent, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t pld_size, ECPNetAddr *addr) { - ECPContext *ctx = sock->ctx; - - return ecp_pkt_pack(ctx, packet, pkt_size, s_idx, c_idx, public, shsec, nonce, seq, payload, pld_size); -} - -ssize_t ecp_conn_pack(ECPConnection *conn, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { - ecp_aead_key_t shsec; - ecp_dh_public_t public; - ecp_seq_t _seq; - unsigned char nonce[ECP_AEAD_SIZE_NONCE]; - int rv = ECP_OK; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - if (s_idx == ECP_ECDH_IDX_INV) { - if (conn->out) { - 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 (conn->out) { - 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; - } - } - rv = conn_shsec_get(conn, s_idx, c_idx, &shsec); - if (!rv) memcpy(nonce, conn->nonce, sizeof(nonce)); - if (!rv) { - if (conn->out) { - ECPDHKey *key = conn_dhkey_get(conn, c_idx); - - if ((key == NULL) || !key->valid) rv = ECP_ERR_ECDH_IDX; - if (!rv) memcpy(&public, &key->public, sizeof(public)); - } else { - memcpy(&public, &conn->remote.key[conn->remote.key_curr].public, sizeof(public)); - } - } - if (!rv) { - if (si) { - if (si->seq_w) { - _seq = si->seq; - } else { - _seq = conn->seq_out + 1; - si->seq = _seq; - } - -#ifdef ECP_WITH_RBUF - if (conn->rbuf.send) rv = ecp_rbuf_pkt_prep(conn->rbuf.send, si, ecp_pld_get_type(payload)); -#endif - - if (!rv && !si->seq_w) conn->seq_out = _seq; - } else { - _seq = conn->seq_out + 1; - conn->seq_out = _seq; - } - if (!rv && addr) *addr = conn->node.addr; - } - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - if (rv) return rv; - - ssize_t _rv = ecp_pkt_pack(conn->sock->ctx, packet, pkt_size, s_idx, c_idx, &public, &shsec, nonce, _seq, payload, pld_size); - if (_rv < 0) return _rv; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - memcpy(conn->nonce, nonce, sizeof(conn->nonce)); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - return _rv; -} - -#ifndef ECP_WITH_VCONN -ssize_t ecp_pack(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { - if ((packet == NULL) || (packet->buffer == NULL)) return ECP_ERR; - if ((payload == NULL) || (payload->buffer == NULL)) return ECP_ERR; - - return ecp_conn_pack(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, si, addr); -} - -ssize_t ecp_pack_raw(ECPSocket *sock, ECPConnection *parent, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, 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; - - return ecp_pkt_pack_raw(sock, parent, packet->buffer, packet->size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size, addr); -} -#endif - -ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size, ECPConnection **_conn, ecp_seq_t *_seq) { - 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; - ecp_aead_key_t shsec; - ecp_dh_public_t public; - ecp_dh_private_t private; - ECPConnection *conn = NULL; - ECPDHKey *key = NULL; - int rv = ECP_OK; - unsigned char is_open = 0; - unsigned char is_new = 0; - unsigned char seq_check = 1; - unsigned char seq_reset = 0; - ecp_seq_t seq_c, seq_p, seq_n; - ecp_ack_t seq_map; - ssize_t dec_size; - - *_conn = NULL; - *_seq = 0; - - s_idx = (packet[ECP_SIZE_PROTO] & 0xF0) >> 4; - c_idx = (packet[ECP_SIZE_PROTO] & 0x0F); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&sock->conn.mutex); -#endif - - conn = ctable_search(sock, c_idx, packet+ECP_SIZE_PROTO+1, NULL); - if (conn && !conn->out && (s_idx == ECP_ECDH_IDX_PERMA)) conn = NULL; - -#ifdef ECP_WITH_PTHREAD - if (conn) pthread_mutex_lock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.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 = conn->out ? 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_open = ecp_conn_is_open(conn); - if (is_open) { - seq_c = conn->seq_in; - seq_map = conn->seq_in_map; - } - } - -#ifdef ECP_WITH_PTHREAD - if (conn) pthread_mutex_unlock(&conn->mutex); -#endif - - if (rv) return rv; - - if (key) { - ecp_cr_dh_pub_from_buf(&public, packet+ECP_SIZE_PROTO+1); - ecp_cr_dh_shsec(&shsec, &public, &private); - memset(&private, 0, sizeof(private)); - } - - dec_size = ecp_cr_aead_dec(payload, bufs->payload->size, packet+ECP_SIZE_PKT_HDR, pkt_size-ECP_SIZE_PKT_HDR, &shsec, packet+ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY); - if (dec_size < ECP_SIZE_PLD_HDR+1) rv = ECP_ERR_DECRYPT; - if (rv) goto ecp_unpack_err; - - seq_p = \ - (payload[0] << 24) | \ - (payload[1] << 16) | \ - (payload[2] << 8) | \ - (payload[3]); - - if ((payload[ECP_SIZE_PLD_HDR] & ECP_MTYPE_MASK) < ECP_MAX_MTYPE_SYS) ecp_tr_release(bufs->packet, 1); - if (conn == NULL) { - if (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_OPEN_REQ) { - is_new = 1; - rv = sock->conn_new(sock, parent, payload+ECP_SIZE_PLD_HDR+1, dec_size-ECP_SIZE_PLD_HDR-1, &conn); - if (rv) return rv; - } else if (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_KGET_REQ) { - ECPBuffer _packet; - ECPBuffer _payload; - unsigned char pkt_buf[ECP_SIZE_PKT_RAW_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent)]; - unsigned char pld_buf[ECP_SIZE_PLD_RAW_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent)]; - - unsigned char *buf = ecp_pld_get_buf(pld_buf, ECP_MTYPE_KGET_REP); - ecp_pld_set_type(pld_buf, ECP_MTYPE_KGET_REP); - - _packet.buffer = pkt_buf; - _packet.size = ECP_SIZE_PKT_RAW_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); - _payload.buffer = pld_buf; - _payload.size = ECP_SIZE_PLD_RAW_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); - - rv = ecp_sock_dhkey_get_curr(sock, buf, buf+1); - if (!rv) { - ssize_t _rv = ecp_pld_send_raw(sock, parent, addr, &_packet, s_idx, c_idx, &public, &shsec, packet+ECP_SIZE_PKT_HDR, seq_p, &_payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP), 0); - if (_rv < 0) rv = _rv; - } - if (rv) return rv; - } else { - return ECP_ERR_CONN_NOT_FOUND; - } - } - - if (conn == NULL) return dec_size; - - if (is_open) { -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv || (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_RBACK) || (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_RBFLUSH)) seq_check = 0; -#endif - - if (seq_check) { - if (ECP_SEQ_LTE(seq_p, seq_c)) { - ecp_seq_t seq_offset = seq_c - seq_p; - 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_n = seq_c; - } else { - rv = ECP_ERR_SEQ; - } - } else { - ecp_seq_t seq_offset = seq_p - seq_c; - 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_n = seq_p; - } else { - rv = ECP_ERR_SEQ; - } - } - - if ((rv == ECP_ERR_SEQ) && (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_OPEN_REQ) && key) { - rv = ECP_OK; - seq_reset = 1; - } - if (rv) goto ecp_unpack_err; - } - } - - if (!is_open || seq_reset) { - seq_n = seq_p; - seq_map = 1; - -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv) { - rv = ecp_rbuf_recv_start(conn, seq_p); - if (rv) goto ecp_unpack_err; - } -#endif - } - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - memcpy(conn->nonce, packet+ECP_SIZE_PKT_HDR, sizeof(conn->nonce)); - if (addr) conn->node.addr = *addr; - if (seq_check) { - conn->seq_in = seq_n; - conn->seq_in_map = seq_map; - } - if (key) { - if (is_new) rv = conn_dhkey_new_pub_remote(conn, c_idx, packet+ECP_SIZE_PROTO+1); - if (!rv) rv = conn_dhkey_new_pub_local(conn, l_idx); - if (!rv) rv = conn_shsec_set(conn, s_idx, c_idx, &shsec); - } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - if (rv) goto ecp_unpack_err; - - *_conn = conn; - *_seq = seq_p; - return dec_size; - -ecp_unpack_err: - if (conn == NULL) return rv; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - conn->refcount--; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - return rv; -} - -ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP2Buffer *bufs, size_t pkt_size) { - ECPConnection *conn; - ecp_seq_t seq; - ssize_t rv = 0; - ssize_t pld_size = ecp_unpack(sock, addr, parent, bufs, pkt_size, &conn, &seq); - - if (pld_size < 0) return pld_size; - if (conn) { - rv = 0; -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv) rv = ecp_rbuf_recv_store(conn, seq, bufs->payload->buffer+ECP_SIZE_PLD_HDR, pld_size-ECP_SIZE_PLD_HDR, bufs); -#endif - if (rv == 0) rv = ecp_msg_handle(conn, seq, bufs->payload->buffer+ECP_SIZE_PLD_HDR, pld_size-ECP_SIZE_PLD_HDR, bufs); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - conn->refcount--; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - } else { - rv = pld_size-ECP_SIZE_PLD_HDR; - } - - if (rv < 0) return rv; - return ECP_SIZE_PKT_HDR+ECP_AEAD_SIZE_TAG+ECP_SIZE_PLD_HDR+rv; -} - -ssize_t ecp_pkt_send(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t pkt_size, unsigned char flags) { - ssize_t rv = ecp_tr_send(sock, packet, pkt_size, addr, flags); - if (rv < 0) return rv; - if (rv < ECP_MIN_PKT) return ECP_ERR_SEND; - - return rv; -} - -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; -} - -unsigned char ecp_msg_get_type(unsigned char *msg) { - return msg[0]; -} - -unsigned char *ecp_msg_get_content(unsigned char *msg, size_t msg_size) { - size_t offset = 1 + ECP_SIZE_MT_FLAG(msg[0]); - - if (msg_size < offset) return NULL; - return msg + offset; -} - -int ecp_msg_get_frag(unsigned char *msg, size_t msg_size, unsigned char *frag_cnt, unsigned char *frag_tot) { - if (!(msg[0] & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; - if (msg_size < 3) return ECP_ERR; - - *frag_cnt = msg[1]; - *frag_tot = msg[2]; - - return ECP_OK; -} - -int ecp_msg_get_pts(unsigned char *msg, size_t msg_size, ecp_pts_t *pts) { - unsigned char mtype = msg[0]; - size_t offset = 1 + ECP_SIZE_MT_FRAG(mtype); - - if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; - 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; -} - -int ecp_msg_defrag(ECPFragIter *iter, ecp_seq_t seq, unsigned char *msg_in, size_t msg_in_size, unsigned char **msg_out, size_t *msg_out_size) { - unsigned char frag_cnt, frag_tot; - int rv = ecp_msg_get_frag(msg_in, msg_in_size, &frag_cnt, &frag_tot); - if (rv == ECP_OK) { - unsigned char mtype = ecp_msg_get_type(msg_in) & (~ECP_MTYPE_FLAG_FRAG); - unsigned char *content = NULL; - size_t content_size = 0; - size_t buf_offset = 0; - - content = ecp_msg_get_content(msg_in, msg_in_size); - if (content == NULL) return ECP_ERR_MIN_MSG; - - content_size = msg_in_size - (content - msg_in); - if (frag_cnt == 0) { - iter->seq = seq; - iter->frag_cnt = 0; - iter->frag_size = content_size; - iter->buffer[0] = mtype; - if (ECP_SIZE_MT_FLAG(mtype)) { - memcpy(iter->buffer + 1, msg_in, ECP_SIZE_MT_FLAG(mtype)); - } - } else { - if (iter->seq + frag_cnt != seq) { - iter->seq = seq - frag_cnt; - iter->frag_cnt = 0; - return ECP_ERR_ITER; - } - if (iter->frag_cnt != frag_cnt) return ECP_ERR_ITER; - } - if ((1 + ECP_SIZE_MT_FLAG(mtype) + iter->frag_size * frag_tot) > iter->buf_size) return ECP_ERR_SIZE; - - buf_offset = 1 + ECP_SIZE_MT_FLAG(mtype) + iter->frag_size * frag_cnt; - memcpy(iter->buffer + buf_offset, content, content_size); - iter->frag_cnt++; - - if (iter->frag_cnt == frag_tot) { - *msg_out = iter->buffer; - *msg_out_size = buf_offset + content_size; - return ECP_OK; - } else { - return ECP_ITER_NEXT; - } - } else { - iter->seq = seq; - *msg_out = msg_in; - *msg_out_size = msg_in_size; - return ECP_OK; - } -} - -ssize_t ecp_msg_handle(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { - ecp_conn_handler_msg_t handler = NULL; - ssize_t rv = 0; - unsigned char mtype = 0; - unsigned char *content = NULL; - size_t rem_size = msg_size; - - while (rem_size) { - mtype = ecp_msg_get_type(msg); - if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; - - ecp_timer_pop(conn, mtype); - -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv && conn->rbuf.recv->frag_iter) { - int _rv = ecp_msg_defrag(conn->rbuf.recv->frag_iter, seq, msg, msg_size, &msg, &rem_size); - if (_rv < 0) return _rv; - if (_rv == ECP_ITER_NEXT) return msg_size; - } -#endif - - content = ecp_msg_get_content(msg, rem_size); - if (content == NULL) return ECP_ERR_MIN_MSG; - rem_size -= content - msg; - - handler = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->msg[mtype & ECP_MTYPE_MASK] : NULL; - if (handler) { - rv = handler(conn, seq, mtype, content, rem_size, bufs); - if (rv < 0) return rv; - if (rv > rem_size) return ECP_ERR; - - rem_size -= rv; - msg = content + rv; - } else { - return msg_size - rem_size - 1; - } - } - - return msg_size; -} - -void ecp_pld_set_type(unsigned char *payload, unsigned char mtype) { - payload[ECP_SIZE_PLD_HDR] = mtype; -} - -int ecp_pld_set_frag(unsigned char *payload, unsigned char mtype, unsigned char frag_cnt, unsigned char frag_tot) { - size_t offset = ECP_SIZE_PLD_HDR + 1; - - if (!(mtype & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; - payload[offset] = frag_cnt; - payload[offset + 1] = frag_tot; - return ECP_OK; -} - -int ecp_pld_set_pts(unsigned char *payload, unsigned char mtype, ecp_pts_t pts) { - size_t offset = ECP_SIZE_PLD_HDR + 1 + ECP_SIZE_MT_FRAG(mtype); - - if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; - - payload[offset] = (pts & 0xFF000000) >> 24; - payload[offset + 1] = (pts & 0x00FF0000) >> 16; - payload[offset + 2] = (pts & 0x0000FF00) >> 8; - payload[offset + 3] = (pts & 0x000000FF); - - return ECP_OK; -} - -unsigned char ecp_pld_get_type(unsigned char *payload) { - return payload[ECP_SIZE_PLD_HDR]; -} - -unsigned char *ecp_pld_get_buf(unsigned char *payload, unsigned char mtype) { - return payload + ECP_SIZE_PLD_HDR + 1 + ECP_SIZE_MT_FLAG(mtype); -} - -static ssize_t 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 = ecp_pack(conn, packet, s_idx, c_idx, payload, pld_size, si, &addr); - if (rv < 0) return rv; - -#ifdef ECP_WITH_RBUF - if (conn->rbuf.send) return ecp_rbuf_pkt_send(conn->rbuf.send, conn->sock, &addr, packet, rv, flags, ti, si); -#endif - - if (ti) { - int _rv = ecp_timer_push(ti); - if (_rv) return _rv; - } - return ecp_pkt_send(sock, &addr, packet, rv, flags); -} - -ssize_t ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, ECPBuffer *payload, size_t pld_size, unsigned char flags) { - return ecp_pld_send_ll(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, 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_ll(conn, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, pld_size, flags, ti); -} - -ssize_t ecp_pld_send_ll(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { - ECPSeqItem *_seq_item = NULL; - -#ifdef ECP_WITH_RBUF - ECPSeqItem seq_item; - - if (conn->rbuf.send) { - int _rv = ecp_seq_item_init(&seq_item); - if (_rv) return _rv; - _seq_item = &seq_item; - } -#endif - - return pld_send(conn, packet, s_idx, c_idx, payload, pld_size, flags, ti, _seq_item); -} - -ssize_t ecp_pld_send_raw(ECPSocket *sock, ECPConnection *parent, ECPNetAddr *addr, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, ECPBuffer *payload, size_t pld_size, unsigned char flags) { - ECPNetAddr _addr; - ssize_t rv; - - rv = ecp_pack_raw(sock, parent, packet, s_idx, c_idx, public, shsec, nonce, seq, payload, pld_size, &_addr); - if (rv < 0) return rv; - - return ecp_pkt_send(sock, parent ? &_addr : addr, packet, rv, flags); -} - -ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *content, size_t content_size) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_MAX_PKT]; - unsigned char pld_buf[ECP_MAX_PLD]; - ssize_t rv = 0; - int pkt_cnt = 0; - int vc_cnt = conn->pcount + 1; - size_t size_max = ECP_MAX_PKT - (ECP_SIZE_PKT_HDR + ECP_AEAD_SIZE_TAG + ECP_SIZE_SEQ + 1) * vc_cnt; - - packet.buffer = pkt_buf; - packet.size = ECP_MAX_PKT; - payload.buffer = pld_buf; - payload.size = ECP_MAX_PLD; - - if (content_size + ECP_SIZE_MT_FLAG(mtype) > size_max) { - int i; - int _rv = ECP_OK; - size_t frag_size, frag_size_final; - ecp_seq_t seq_start = 0; - ECPSeqItem seq_item; - - _rv = ecp_seq_item_init(&seq_item); - if (_rv) return _rv; - - mtype |= ECP_MTYPE_FLAG_FRAG; - frag_size = size_max - ECP_SIZE_MT_FLAG(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++) { - if ((i == pkt_cnt - 1) && frag_size_final) frag_size = frag_size_final; - ecp_pld_set_type(pld_buf, mtype); - ecp_pld_set_frag(pld_buf, mtype, i, pkt_cnt); - memcpy(ecp_pld_get_buf(pld_buf, mtype), content, frag_size); - content += frag_size; - - seq_item.seq = seq_start + i; - ssize_t _rv = 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 += _rv; - } - } else { - ecp_pld_set_type(pld_buf, mtype); - memcpy(ecp_pld_get_buf(pld_buf, mtype), content, content_size); - rv = ecp_pld_send(conn, &packet, &payload, ECP_SIZE_PLD(content_size, mtype), 0); - } - return rv; -} - -ssize_t ecp_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, ecp_cts_t timeout) { -#ifdef ECP_WITH_RBUF -#ifdef ECP_WITH_MSGQ - pthread_mutex_lock(&conn->rbuf.recv->msgq.mutex); - ssize_t rv = ecp_conn_msgq_pop(conn, mtype, msg, msg_size, timeout); - pthread_mutex_unlock(&conn->rbuf.recv->msgq.mutex); - return rv; -#else - return ECP_ERR_NOT_IMPLEMENTED; -#endif -#else - return ECP_ERR_NOT_IMPLEMENTED; -#endif -} - -#ifdef ECP_DEBUG -static char *_utoa(unsigned value, char *str, int base) { - const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - int i, j; - unsigned remainder; - char c; - - /* Check base is supported. */ - if ((base < 2) || (base > 36)) - { - str[0] = '\0'; - return NULL; - } - - /* Convert to string. Digits are in reverse order. */ - i = 0; - do - { - remainder = value % base; - str[i++] = digits[remainder]; - value = value / base; - } while (value != 0); - str[i] = '\0'; - - /* Reverse string. */ - for (j = 0, i--; j < i; j++, i--) - { - c = str[j]; - str[j] = str[i]; - str[i] = c; - } - - return str; -} - -static char *_itoa(int value, char *str, int base) { - unsigned uvalue; - int i = 0; - - /* Check base is supported. */ - if ((base < 2) || (base > 36)) - { - str[0] = '\0'; - return NULL; - } - - /* Negative numbers are only supported for decimal. - * Cast to unsigned to avoid overflow for maximum negative value. */ - if ((base == 10) && (value < 0)) - { - str[i++] = '-'; - uvalue = (unsigned)-value; - } - else - uvalue = (unsigned)value; - - _utoa(uvalue, &str[i], base); - return str; -} -#endif - -static int recv_p(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_t size) { - ECP2Buffer bufs; - ECPBuffer payload; - unsigned char pld_buf[ECP_MAX_PLD]; - - bufs.packet = packet; - bufs.payload = &payload; - - payload.buffer = pld_buf; - payload.size = ECP_MAX_PLD; - - ssize_t rv = ecp_pkt_handle(sock, addr, NULL, &bufs, size); - if (rv < 0) return rv; - - return ECP_OK; -} - -int ecp_receiver(ECPSocket *sock) { - ECPNetAddr addr; - ECPBuffer packet; - unsigned char pkt_buf[ECP_MAX_PKT]; - ecp_cts_t next = 0; - ssize_t rv = 0; - - sock->running = 1; - while(sock->running) { - packet.buffer = pkt_buf; - packet.size = ECP_MAX_PKT; - - rv = ecp_tr_recv(sock, &packet, &addr, next ? next : sock->poll_timeout); - if (rv > 0) { - int _rv = recv_p(sock, &addr, &packet, rv); -#ifdef ECP_DEBUG - if (_rv) { - char b[16]; - puts("ERR:"); - puts(_itoa(_rv, b, 10)); - puts("\n"); - } -#endif - } - next = ecp_timer_exe(sock); - } - return ECP_OK; -} - -int ecp_start_receiver(ECPSocket *sock) { -#ifdef ECP_WITH_PTHREAD - int rv = pthread_create(&sock->rcvr_thd, NULL, (void *(*)(void *))ecp_receiver, sock); - if (rv) return ECP_ERR; - return ECP_OK; -#else - return ECP_ERR_NOT_IMPLEMENTED; -#endif -} - -int ecp_stop_receiver(ECPSocket *sock) { - sock->running = 0; -#ifdef ECP_WITH_PTHREAD - int rv = pthread_join(sock->rcvr_thd, NULL); - if (rv) return ECP_ERR; - return ECP_OK; -#else - return ECP_ERR_NOT_IMPLEMENTED; -#endif -} |