Skip to content
Snippets Groups Projects
main.c 15.1 KiB
Newer Older
/*
 * Authors:
 * Dmitriy A. Gearasimov <kahovski@gmail.com>
 * DeM Labs Inc.   https://demlabs.net
 * DeM Labs Open source community https://github.com/demlabsinc
 * Copyright  (c) 2017-2019
 * All rights reserved.

 This file is part of DAP (Deus Applications Prototypes) the open source project

    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DAP is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
*/
ANTA's avatar
ANTA committed

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include <unistd.h>
#include <sys/types.h>
#include <getopt.h>
#include <signal.h>
ANTA's avatar
ANTA committed
#ifdef _WIN32
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <io.h>
//#include "wrappers.h"
#include <wepoll.h>
#include <pthread.h>
Constantin Papizh's avatar
Constantin Papizh committed
#include "userenv.h"
Station's avatar
Station committed

ANTA's avatar
ANTA committed
#endif

Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#define LOG_TAG "main"
ANTA's avatar
ANTA committed
#ifndef _WIN32
  #include "sig_unix_handler.h"
#else
Constantin Papizh's avatar
Constantin Papizh committed
    #include "sig_win32_handler.h"
    #include "registry.h"
    void  S_SetExceptionFilter( void );
ANTA's avatar
ANTA committed
#endif

#include "dap_config.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_server.h"
#include "dap_http.h"
#include "dap_http_folder.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_enc.h"
#include "dap_enc_ks.h"
#include "dap_enc_http.h"
ANTA's avatar
ANTA committed

#include "dap_chain.h"
#include "dap_chain_wallet.h"

#include "dap_chain_cs_dag.h"
#include "dap_chain_cs_dag_poa.h"
#include "dap_chain_cs_dag_pos.h"
#include "dap_chain_gdb.h"

#include "dap_chain_net.h"
#include "dap_chain_net_srv.h"
#include "dap_chain_net_srv_app.h"
#include "dap_chain_net_srv_app_db.h"
#include "dap_chain_net_srv_datum.h"
#include "dap_chain_net_srv_datum_pool.h"
#include "dap_chain_net_srv_vpn.h"
#include "dap_chain_global_db.h"
#include "dap_chain_mempool.h"
#include "dap_stream_session.h"
#include "dap_stream.h"
#include "dap_stream_ctl.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_stream_ch_vpn.h"
#include "dap_stream_ch_chain.h"
#include "dap_stream_ch_chain_net.h"
#include "dap_stream_ch_chain_net_srv.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_common.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_client_remote.h"
#include "dap_client.h"
#include "dap_http_client.h"
#include "dap_http_client_simple.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_http_simple.h"
#include "dap_process_manager.h"
#include "dap_traffic_track.h"

#include "dap_defines.h"
Constantin Papizh's avatar
Constantin Papizh committed
#include "dap_file_utils.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed

#define ENC_HTTP_URL "/enc_init"
#define STREAM_CTL_URL "/stream_ctl"
#define STREAM_URL "/stream"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#define SLIST_URL "/nodelist"
#define MEMPOOL_URL "/mempool"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#define MAIN_URL "/"

Constantin Papizh's avatar
Constantin Papizh committed
#ifndef MAX_PATH
#define MAX_PATH 120
#endif

ANTA's avatar
ANTA committed
void parse_args( int argc, const char **argv );
void exit_if_server_already_running( void );
static char s_pid_file_path[MAX_PATH];
Station's avatar
Station committed

ANTA's avatar
ANTA committed
int main( int argc, const char **argv )
Station's avatar
Station committed
	dap_server_t *l_server = NULL; // DAP Server instance
	bool bDebugMode = true;
	bool bServerEnabled = true;
	int rc = 0;

	#if defined(_WIN32) && defined(NDEBUG)
		S_SetExceptionFilter( );
	#endif

