From 4a6d383192ac59195cfe927f5a0b1eb104da5550 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Thu, 6 Jun 2024 22:33:46 +0200 Subject: open / keyx sync implemented; vconn close fixed; rendezvous hashing fixed --- ecp/server/dir.c | 8 +- ecp/server/dir.h | 4 +- ecp/server/server.c | 173 +++++++++++++++++++++----------- ecp/server/server.h | 10 +- ecp/server/sig.c | 4 - ecp/server/vlink.h | 1 + ecp/src/ecp/common.mk | 3 + ecp/src/ecp/core.c | 94 ++++++++++++++++- ecp/src/ecp/core.h | 17 +++- ecp/src/ecp/crypto/crypto.c | 14 ++- ecp/src/ecp/dir/dir.c | 32 +++++- ecp/src/ecp/dir/dir.h | 2 + ecp/src/ecp/dir/dir_client.c | 96 ++++++++++++++---- ecp/src/ecp/dir/dir_client.h | 9 +- ecp/src/ecp/vconn/vconn.c | 57 ++++------- ecp/src/ecp/vconn/vconn.h | 1 - ecp/src/platform/posix/features_tmpl.mk | 1 + ecp/test/dir.c | 8 +- ecp/test/vconn_inb.c | 86 ++++++++++++---- ecp/test/vconn_outb.c | 92 ++++++++++++----- 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; icount; i++) { - if (list->items[i].roles & ECP_ROLE_DIR) dir_cnt++; + for (i=0; icount; 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; icount; i++) { - dir_process_item(&list->items[i], sock, NULL); + for (i=0; icount; 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> 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; icount; 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; icount; 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; icount; 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; icount; 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; icount - 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[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; jcount; 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 #include #include +#include #include #include @@ -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; icount; 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); -- cgit v1.2.3