diff options
Diffstat (limited to 'ecp/src/ecp/vconn/vconn.c')
-rw-r--r-- | ecp/src/ecp/vconn/vconn.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/ecp/src/ecp/vconn/vconn.c b/ecp/src/ecp/vconn/vconn.c index 780faab..e8d9b35 100644 --- a/ecp/src/ecp/vconn/vconn.c +++ b/ecp/src/ecp/vconn/vconn.c @@ -257,6 +257,7 @@ void ecp_vconn_init(ECPVConnOutb vconn[], ecp_ecdh_public_t keys[], size_t vconn for (i=0; i<vconn_size; i++) { memcpy(&key.public, &keys[i], sizeof(keys[i])); ecp_conn_init(&vconn[i].b, sock, ECP_CTYPE_VCONN); + if (i != 0) ecp_conn_set_flags(&vconn[i].b, ECP_CONN_FLAG_NOFREE); ecp_conn_set_remote_key(&vconn[i].b, &key); if (i < vconn_size - 1) { vconn[i].next = &vconn[i + 1].b; @@ -298,6 +299,30 @@ int ecp_vconn_open(ECPVConnOutb *vconn, ECPConnection *conn, ECPNode *node) { return rv; } +static void vconn_close(ECPVConnOutb *vconn) { + ECPConnection *conn, *parent, *next; + + conn = vconn->next; + while (conn->type == ECP_CTYPE_VCONN) { + next = ((ECPVConnOutb *)conn)->next; + ecp_conn_free(conn); + conn = next; + } + conn = &vconn->b; + while (conn) { + parent = conn->parent; + ecp_conn_close(conn); + conn = parent; + } +} + +void ecp_vconn_close(ECPConnection *conn) { + ECPVConnOutb *vconn; + + vconn = (ECPVConnOutb *)conn->parent; + if (vconn) vconn_close(vconn); +} + int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *bufs) { ECPVConnOutb *vconn = (ECPVConnOutb *)conn; int rv; @@ -308,6 +333,7 @@ int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *bufs) { /* we should release incoming packet before sending next open packet */ ecp_tr_release(bufs->packet, 1); rv = _ecp_conn_open(vconn->next, conn, NULL, 1); + /* err will be handled by ecp_vconn_handle_err */ return rv; } @@ -341,6 +367,30 @@ void ecp_vconn_handle_close(ECPConnection *conn) { #endif /* ECP_WITH_HTABLE */ +void ecp_vconn_handle_err(ECPConnection *conn, unsigned char mtype, int err) { + if (ecp_conn_is_outb(conn) && (mtype == ECP_MTYPE_OPEN_REP)) { + ECPVConnOutb *vconn = (ECPVConnOutb *)conn; + + while (vconn) { + ECPConnection *_conn = &vconn->b; + + if (_conn->type != ECP_CTYPE_VCONN) { + ecp_err_handle(_conn, mtype, err); + break; + } + vconn = (ECPVConnOutb *)vconn->next; + } + vconn = (ECPVConnOutb *)conn; + vconn_close(vconn); + } else { + ECPContext *ctx = conn->sock->ctx; + + if (ctx->handle_err) { + ctx->handle_err(conn, mtype, err); + } + } +} + ssize_t ecp_vconn_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *bufs) { ssize_t rv; @@ -539,7 +589,7 @@ void ecp_vconn_sock_destroy(ECPSocket *sock) { int ecp_vconn_handler_init(ECPContext *ctx, ECPConnHandler *vconn_handler) { int rv; - ecp_conn_handler_init(vconn_handler, ecp_vconn_handle_open, ecp_vconn_handle_close, ecp_vconn_handle_msg, NULL); + ecp_conn_handler_init(vconn_handler, ecp_vconn_handle_open, ecp_vconn_handle_close, ecp_vconn_handle_msg, ecp_vconn_handle_err); ecp_conn_handler_set_oreq_f(vconn_handler, ecp_vconn_send_open_req); rv = ecp_ctx_set_handler(ctx, ECP_CTYPE_VCONN, vconn_handler); return rv; |