diff options
Diffstat (limited to 'ecp/src/core.c')
-rw-r--r-- | ecp/src/core.c | 994 |
1 files changed, 572 insertions, 422 deletions
diff --git a/ecp/src/core.c b/ecp/src/core.c index 51f2849..a0f1bdb 100644 --- a/ecp/src/core.c +++ b/ecp/src/core.c @@ -8,15 +8,18 @@ #include "ht.h" #endif -int ecp_dhkey_generate(ECPContext *ctx, ECPDHKey *key) { +int ecp_ctx_init(ECPContext *ctx) { int rv; - if (ctx->rng == NULL) return ECP_ERR_RNG; + if (ctx == NULL) return ECP_ERR; - rv = ecp_cr_dh_mkpair(&key->public, &key->private, ctx->rng); + memset(ctx, 0, sizeof(ECPContext)); + + rv = ecp_tr_init(ctx); + if (rv) return rv; + rv = ecp_tm_init(ctx); if (rv) return rv; - key->valid = 1; return ECP_OK; } @@ -35,18 +38,35 @@ int ecp_node_init(ECPNode *node, ecp_dh_public_t *public, void *addr) { return ECP_OK; } -int ecp_ctx_init(ECPContext *ctx) { - int rv; +int ecp_seq_item_init(ECPSeqItem *seq_item) { + memset(seq_item, 0, sizeof(ECPSeqItem)); - if (ctx == NULL) return ECP_ERR; + return ECP_OK; +} - memset(ctx, 0, sizeof(ECPContext)); +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; - rv = ecp_tr_init(ctx); - if (rv) return rv; - rv = ecp_tm_init(ctx); + return ECP_OK; +} + +void ecp_frag_iter_reset(ECPFragIter *iter) { + iter->content_size = 0; + iter->seq = 0; + iter->frag_cnt = 0; +} + +int ecp_dhkey_gen(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; } @@ -182,9 +202,10 @@ int ecp_sock_create(ECPSocket *sock, ECPContext *ctx, ECPDHKey *key) { sock->poll_timeout = ECP_POLL_TIMEOUT; sock->key_curr = 0; if (key) sock->key_perma = *key; - sock->conn_new = ecp_conn_handle_new; + sock->handler[ECP_MTYPE_OPEN] = ecp_sock_handle_open; + sock->handler[ECP_MTYPE_KGET] = ecp_sock_handle_kget; - rv = ecp_dhkey_generate(sock->ctx, &sock->key[sock->key_curr]); + rv = ecp_dhkey_gen(sock->ctx, &sock->key[sock->key_curr]); if (!rv) rv = ctable_create(&sock->conn, sock->ctx); if (rv) return rv; @@ -247,7 +268,7 @@ int ecp_sock_dhkey_new(ECPSocket *sock) { ECPDHKey new_key; int rv; - rv = ecp_dhkey_generate(sock->ctx, &new_key); + rv = ecp_dhkey_gen(sock->ctx, &new_key); if (rv) return rv; #ifdef ECP_WITH_PTHREAD @@ -329,7 +350,6 @@ static int conn_dhkey_new_pub_local(ECPConnection *conn, unsigned char idx) { 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; @@ -434,6 +454,26 @@ static int conn_shsec_set(ECPConnection *conn, unsigned char s_idx, unsigned cha return ECP_OK; } +int ecp_conn_init(ECPConnection *conn, ECPNode *node) { + ECPDHKey key; + ECPContext *ctx = conn->sock->ctx; + int rv; + + if (node == NULL) return ECP_ERR; + + conn->out = 1; + 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); + if (!rv) rv = ecp_conn_register(conn); + + return rv; +} + int ecp_conn_create(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) { int i, rv; @@ -505,40 +545,6 @@ void ecp_conn_unregister(ECPConnection *conn) { #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; - - 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; ssize_t _rv; @@ -546,7 +552,7 @@ int ecp_conn_open(ECPConnection *conn, ECPNode *node) { rv = ecp_conn_init(conn, node); if (rv) return rv; - _rv = ecp_timer_send(conn, _conn_send_kget, ECP_MTYPE_KGET_REP, 3, 500); + _rv = ecp_conn_send_kget(conn); if (_rv < 0) { ecp_conn_unregister(conn); return _rv; @@ -606,7 +612,7 @@ int ecp_conn_reset(ECPConnection *conn) { int rv; int i; - rv = ecp_dhkey_generate(ctx, &key); + rv = ecp_dhkey_gen(ctx, &key); if (rv) return rv; #ifdef ECP_WITH_PTHREAD @@ -650,94 +656,149 @@ int ecp_conn_handler_init(ECPConnHandler *handler) { return ECP_OK; } +int ecp_conn_dhkey_new(ECPConnection *conn) { + ECPSocket *sock = conn->sock; + ECPDHKey new_key; + int rv; + ssize_t _rv; + + rv = ecp_dhkey_gen(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_conn_send_kput(conn); + 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; +} + 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); + unsigned char *buf; 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); + 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; 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; - ecp_conn_create_t handle_create = NULL; - ecp_conn_destroy_t handle_destroy = NULL; - unsigned char ctype = 0; - int rv; +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)]; - if (payload_size < 1) return ECP_ERR; + 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 = payload[0]; + 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, NULL, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), 0, ti); +} - conn = sock->ctx->conn_alloc ? sock->ctx->conn_alloc(ctype) : NULL; - if (conn == NULL) return ECP_ERR_ALLOC; +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; - rv = ecp_conn_create(conn, sock, ctype); - if (rv) { - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } - rv = sock->ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); - if (rv) { - ecp_conn_destroy(conn); - if (sock->ctx->conn_free) sock->ctx->conn_free(conn); - return rv; - } + 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); - 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; + 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; - 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; - } + return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ), 0, ti); +} - 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; - } +ssize_t ecp_conn_send_open(ECPConnection *conn) { + return ecp_timer_send(conn, _conn_send_open, ECP_MTYPE_OPEN_REP, 3, 500); +} - if (parent) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&parent->mutex); -#endif - parent->refcount++; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&parent->mutex); -#endif - } +ssize_t ecp_conn_send_kget(ECPConnection *conn) { + return ecp_timer_send(conn, _conn_send_kget, ECP_MTYPE_KGET_REP, 3, 500); +} - *_conn = conn; - return rv; +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_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { + int is_open; + #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&conn->mutex); #endif - int is_open = ecp_conn_is_open(conn); + 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); @@ -774,7 +835,7 @@ ssize_t ecp_conn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char m 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); + 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 1; @@ -786,13 +847,14 @@ ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char m if (mtype & ECP_MTYPE_FLAG_REP) { ECPContext *ctx = conn->sock->ctx; int rv; + int is_open; if (!conn->out) return ECP_ERR; #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&conn->mutex); #endif - int is_open = ecp_conn_is_open(conn); + is_open = ecp_conn_is_open(conn); #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); #endif @@ -826,7 +888,7 @@ ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char m 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); + unsigned char *buf; int rv; ssize_t _rv; @@ -835,7 +897,9 @@ ssize_t ecp_conn_handle_kget(ECPConnection *conn, ecp_seq_t seq, unsigned char m 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); + ecp_pld_set_type(payload.buffer, payload.size, ECP_MTYPE_KGET_REP); + buf= ecp_pld_get_buf(payload.buffer, payload.size); + 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); @@ -870,7 +934,7 @@ ssize_t ecp_conn_handle_kput(ECPConnection *conn, ecp_seq_t seq, unsigned char m 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); + 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); return ECP_ECDH_SIZE_KEY+1; @@ -878,7 +942,9 @@ ssize_t ecp_conn_handle_kput(ECPConnection *conn, ecp_seq_t seq, unsigned char m return ECP_ERR; } -/* Memory limited version: */ +#ifdef ECP_MEM_TINY +/* 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; @@ -888,8 +954,8 @@ ssize_t ecp_conn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char m return ecp_pkt_handle(conn->sock, NULL, conn, b, size); } -/* Non memory limited version: */ -/* +#else + 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; @@ -909,134 +975,192 @@ ssize_t ecp_conn_handle_exec(ECPConnection *conn, ecp_seq_t seq, unsigned char m 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; +#endif - 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); +ssize_t ecp_conn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { + ecp_conn_handler_msg_t handler = NULL; + unsigned char mtype = 0; + unsigned char *content = NULL; + size_t rem_size = msg_size; + ssize_t rv; + int _rv; - ecp_pld_set_type(pld_buf, ECP_MTYPE_KPUT_REQ); - rv = ecp_conn_dhkey_get_curr(conn, buf, buf+1); - if (rv) return rv; + while (rem_size) { + _rv = ecp_msg_get_type(msg, rem_size, &mtype); + if (_rv) return ECP_ERR_MIN_MSG; + if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KPUT_REQ), 0, ti); + ecp_timer_pop(conn, mtype); + + if (mtype & ECP_MTYPE_FLAG_FRAG) { +#ifdef ECP_WITH_RBUF + if (conn->rbuf.recv && conn->rbuf.recv->frag_iter) { + _rv = ecp_msg_defrag(conn->rbuf.recv->frag_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; + } +#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; + if (mtype & ECP_MTYPE_FLAG_FRAG) break; + + rem_size -= rv; + msg = content + rv; + } else { + return msg_size - rem_size - 1; + } + } + + return msg_size; } -int ecp_conn_dhkey_new(ECPConnection *conn) { - ECPSocket *sock = conn->sock; - ECPDHKey new_key; +int 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; + ecp_conn_create_t handle_create = NULL; + ecp_conn_destroy_t handle_destroy = NULL; + unsigned char ctype; + unsigned char c_idx = pkt_meta->c_idx; + unsigned char s_idx = pkt_meta->s_idx; int rv; - ssize_t _rv; - rv = ecp_dhkey_generate(sock->ctx, &new_key); - if (rv) return rv; + if (msg_size < 1) return ECP_ERR; -#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 + ctype = msg[0]; - if (rv) return rv; + conn = sock->ctx->conn_alloc ? sock->ctx->conn_alloc(ctype) : NULL; + if (conn == NULL) return ECP_ERR_ALLOC; - _rv = ecp_timer_send(conn, _conn_send_kput, ECP_MTYPE_KPUT_REP, 3, 500); - if (_rv < 0) return _rv; + rv = ecp_conn_create(conn, sock, ctype); + if (rv) { + if (sock->ctx->conn_free) sock->ctx->conn_free(conn); + return rv; + } + rv = sock->ctx->rng(&conn->seq_out, sizeof(conn->seq_out)); + if (rv) { + ecp_conn_destroy(conn); + if (sock->ctx->conn_free) sock->ctx->conn_free(conn); + return rv; + } - return ECP_OK; -} + 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; -int ecp_conn_dhkey_new_pub(ECPConnection *conn, unsigned char idx, unsigned char *public) { - ECPSocket *sock = conn->sock; - int rv; + if (handle_create) rv = handle_create(conn, msg+1, msg_size-1); + if (rv) { + ecp_conn_destroy(conn); + if (sock->ctx->conn_free) sock->ctx->conn_free(conn); + return rv; + } - if (conn == NULL) return ECP_ERR; - if (public == NULL) return ECP_ERR; + rv = conn_dhkey_new_pub_remote(conn, c_idx, ecp_cr_dh_pub_get_buf(&pkt_meta->public)); + 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(&sock->conn.mutex); - pthread_mutex_lock(&conn->mutex); + pthread_mutex_lock(&parent->mutex); #endif - rv = conn_dhkey_new_pub_remote(conn, idx, public); + parent->refcount++; #ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&sock->conn.mutex); + pthread_mutex_unlock(&parent->mutex); #endif - if (rv == ECP_ERR_ECDH_KEY_DUP) rv = ECP_OK; + } - return rv; + *_conn = conn; + return ECP_OK; } -int ecp_conn_dhkey_get_curr(ECPConnection *conn, unsigned char *idx, unsigned char *public) { - unsigned char _idx; - ECPSocket *sock = conn->sock; +int ecp_sock_handle_kget(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, unsigned char *msg, size_t msg_size, ECPPktMeta *pkt_meta, ECP2Buffer *bufs, 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; + int rv; + ssize_t _rv; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif + _packet.buffer = pkt_buf; + _packet.size = ECP_SIZE_PKT_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); + _payload.buffer = pld_buf; + _payload.size = ECP_SIZE_PLD_BUF_TR(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_KGET_REP, parent); - _idx = conn->key_curr; - if (_idx != ECP_ECDH_IDX_INV) ecp_cr_dh_pub_to_buf(public, &conn->key[_idx].public); + ecp_pld_set_type(_payload.buffer, _payload.size, ECP_MTYPE_KGET_REP); + buf = ecp_pld_get_buf(_payload.buffer, _payload.size); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif + rv = ecp_sock_dhkey_get_curr(sock, buf, buf+1); + if (rv) return rv; - if (_idx == ECP_ECDH_IDX_INV) return ecp_sock_dhkey_get_curr(sock, idx, public); + _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; - 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 _ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, ECPPktMeta *pkt_meta, unsigned char *payload, size_t pld_size) { ssize_t rv; + unsigned char s_idx, c_idx; 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; + s_idx = pkt_meta->s_idx & 0x0F; + c_idx = pkt_meta->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); + ecp_cr_dh_pub_to_buf(packet+ECP_SIZE_PROTO+1, &pkt_meta->public); + 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; - memcpy(nonce, packet+ECP_SIZE_PKT_HDR, ECP_AEAD_SIZE_NONCE); + memcpy(pkt_meta->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; +#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; - return ecp_pkt_pack(ctx, packet, pkt_size, s_idx, c_idx, public, shsec, nonce, seq, payload, pld_size); + return _ecp_pack(ctx, packet->buffer, packet->size, pkt_meta, payload->buffer, pld_size); } +#endif -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]; +ssize_t _ecp_pack_conn(ECPConnection *conn, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ECPSeqItem *si, unsigned char *payload, size_t pld_size, ECPNetAddr *addr) { + ECPPktMeta pkt_meta; int rv; ssize_t _rv; @@ -1057,35 +1181,40 @@ ssize_t ecp_conn_pack(ECPConnection *conn, unsigned char *packet, size_t pkt_siz 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)); + 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 (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)); + if (!rv) memcpy(&pkt_meta.public, &key->public, sizeof(pkt_meta.public)); } else { - memcpy(&public, &conn->remote.key[conn->remote.key_curr].public, sizeof(public)); + memcpy(&pkt_meta.public, &conn->remote.key[conn->remote.key_curr].public, sizeof(pkt_meta.public)); } } if (!rv) { if (si) { if (si->seq_w) { - _seq = si->seq; + pkt_meta.seq = si->seq; } else { - _seq = conn->seq_out + 1; - si->seq = _seq; + pkt_meta.seq = conn->seq_out + 1; + si->seq = pkt_meta.seq; } #ifdef ECP_WITH_RBUF - if (conn->rbuf.send) rv = ecp_rbuf_pkt_prep(conn->rbuf.send, si, ecp_pld_get_type(payload)); + if (conn->rbuf.send) { + unsigned char mtype; + + rv = ecp_pld_get_type(payload, pld_size, &mtype); + if (!rv) rv = ecp_rbuf_pkt_prep(conn->rbuf.send, si, mtype); + } #endif - if (!rv && !si->seq_w) conn->seq_out = _seq; + if (!rv && !si->seq_w) conn->seq_out = pkt_meta.seq; } else { - _seq = conn->seq_out + 1; - conn->seq_out = _seq; + pkt_meta.seq = conn->seq_out + 1; + conn->seq_out = pkt_meta.seq; } if (!rv && addr) *addr = conn->node.addr; } @@ -1096,13 +1225,15 @@ ssize_t ecp_conn_pack(ECPConnection *conn, unsigned char *packet, size_t pkt_siz if (rv) return rv; - _rv = ecp_pkt_pack(conn->sock->ctx, packet, pkt_size, s_idx, c_idx, &public, &shsec, nonce, _seq, payload, pld_size); + 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; #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&conn->mutex); #endif - memcpy(conn->nonce, nonce, sizeof(conn->nonce)); + memcpy(conn->nonce, pkt_meta.nonce, sizeof(conn->nonce)); #ifdef ECP_WITH_PTHREAD pthread_mutex_unlock(&conn->mutex); #endif @@ -1111,18 +1242,11 @@ ssize_t ecp_conn_pack(ECPConnection *conn, unsigned char *packet, size_t pkt_siz } #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) { +ssize_t ecp_pack_conn(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPSeqItem *si, 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_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); + return _ecp_pack_conn(conn, packet->buffer, packet->size, s_idx, c_idx, si, payload->buffer, pld_size, addr); } #endif @@ -1132,18 +1256,22 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP 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 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; + unsigned char seq_check; + unsigned char seq_reset; + ecp_seq_t seq_pkt, seq_conn, seq_last; ecp_ack_t seq_map; - ssize_t dec_size; int rv = ECP_OK; *_conn = NULL; @@ -1152,11 +1280,14 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP 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; + #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&sock->conn.mutex); #endif - conn = ctable_search(sock, c_idx, packet+ECP_SIZE_PROTO+1, NULL); + conn = ctable_search(sock, c_idx, public_buf, NULL); if (conn && !conn->out && (s_idx == ECP_ECDH_IDX_PERMA)) conn = NULL; #ifdef ECP_WITH_PTHREAD @@ -1188,7 +1319,7 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP conn->refcount++; is_open = ecp_conn_is_open(conn); if (is_open) { - seq_c = conn->seq_in; + seq_conn = conn->seq_in; seq_map = conn->seq_in_map; } } @@ -1200,73 +1331,73 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP if (rv) return rv; if (key) { - ecp_cr_dh_pub_from_buf(&public, packet+ECP_SIZE_PROTO+1); + ecp_cr_dh_pub_from_buf(&public, public_buf); 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); + 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; - seq_p = \ + seq_pkt = \ (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); + 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) { - 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; - - _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; - } + 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_handler_msg_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, sizeof(pkt_meta.public)); + memcpy(&pkt_meta.shsec, &shsec, sizeof(pkt_meta.shsec)); + memcpy(pkt_meta.nonce, nonce_next, sizeof(pkt_meta.nonce)); + pkt_meta.seq = seq_pkt; + pkt_meta.s_idx = s_idx; + pkt_meta.c_idx = c_idx; + + handler = sock->handler[mtype & ECP_MTYPE_MASK]; + if (handler) { + rv = handler(sock, addr, parent, msg, msg_size, &pkt_meta, bufs, &conn); if (rv) return rv; - } else { - return ECP_ERR_CONN_NOT_FOUND; } } if (conn == NULL) return dec_size; + seq_check = 1; + seq_reset = 0; + 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; + if (conn->rbuf.recv || (mtype == ECP_MTYPE_RBACK) || (mtype == 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 (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_n = seq_c; + if (!rv) seq_last = seq_conn; } else { rv = ECP_ERR_SEQ; } } else { - ecp_seq_t seq_offset = seq_p - seq_c; + 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; @@ -1274,13 +1405,13 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP seq_map = 0; } seq_map |= 1; - seq_n = seq_p; + seq_last = seq_pkt; } else { rv = ECP_ERR_SEQ; } } - if ((rv == ECP_ERR_SEQ) && (payload[ECP_SIZE_PLD_HDR] == ECP_MTYPE_OPEN_REQ) && key) { + if ((rv == ECP_ERR_SEQ) && (mtype == ECP_MTYPE_OPEN_REQ) && key) { rv = ECP_OK; seq_reset = 1; } @@ -1289,12 +1420,12 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP } if (!is_open || seq_reset) { - seq_n = seq_p; + seq_last = seq_pkt; seq_map = 1; #ifdef ECP_WITH_RBUF if (conn->rbuf.recv) { - rv = ecp_rbuf_recv_start(conn, seq_p); + rv = ecp_rbuf_recv_start(conn, seq_pkt); if (rv) goto ecp_unpack_err; } #endif @@ -1303,14 +1434,13 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP #ifdef ECP_WITH_PTHREAD pthread_mutex_lock(&conn->mutex); #endif - memcpy(conn->nonce, packet+ECP_SIZE_PKT_HDR, sizeof(conn->nonce)); + memcpy(conn->nonce, nonce_next, sizeof(conn->nonce)); if (addr) conn->node.addr = *addr; if (seq_check) { - conn->seq_in = seq_n; + conn->seq_in = seq_last; 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); } @@ -1321,7 +1451,7 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, ECP if (rv) goto ecp_unpack_err; *_conn = conn; - *_seq = seq_p; + *_seq = seq_pkt; return dec_size; ecp_unpack_err: @@ -1350,9 +1480,11 @@ ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *parent, if (conn) { #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); + 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); + if (rv == 0) rv = ecp_conn_handle_msg(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); @@ -1379,46 +1511,56 @@ ssize_t ecp_pkt_send(ECPSocket *sock, ECPNetAddr *addr, ECPBuffer *packet, size_ return rv; } -int ecp_seq_item_init(ECPSeqItem *seq_item) { - memset(seq_item, 0, sizeof(ECPSeqItem)); +int ecp_msg_get_type(unsigned char *msg, size_t msg_size, unsigned char *mtype) { + if (msg_size == 0) ECP_ERR; + *mtype = msg[0]; 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; +int ecp_msg_set_type(unsigned char *msg, size_t msg_size, unsigned char type) { + if (msg_size == 0) ECP_ERR; + msg[0] = type; return ECP_OK; } -unsigned char ecp_msg_get_type(unsigned char *msg) { - return msg[0]; -} +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; -unsigned char *ecp_msg_get_content(unsigned char *msg, size_t msg_size) { - size_t offset = 1 + ECP_SIZE_MT_FLAG(msg[0]); + *frag_cnt = msg[1]; + *frag_tot = msg[2]; + *frag_size = \ + (msg[3] << 8) | \ + (msg[4]); - if (msg_size < offset) return NULL; - return msg + offset; + return ECP_OK; } -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; +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; - *frag_cnt = msg[1]; - *frag_tot = msg[2]; + msg[1] = frag_cnt; + msg[2] = frag_tot; + msg[3] = (frag_size & 0xFF00) >> 8; + msg[4] = (frag_size & 0x00FF); 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); + 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 = \ @@ -1430,145 +1572,148 @@ int ecp_msg_get_pts(unsigned char *msg, size_t msg_size, ecp_pts_t *pts) { 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; +int ecp_msg_set_pts(unsigned char *msg, size_t msg_size, ecp_pts_t pts) { + unsigned char mtype; + size_t offset; - 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; + if (msg_size == 0) ECP_ERR; - content = ecp_msg_get_content(msg_in, msg_in_size); - if (content == NULL) return ECP_ERR_MIN_MSG; + mtype = msg[0]; + if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; - 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; + offset = 1 + ECP_SIZE_MT_FRAG(mtype); + if (msg_size < offset + sizeof(ecp_pts_t)) return ECP_ERR; - buf_offset = 1 + ECP_SIZE_MT_FLAG(mtype) + iter->frag_size * frag_cnt; - memcpy(iter->buffer + buf_offset, content, content_size); - iter->frag_cnt++; + msg[offset] = (pts & 0xFF000000) >> 24; + msg[offset + 1] = (pts & 0x00FF0000) >> 16; + msg[offset + 2] = (pts & 0x0000FF00) >> 8; + msg[offset + 3] = (pts & 0x000000FF); - 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; - } + 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; - unsigned char mtype = 0; - unsigned char *content = NULL; - size_t rem_size = msg_size; - ssize_t rv; - int _rv; +unsigned char *ecp_msg_get_content(unsigned char *msg, size_t msg_size) { + unsigned char mtype; + size_t offset; - while (rem_size) { - mtype = ecp_msg_get_type(msg); - if ((mtype & ECP_MTYPE_MASK) >= ECP_MAX_MTYPE) return ECP_ERR_MAX_MTYPE; + if (msg_size == 0) ECP_ERR; - ecp_timer_pop(conn, mtype); + mtype = msg[0]; + offset = 1 + ECP_SIZE_MT_FLAG(mtype); + if (msg_size < offset) return NULL; -#ifdef ECP_WITH_RBUF - if (conn->rbuf.recv && conn->rbuf.recv->frag_iter) { + return msg + offset; +} - _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 +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 content_size; + size_t buf_offset; + int rv; - content = ecp_msg_get_content(msg, rem_size); - if (content == NULL) return ECP_ERR_MIN_MSG; - rem_size -= content - msg; + rv = ecp_msg_get_frag(msg_in, msg_in_size, &frag_cnt, &frag_tot, &frag_size); + if (rv) return ECP_ERR_MIN_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; + content = ecp_msg_get_content(msg_in, msg_in_size); + if (content == NULL) return ECP_ERR_MIN_MSG; - rem_size -= rv; - msg = content + rv; - } else { - return msg_size - rem_size - 1; + content_size = msg_in_size - (content - msg_in); + if (content_size == 0) return ECP_ERR_MIN_MSG; + + if (iter->content_size && (iter->seq + frag_cnt != seq)) ecp_frag_iter_reset(iter); + + if (iter->content_size == 0) { + iter->seq = seq - frag_cnt; + iter->frag_cnt = 0; + } + + mtype &= (~ECP_MTYPE_FLAG_FRAG); + if (frag_cnt == 0) { + if (1 + ECP_SIZE_MT_FLAG(mtype) > iter->buf_size) return ECP_ERR_SIZE; + iter->buffer[0] = mtype; + if (ECP_SIZE_MT_FLAG(mtype)) { + memcpy(iter->buffer + 1, msg_in, ECP_SIZE_MT_FLAG(mtype)); } } - return msg_size; + buf_offset = 1 + ECP_SIZE_MT_FLAG(mtype) + frag_size * frag_cnt; + if (buf_offset + content_size > iter->buf_size) return ECP_ERR_SIZE; + + memcpy(iter->buffer + buf_offset, content, content_size); + iter->frag_cnt++; + iter->content_size += content_size; + if (iter->frag_cnt == frag_tot) { + *msg_out = iter->buffer; + *msg_out_size = iter->content_size; + return ECP_OK; + } else { + return ECP_ITER_NEXT; + } } -void ecp_pld_set_type(unsigned char *payload, unsigned char mtype) { - payload[ECP_SIZE_PLD_HDR] = mtype; +int ecp_pld_get_type(unsigned char *payload, size_t pld_size, unsigned char *mtype) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; + + return ecp_msg_get_type(payload, pld_size, 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; +int ecp_pld_set_type(unsigned char *payload, size_t pld_size, unsigned char mtype) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; - if (!(mtype & ECP_MTYPE_FLAG_FRAG)) return ECP_ERR; - payload[offset] = frag_cnt; - payload[offset + 1] = frag_tot; - return ECP_OK; + return ecp_msg_set_type(payload, pld_size, mtype); } -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); +int ecp_pld_get_frag(unsigned char *payload, size_t pld_size, unsigned char *frag_cnt, unsigned char *frag_tot, uint16_t *frag_size) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; - if (!(mtype & ECP_MTYPE_FLAG_PTS)) return ECP_ERR; + return ecp_msg_get_frag(payload, pld_size, frag_cnt, frag_tot, frag_size); +} - payload[offset] = (pts & 0xFF000000) >> 24; - payload[offset + 1] = (pts & 0x00FF0000) >> 16; - payload[offset + 2] = (pts & 0x0000FF00) >> 8; - payload[offset + 3] = (pts & 0x000000FF); +int ecp_pld_set_frag(unsigned char *payload, size_t pld_size, unsigned char frag_cnt, unsigned char frag_tot, uint16_t frag_size) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; - return ECP_OK; + return ecp_msg_set_frag(payload, pld_size, frag_cnt, frag_tot, frag_size); } -unsigned char ecp_pld_get_type(unsigned char *payload) { - return payload[ECP_SIZE_PLD_HDR]; +int ecp_pld_get_pts(unsigned char *payload, size_t pld_size, ecp_pts_t *pts) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; + + return ecp_msg_get_pts(payload, pld_size, pts); } -unsigned char *ecp_pld_get_buf(unsigned char *payload, unsigned char mtype) { - return payload + ECP_SIZE_PLD_HDR + 1 + ECP_SIZE_MT_FLAG(mtype); +int ecp_pld_set_pts(unsigned char *payload, size_t pld_size, ecp_pts_t pts) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; + + return ecp_msg_set_pts(payload, pld_size, pts); +} + +unsigned char *ecp_pld_get_buf(unsigned char *payload, size_t pld_size) { + payload += ECP_SIZE_PLD_HDR; + pld_size -= ECP_SIZE_PLD_HDR; + + return ecp_msg_get_content(payload, pld_size); } -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) { +static ssize_t pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPSeqItem *si, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { ECPSocket *sock = conn->sock; ECPNetAddr addr; ssize_t rv; - rv = ecp_pack(conn, packet, s_idx, c_idx, payload, pld_size, si, &addr); + rv = ecp_pack_conn(conn, packet, s_idx, c_idx, si, payload, pld_size, &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); + if (conn->rbuf.send) { + return ecp_rbuf_pkt_send(conn->rbuf.send, conn->sock, &addr, packet, rv, flags, ti, si); + } #endif if (ti) { @@ -1577,42 +1722,42 @@ static ssize_t pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_ _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); + return ecp_pkt_send(sock, &addr, packet, rv, flags); } -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; - +ssize_t _ecp_pld_send(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPSeqItem *si, ECPBuffer *payload, size_t pld_size, unsigned char flags, ECPTimerItem *ti) { #ifdef ECP_WITH_RBUF - ECPSeqItem seq_item; - int rv; + if ((si == NULL) && conn->rbuf.send) { + ECPSeqItem seq_item; + int rv; - if (conn->rbuf.send) { rv = ecp_seq_item_init(&seq_item); if (rv) return rv; - _seq_item = &seq_item; + + return pld_send(conn, packet, s_idx, c_idx, &seq_item, payload, pld_size, flags, ti); } #endif - return pld_send(conn, packet, s_idx, c_idx, payload, pld_size, flags, ti, _seq_item); + return pld_send(conn, packet, s_idx, c_idx, NULL, payload, pld_size, flags, ti); +} + +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, 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, NULL, payload, pld_size, flags, ti); } -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) { +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 rv; - rv = ecp_pack_raw(sock, parent, packet, s_idx, c_idx, public, shsec, nonce, seq, payload, pld_size, &_addr); + rv = ecp_pack(sock->ctx, parent, packet, pkt_meta, payload, pld_size, &_addr); if (rv < 0) return rv; - return ecp_pkt_send(sock, parent ? &_addr : addr, packet, rv, flags); + return ecp_pkt_send(sock, addr ? addr : &_addr, packet, rv, flags); } ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *content, size_t content_size) { @@ -1620,28 +1765,29 @@ ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *conten 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 + 1; - size_t size_max = ECP_MAX_PKT - (ECP_SIZE_PKT_HDR + ECP_AEAD_SIZE_TAG + ECP_SIZE_SEQ + 1) * vc_cnt; + size_t pld_max = ECP_MAX_PKT - (ECP_SIZE_PKT_HDR + ECP_AEAD_SIZE_TAG + ECP_SIZE_PLD_HDR + 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; + if (ECP_SIZE_PLD(content_size, mtype) > pld_max) { size_t frag_size, frag_size_final; - ecp_seq_t seq_start = 0; + 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 = size_max - ECP_SIZE_MT_FLAG(mtype); + frag_size = pld_max - (ECP_SIZE_PLD_HDR +1 +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++; @@ -1661,21 +1807,25 @@ ssize_t ecp_send(ECPConnection *conn, unsigned char mtype, unsigned char *conten 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; - 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); + memcpy(content_buf, content, frag_size); content += frag_size; - seq_item.seq = seq_start + i; - _rv = pld_send(conn, &packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(frag_size, mtype), 0, NULL, &seq_item); + + _rv = _ecp_pld_send(conn, &packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &seq_item, &payload, ECP_SIZE_PLD(frag_size, mtype), 0, NULL); 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); + ecp_pld_set_type(pld_buf, ECP_MAX_PLD, mtype); + content_buf = ecp_pld_get_buf(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); } return rv; |