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; | 
