summaryrefslogtreecommitdiff
path: root/ecp/src/ecp/vconn/vconn.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecp/src/ecp/vconn/vconn.c')
-rw-r--r--ecp/src/ecp/vconn/vconn.c52
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;