Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions src/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -2512,6 +2512,110 @@ nc_session_tls_crl_verify_post_handshake(void *tls_session, void *cert_store)

#endif /* NC_ENABLED_SSH_TLS */

/**
* @brief Initialize or destroy the global state of the libraries used by libnetconf2.
*
* @param[in] side Side that is being initialized/destroyed.
* @param[in] destroy Whether to destroy the global state instead of initializing it.
* @return 0 on success, -1 on error.
*/
static int
nc_global_init_destroy(NC_SIDE side, int destroy)
{
#ifdef NC_ENABLED_SSH_TLS
/* lock protecting the init flags and the global init of the libraries, which is not thread-safe */
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

/* whether the client/server side has the libraries initialized */
static int init_client = 0, init_server = 0;

int rc = 0, curl_inited = 0, tls_inited = 0, *inited;

inited = (side == NC_CLIENT) ? &init_client : &init_server;

/* GLOBAL INIT LOCK */
pthread_mutex_lock(&lock);

if (destroy) {
if (!*inited) {
/* this side has not initialized the libraries */
goto cleanup;
}
*inited = 0;

if (!init_client && !init_server) {
/* the last side using the libraries, destroy them in the reverse order */
ssh_finalize();
nc_tls_backend_destroy_wrap();
curl_global_cleanup();
}
goto cleanup;
}

if (init_client || init_server) {
/* the libraries are already initialized by the other side */
*inited = 1;
goto cleanup;
}

if (curl_global_init(CURL_GLOBAL_SSL | CURL_GLOBAL_ACK_EINTR)) {
ERR(NULL, "%s: failed to init CURL.", __func__);
rc = -1;
goto cleanup;
}
curl_inited = 1;

if (nc_tls_backend_init_wrap()) {
ERR(NULL, "%s: failed to init the SSL library backend.", __func__);
rc = -1;
goto cleanup;
}
tls_inited = 1;

/* optional for dynamic library, mandatory for static */
if (ssh_init()) {
ERR(NULL, "%s: failed to init libssh.", __func__);
rc = -1;
goto cleanup;
}

*inited = 1;

cleanup:
if (rc) {
/* leave no library initialized behind */
if (tls_inited) {
nc_tls_backend_destroy_wrap();
}
if (curl_inited) {
curl_global_cleanup();
}
}

/* GLOBAL INIT UNLOCK */
pthread_mutex_unlock(&lock);

return rc;
#else
(void)side;
(void)destroy;

return 0;
#endif /* NC_ENABLED_SSH_TLS */
}

int
nc_global_init(NC_SIDE side)
{
return nc_global_init_destroy(side, 0);
}

void
nc_global_destroy(NC_SIDE side)
{
nc_global_init_destroy(side, 1);
}

API const char *
nc_yang_module_dir(void)
{
Expand Down
17 changes: 3 additions & 14 deletions src/session_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1908,18 +1908,7 @@ nc_session_ntf_thread_running(const struct nc_session *session)
API int
nc_client_init(void)
{
#ifdef NC_ENABLED_SSH_TLS
if (nc_tls_backend_init_wrap()) {
ERR(NULL, "%s: failed to init the SSL library backend.", __func__);
return -1;
}
if (ssh_init()) {
ERR(NULL, "%s: failed to init libssh.", __func__);
return -1;
}
#endif

return 0;
return nc_global_init(NC_CLIENT);
}

API void
Expand All @@ -1931,9 +1920,9 @@ nc_client_destroy(void)
nc_client_ch_del_bind(NULL, 0, 0);
nc_client_ssh_destroy_opts();
nc_client_tls_destroy_opts();
nc_tls_backend_destroy_wrap();
ssh_finalize();
#endif /* NC_ENABLED_SSH_TLS */

nc_global_destroy(NC_CLIENT);
}

