#include "config.h"
#include <stdio.h>
#include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/dh.h"
#include "libssh/poll.h"
#include "libssh/threads.h"
#ifdef _WIN32
#include <winsock2.h>
#endif
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
#else
#define CONSTRUCTOR_ATTRIBUTE
#endif
#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
#define DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
#else
#define DESTRUCTOR_ATTRIBUTE
#endif
static SSH_MUTEX ssh_init_mutex = SSH_MUTEX_STATIC_INIT;
static int _ssh_initialized = 0;
static int _ssh_init_ret = 0;
void libssh_constructor(void) CONSTRUCTOR_ATTRIBUTE;
void libssh_destructor(void) DESTRUCTOR_ATTRIBUTE;
static int _ssh_init(unsigned constructor) {
int rc = 0;
if (!constructor) {
ssh_mutex_lock(&ssh_init_mutex);
}
_ssh_initialized++;
if (_ssh_initialized > 1) {
rc = _ssh_init_ret;
goto _ret;
}
rc = ssh_threads_init();
if (rc) {
goto _ret;
}
rc = ssh_crypto_init();
if (rc) {
goto _ret;
}
rc = ssh_dh_init();
if (rc) {
goto _ret;
}
rc = ssh_socket_init();
if (rc) {
goto _ret;
}
_ret:
_ssh_init_ret = rc;
if (!constructor) {
ssh_mutex_unlock(&ssh_init_mutex);
}
return rc;
}
void libssh_constructor(void)
{
int rc;
rc = _ssh_init(1);
if (rc < 0) {
fprintf(stderr, "Error in auto_init()\n");
}
return;
}
int ssh_init(void) {
return _ssh_init(0);
}
static int _ssh_finalize(unsigned destructor) {
if (!destructor) {
ssh_mutex_lock(&ssh_init_mutex);
if (_ssh_initialized > 1) {
_ssh_initialized--;
ssh_mutex_unlock(&ssh_init_mutex);
return 0;
}
if (_ssh_initialized == 1) {
if (_ssh_init_ret < 0) {
ssh_mutex_unlock(&ssh_init_mutex);
return 0;
}
}
}
ssh_dh_finalize();
ssh_crypto_finalize();
ssh_socket_cleanup();
ssh_threads_finalize();
_ssh_initialized = 0;
if (!destructor) {
ssh_mutex_unlock(&ssh_init_mutex);
}
#if (defined(_WIN32) && !defined(HAVE_PTHREAD))
if (ssh_init_mutex != NULL) {
DeleteCriticalSection(ssh_init_mutex);
SAFE_FREE(ssh_init_mutex);
}
#endif
return 0;
}
void libssh_destructor(void)
{
int rc;
rc = _ssh_finalize(1);
if (rc < 0) {
fprintf(stderr, "Error in libssh_destructor()\n");
}
}
int ssh_finalize(void) {
return _ssh_finalize(0);
}
#ifdef _WIN32
#if defined(_MSC_VER) && !defined(LIBSSH_STATIC)
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
int rc = 0;
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
rc = _ssh_init(1);
if (rc != 0) {
fprintf(stderr, "DllMain: ssh_init failed!");
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
_ssh_finalize(1);
break;
default:
break;
}
return TRUE;
}
#endif
#endif
bool is_ssh_initialized(void) {
bool is_initialized = false;
ssh_mutex_lock(&ssh_init_mutex);
is_initialized = _ssh_initialized > 0;
ssh_mutex_unlock(&ssh_init_mutex);
return is_initialized;
}