summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecp/src/ecp/core.c206
-rw-r--r--ecp/src/ecp/core.h10
-rw-r--r--ecp/src/ecp/timer.c8
3 files changed, 142 insertions, 82 deletions
diff --git a/ecp/src/ecp/core.c b/ecp/src/ecp/core.c
index be70614..3def373 100644
--- a/ecp/src/ecp/core.c
+++ b/ecp/src/ecp/core.c
@@ -235,17 +235,6 @@ static int conn_table_insert(ECPConnection *conn) {
return ECP_OK;
}
-static int conn_table_insert_gc(ECPConnection *conn) {
- ECPSocket *sock = conn->sock;
- int rv = ECP_OK;
-
-#ifdef ECP_WITH_HTABLE
- rv = ecp_ht_insert(sock->conn_table.keys_gc, &conn->remote.key_perma.public, conn);
-#endif
-
- return rv;
-}
-
static void conn_table_remove(ECPConnection *conn) {
ECPSocket *sock = conn->sock;
int i;
@@ -421,7 +410,7 @@ static void conn_table_expire(ECPSocket *sock, ecp_sts_t to, ecp_conn_expired_t
pthread_mutex_lock(&conn->mutex);
#endif
- expired = conn_expired(conn, now, to) || !_ecp_conn_is_reg(conn);
+ expired = conn_expired(conn, now, to);
#ifdef ECP_WITH_PTHREAD
pthread_mutex_unlock(&conn->mutex);
@@ -451,7 +440,7 @@ static void conn_table_expire(ECPSocket *sock, ecp_sts_t to, ecp_conn_expired_t
#endif
for (i=0; i<remove_cnt; i++) {
- ecp_conn_close(to_remove[i]);
+ ecp_conn_remove(to_remove[i]);
ecp_conn_refcount_dec(to_remove[i]);
}
} while (remove_next);
@@ -472,7 +461,7 @@ static void conn_table_expire(ECPSocket *sock, ecp_sts_t to, ecp_conn_expired_t
pthread_mutex_lock(&conn->mutex);
#endif
- expired = conn_expired(conn, now, to) || !_ecp_conn_is_reg(conn);
+ expired = conn_expired(conn, now, to);
#ifdef ECP_WITH_PTHREAD
pthread_mutex_unlock(&conn->mutex);
@@ -491,7 +480,7 @@ static void conn_table_expire(ECPSocket *sock, ecp_sts_t to, ecp_conn_expired_t
#endif
for (i=0; i<remove_cnt; i++) {
- ecp_conn_close(to_remove[i]);
+ ecp_conn_remove(to_remove[i]);
ecp_conn_refcount_dec(to_remove[i]);
}
@@ -935,6 +924,21 @@ void ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype) {
conn->keyx_ts = 0;
}
+int ecp_conn_init_outb(ECPConnection *conn) {
+ ECPDHKey key;
+ int rv;
+
+ conn->key_curr = 0;
+
+ rv = ecp_dhkey_gen(&key);
+ if (rv) return rv;
+
+ rv = conn_dhkey_new(conn, conn->key_curr, &key);
+ if (rv) return rv;
+
+ return ECP_OK;
+}
+
int ecp_conn_reset(ECPConnection *conn) {
if (conn->flags) return ECP_ERR;
@@ -984,6 +988,7 @@ int ecp_conn_create(ECPConnection *conn, ECPConnection *parent) {
ecp_conn_refcount_inc(parent);
}
#endif
+ if (!ecp_conn_is_gc(conn)) conn->refcount++;
return ECP_OK;
}
@@ -1002,7 +1007,6 @@ int ecp_conn_create_inb(ECPConnection *conn, ECPConnection *parent, unsigned cha
rv = conn_shkey_set(conn, s_idx, c_idx, shkey);
if (rv) return rv;
- ecp_conn_set_flags(conn, ECP_CONN_FLAG_GC);
conn->refcount = 1;
conn->key_curr = s_idx;
conn->rkey_curr = c_idx;
@@ -1025,23 +1029,34 @@ int ecp_conn_create_outb(ECPConnection *conn, ECPConnection *parent, ECPNode *no
conn->refcount = 1;
if (node) conn->remote = *node;
- rv = ecp_conn_reset_outb(conn);
+ rv = ecp_conn_init_outb(conn);
if (rv) return rv;
rv = ecp_conn_create(conn, parent);
- return rv;
+ if (rv) return rv;
+
+ return ECP_OK;
}
int ecp_conn_reset_outb(ECPConnection *conn) {
- ECPDHKey key;
- int rv;
+ int rv = ECP_OK;
- conn->key_curr = 0;
+ ecp_conn_remove(conn);
- rv = ecp_dhkey_gen(&key);
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_lock(&conn->mutex);
+#endif
+
+ if (_ecp_conn_is_open(conn)) rv = ECP_ERR;
+ if (!rv) rv = ecp_conn_reset(conn);
+ if (!rv) rv = ecp_conn_init_outb(conn);
+
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_unlock(&conn->mutex);
+#endif
if (rv) return rv;
- rv = conn_dhkey_new(conn, conn->key_curr, &key);
+ rv = ecp_conn_insert(conn);
if (rv) return rv;
return ECP_OK;
@@ -1051,6 +1066,7 @@ void ecp_conn_destroy(ECPConnection *conn) {
#ifdef ECP_WITH_VCONN
if (conn->parent) {
ecp_conn_refcount_dec(conn->parent);
+ conn->parent = NULL;
}
#endif
@@ -1073,54 +1089,54 @@ int ecp_conn_insert(ECPConnection *conn) {
ECPSocket *sock = conn->sock;
int rv;
- _ecp_conn_set_reg(conn);
-
#ifdef ECP_WITH_PTHREAD
pthread_mutex_lock(&sock->conn_table.mutex);
+ pthread_mutex_lock(&conn->mutex);
#endif
+ _ecp_conn_set_reg(conn);
rv = conn_table_insert(conn);
+ if (rv) _ecp_conn_clr_reg(conn);
#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_unlock(&conn->mutex);
pthread_mutex_unlock(&sock->conn_table.mutex);
#endif
- if (rv) _ecp_conn_clr_reg(conn);
-
return rv;
}
int ecp_conn_insert_gc(ECPConnection *conn) {
ECPSocket *sock = conn->sock;
- int rv;
+ int rv = ECP_OK;
+#ifdef ECP_WITH_HTABLE
#ifdef ECP_WITH_PTHREAD
pthread_mutex_lock(&sock->conn_table.mutex_gc);
#endif
- rv = conn_table_insert_gc(conn);
+ rv = ecp_ht_insert(sock->conn_table.keys_gc, &conn->remote.key_perma.public, conn);
#ifdef ECP_WITH_PTHREAD
pthread_mutex_unlock(&sock->conn_table.mutex_gc);
#endif
+ if (!rv) ecp_conn_refcount_inc(conn);
+
+#endif /* ECP_WITH_HTABLE */
+
return rv;
}
-int ecp_conn_remove(ECPConnection *conn, int *refcount) {
+void ecp_conn_remove(ECPConnection *conn) {
ECPSocket *sock = conn->sock;
- int rv = ECP_OK;
#ifdef ECP_WITH_PTHREAD
pthread_mutex_lock(&sock->conn_table.mutex);
pthread_mutex_lock(&conn->mutex);
#endif
- if (refcount) {
- if ((*refcount != -1) && (*refcount != conn->refcount)) rv = ECP_ERR_BUSY;
- *refcount = conn->refcount;
- }
- if (!rv && _ecp_conn_is_reg(conn)) {
+ if (_ecp_conn_is_reg(conn)) {
conn_table_remove(conn);
_ecp_conn_clr_reg(conn);
}
@@ -1129,8 +1145,6 @@ int ecp_conn_remove(ECPConnection *conn, int *refcount) {
pthread_mutex_unlock(&conn->mutex);
pthread_mutex_unlock(&sock->conn_table.mutex);
#endif
-
- return rv;
}
void ecp_conn_remove_addr(ECPConnection *conn) {
@@ -1150,8 +1164,45 @@ void ecp_conn_remove_addr(ECPConnection *conn) {
}
+void ecp_conn_remove_gc(ECPConnection *conn) {
+ ECPSocket *sock = conn->sock;
+ ECPConnection *_conn = NULL;
+
+#ifdef ECP_WITH_HTABLE
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_lock(&sock->conn_table.mutex_gc);
+#endif
+
+ _conn = ecp_ht_remove_kv(sock->conn_table.keys_gc, &conn->remote.key_perma.public, conn);
+
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_unlock(&sock->conn_table.mutex_gc);
+#endif
+#endif
+
+ if (_conn) {
+ ecp_conn_refcount_dec(conn);
+ } else {
+ int destroy = 0;
+
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_lock(&conn->mutex);
+#endif
+
+ if ((conn->refcount == 0) && !_ecp_conn_is_reg(conn)) destroy = 1;
+
+#ifdef ECP_WITH_PTHREAD
+ pthread_mutex_unlock(&conn->mutex);
+#endif
+
+ if (destroy) {
+ _ecp_conn_close(conn);
+ }
+ }
+}
+
int _ecp_conn_open(ECPConnection *conn, ECPConnection *parent, ECPNode *node, int retry) {
- int rv = ECP_OK;
+ int rv;
ssize_t _rv;
rv = ecp_conn_create_outb(conn, parent, node);
@@ -1165,7 +1216,9 @@ int _ecp_conn_open(ECPConnection *conn, ECPConnection *parent, ECPNode *node, in
_rv = ecp_send_init_req(conn, retry);
if (_rv < 0) {
- ecp_conn_close(conn);
+ ecp_timer_remove(conn);
+ ecp_conn_remove(conn);
+ if (!ecp_conn_is_gc(conn)) ecp_conn_refcount_dec(conn);
rv = _rv;
}
@@ -1174,6 +1227,15 @@ int _ecp_conn_open(ECPConnection *conn, ECPConnection *parent, ECPNode *node, in
return rv;
}
+int _ecp_conn_reopen(ECPConnection *conn, int retry) {
+ int rv;
+
+ rv = ecp_conn_reset_outb(conn);
+ if (rv) return rv;
+
+ return ecp_send_init_req(conn, retry);
+}
+
int ecp_conn_open(ECPConnection *conn, ECPNode *node) {
int rv;
@@ -1188,7 +1250,14 @@ int ecp_conn_try_open(ECPConnection *conn, ECPNode *node) {
return rv;
}
-static void _conn_close(ECPConnection *conn) {
+int ecp_conn_reopen(ECPConnection *conn) {
+ int rv;
+
+ rv = _ecp_conn_reopen(conn, 1);
+ return rv;
+}
+
+void _ecp_conn_close(ECPConnection *conn) {
if (_ecp_conn_is_open(conn)) {
ecp_close_handler_t handler;
@@ -1200,15 +1269,14 @@ static void _conn_close(ECPConnection *conn) {
ecp_conn_destroy(conn);
}
-int ecp_conn_close(ECPConnection *conn) {
- int refcount = -1;
-
+void ecp_conn_close(ECPConnection *conn) {
ecp_timer_remove(conn);
- ecp_conn_remove(conn, &refcount);
- if (refcount) return ECP_ERR_BUSY;
- _conn_close(conn);
-
- return ECP_OK;
+ ecp_conn_remove(conn);
+ if (ecp_conn_is_gc(conn)) {
+ ecp_conn_remove_gc(conn);
+ } else {
+ ecp_conn_refcount_dec(conn);
+ }
}
int _ecp_conn_expired(ECPConnection *conn, ecp_sts_t now, ecp_sts_t to) {
@@ -1260,7 +1328,9 @@ void ecp_conn_refcount_dec(ECPConnection *conn) {
pthread_mutex_unlock(&conn->mutex);
#endif
- if (!is_reg && (refcount == 0)) _conn_close(conn);
+ if (!is_reg && (refcount == 0)) {
+ _ecp_conn_close(conn);
+ }
}
void ecp_conn_set_flags(ECPConnection *conn, unsigned char flags) {
@@ -1534,22 +1604,11 @@ static ssize_t _send_ireq(ECPConnection *conn, ECPTimerItem *ti) {
}
static ssize_t _retry_ireq(ECPConnection *conn, ECPTimerItem *ti) {
- int refcount = 1;
int rv;
- /* timer holds one reference to this connection, nobody else should */
- rv = ecp_conn_remove(conn, &refcount);
- if (rv) return rv;
-
- rv = ecp_conn_reset(conn);
- if (rv) return rv;
-
rv = ecp_conn_reset_outb(conn);
if (rv) return rv;
- rv = ecp_conn_insert(conn);
- if (rv) return rv;
-
return _send_ireq(conn, ti);
}
@@ -1844,31 +1903,21 @@ ssize_t ecp_handle_open(ECPConnection *conn, unsigned char mtype, unsigned char
is_gc = ecp_conn_is_gc(conn);
if (is_gc) {
- ECPSocket *sock = conn->sock;
-
-#ifdef ECP_WITH_PTHREAD
- pthread_mutex_lock(&sock->conn_table.mutex_gc);
- pthread_mutex_lock(&conn->mutex);
-#endif
-
- _rv = conn_table_insert_gc(conn);
- if (!_rv) conn->refcount++;
-
-#ifdef ECP_WITH_PTHREAD
- pthread_mutex_unlock(&conn->mutex);
- pthread_mutex_unlock(&sock->conn_table.mutex_gc);
-#endif
-
+ _rv = ecp_conn_insert_gc(conn);
if (_rv) return _rv;
}
_rv = ecp_ext_conn_open(conn);
- if (_rv) return _rv;
+ if (_rv) {
+ if (is_gc) ecp_conn_remove_gc(conn);
+ return _rv;
+ }
handler = ecp_get_open_handler(conn);
if (handler) {
_rv = handler(conn, bufs);
if (_rv) {
+ if (is_gc) ecp_conn_remove_gc(conn);
ecp_ext_conn_close(conn);
return _rv;
}
@@ -2351,7 +2400,8 @@ ssize_t ecp_unpack(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *addr,
if (is_open_msg) {
rv = ecp_pld_handle_one(conn, seq, payload, pld_size, bufs);
if (rv < 0) {
- ecp_conn_close(conn);
+ ecp_conn_remove(conn);
+ if (!ecp_conn_is_gc(conn)) ecp_conn_refcount_dec(conn);
goto unpack_fin;
}
diff --git a/ecp/src/ecp/core.h b/ecp/src/ecp/core.h
index b40d813..f988c19 100644
--- a/ecp/src/ecp/core.h
+++ b/ecp/src/ecp/core.h
@@ -381,6 +381,7 @@ int ecp_cookie_verify(ECPSocket *sock, unsigned char *cookie, unsigned char *pub
ECPConnection *ecp_conn_new_inb(ECPSocket *sock, unsigned char ctype);
void ecp_conn_init(ECPConnection *conn, ECPSocket *sock, unsigned char ctype);
+int ecp_conn_init_outb(ECPConnection *conn);
int ecp_conn_reset(ECPConnection *conn);
int ecp_conn_create(ECPConnection *conn, ECPConnection *parent);
int ecp_conn_create_inb(ECPConnection *conn, ECPConnection *parent, unsigned char s_idx, unsigned char c_idx, ecp_ecdh_public_t *public, ECPDHPub *rkey_perma, ecp_aead_key_t *shkey);
@@ -391,13 +392,18 @@ void ecp_conn_free(ECPConnection *conn);
int ecp_conn_insert(ECPConnection *conn);
int ecp_conn_insert_gc(ECPConnection *conn);
-int ecp_conn_remove(ECPConnection *conn, int *refcount);
+void ecp_conn_remove(ECPConnection *conn);
void ecp_conn_remove_addr(ECPConnection *conn);
+void ecp_conn_remove_gc(ECPConnection *conn);
int _ecp_conn_open(ECPConnection *conn, ECPConnection *parent, ECPNode *node, int retry);
+int _ecp_conn_reopen(ECPConnection *conn, int retry);
int ecp_conn_open(ECPConnection *conn, ECPNode *node);
int ecp_conn_try_open(ECPConnection *conn, ECPNode *node);
-int ecp_conn_close(ECPConnection *conn);
+int ecp_conn_reopen(ECPConnection *conn);
+
+void _ecp_conn_close(ECPConnection *conn);
+void ecp_conn_close(ECPConnection *conn);
int _ecp_conn_expired(ECPConnection *conn, ecp_sts_t now, ecp_sts_t to);
int ecp_conn_is_zombie(ECPConnection *conn, ecp_sts_t now, ecp_sts_t to);
void ecp_conn_refcount_inc(ECPConnection *conn);
diff --git a/ecp/src/ecp/timer.c b/ecp/src/ecp/timer.c
index 9e86a88..c8e03b9 100644
--- a/ecp/src/ecp/timer.c
+++ b/ecp/src/ecp/timer.c
@@ -181,11 +181,15 @@ ecp_sts_t ecp_timer_exe(ECPSocket *sock) {
_rv = retry(conn, to_exec+i);
if (_rv < 0) rv = _rv;
}
- if (rv && (rv != ECP_ERR_CLOSED)) ecp_err_handle(conn, mtype, rv);
+ if (rv && (rv != ECP_ERR_CLOSED)) {
+ ecp_err_handle(conn, mtype, rv);
+ }
} else {
rv = ECP_ERR_TIMEOUT;
ecp_err_handle(conn, mtype, rv);
- if (mtype == ECP_MTYPE_OPEN_REP) ecp_conn_close(conn);
+ if (mtype == ECP_MTYPE_OPEN_REP) {
+ ecp_conn_remove(conn);
+ }
}
#ifdef ECP_DEBUG