static NC_MSG_TYPE
Expand Down
15 changes: 15 additions & 0 deletions src/session_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,21 @@ int nc_poll(struct pollfd *pfd, uint16_t pfd_count, int timeout);
*/
int nc_sock_configure_ka(int sock, const struct nc_keepalives *ka);

/**
* @brief Initialize the global state of the libraries used by libnetconf2.
*
* @param[in] side Side that is being initialized.
* @return 0 on success, -1 on error.
*/
int nc_global_init(NC_SIDE side);

/**
* @brief Destroy the global state of the libraries used by libnetconf2.
*
* @param[in] side Side that is being destroyed.
*/
void nc_global_destroy(NC_SIDE side);

struct nc_session *nc_new_session(NC_SIDE side, int shared_ti);

int nc_session_rpc_lock(struct nc_session *session, int timeout, const char *func);
Expand Down
29 changes: 11 additions & 18 deletions src/session_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,8 @@ nc_server_init_rwlock(pthread_rwlock_t *rwlock)
API int
nc_server_init(void)
{
int glob_inited = 0;

#ifdef NC_ENABLED_SSH_TLS
int r;
#endif /* NC_ENABLED_SSH_TLS */
Expand All @@ -1547,23 +1549,13 @@ nc_server_init(void)
ATOMIC_STORE_RELAXED(server_opts.config->refcount, 1);
ATOMIC_STORE_RELAXED(server_opts.idle_timeout, 0);

#ifdef NC_ENABLED_SSH_TLS
if (curl_global_init(CURL_GLOBAL_SSL | CURL_GLOBAL_ACK_EINTR)) {
ERR(NULL, "%s: failed to init CURL.", __func__);
goto error;
}

if (nc_tls_backend_init_wrap()) {
ERR(NULL, "%s: failed to init the SSL library backend.", __func__);
goto error;
}

/* optional for dynamic library, mandatory for static */
if (ssh_init()) {
ERR(NULL, "%s: failed to init libssh.", __func__);
/* initialize the global state of the used libraries, shared with the client side */
if (nc_global_init(NC_SERVER)) {
goto error;
}
glob_inited = 1;

#ifdef NC_ENABLED_SSH_TLS
if ((r = pthread_mutex_init(&server_opts.cert_exp_notif.lock, NULL))) {
ERR(NULL, "%s: failed to init certificate expiration notification thread lock(%s).", __func__, strerror(r));
goto error;
Expand All @@ -1584,6 +1576,9 @@ nc_server_init(void)
nc_server_config_release(server_opts.config);
server_opts.config = NULL;
ATOMIC_STORE_RELAXED(server_opts.new_session_id, 0);
if (glob_inited) {
nc_global_destroy(NC_SERVER);
}
return -1;
}

Expand Down Expand Up @@ -1701,17 +1696,15 @@ nc_server_destroy(void)
nc_server_config_release(config);

#ifdef NC_ENABLED_SSH_TLS
curl_global_cleanup();
nc_tls_backend_destroy_wrap();
ssh_finalize();

/* close the TLS keylog file */
if (server_opts.tls_keylog_file) {
fclose(server_opts.tls_keylog_file);
server_opts.tls_keylog_file = NULL;
}
#endif /* NC_ENABLED_SSH_TLS */

nc_global_destroy(NC_SERVER);

cleanup:
if (opts_locked) {
nc_rwlock_unlock(&server_opts.opts_lock, __func__);
Expand Down
2 changes: 2 additions & 0 deletions tests/test_thread_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ server_thread(void *arg)
pthread_barrier_wait(&barrier);

nc_server_notif_free(notif);
nc_assert(!nc_server_destroy());
return arg;
}

Expand Down Expand Up @@ -227,6 +228,7 @@ main(void)

/* cleanup */
nc_session_free(sess, NULL);
nc_client_destroy();
ly_ctx_destroy(server_ctx);
ly_ctx_destroy(client_ctx);
for (uint8_t i = 0; i < 4; i++) {
Expand Down