Constantin Papizh's avatar
Constantin Papizh committed
    {
        char l_log_file_path[MAX_PATH];
Constantin Papizh's avatar
Constantin Papizh committed
#ifdef _WIN32
        dap_sprintf(s_sys_dir_path, "%s/%s", regGetUsrPath(), DAP_APP_NAME);
        l_sys_dir_path_len = strlen(s_sys_dir_path);
        memcpy(l_log_file_path, s_sys_dir_path, l_sys_dir_path_len);
        memcpy(s_pid_file_path, s_sys_dir_path, l_sys_dir_path_len);
Constantin Papizh's avatar
Constantin Papizh committed
#endif
        memcpy( l_log_file_path + l_sys_dir_path_len, SYSTEM_LOGS_DIR, sizeof(SYSTEM_LOGS_DIR) );
Constantin Papizh's avatar
Constantin Papizh committed
        dap_mkdir_with_parents( l_log_file_path );
Station's avatar
Station committed

        dap_sprintf( l_log_file_path + l_sys_dir_path_len + sizeof(SYSTEM_LOGS_DIR) - 1, "/%s_logs.txt", DAP_APP_NAME );
Station's avatar
Station committed

Constantin Papizh's avatar
Constantin Papizh committed
        if ( dap_common_init( DAP_APP_NAME, l_log_file_path ) != 0 ) {
            printf( "Fatal Error: Can't init common functions module" );
            return -2;
        }
        memcpy( s_sys_dir_path + l_sys_dir_path_len, SYSTEM_CONFIGS_DIR, sizeof(SYSTEM_CONFIGS_DIR) );
        dap_config_init( s_sys_dir_path );
Station's avatar
Station committed

        memset(s_sys_dir_path + l_sys_dir_path_len, '\0', MAX_PATH - l_sys_dir_path_len);
Constantin Papizh's avatar
Constantin Papizh committed
        if ( (g_config = dap_config_open(DAP_APP_NAME)) == NULL ) {
            log_it( L_CRITICAL,"Can't init general configurations" );
            return -1;
        }
        dap_sprintf(s_pid_file_path + l_sys_dir_path_len, "%s", dap_config_get_item_str( g_config,
Constantin Papizh's avatar
Constantin Papizh committed
                                                                                   "resources",
                                                                                   "pid_path"));
Constantin Papizh's avatar
Constantin Papizh committed
    }
Station's avatar
Station committed
	parse_args( argc, argv );
	#ifdef _WIN32
	    CreateMutexW( NULL, FALSE, (WCHAR *) L"DAP_KELVIN_NODE_74E9201D33F7F7F684D2FEF1982799A79B6BF94B568446A8D1DE947B00E3C75060F3FD5BF277592D02F77D7E50935E56" );
	#endif

	//  bDebugMode = dap_config_get_item_bool_default( g_config,"general","debug_mode", false );
	  bDebugMode = true;//dap_config_get_item_bool_default( g_config,"general","debug_mode", false );

	if ( bDebugMode )
	    log_it( L_ATT, "*** DEBUG MODE ***" );
	else
 	   log_it( L_ATT, "*** NORMAL MODE ***" );

	dap_log_level_set( bDebugMode ? L_DEBUG: L_NOTICE );

	log_it( L_DAP, "*** Kelvin Node version: %s ***", "0.0.0" ); //DAP_SERVER_VERSION_STR );

	// change to dap_config_get_item_int_default when it's will be possible
	size_t l_thread_cnt = 0;

	const char *s_thrd_cnt = dap_config_get_item_str( g_config, "resources", "threads_cnt" );
	if ( s_thrd_cnt != NULL )
	    l_thread_cnt = (size_t)atoi( s_thrd_cnt );

	if ( !l_thread_cnt ) {
    	#ifndef _WIN32
      		l_thread_cnt = (size_t)sysconf(_SC_NPROCESSORS_ONLN);
    	#else
      		SYSTEM_INFO si;
      		GetSystemInfo( &si );
      		l_thread_cnt = si.dwNumberOfProcessors;
    	#endif
  	}

	if ( dap_server_init(l_thread_cnt) != 0 ) {
    	log_it( L_CRITICAL, "Can't init socket server module" );
	    return -4;
	}

	if ( dap_http_init() != 0 ) {
    	log_it( L_CRITICAL, "Can't init http server module" );
	    return -5;
	}

	if ( dap_http_folder_init() != 0 ){
	    log_it( L_CRITICAL, "Can't init http server module" );
	    return -55;
	}

	if ( dap_enc_init() != 0 ){
	    log_it( L_CRITICAL, "Can't init encryption module" );
	    return -56;
	}

	if ( dap_enc_ks_init( false, 60 *60 * 2 ) != 0 ) {
		log_it( L_CRITICAL, "Can't init encryption key storage module" );
		return -57;
	}
