summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2024-06-06 22:33:46 +0200
committerUros Majstorovic <majstor@majstor.org>2024-06-06 22:33:46 +0200
commit4a6d383192ac59195cfe927f5a0b1eb104da5550 (patch)
tree67a787120f0332f619ee333b1b9f65393acfc563
parent109f39e09630409a30a9f4e8183f539c499f07ba (diff)
open / keyx sync implemented; vconn close fixed; rendezvous hashing fixed
-rw-r--r--ecp/server/dir.c8
-rw-r--r--ecp/server/dir.h4
-rw-r--r--ecp/server/server.c173
-rw-r--r--ecp/server/server.h10
-rw-r--r--ecp/server/sig.c4
-rw-r--r--ecp/server/vlink.h1
-rw-r--r--ecp/src/ecp/common.mk3
-rw-r--r--ecp/src/ecp/core.c94
-rw-r--r--ecp/src/ecp/core.h17
-rw-r--r--ecp/src/ecp/crypto/crypto.c14
-rw-r--r--ecp/src/ecp/dir/dir.c32
-rw-r--r--ecp/src/ecp/dir/dir.h2
-rw-r--r--ecp/src/ecp/dir/dir_client.c96
-rw-r--r--ecp/src/ecp/dir/dir_client.h9
-rw-r--r--ecp/src/ecp/vconn/vconn.c57
-rw-r--r--ecp/src/ecp/vconn/vconn.h1
-rw-r--r--ecp/src/platform/posix/features_tmpl.mk1
-rw-r--r--ecp/test/dir.c8
-rw-r--r--ecp/test/vconn_inb.c86
-rw-r--r--ecp/test/vconn_outb.c92
20 files changed, 518 insertions, 194 deletions
diff --git a/ecp/server/dir.c b/ecp/server/dir.c
index 8064d0c..a43ff91 100644
--- a/ecp/server/dir.c
+++ b/ecp/server/dir.c
@@ -408,7 +408,7 @@ void dir_process_item(ECPDirItem *dir_item, ECPSocket *sock, ecp_ecdh_public_t *
if (node == NULL) {
pthread_rwlock_unlock(&dir_shadow_rwlock);
- rv = dir_create_node(dir_item, sock, &node);
+ rv = dir_create_node(dir_item, &node);
if (!rv) {
pthread_rwlock_wrlock(&dir_shadow_rwlock);
if (ecp_ht_count(dir_shadow) > MAX_DIR_ITEM) rv = ECP_ERR_FULL;
@@ -512,7 +512,7 @@ int dir_open_conn(DIRNode *node, ECPSocket *sock) {
return rv;
}
-int dir_create_node(ECPDirItem *dir_item, ECPSocket *sock, DIRNode **node) {
+int dir_create_node(ECPDirItem *dir_item, DIRNode **node) {
DIRNode *_node;
int rv;
@@ -543,7 +543,7 @@ void dir_destroy_node(DIRNode *node) {
static int online_switch_expired(ECPConnection *conn, ecp_sts_t now) {
if (conn->type == CTYPE_DIR) return 1;
- return _ecp_conn_is_zombie(conn, now, CONN_EXPIRE_TO);
+ return conn_expired(conn, now);
}
static void remove_nodes(DIRNode *remove_node[], int remove_cnt) {
@@ -737,6 +737,8 @@ void dir_announce_allow(void) {
pthread_rwlock_wrlock(&dir_timer_rwlock);
dir_process_enable = PROC_ALLOW_ALL;
pthread_rwlock_unlock(&dir_timer_rwlock);
+
+ LOG(LOG_DEBUG, "dir_announce_allow\n");
}
void dir_announce_block(void) {
diff --git a/ecp/server/dir.h b/ecp/server/dir.h
index e5eba75..879f1eb 100644
--- a/ecp/server/dir.h
+++ b/ecp/server/dir.h
@@ -21,7 +21,7 @@
#define PROC_ALLOW_ALL 2
#define ANN_PERIOD 600 /* announce priod (s); can't exceed 1h */
-#define CONN_EXPIRE_TO 60
+#define DIR_EXPIRE_TO 60
#define DIR_UFLAG_RECONNECT 0x80
@@ -61,7 +61,7 @@ ssize_t dir_handle_msg(struct ECPConnection *conn, ecp_seq_t seq, unsigned char
void dir_process_item(ECPDirItem *dir_item, ECPSocket *sock, ecp_ecdh_public_t *s_public);
int dir_open_conn(DIRNode *node, ECPSocket *sock);
-int dir_create_node(ECPDirItem *dir_item, ECPSocket *sock, DIRNode **node);
+int dir_create_node(ECPDirItem *dir_item, DIRNode **node);
void dir_destroy_node(DIRNode *node);
void dir_online_switch(ECPSocket *sock, int inc_serial);
diff --git a/ecp/server/server.c b/ecp/server/server.c
index fd8b317..91287e2 100644
--- a/ecp/server/server.c
+++ b/ecp/server/server.c
@@ -24,13 +24,12 @@
static SRVConfig srv_config;
static int proc_forked = 0;
-static pthread_t rcvr_thd[MAX_THREADS];
+
+/* dir client result sync */
static pthread_mutex_t dir_sync_mutex;
static pthread_cond_t dir_sync_cond;
static int dir_sync_res = 0;
-static FILE *log_file = NULL;
-int log_level;
static const char *log_level_str[] = {
"ERROR",
"INFO",
@@ -131,7 +130,7 @@ static int core_logger(const char *format, ...) {
return 0;
}
-int ecp_init(ECPContext *ctx, ECPConnHandler *vconn_handler, ECPConnHandler *vlink_handler) {
+static int ecp_init(ECPContext *ctx, ECPConnHandler *vconn_handler, ECPConnHandler *vlink_handler) {
int rv;
rv = ecp_ctx_init(ctx, conn_auth, conn_new, conn_free, handle_err, core_logger);
@@ -146,10 +145,29 @@ int ecp_init(ECPContext *ctx, ECPConnHandler *vconn_handler, ECPConnHandler *vli
return ECP_OK;
}
+int conn_expired(ECPConnection *conn, ecp_sts_t now) {
+ switch (conn->type) {
+ case CTYPE_DIR:
+ return _ecp_conn_is_zombie(conn, now, ANN_PERIOD * 3);
+ case ECP_CTYPE_VLINK:
+ if (conn->parent) {
+ return _ecp_conn_is_zombie(conn, now, VCONN_EXPIRE_TO);
+ } else {
+ return _ecp_conn_is_zombie(conn, now, KEYX_PERIOD * 3);
+ }
+ return _ecp_conn_is_zombie(conn, now, KEYX_PERIOD * 3);
+ case ECP_CTYPE_VCONN:
+ return _ecp_conn_is_zombie(conn, now, VCONN_EXPIRE_TO);
+ case ECP_CTYPE_DIR:
+ return _ecp_conn_is_zombie(conn, now, DIR_EXPIRE_TO);
+ }
+ return 0;
+}
+
void log_vprintf(int level, const char *format, va_list ap) {
FILE *file;
- if (level > log_level) return;
+ if (level > srv_config.log_level) return;
if (level >= (sizeof(log_level_str) / sizeof(char *))) return;
file = srv_config.log_file ? srv_config.log_file : stderr;
@@ -183,7 +201,7 @@ void log_vprintf(int level, const char *format, va_list ap) {
void log_printf(int level, const char *format, ...) {
va_list ap;
- if (level > log_level) return;
+ if (level > srv_config.log_level) return;
va_start(ap, format);
log_vprintf(level, format, ap);
@@ -275,29 +293,30 @@ static int start_receivers(ECPSocket *sock) {
int i, rv;
for (i=0; i<srv_config.rcvr_thd_num; i++) {
- rv = pthread_create(&rcvr_thd[i], NULL, _ecp_receiver, sock);
+ rv = pthread_create(&srv_config.rcvr_thd[i], NULL, _ecp_receiver, sock);
if (rv) return ECP_ERR;
}
return ECP_OK;
}
-static void dir_result(ECPSocket *sock, ECPDirList *list, int rv) {
+static void dir_result(ECPConnection *conn, void *list, int rv) {
+ ECPDirList *dir_list = list;
unsigned int dir_cnt;
int i;
if (rv) fail("Fetching directory listing failed err:%d\n", rv);
dir_cnt = 0;
- for (i=0; i<list->count; i++) {
- if (list->items[i].roles & ECP_ROLE_DIR) dir_cnt++;
+ for (i=0; i<dir_list->count; i++) {
+ if (dir_list->items[i].roles & ECP_ROLE_DIR) dir_cnt++;
}
- rv = dir_init_dir_cnt(dir_cnt, list->serial);
+ rv = dir_init_dir_cnt(dir_cnt, dir_list->serial);
if (rv) fail("Bad timing\n");
- for (i=0; i<list->count; i++) {
- dir_process_item(&list->items[i], sock, NULL);
+ for (i=0; i<dir_list->count; i++) {
+ dir_process_item(&dir_list->items[i], srv_config.sock, NULL);
}
- ecp_dir_list_destroy(list);
+ ecp_dir_list_destroy(dir_list);
pthread_mutex_lock(&dir_sync_mutex);
dir_sync_res = 1;
@@ -306,16 +325,16 @@ static void dir_result(ECPSocket *sock, ECPDirList *list, int rv) {
}
int main(int argc, char *argv[]) {
- char *endptr;
- char *init_switch;
ecp_ecdh_public_t remote_pub;
ecp_tr_addr_t remote_addr;
ECPContext ctx;
ECPSocket sock;
- ECPConnection dir_conn;
ECPConnHandler vconn_handler;
ECPConnHandler vlink_handler;
- ECPConnHandler dir_handler;
+ char opt;
+ char *opt_arg;
+ char *endptr;
+ char *init_switch;
int _argi, _argc, remote, fd;
int rv;
@@ -328,72 +347,74 @@ int main(int argc, char *argv[]) {
srv_config.rcvr_thd_num = 1;
while (_argc && (argv[_argi][0] == '-')) {
- switch (argv[_argi][1]) {
+ if (strlen(argv[_argi]) < 2) usage(argv[0]);
+ opt = argv[_argi][1];
+ switch (opt) {
case 'd': {
_argi++;
_argc--;
+ break;
+ }
+
+ case 't':
+ case 'l':
+ case 'f':
+ case 'u':
+ case 'g': {
+ if (strlen(argv[_argi]) > 2) {
+ opt_arg = argv[_argi] + 2;
+ _argi++;
+ _argc--;
+ } else {
+ _argi++;
+ _argc--;
+ if (_argc == 0) usage(argv[0]);
+ opt_arg = argv[_argi];
+ _argi++;
+ _argc--;
+ }
+ break;
+ }
+
+ default:
+ usage(argv[0]);
+ }
+ switch (opt) {
+ case 'd': {
srv_config.detach = 1;
break;
}
case 't': {
- _argi++;
- _argc--;
- if (_argc == 0) usage(argv[0]);
- srv_config.rcvr_thd_num = (unsigned int)strtol(argv[_argi], &endptr, 10);
- if (endptr[0] != '\0') fail("Bad number of receiver threads: %s\n", argv[_argi]);
+ srv_config.rcvr_thd_num = (unsigned int)strtol(opt_arg, &endptr, 10);
+ if (endptr[0] != '\0') fail("Bad number of receiver threads: %s\n", opt_arg);
if (srv_config.rcvr_thd_num > MAX_THREADS) fail ("Maximum number of threads allowed: %d\n", MAX_THREADS);
- _argi++;
- _argc--;
break;
}
case 'l': {
- _argi++;
- _argc--;
- if (_argc == 0) usage(argv[0]);
- log_level = (uint8_t)strtol(argv[_argi], &endptr, 10);
- if (endptr[0] != '\0') fail("Bad log level: %s\n", argv[_argi]);
- if (log_level > LOG_MAX_LEVEL) fail("Maximum log level allowed: %d\n", LOG_MAX_LEVEL);
- _argi++;
- _argc--;
+ srv_config.log_level = (unsigned int)strtol(opt_arg, &endptr, 10);
+ if (endptr[0] != '\0') fail("Bad log level: %s\n", opt_arg);
+ if (srv_config.log_level > LOG_MAX_LEVEL) fail("Maximum log level allowed: %d\n", LOG_MAX_LEVEL);
break;
}
case 'f': {
- _argi++;
- _argc--;
- if (_argc == 0) usage(argv[0]);
- srv_config.log_fn = strdup(argv[_argi]);
- _argi++;
- _argc--;
+ srv_config.log_fn = strdup(opt_arg);
break;
}
case 'u': {
- _argi++;
- _argc--;
- if (_argc == 0) usage(argv[0]);
- srv_config.uid = (uid_t)strtol(argv[_argi], &endptr, 10);
- if (endptr[0] != '\0') fail("Bad uid: %s\n", argv[_argi]);
- _argi++;
- _argc--;
+ srv_config.uid = (uid_t)strtol(opt_arg, &endptr, 10);
+ if (endptr[0] != '\0') fail("Bad uid: %s\n", opt_arg);
break;
}
case 'g': {
- _argi++;
- _argc--;
- if (_argc == 0) usage(argv[0]);
- srv_config.gid = (gid_t)strtol(argv[_argi], &endptr, 10);
- if (endptr[0] != '\0') fail("Bad gid: %s\n", argv[_argi]);
- _argi++;
- _argc--;
+ srv_config.gid = (gid_t)strtol(opt_arg, &endptr, 10);
+ if (endptr[0] != '\0') fail("Bad gid: %s\n", opt_arg);
break;
}
-
- default:
- usage(argv[0]);
}
}
@@ -487,6 +508,7 @@ int main(int argc, char *argv[]) {
rv = ecp_sock_open(&sock, &srv_config.my_addr);
if (rv) fail("ecp_sock_open err:%d\n", rv);
+ srv_config.sock = &sock;
if (srv_config.uid || srv_config.gid) {
if (srv_config.gid) {
@@ -511,11 +533,37 @@ int main(int argc, char *argv[]) {
init_switch = getenv("ECP_INITSW");
if (remote) {
if (init_switch == NULL) {
+ ECPContext ctx;
+ ECPSocket sock;
+ ECPConnHandler dir_handler;
+ ECPConnection *dir_conn;
+
+ rv = pthread_mutex_init(&dir_sync_mutex, NULL);
+ if (rv) fail("pthread_mutex_init (client) failed\n");
+
+ rv = pthread_cond_init(&dir_sync_cond, NULL);
+ if (rv) fail("pthread_cond_init (client) failed\n");
+
+ rv = ecp_ctx_init(&ctx, NULL, NULL, (ecp_conn_free_t)free, handle_err, core_logger);
+ if (rv) fail("ecp_ctx_init (client) err:%d\n", rv);
+
rv = ecp_dir_set_handler(&ctx, &dir_handler, dir_result);
- if (rv) fail("ecp_dir_set_handler err:%d\n", rv);
+ if (rv) fail("ecp_dir_set_handler (client) err:%d\n", rv);
+
+ rv = ecp_sock_create(&sock, &ctx, NULL);
+ if (rv) fail("ecp_sock_create (client) err:%d\n", rv);
+
+ rv = ecp_sock_open(&sock, NULL);
+ if (rv) fail("ecp_sock_open (client) err:%d\n", rv);
+
+ rv = ecp_start_receiver(&sock);
+ if (rv) fail("ecp_start_receiver (client) err:%d\n", rv);
- rv = ecp_dir_get(&dir_conn, &sock, &remote_pub, &remote_addr, 0);
- if (rv) fail("ecp_dir_get err:%d\n", rv);
+ dir_conn = malloc(sizeof(ECPConnection));
+ if (dir_conn == NULL) fail("dir_conn malloc (client) failed\n");
+
+ rv = ecp_dir_get(dir_conn, &sock, &remote_pub, &remote_addr, 0);
+ if (rv) fail("ecp_dir_get (client) err:%d\n", rv);
pthread_mutex_lock(&dir_sync_mutex);
while (dir_sync_res == 0) {
@@ -523,6 +571,11 @@ int main(int argc, char *argv[]) {
}
pthread_mutex_unlock(&dir_sync_mutex);
LOG(LOG_DEBUG, "ecp_dir_get: done\n");
+
+ rv = ecp_stop_receiver(&sock);
+ if (rv) fail("ecp_stop_receiver (client) err:%d\n", rv);
+
+ ecp_sock_close(&sock);
} else {
rv = dir_init_ann(&sock, &remote_pub, &remote_addr);
if (rv) fail("dir_init_ann err:%d\n", rv);
diff --git a/ecp/server/server.h b/ecp/server/server.h
index c17fa62..e8705a7 100644
--- a/ecp/server/server.h
+++ b/ecp/server/server.h
@@ -9,21 +9,23 @@
typedef struct SRVConfig {
ECPDHKey key_perma;
+ ECPSocket *sock;
char *acl_fn;
char *acl_fn_dir;
ecp_tr_addr_t my_addr;
uint8_t region;
uint8_t roles;
int detach;
- pthread_t rcvr_thd[MAX_THREADS];
unsigned int rcvr_thd_num;
- uid_t uid;
- gid_t gid;
- int log_level;
+ pthread_t rcvr_thd[MAX_THREADS];
+ unsigned int log_level;
char *log_fn;
FILE *log_file;
+ uid_t uid;
+ gid_t gid;
} SRVConfig;
SRVConfig *srv_get_config(void);
+int conn_expired(ECPConnection *conn, ecp_sts_t now);
void log_vprintf(int level, const char *format, va_list ap);
void log_printf(int level, const char *format, ...);
diff --git a/ecp/server/sig.c b/ecp/server/sig.c
index 6128838..397fef1 100644
--- a/ecp/server/sig.c
+++ b/ecp/server/sig.c
@@ -15,10 +15,6 @@
static pthread_t sig_handler_thd;
static sigset_t sig_set;
-static int conn_expired(ECPConnection *conn, ecp_sts_t now) {
- return _ecp_conn_is_zombie(conn, now, CONN_EXPIRE_TO);
-}
-
static void * _sig_handler(void *arg) {
ECPSocket *sock = arg;
int rv, sig;
diff --git a/ecp/server/vlink.h b/ecp/server/vlink.h
index b591d11..4affada 100644
--- a/ecp/server/vlink.h
+++ b/ecp/server/vlink.h
@@ -1,6 +1,7 @@
#define MAX_KEYX_CNT 100
#define KEYX_PERIOD 600 /* key exchange priod (s); can't exceed 1h */
+#define VCONN_EXPIRE_TO 7200
#define VLINK_UFLAG_DISCONNECT 0x80
diff --git a/ecp/src/ecp/common.mk b/ecp/src/ecp/common.mk
index d23c68d..c8c373b 100644
--- a/ecp/src/ecp/common.mk
+++ b/ecp/src/ecp/common.mk
@@ -11,6 +11,9 @@ CFLAGS += -I$(src_dir) -I$(platform_dir) -I$(ssl_dir)/include -I$(ssl_dir)/crypt
ifeq ($(with_pthread),yes)
CFLAGS += -DECP_WITH_PTHREAD=1
+ifeq ($(with_sync),yes)
+CFLAGS += -DECP_WITH_SYNC=1
+endif
endif
ifeq ($(with_htable),yes)
diff --git a/ecp/src/ecp/core.c b/ecp/src/ecp/core.c
index 60a346b..2cef860 100644
--- a/ecp/src/ecp/core.c
+++ b/ecp/src/ecp/core.c
@@ -546,8 +546,8 @@ int ecp_sock_open(ECPSocket *sock, ecp_tr_addr_t *myaddr) {
}
void ecp_sock_close(ECPSocket *sock) {
- ecp_sock_destroy(sock);
ecp_tr_close(sock);
+ ecp_sock_destroy(sock);
}
void ecp_sock_ckey_new(ECPSocket *sock) {
@@ -1231,6 +1231,18 @@ int ecp_conn_create(ECPConnection *conn, ECPConnection *parent) {
}
#endif
+#ifdef ECP_WITH_SYNC
+ rv = pthread_cond_init(&conn->cond, NULL);
+ if (rv) {
+ pthread_mutex_destroy(&conn->mutex);
+#ifdef ECP_WITH_VCONN
+ if (conn->parent) ecp_conn_refcount_dec(conn->parent);
+#endif
+
+ return ECP_ERR;
+ }
+#endif
+
if (!ecp_conn_is_gc(conn)) conn->refcount++;
return ECP_OK;
@@ -1287,6 +1299,10 @@ void ecp_conn_destroy(ECPConnection *conn) {
if (conn->parent) ecp_conn_refcount_dec(conn->parent);
#endif
+#ifdef ECP_WITH_SYNC
+ pthread_cond_destroy(&conn->cond);
+#endif
+
#ifdef ECP_WITH_PTHREAD
pthread_mutex_destroy(&conn->mutex);
#endif
@@ -1617,6 +1633,64 @@ void ecp_conn_refcount_dec(ECPConnection *conn) {
}
}
+#ifdef ECP_WITH_SYNC
+
+int ecp_conn_open_sync(ECPConnection *conn, ecp_ecdh_public_t *public, ecp_tr_addr_t *addr) {
+ int rv;
+
+ conn->rv_sync = 1;
+ rv = ecp_conn_open(conn, public, addr);
+ return rv;
+}
+
+int ecp_conn_keyx_sync(ECPConnection *conn) {
+ ssize_t rv;
+ int rv_sync;
+
+ pthread_mutex_lock(&conn->mutex);
+ rv_sync = conn->rv_sync;
+ if (!rv_sync) conn->rv_sync = 1;
+ pthread_mutex_unlock(&conn->mutex);
+
+ if (rv_sync) return ECP_ERR_BUSY;
+
+ rv = ecp_send_keyx_req(conn, 1);
+ if (rv < 0) return rv;
+
+ return ECP_OK;
+}
+
+int ecp_conn_signal(ECPConnection *conn, int rv_sync) {
+ int rv;
+
+ pthread_mutex_lock(&conn->mutex);
+ if (conn->rv_sync > 0) {
+ conn->rv_sync = rv_sync;
+ pthread_cond_signal(&conn->cond);
+ rv = 1;
+ } else {
+ rv = 0;
+ }
+ pthread_mutex_unlock(&conn->mutex);
+
+ return rv;
+}
+
+int ecp_conn_wait(ECPConnection *conn) {
+ int rv;
+
+ pthread_mutex_lock(&conn->mutex);
+ while (conn->rv_sync > 0) {
+ pthread_cond_wait(&conn->cond, &conn->mutex);
+ }
+ rv = conn->rv_sync;
+ pthread_mutex_unlock(&conn->mutex);
+
+ return rv;
+}
+
+#endif
+
int ecp_conn_dhkey_new(ECPConnection *conn) {
ECPSocket *sock = conn->sock;
ECPDHKey new_key;
@@ -1817,9 +1891,16 @@ ecp_oreq_send_t ecp_get_oreq_send_f(ECPConnection *conn) {
void ecp_err_handle(ECPConnection *conn, unsigned char mtype, int err) {
ECPContext *ctx = conn->sock->ctx;
ecp_err_handler_t err_handler;
- int rv;
if (err == ECP_ERR_CLOSED) return;
+#ifdef ECP_WITH_SYNC
+ if ((mtype == ECP_MTYPE_OPEN_REP) || (mtype == ECP_MTYPE_KEYX_REP)) {
+ int rv;
+
+ rv = ecp_conn_signal(conn, err);
+ if (rv) return;
+ }
+#endif
err_handler = ecp_get_err_handler(conn);
if (err_handler == NULL) err_handler = ctx->handle_err;
@@ -2291,6 +2372,9 @@ ssize_t ecp_handle_keyx(ECPConnection *conn, unsigned char mtype, unsigned char
if (ecp_conn_is_inb(conn)) return ECP_ERR;
ecp_conn_dhkey_set_curr(conn);
+#ifdef ECP_WITH_SYNC
+ ecp_conn_signal(conn, ECP_OK);
+#endif
} else {
if (ecp_conn_is_outb(conn)) return ECP_ERR;
@@ -2749,6 +2833,10 @@ ssize_t ecp_pkt_handle(ECPSocket *sock, ECPConnection *parent, ecp_tr_addr_t *ad
mtype = ecp_conn_is_inb(conn) ? ECP_MTYPE_OPEN_REQ : ECP_MTYPE_OPEN_REP;
ecp_err_handle(conn, mtype, _rv);
rv = 0;
+ } else {
+#ifdef ECP_WITH_SYNC
+ ecp_conn_signal(conn, ECP_OK);
+#endif
}
}
@@ -3274,7 +3362,7 @@ void ecp_receiver(ECPSocket *sock) {
ctx = sock->ctx;
sock->running = 1;
- while(sock->running) {
+ while (sock->running) {
packet.buffer = pkt_buf;
packet.size = ECP_MAX_PKT;
diff --git a/ecp/src/ecp/core.h b/ecp/src/ecp/core.h
index 5fa00a7..da200b7 100644
--- a/ecp/src/ecp/core.h
+++ b/ecp/src/ecp/core.h
@@ -299,6 +299,7 @@ typedef ssize_t (*ecp_conn_auth_t) (struct ECPSocket *sock, struct ECPConnection
typedef struct ECPConnection * (*ecp_conn_new_t) (struct ECPSocket *sock, struct ECPConnection *parent, unsigned char type);
typedef void (*ecp_conn_free_t) (struct ECPConnection *conn);
typedef void (*ecp_err_handler_t) (struct ECPConnection *conn, unsigned char mtype, int err);
+typedef void (*ecp_dir_handler_t) (struct ECPConnection *conn, void *dir_list, int err);
typedef int (*ecp_logger_t) (const char *fmt, ...);
typedef int (*ecp_open_handler_t) (struct ECPConnection *conn, struct ECP2Buffer *b);
@@ -364,6 +365,9 @@ typedef struct ECPContext {
ecp_conn_new_t conn_new; /* inbound connections only */
ecp_conn_free_t conn_free;
ecp_err_handler_t handle_err;
+#ifdef ECP_WITH_DIR
+ ecp_dir_handler_t handle_dir;
+#endif
ecp_logger_t logger;
ECPConnHandler *handler[ECP_MAX_CTYPE];
ECPConnHandler *handler_sys[ECP_MAX_CTYPE_SYS];
@@ -399,7 +403,7 @@ typedef struct ECPVConnTable {
typedef struct ECPSocket {
ECPContext *ctx;
- unsigned char running;
+ volatile int running;
ecp_tr_sock_t sock;
ecp_nonce_t nonce_out;
ECPDHKey key_perma;
@@ -448,6 +452,10 @@ typedef struct ECPConnection {
#ifdef ECP_WITH_PTHREAD
pthread_mutex_t mutex;
#endif
+#ifdef ECP_WITH_SYNC
+ pthread_cond_t cond;
+ int rv_sync;
+#endif
} ECPConnection;
int ecp_dhkey_gen(ECPDHKey *key);
@@ -523,6 +531,13 @@ void ecp_conn_unlock(ECPConnection *conn);
int ecp_conn_refcount_inc(ECPConnection *conn);
void ecp_conn_refcount_dec(ECPConnection *conn);
+#ifdef ECP_WITH_SYNC
+int ecp_conn_open_sync(ECPConnection *conn, ecp_ecdh_public_t *public, ecp_tr_addr_t *addr);
+int ecp_conn_keyx_sync(ECPConnection *conn);
+int ecp_conn_signal(ECPConnection *conn, int rv_sync);
+int ecp_conn_wait(ECPConnection *conn);
+#endif
+
int ecp_conn_dhkey_new(ECPConnection *conn);
int ecp_conn_dhkey_get(ECPConnection *conn, unsigned char idx, ECPDHKey *key);
void ecp_conn_dhkey_set_curr(ECPConnection *conn);
diff --git a/ecp/src/ecp/crypto/crypto.c b/ecp/src/ecp/crypto/crypto.c
index 95598da..53cedfa 100644
--- a/ecp/src/ecp/crypto/crypto.c
+++ b/ecp/src/ecp/crypto/crypto.c
@@ -142,19 +142,23 @@ void ecp_hash(unsigned char *hd, unsigned char *m, size_t ml) {
}
int ecp_str2key(uint8_t *key, char *str) {
- uint32_t u[8];
+ unsigned int u[8];
int i, rv;
if (str[ECP_SIZE_ECDH_KEY_BUF - 1] != '\0') return ECP_ERR;
+ for (i=8; i<ECP_SIZE_ECDH_KEY_BUF - 1; i+=9) {
+ if (str[i] != ':') return ECP_ERR;
+ }
+
rv = sscanf(str, "%X:%X:%X:%X:%X:%X:%X:%X", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5], &u[6], &u[7]);
if (rv != 8) return ECP_ERR;
for (i=0; i<8; i++) {
- key[0] = u[i] >> 24;
- key[1] = u[i] >> 16;
- key[2] = u[i] >> 8;
- key[3] = u[i];
+ key[0] = (uint32_t)u[i] >> 24;
+ key[1] = (uint32_t)u[i] >> 16;
+ key[2] = (uint32_t)u[i] >> 8;
+ key[3] = (uint32_t)u[i];
key += 4;
}
diff --git a/ecp/src/ecp/dir/dir.c b/ecp/src/ecp/dir/dir.c
index b997f5c..d7b8f1d 100644
--- a/ecp/src/ecp/dir/dir.c
+++ b/ecp/src/ecp/dir/dir.c
@@ -96,10 +96,12 @@ int ecp_dir_handle_open(ECPConnection *conn, ECP2Buffer *b) {
if (ecp_conn_is_inb(conn)) return ECP_ERR;
+#ifndef ECP_WITH_SYNC
region = (unsigned char)ecp_conn_set_param(conn, NULL);
rv = ecp_dir_send_req(conn, region);
if (rv < 0) return rv;
+#endif
return ECP_OK;
}
@@ -135,9 +137,37 @@ void ecp_dir_conn_init(ECPConnection *conn, ECPSocket *sock) {
}
int ecp_dir_request(ECPConnection *conn, ecp_ecdh_public_t *public, ecp_tr_addr_t *addr, unsigned char region) {
+ ssize_t _rv;
int rv;
+#ifdef ECP_WITH_SYNC
+
+ rv = ecp_conn_open_sync(conn, public, addr);
+ if (rv) {
+ ecp_conn_free(conn);
+ return rv;
+ }
+ rv = ecp_conn_wait(conn);
+ if (rv) {
+ ecp_conn_close(conn);
+ return rv;
+ }
+ _rv = ecp_dir_send_req(conn, region);
+ if (_rv < 0) {
+ ecp_conn_close(conn);
+ return _rv;
+ }
+
+#else
+
ecp_conn_set_param(conn, (void *)region);
rv = ecp_conn_open(conn, public, addr);
- return rv;
+ if (rv) {
+ ecp_conn_free(conn);
+ return rv;
+ }
+
+#endif
+
+ return ECP_OK;
}
diff --git a/ecp/src/ecp/dir/dir.h b/ecp/src/ecp/dir/dir.h
index e343ecc..a7bbd49 100644
--- a/ecp/src/ecp/dir/dir.h
+++ b/ecp/src/ecp/dir/dir.h
@@ -9,6 +9,8 @@
#define ECP_ROLE_DIR 0x01
#define ECP_ROLE_VCONN 0x02
+#define ECP_ROLE_UNAVAILABLE 0x80
+
typedef struct ECPDirItem {
ECPNode node;
uint8_t region;
diff --git a/ecp/src/ecp/dir/dir_client.c b/ecp/src/ecp/dir/dir_client.c
index 7c34189..cf82754 100644
--- a/ecp/src/ecp/dir/dir_client.c
+++ b/ecp/src/ecp/dir/dir_client.c
@@ -7,8 +7,6 @@
#include "dir_client.h"
-static ecp_dir_result_t dir_result_f = NULL;
-
static int dir_list_create_items(ECPDirList *dir_list, uint16_t list_size) {
dir_list->items = malloc(list_size * sizeof(ECPDirItem));
if (dir_list->items == NULL) return ECP_ERR_ALLOC;
@@ -106,7 +104,9 @@ handle_dir_msg_fin:
ecp_frag_end(conn, seq, frag_cnt, rv);
if (rv || is_last) {
- if (dir_result_f) dir_result_f(conn->sock, dir_list_fin, rv);
+ ECPContext *ctx = conn->sock->ctx;
+
+ if (ctx->handle_dir) ctx->handle_dir(conn, dir_list_fin, rv);
ecp_conn_close(conn);
}
@@ -114,8 +114,10 @@ handle_dir_msg_fin:
return msg_size;
}
-static void dir_handle_err(ECPConnection *conn, unsigned char mtype, int err) {
- if (dir_result_f) dir_result_f(conn->sock, NULL, err);
+void ecp_dir_handle_err(ECPConnection *conn, unsigned char mtype, int err) {
+ ECPContext *ctx = conn->sock->ctx;
+
+ if (ctx->handle_dir) ctx->handle_dir(conn, NULL, err);
ecp_conn_close(conn);
}
@@ -154,11 +156,11 @@ ECPDirList *ecp_dir_list_copy(ECPDirList *dir_list) {
return dir_list_copy;
}
-int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_result_t dir_result) {
+int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_handler_t handle_dir) {
int rv;
- dir_result_f = dir_result;
- ecp_conn_handler_init(handler, dir_handle_open, dir_handle_close, dir_handle_msg, dir_handle_err);
+ ctx->handle_dir = handle_dir;
+ ecp_conn_handler_init(handler, dir_handle_open, dir_handle_close, dir_handle_msg, ecp_dir_handle_err);
rv = ecp_ctx_set_handler(ctx, ECP_CTYPE_DIR, handler);
return rv;
}
@@ -171,40 +173,85 @@ int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ecp_ecdh_public_t *public,
return rv;
}
+void ecp_dir_set_unavailable(ECPDirList *dir_list, ecp_ecdh_public_t *public) {
+ ECPDHPub *key;
+ int i;
+
+ for (i=0; i<dir_list->count; i++) {
+ key = &dir_list->items[i].node.key_perma;
+ if (memcmp(&key->public, public, sizeof(key->public)) == 0) {
+ dir_list->items[i].roles |= ECP_ROLE_UNAVAILABLE;
+ }
+ }
+}
+
+int ecp_dir_sel_dir(ECPDirList *dir_list, ecp_ecdh_public_t *public, struct ECPNetAddr *addr) {
+ ECPDHPub *key;
+ uint16_t dir_cnt;
+ uint32_t rnd_sel;
+ int i;
+
+ dir_cnt = 0;
+ for (i=0; i<dir_list->count; i++) {
+ if (!(dir_list->items[i].roles & ECP_ROLE_DIR) || (dir_list->items[i].roles & ECP_ROLE_UNAVAILABLE)) continue;
+ dir_cnt++;
+ }
+ if (dir_cnt == 0) return ECP_ERR_EMPTY;
+
+ rnd_sel = arc4random_uniform(dir_cnt);
+ dir_cnt = 0;
+ for (i=0; i<dir_list->count; i++) {
+ if (!(dir_list->items[i].roles & ECP_ROLE_DIR) || (dir_list->items[i].roles & ECP_ROLE_UNAVAILABLE)) continue;
+ if (rnd_sel == dir_cnt) {
+ key = &dir_list->items[i].node.key_perma;
+ memcpy(public, &key->public, sizeof(key->public));
+ *addr = dir_list->items[i].node.addr;
+ break;
+ }
+ }
+
+ return ECP_OK;
+}
+
#ifdef ECP_WITH_VCONN
-ssize_t ecp_dir_hrw_select(ECPDirList *dir_list, ecp_ecdh_public_t *srv_pub, ecp_ecdh_public_t vconn_keys[], size_t vconn_size, struct ECPNetAddr *addr) {
+ssize_t ecp_dir_sel_vconn(ECPDirList *dir_list, ecp_ecdh_public_t *srv_pub, ecp_ecdh_public_t vconn_keys[], size_t vconn_size, struct ECPNetAddr *addr) {
unsigned char tmp_hash[ECP_SIZE_HASH_DIGEST];
unsigned char hrw_hash[ECP_SIZE_HASH_DIGEST];
ecp_ecdh_public_t public[2];
uint16_t sel[ECP_MAX_PARENT];
- uint16_t hrw_i, sel_cnt;
- uint32_t rnd_i;
+ uint16_t hrw_i, hrw_sel, sel_cnt, vconn_cnt, _vconn_cnt;
+ uint32_t rnd_sel;
int i, j, k;
- if ((dir_list->count == 0) || (vconn_size == 0)) return ECP_ERR_EMPTY;
+ if (vconn_size == 0) return ECP_ERR_EMPTY;
if (vconn_size > ECP_MAX_PARENT) vconn_size = ECP_MAX_PARENT;
memset(hrw_hash, 0, sizeof(hrw_hash));
memcpy(&public[0], srv_pub, sizeof(public[0]));
+ vconn_cnt = 0;
for (i=0; i<dir_list->count; i++) {
+ if (!(dir_list->items[i].roles & ECP_ROLE_VCONN) || (dir_list->items[i].roles & ECP_ROLE_UNAVAILABLE)) continue;
memcpy(&public[1], &dir_list->items[i].node.key_perma.public, sizeof(public[1]));
ecp_hash(tmp_hash, (unsigned char *)public, sizeof(public));
if (memcmp(hrw_hash, tmp_hash, sizeof(hrw_hash)) < 0) {
hrw_i = i;
+ hrw_sel = vconn_cnt;
memcpy(hrw_hash, tmp_hash, sizeof(hrw_hash));
}
+ vconn_cnt++;
}
- sel[0] = hrw_i;
+ if (vconn_cnt == 0) return ECP_ERR_EMPTY;
+ sel[0] = hrw_sel;
sel_cnt = 1;
for (i=0; i<vconn_size-1; i++) {
- if ((dir_list->count - sel_cnt) == 0) goto dir_hrw_select_fin;
- rnd_i = arc4random_uniform(dir_list->count - sel_cnt);
+ if ((vconn_cnt - sel_cnt) == 0) goto dir_sel_vconn_fin;
+ rnd_sel = arc4random_uniform(vconn_cnt - sel_cnt);
for (j=0; j<sel_cnt; j++) {
- if (rnd_i >= sel[j]) {
- rnd_i++;
+ if (rnd_sel >= sel[j]) {
+ rnd_sel++;
} else {
for (k=sel_cnt; k>j; k--) {
sel[k] = sel[k-1];
@@ -212,13 +259,20 @@ ssize_t ecp_dir_hrw_select(ECPDirList *dir_list, ecp_ecdh_public_t *srv_pub, ecp
break;
}
}
- sel[j] = rnd_i;
+ sel[j] = rnd_sel;
sel_cnt++;
- memcpy(&vconn_keys[i], &dir_list->items[rnd_i].node.key_perma.public, sizeof(vconn_keys[i]));
- if (i == 0) *addr = dir_list->items[rnd_i].node.addr;
+ _vconn_cnt = 0;
+ for (j=0; j<dir_list->count; j++) {
+ if (!(dir_list->items[j].roles & ECP_ROLE_VCONN) || (dir_list->items[j].roles & ECP_ROLE_UNAVAILABLE)) continue;
+ if (_vconn_cnt == rnd_sel) {
+ memcpy(&vconn_keys[i], &dir_list->items[j].node.key_perma.public, sizeof(vconn_keys[i]));
+ if (i == 0) *addr = dir_list->items[j].node.addr;
+ }
+ _vconn_cnt++;
+ }
}
-dir_hrw_select_fin:
+dir_sel_vconn_fin:
memcpy(&vconn_keys[i], &dir_list->items[hrw_i].node.key_perma.public, sizeof(vconn_keys[i]));
if (i == 0) *addr = dir_list->items[hrw_i].node.addr;
return sel_cnt;
diff --git a/ecp/src/ecp/dir/dir_client.h b/ecp/src/ecp/dir/dir_client.h
index a1be56d..8efed1c 100644
--- a/ecp/src/ecp/dir/dir_client.h
+++ b/ecp/src/ecp/dir/dir_client.h
@@ -5,15 +5,18 @@ typedef struct ECPDirList {
ECPDirItem *items;
} ECPDirList;
-typedef void (*ecp_dir_result_t) (ECPSocket *sock, ECPDirList *dir_list, int err);
+void ecp_dir_handle_err(ECPConnection *conn, unsigned char mtype, int err);
ECPDirList *ecp_dir_list_create(uint16_t list_size);
void ecp_dir_list_destroy(ECPDirList *dir_list);
ECPDirList *ecp_dir_list_copy(ECPDirList *dir_list);
-int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_result_t dir_result);
+int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_handler_t handle_dir);
int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ecp_ecdh_public_t *public, ecp_tr_addr_t *addr, unsigned char region);
+void ecp_dir_set_unavailable(ECPDirList *dir_list, ecp_ecdh_public_t *public);
+int ecp_dir_sel_dir(ECPDirList *dir_list, ecp_ecdh_public_t *public, struct ECPNetAddr *addr);
+
#ifdef ECP_WITH_VCONN
-ssize_t ecp_dir_hrw_select(ECPDirList *dir_list, ecp_ecdh_public_t *srv_pub, ecp_ecdh_public_t vconn_keys[], size_t vconn_size, struct ECPNetAddr *addr);
+ssize_t ecp_dir_sel_vconn(ECPDirList *dir_list, ecp_ecdh_public_t *srv_pub, ecp_ecdh_public_t vconn_keys[], size_t vconn_size, struct ECPNetAddr *addr);
#endif
diff --git a/ecp/src/ecp/vconn/vconn.c b/ecp/src/ecp/vconn/vconn.c
index 615474c..3aaa1b9 100644
--- a/ecp/src/ecp/vconn/vconn.c
+++ b/ecp/src/ecp/vconn/vconn.c
@@ -330,16 +330,9 @@ int ecp_vconn_open_vlink(ECPVConnOutb *vconn, ecp_ecdh_public_t vconn_pub[], ecp
return rv;
}
-static void vconn_close(ECPVConnOutb *vconn) {
- ECPConnection *conn, *parent, *next;
+static void vconn_close(ECPConnection *conn) {
+ ECPConnection *parent;
- 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);
@@ -348,10 +341,22 @@ static void vconn_close(ECPVConnOutb *vconn) {
}
void ecp_vconn_close(ECPConnection *conn) {
- ECPVConnOutb *vconn;
+ if (ecp_conn_is_inb(conn)) return;
- vconn = (ECPVConnOutb *)conn->parent;
- if (vconn) vconn_close(vconn);
+ if (conn->type == ECP_CTYPE_VCONN) {
+ ECPConnection *_conn, *next;
+
+ _conn = ((ECPVConnOutb *)conn)->next;
+ while (_conn->type == ECP_CTYPE_VCONN) {
+ next = ((ECPVConnOutb *)_conn)->next;
+ ecp_conn_free(_conn);
+ _conn = next;
+ }
+ ecp_conn_free(_conn);
+ vconn_close(conn);
+ } else {
+ vconn_close(conn);
+ }
}
int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *bufs) {
@@ -364,7 +369,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, 1);
- /* err will be handled by ecp_vconn_handle_err */
+ /* err will be handled by vconn err handler */
return rv;
}
@@ -398,30 +403,6 @@ 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;
@@ -620,7 +601,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, ecp_vconn_handle_err);
+ ecp_conn_handler_init(vconn_handler, ecp_vconn_handle_open, ecp_vconn_handle_close, ecp_vconn_handle_msg, NULL);
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;
diff --git a/ecp/src/ecp/vconn/vconn.h b/ecp/src/ecp/vconn/vconn.h
index ab1d2d1..431671d 100644
--- a/ecp/src/ecp/vconn/vconn.h
+++ b/ecp/src/ecp/vconn/vconn.h
@@ -37,7 +37,6 @@ int ecp_vconn_handle_open(ECPConnection *conn, ECP2Buffer *bufs);
#ifdef ECP_WITH_HTABLE
void ecp_vconn_handle_close(ECPConnection *conn);
#endif
-void ecp_vconn_handle_err(ECPConnection *conn, unsigned char mtype, int 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 ecp_vconn_send_open_req(ECPConnection *conn, unsigned char *cookie);
diff --git a/ecp/src/platform/posix/features_tmpl.mk b/ecp/src/platform/posix/features_tmpl.mk
index 2887e08..85f22e3 100644
--- a/ecp/src/platform/posix/features_tmpl.mk
+++ b/ecp/src/platform/posix/features_tmpl.mk
@@ -1,4 +1,5 @@
with_pthread = yes
+with_sync = yes
with_htable = yes
with_vconn = yes
with_dir = yes
diff --git a/ecp/test/dir.c b/ecp/test/dir.c
index f9a4543..9beea27 100644
--- a/ecp/test/dir.c
+++ b/ecp/test/dir.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <unistd.h>
#include <stdio.h>
+#include <arpa/inet.h>
#include <ecp/core.h>
#include <ecp/dir/dir.h>
@@ -20,10 +21,13 @@ static void handle_err(ECPConnection *conn, unsigned char mtype, int err) {
printf("ERROR: CTYPE:0x%x MTYPE:0x%x ERR:%d\n", conn->type, mtype, err);
}
-static void print_list(ECPSocket *sock, ECPDirList *dir_list, int err) {
- int i;
+static void print_list(ECPConnection *conn, void *list, int err) {
+ ECPDirList *dir_list = list;
unsigned char *host;
uint16_t port;
+ int i;
+
+ LOG("print_list", err);
printf("DIR LIST COUNT:%d\n", dir_list->count);
for (i=0; i<dir_list->count; i++) {
diff --git a/ecp/test/vconn_inb.c b/ecp/test/vconn_inb.c
index 7701a2d..53e8807 100644
--- a/ecp/test/vconn_inb.c
+++ b/ecp/test/vconn_inb.c
@@ -12,18 +12,30 @@
#include "init_vconn.h"
-ECPContext ctx;
-ECPSocket sock;
-ECPConnHandler handler;
-ECPConnHandler vconn_handler;
-ECPConnHandler vlink_handler;
-ECPConnHandler dir_handler;
-ECPConnection dir_conn;
-ECPVConnOutb vconn[ECP_MAX_PARENT];
+ECPDirList *_dir_list = NULL;
#define CTYPE_TEST 0
#define MTYPE_MSG 0
+static void vlink_open(ECPSocket *sock) {
+ ECPVConnOutb *vconn;
+ ecp_tr_addr_t addr;
+ ecp_ecdh_public_t vconn_pub[ECP_MAX_PARENT];
+ ssize_t vconn_size, _rv;
+ int rv;
+
+ _rv = ecp_dir_sel_vconn(_dir_list, &sock->key_perma.public, vconn_pub, ECP_MAX_PARENT, &addr);
+ LOG("ecp_dir_sel_vconn", (int)_rv);
+
+ vconn_size = _rv;
+ vconn = malloc(vconn_size * sizeof(ECPVConnOutb));
+ if (vconn == NULL) LOG("vconn malloc", ECP_ERR_ALLOC);
+
+ ecp_vconn_init_vlink(vconn, vconn_size, sock);
+ rv = ecp_vconn_open_vlink(vconn, vconn_pub, &addr);
+ LOG("ecp_vconn_open_vlink", rv);
+}
+
static int handle_open(ECPConnection *conn, ECP2Buffer *b) {
printf("OPEN\n");
@@ -40,23 +52,41 @@ static ssize_t handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtyp
return msg_size;
}
-static void handle_dir_list(ECPSocket *sock, ECPDirList *dir_list, int err) {
- ecp_tr_addr_t addr;
- ecp_ecdh_public_t vconn_pub[ECP_MAX_PARENT];
- ssize_t _rv, vconn_size;
- int rv;
+static void handle_err(ECPConnection *conn, unsigned char mtype, int err) {
+ if (mtype == ECP_MTYPE_OPEN_REP) {
+ ecp_dir_set_unavailable(_dir_list, &conn->remote.key_perma.public);
+ vlink_open(conn->sock);
+ }
+ ecp_vconn_close(conn);
+}
- LOG("handle_dir_list", err);
+static void handle_dir_list(ECPConnection *conn, void *list, int err) {
+ ECPDirList *dir_list = list;
- _rv = ecp_dir_hrw_select(dir_list, &sock->key_perma.public, vconn_pub, ECP_MAX_PARENT, &addr);
- LOG("ecp_dir_hrw_select", (int)_rv);
+ if (err && _dir_list) {
+ ECPConnection *dir_conn;
+ ecp_tr_addr_t addr;
+ ecp_ecdh_public_t public;
+ int rv;
- vconn_size = _rv;
- ecp_vconn_init_vlink(vconn, vconn_size, sock);
- rv = ecp_vconn_open_vlink(vconn, vconn_pub, &addr);
- LOG("ecp_vconn_open_vlink", rv);
+ ecp_dir_set_unavailable(_dir_list, &conn->remote.key_perma.public);
+ rv = ecp_dir_sel_dir(_dir_list, &public, &addr);
+ LOG("ecp_dir_sel_dir", rv);
- ecp_dir_list_destroy(dir_list);
+ dir_conn = malloc(sizeof(ECPConnection));
+ if (dir_conn == NULL) LOG("dir_conn malloc", ECP_ERR_ALLOC);
+
+ rv = ecp_dir_get(dir_conn, conn->sock, &public, &addr, 0);
+ LOG("ecp_dir_get", rv);
+
+ return;
+ }
+ LOG("handle_dir_list", err);
+
+ if (_dir_list) ecp_dir_list_destroy(_dir_list);
+ _dir_list = dir_list;
+
+ vlink_open(conn->sock);
}
static void usage(char *arg) {
@@ -65,7 +95,14 @@ static void usage(char *arg) {
}
int main(int argc, char *argv[]) {
+ ECPContext ctx;
+ ECPSocket sock;
ECPDHKey key_perma;
+ ECPConnHandler handler;
+ ECPConnHandler vconn_handler;
+ ECPConnHandler vlink_handler;
+ ECPConnHandler dir_handler;
+ ECPConnection *dir_conn;
ecp_tr_addr_t addr;
ecp_ecdh_public_t public;
int rv;
@@ -74,6 +111,8 @@ int main(int argc, char *argv[]) {
rv = ecp_init(&ctx, &vconn_handler, &vlink_handler);
LOG("ecp_init", rv);
+ vconn_handler.handle_err = handle_err;
+ vlink_handler.handle_err = handle_err;
rv = ecp_dir_set_handler(&ctx, &dir_handler, handle_dir_list);
LOG("ecp_dir_set_handler", rv);
@@ -103,7 +142,10 @@ int main(int argc, char *argv[]) {
rv = ecp_util_load_key(argv[3], &public, NULL);
LOG("ecp_util_load_key", rv);
- rv = ecp_dir_get(&dir_conn, &sock, &public, &addr, 0);
+ dir_conn = malloc(sizeof(ECPConnection));
+ if (dir_conn == NULL) LOG("dir_conn malloc", ECP_ERR_ALLOC);
+
+ rv = ecp_dir_get(dir_conn, &sock, &public, &addr, 0);
LOG("ecp_dir_get", rv);
while(1) pause();
diff --git a/ecp/test/vconn_outb.c b/ecp/test/vconn_outb.c
index 8b7782b..69c0929 100644
--- a/ecp/test/vconn_outb.c
+++ b/ecp/test/vconn_outb.c
@@ -12,20 +12,36 @@
#include "init_vconn.h"
-ECPContext ctx;
-ECPSocket sock;
-ECPConnHandler handler;
-ECPConnHandler vconn_handler;
-ECPConnHandler vlink_handler;
-ECPConnHandler dir_handler;
-ECPConnection dir_conn;
-ECPConnection conn;
-ECPVConnOutb vconn[ECP_MAX_PARENT];
+ECPDirList *_dir_list = NULL;
ecp_ecdh_public_t srv_public;
#define CTYPE_TEST 0
#define MTYPE_MSG 0
+static void vconn_open(ECPSocket *sock) {
+ ECPConnection *conn;
+ ECPVConnOutb *vconn;
+ ecp_tr_addr_t addr;
+ ecp_ecdh_public_t vconn_pub[ECP_MAX_PARENT];
+ ssize_t vconn_size, _rv;
+ int rv;
+
+ _rv = ecp_dir_sel_vconn(_dir_list, &srv_public, vconn_pub, ECP_MAX_PARENT, &addr);
+ LOG("ecp_dir_sel_vconn", (int)_rv);
+
+ vconn_size = _rv;
+ conn = malloc(sizeof(ECPConnection));
+ if (conn == NULL) LOG("conn malloc", ECP_ERR_ALLOC);
+
+ vconn = malloc(vconn_size * sizeof(ECPVConnOutb));
+ if (vconn == NULL) LOG("vconn malloc", ECP_ERR_ALLOC);
+
+ ecp_conn_init(conn, sock, CTYPE_TEST);
+ ecp_vconn_init(vconn, vconn_size, conn, sock);
+ rv = ecp_vconn_open(vconn, vconn_pub, &addr, &srv_public);
+ LOG("ecp_vconn_open", rv);
+}
+
static int handle_open(ECPConnection *conn, ECP2Buffer *b) {
char *_msg = "PERA JE CAR!";
ssize_t rv;
@@ -44,24 +60,41 @@ static ssize_t handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtyp
return msg_size;
}
-static void handle_dir_list(ECPSocket *sock, ECPDirList *dir_list, int err) {
- ecp_tr_addr_t addr;
- ecp_ecdh_public_t vconn_pub[ECP_MAX_PARENT];
- ssize_t _rv, vconn_size;
- int rv;
+static void handle_err(ECPConnection *conn, unsigned char mtype, int err) {
+ if (mtype == ECP_MTYPE_OPEN_REP) {
+ ecp_dir_set_unavailable(_dir_list, &conn->remote.key_perma.public);
+ vconn_open(conn->sock);
+ }
+ ecp_vconn_close(conn);
+}
- LOG("handle_dir_list", err);
+static void handle_dir_list(ECPConnection *conn, void *list, int err) {
+ ECPDirList *dir_list = list;
- _rv = ecp_dir_hrw_select(dir_list, &srv_public, vconn_pub, ECP_MAX_PARENT, &addr);
- LOG("ecp_dir_hrw_select", (int)_rv);
+ if (err && _dir_list) {
+ ECPConnection *dir_conn;
+ ecp_tr_addr_t addr;
+ ecp_ecdh_public_t public;
+ int rv;
- vconn_size = _rv;
- ecp_conn_init(&conn, sock, CTYPE_TEST);
- ecp_vconn_init(vconn, vconn_size, &conn, sock);
- rv = ecp_vconn_open(vconn, vconn_pub, &addr, &srv_public);
- LOG("ecp_vconn_open", rv);
+ ecp_dir_set_unavailable(_dir_list, &conn->remote.key_perma.public);
+ rv = ecp_dir_sel_dir(_dir_list, &public, &addr);
+ LOG("ecp_dir_sel_dir", rv);
- ecp_dir_list_destroy(dir_list);
+ dir_conn = malloc(sizeof(ECPConnection));
+ if (dir_conn == NULL) LOG("dir_conn malloc", ECP_ERR_ALLOC);
+
+ rv = ecp_dir_get(dir_conn, conn->sock, &public, &addr, 0);
+ LOG("ecp_dir_get", rv);
+
+ return;
+ }
+ LOG("handle_dir_list", err);
+
+ if (_dir_list) ecp_dir_list_destroy(_dir_list);
+ _dir_list = dir_list;
+
+ vconn_open(conn->sock);
}
static void usage(char *arg) {
@@ -70,7 +103,14 @@ static void usage(char *arg) {
}
int main(int argc, char *argv[]) {
+ ECPContext ctx;
+ ECPSocket sock;
ECPDHKey key_perma;
+ ECPConnHandler handler;
+ ECPConnHandler vconn_handler;
+ ECPConnHandler vlink_handler;
+ ECPConnHandler dir_handler;
+ ECPConnection *dir_conn;
ecp_tr_addr_t addr;
ecp_ecdh_public_t public;
int rv;
@@ -79,6 +119,7 @@ int main(int argc, char *argv[]) {
rv = ecp_init(&ctx, &vconn_handler, &vlink_handler);
LOG("ecp_init", rv);
+ vconn_handler.handle_err = handle_err;
rv = ecp_dir_set_handler(&ctx, &dir_handler, handle_dir_list);
LOG("ecp_dir_set_handler", rv);
@@ -110,7 +151,10 @@ int main(int argc, char *argv[]) {
rv = ecp_util_load_key(argv[3], &public, NULL);
LOG("ecp_util_load_key", rv);
- rv = ecp_dir_get(&dir_conn, &sock, &public, &addr, 0);
+ dir_conn = malloc(sizeof(ECPConnection));
+ if (dir_conn == NULL) LOG("dir_conn malloc", ECP_ERR_ALLOC);
+
+ rv = ecp_dir_get(dir_conn, &sock, &public, &addr, 0);
LOG("ecp_dir_get", rv);
while (1) sleep(1);