Station's avatar
Station committed
	if ( dap_chain_global_db_init(g_config) ) {
	    log_it( L_CRITICAL, "Can't init global db module" );
	    return -58;
	}
Station's avatar
Station committed
	dap_client_init();
Station's avatar
Station committed
	dap_http_client_simple_init( );
Station's avatar
Station committed
	if ( dap_datum_mempool_init() ) {
	    log_it( L_CRITICAL, "Can't init mempool module" );
	    return -59;
	}
    if( dap_chain_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain modules");
    }

    if( dap_chain_wallet_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain wallet module");
    if( dap_chain_cs_dag_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain dag consensus module");
        return -62;
    if( dap_chain_cs_dag_poa_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain dag consensus PoA module");
        return -63;
    if( dap_chain_cs_dag_pos_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain dag consensus PoA module");
        return -64;
    if(dap_chain_gdb_init() != 0) {
        log_it(L_CRITICAL, "Can't init dap chain gdb module");
        return -71;
    }

    if( dap_chain_net_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain network module");
        return -65;
    }

    if( dap_chain_net_srv_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain network service module");
        return -66;
ANTA's avatar
ANTA committed
#if 0
    if( dap_chain_net_srv_app_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain network service applications module");
        return -67;
    }

    if( dap_chain_net_srv_datum_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain network service datum module");
        return -68;
ANTA's avatar
ANTA committed

    if( dap_chain_net_srv_datum_pool_init() !=0){
        log_it(L_CRITICAL,"Can't init dap chain network service datum pool module");
        return -69;
    if( dap_chain_net_srv_vpn_init(g_config) !=0){
        log_it(L_ERROR,"Can't init dap chain network service vpn module");
        //return -70;
ANTA's avatar
ANTA committed
#endif

Station's avatar
Station committed
	if ( enc_http_init() != 0 ) {
	    log_it( L_CRITICAL, "Can't init encryption http session storage module" );
	    return -81;
	}
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	if ( dap_stream_init(dap_config_get_item_bool_default(g_config,"general","debug_dump_stream_headers",false)) != 0 ) {
	    log_it( L_CRITICAL, "Can't init stream server module" );
	    return -82;
	}
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	if ( dap_stream_ctl_init(DAP_ENC_KEY_TYPE_OAES, 32) != 0 ){
	    log_it( L_CRITICAL, "Can't init stream control module" );
	    return -83;
	}
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	if ( dap_http_simple_module_init() != 0 ) {
	    log_it(L_CRITICAL,"Can't init http simple module");
	    return -9;
	}
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	if ( dap_chain_node_cli_init(g_config) ) {
	    log_it( L_CRITICAL, "Can't init server for console" );
	    return -11;
	}
ANTA's avatar
ANTA committed

#ifndef _WIN32
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
    if (sig_unix_handler_init(dap_config_get_item_str_default(g_config,
                                                              "resources",
                                                              "pid_path",
                                                              SYSTEM_PID_FILE_PATH)) != 0) {
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
        log_it(L_CRITICAL,"Can't init sig unix handler module");
ANTA's avatar
ANTA committed
        return -12;
ANTA's avatar
ANTA committed
#else
    if ( sig_win32_handler_init( NULL ) ) {
        log_it( L_CRITICAL,"Can't init sig win32 handler module" );
        return -12;
    }
#endif
Constantin Papizh's avatar
Constantin Papizh committed
    save_process_pid_in_file(s_pid_file_path);
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	bServerEnabled = dap_config_get_item_bool_default( g_config, "server", "enabled", false );
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	log_it ( L_DEBUG,"config server->enabled = \"%u\" ", bServerEnabled );

	if ( bServerEnabled ) {

Constantin Papizh's avatar
Constantin Papizh committed
        int32_t l_port = dap_config_get_item_int32(g_config, "server", "listen_port_tcp");
Constantin Papizh's avatar
Constantin Papizh committed
            l_server = dap_server_listen((dap_config_get_item_str(g_config, "server", "listen_address")),
ANTA's avatar
ANTA committed
                                   DAP_SERVER_TCP );
        } else
            log_it( L_WARNING, "Server is enabled but no port is defined" );
ANTA's avatar
ANTA committed
    if ( l_server ) { // If listener server is initialized
        //bool is_traffick_track_enable = dap_config_get_item_bool_default(g_config, "traffic_track", "enable", false);
ANTA's avatar
ANTA committed
#if 0
        if ( is_traffick_track_enable ) {
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
            time_t timeout = // TODO add default timeout (get_item_int32_default)
                    dap_config_get_item_int32(g_config, "traffic_track", "callback_timeout");

ANTA's avatar
ANTA committed
            dap_traffic_track_init( l_server, timeout );
            dap_traffic_callback_set( dap_chain_net_srv_traffic_callback );
            //dap_traffic_callback_set(db_auth_traffic_track_callback);
ANTA's avatar
ANTA committed
#endif
        // TCP-specific things
Station's avatar
Station committed
		if ( dap_config_get_item_int32_default(g_config, "server", "listen_port_tcp",-1) > 0) {
            // Init HTTP-specific values
Station's avatar
Station committed
	    	dap_http_new( l_server, DAP_APP_NAME );
Station's avatar
Station committed
	        // Handshake URL
	        enc_http_add_proc( DAP_HTTP(l_server), ENC_HTTP_URL );
Station's avatar
Station committed
	        // Streaming URLs
	        dap_stream_add_proc_http( DAP_HTTP(l_server), STREAM_URL );
	        dap_stream_ctl_add_proc( DAP_HTTP(l_server), STREAM_CTL_URL );
Station's avatar
Station committed
	        const char *str_start_mempool = dap_config_get_item_str( g_config, "mempool", "accept" );
	        if ( str_start_mempool && !strcmp(str_start_mempool, "true")) {
	                dap_chain_mempool_add_proc(DAP_HTTP(l_server), MEMPOOL_URL);
	        }
Station's avatar
Station committed
	        // Built in WWW server
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed

Station's avatar
Station committed
	        if (  dap_config_get_item_bool_default(g_config,"www","enabled",false)  ){
	                dap_http_folder_add( DAP_HTTP(l_server), "/",
	                                dap_config_get_item_str(g_config,
ANTA's avatar
ANTA committed
                                                                "www_root") );
Station's avatar
Station committed
	        }
Station's avatar
Station committed
		}
ANTA's avatar
ANTA committed
    } else
Station's avatar
Station committed
        log_it( L_INFO, "No enabled server, working in client mode only" );


ANTA's avatar
ANTA committed
///    if (dap_config_get_item_bool_default(g_config,"vpn","enabled",false)){
///        dap_stream_ch_vpn_init(dap_config_get_item_str_default(g_config, "vpn", "network_address", NULL),
///                   dap_config_get_item_str_default(g_config, "vpn", "network_mask", NULL));
///
///    }
Station's avatar
Station committed
	dap_stream_ch_chain_init( );
	dap_stream_ch_chain_net_init( );
ANTA's avatar
ANTA committed

///    dap_stream_ch_chain_net_srv_init();
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
    // New event loop init
Station's avatar
Station committed
	dap_events_init( 0, 0 );
	dap_events_t *l_events = dap_events_new( );
	dap_events_start( l_events );
ANTA's avatar
ANTA committed

///    if (dap_config_get_item_bool_default(g_config,"vpn","enabled",false))
///        dap_stream_ch_vpn_deinit();
Station's avatar
Station committed
	dap_chain_net_load_all();
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	// Endless loop for server's requests processing
	rc = dap_server_loop(l_server);
	// After loop exit actions
	log_it( rc ? L_CRITICAL : L_NOTICE, "Server loop stopped with return code %d", rc );
Constantin Papizh's avatar
Constantin Papizh committed
failure:
Station's avatar
Station committed

	dap_stream_deinit();
	dap_stream_ctl_deinit();
	dap_http_folder_deinit();
	dap_http_deinit();
	dap_server_deinit();
	dap_enc_ks_deinit();

	dap_config_close( g_config );
	dap_common_deinit();

	return rc * 10;
ANTA's avatar
ANTA committed
static struct option long_options[] = {

Station's avatar
Station committed
	{ "stop", 0, NULL, 0 },
	{ NULL,   0, NULL, 0 } // must be a last element
ANTA's avatar
ANTA committed
};

void parse_args( int argc, const char **argv ) {
Station's avatar
Station committed
	int opt, option_index = 0, is_daemon = 0;
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	while ( (opt = getopt_long(argc, (char *const *)argv, "D0",
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
                              long_options, &option_index)) != -1) {
Station's avatar
Station committed
	    switch ( opt ) {

	    case 0: // --stop
    	{
Constantin Papizh's avatar
Constantin Papizh committed
            pid_t pid = get_pid_from_file(s_pid_file_path);
Station's avatar
Station committed

	    	if ( pid == 0 ) {
	        	log_it( L_ERROR, "Can't read pid from file" );
	        	exit( -20 );
	      	} 

	    	if ( kill_process(pid) ) {
	        	log_it( L_INFO, "Server successfully stopped" );
	        	exit( 0 );
	      	}

	    	log_it( L_WARNING, "Server not stopped. Maybe he is not running now?" );
	    	exit( -21 );
	    }

    	case 'D': 
    	{
        	log_it( L_INFO, "Daemonize server starting..." );
        	exit_if_server_already_running( );
        	is_daemon = 1;
        	daemonize_process( );
        	break;
      	}

      	default:
        log_it( L_WARNING, "Unknown option from command line" );
		}
	}

	if( !is_daemon )
		exit_if_server_already_running( );
}
Station's avatar
Station committed
void exit_if_server_already_running( void ) {
ANTA's avatar
ANTA committed

Constantin Papizh's avatar
Constantin Papizh committed
    pid_t pid = get_pid_from_file(s_pid_file_path);
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	bool  mf = false;
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	#ifdef _WIN32
    	CreateMutexW( NULL, FALSE, (WCHAR *) L"DAP_KELVIN_NODE_74E9201D33F7F7F684D2FEF1982799A79B6BF94B568446A8D1DE947B00E3C75060F3FD5BF277592D02F77D7E50935E56" );
ANTA's avatar
ANTA committed

Station's avatar
Station committed
		if ( GetLastError( ) == 183 ) {
      		mf = true;
    	}
	#endif
ANTA's avatar
ANTA committed

Station's avatar
Station committed
	if ( (pid != 0 && is_process_running(pid)) || mf ) {
    	log_it( L_WARNING, "Proccess %d is running, don't allow "
        	                "to run more than one copy of DapServer, exiting...", pid );
		exit( -2 );
	}