Navigation


Changeset 658:f198d16fa7f4 in freeDiameter for freeDiameterd/main.c


Ignore:
Timestamp:
Jan 14, 2011, 3:15:23 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Initial commit for 1.1.0:

  • Restructuring:
    • libfreeDiameter:
      • renamed folder & binary into libfdproto
      • renamed libfD.h into fdproto-internal.h
      • removed signals management (replaced by triggers in libfdcore)
  • freeDiameter split into:
    • libfdcore (most contents)
      • renamed fD.h into fdcore-internal.h
      • added core.c for framework init/shutdown.
      • new triggers mechanism in events.c.
  • freeDiameterd (main, command line parsing, signals management)
  • tests:
    • now in top-level directory tests.
  • other changes:
    • fd_dict_new now returns 0 on duplicate identical entries.
    • fixes in dict_legacy_xml
    • fixes in some dictionaries
    • moved FD_DEFAULT_CONF_FILENAME definition to freeDiameter-host.h
File:
1 moved

Legend:

Unmodified
Added
Removed
  • freeDiameterd/main.c

    r628 r658  
    3434*********************************************************************************************************/
    3535
    36 #include "fD.h"
     36#include <freeDiameter/freeDiameter-host.h>
     37#include <freeDiameter/libfdcore.h>
    3738
    3839#include <signal.h>
    3940#include <getopt.h>
    4041#include <locale.h>
    41 #include <gcrypt.h>
     42
    4243
    4344/* forward declarations */
    44 static void fd_shutdown(int signal);
    4545static int main_cmdline(int argc, char *argv[]);
    46 static void main_version(void);
    47 static void main_help( void );
    48 static int signal_framework_ready(void);
    49 
    50 /* The static configuration structure */
    51 static struct fd_config conf;
    52 struct fd_config * fd_g_config = &conf;
    53 
    54 /* gcrypt functions to support posix threads */
    55 GCRY_THREAD_OPTION_PTHREAD_IMPL;
    56 
    57 /* freeDiameter starting point */
    58 int main(int argc, char * argv[])
    59 {
    60         int ret;
    61        
    62         memset(fd_g_config, 0, sizeof(struct fd_config));
    63        
    64         /* Initialize the library -- must come first since it initializes the debug facility */
    65         CHECK_FCT( fd_lib_init(1) );
    66         TRACE_DEBUG(INFO, "libfreeDiameter initialized.");
    67        
    68         /* Name this thread */
    69         fd_log_threadname("Main");
    70        
    71         /* Initialize gcrypt and gnutls */
    72         GNUTLS_TRACE( (void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread) );
    73         GNUTLS_TRACE( (void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0) );
    74         CHECK_GNUTLS_DO( gnutls_global_init(), return EINVAL );
    75         if ( ! gnutls_check_version(GNUTLS_VERSION) ) {
    76                 fprintf(stderr, "The GNUTLS library is too old; found '%s', need '" GNUTLS_VERSION "'\n", gnutls_check_version(NULL));
    77                 return EINVAL;
    78         } else {
    79                 TRACE_DEBUG(INFO, "libgnutls '%s', libgcrypt '%s', initialized.", gnutls_check_version(NULL), gcry_check_version(NULL) );
    80         }
    81        
    82         /* Initialize the config */
    83         CHECK_FCT( fd_conf_init() );
    84 
    85         /* Parse the command-line */
    86         CHECK_FCT(  main_cmdline(argc, argv)  );
    87        
    88         /* Allow SIGINT and SIGTERM from this point to terminate the application */
    89         CHECK_FCT( fd_sig_register(SIGINT,  "freeDiameter.main", fd_shutdown) );
    90         CHECK_FCT( fd_sig_register(SIGTERM, "freeDiameter.main", fd_shutdown) );
    91        
    92         /* Add definitions of the base protocol */
    93         CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) );
    94        
    95         /* Initialize other modules */
    96         CHECK_FCT(  fd_queues_init()  );
    97         CHECK_FCT(  fd_msg_init()  );
    98         CHECK_FCT(  fd_sess_start()  );
    99         CHECK_FCT(  fd_p_expi_init()  );
    100        
    101         /* Parse the configuration file */
    102         CHECK_FCT( fd_conf_parse() );
    103        
    104         /* Create the daemon's threads */
    105         CHECK_FCT(  fd_rtdisp_init()  );
    106        
    107         /* Load the dynamic extensions */
    108         CHECK_FCT(  fd_ext_load()  );
    109        
    110         fd_conf_dump();
    111         fd_sig_dump(FULL, 1);
    112        
    113         /* Start the servers */
    114         CHECK_FCT( fd_servers_start() );
    115        
    116         /* Start the peer state machines */
    117         CHECK_FCT( fd_psm_start() );
    118        
    119         /* Now, just wait for events */
    120         TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
    121         CHECK_FCT( signal_framework_ready() );
    122         while (1) {
    123                 int code; size_t sz; void * data;
    124                 CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data),  break  );
    125                 switch (code) {
    126                         case FDEV_DUMP_DICT:
    127                                 fd_dict_dump(fd_g_config->cnf_dict);
    128                                 break;
    129                        
    130                         case FDEV_DUMP_EXT:
    131                                 fd_ext_dump();
    132                                 break;
    133                        
    134                         case FDEV_DUMP_SERV:
    135                                 fd_servers_dump();
    136                                 break;
    137                        
    138                         case FDEV_DUMP_QUEUES:
    139                                 fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk);
    140                                 fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk);
    141                                 fd_fifo_dump(0, "Local messages",    fd_g_local,    fd_msg_dump_walk);
    142                                 break;
    143                        
    144                         case FDEV_DUMP_CONFIG:
    145                                 fd_conf_dump();
    146                                 break;
    147                        
    148                         case FDEV_DUMP_PEERS:
    149                                 fd_peer_dump_list(FULL);
    150                                 break;
    151                        
    152                         case FDEV_TERMINATE:
    153                                 ret = 0;
    154                                 goto end;
    155                        
    156                         default:
    157                                 TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), ignored.\n", code);
    158                 }
    159         }
    160        
    161 end:
    162         TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
    163        
    164         /* cleanups */
    165         CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ );
    166         CHECK_FCT_DO( fd_rtdisp_cleanstop(), /* Stop dispatch thread(s) after a clean loop if possible */ );
    167         CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
    168         CHECK_FCT_DO( fd_rtdisp_fini(), /* Stop routing threads and destroy routing queues */ );
    169        
    170         CHECK_FCT_DO( fd_ext_term(), /* Cleanup all extensions */ );
    171         CHECK_FCT_DO( fd_rtdisp_cleanup(), /* destroy remaining handlers */ );
    172        
    173         GNUTLS_TRACE( gnutls_global_deinit() );
    174        
    175         CHECK_FCT_DO( fd_conf_deinit(), );
    176        
    177         fd_log_debug(FD_PROJECT_BINARY " daemon is terminated.\n");
    178        
    179         fd_lib_fini();
    180        
    181         return ret;
    182 }
     46static void * catch_signals(void * arg);
     47static pthread_t signals_thr;
     48
     49static char *conffile = NULL;
     50static int gnutls_debug = 0;
    18351
    18452/* gnutls debug */
     
    18755}
    18856
    189 /* Parse the command-line */
    190 static int main_cmdline(int argc, char *argv[])
    191 {
    192         int c;
    193         int option_index = 0;
    194         char * locale;
    195        
    196         struct option long_options[] = {
    197                 { "help",       no_argument,            NULL, 'h' },
    198                 { "version",    no_argument,            NULL, 'V' },
    199                 { "config",     required_argument,      NULL, 'c' },
    200                 { "debug",      no_argument,            NULL, 'd' },
    201                 { "quiet",      no_argument,            NULL, 'q' },
    202                 { "dbglocale",  optional_argument,      NULL, 'l' },
    203                 { "dbg_func",   required_argument,      NULL, 'f' },
    204                 { "dbg_file",   required_argument,      NULL, 'F' },
    205                 { "dbg_gnutls", required_argument,      NULL, 'g' },
    206                 { NULL,         0,                      NULL, 0 }
    207         };
    208        
    209         TRACE_ENTRY("%d %p", argc, argv);
    210        
    211         /* Loop on arguments */
    212         while (1) {
    213                 c = getopt_long (argc, argv, "hVc:dql:", long_options, &option_index);
    214                 if (c == -1)
    215                         break;  /* Exit from the loop.  */
    216                
    217                 switch (c) {
    218                         case 'h':       /* Print help and exit.  */
    219                                 main_help();
    220                                 exit(0);
    221 
    222                         case 'V':       /* Print version and exit.  */
    223                                 main_version();
    224                                 exit(0);
    225 
    226                         case 'c':       /* Read configuration from this file instead of the default location..  */
    227                                 CHECK_PARAMS( optarg );
    228                                 fd_g_config->cnf_file = optarg;
    229                                 break;
    230 
    231                         case 'l':       /* Change the locale.  */
    232                                 locale = setlocale(LC_ALL, optarg?:"");
    233                                 if (locale) {
    234                                         TRACE_DEBUG(INFO, "Locale set to: %s", optarg ?: locale);
    235                                 } else {
    236                                         TRACE_DEBUG(INFO, "Unable to set locale (%s)", optarg);
    237                                         return EINVAL;
    238                                 }
    239                                 break;
    240 
    241                         case 'd':       /* Increase verbosity of debug messages.  */
    242                                 fd_g_debug_lvl++;
    243                                 break;
    244                                
    245                         case 'f':       /* Full debug for the function with this name.  */
    246                                 #ifdef DEBUG
    247                                 fd_debug_one_function = optarg;
    248                                 #else /* DEBUG */
    249                                 TRACE_DEBUG(INFO, "Error: must compile with DEBUG support to use this feature");
    250                                 return EINVAL;
    251                                 #endif /* DEBUG */
    252                                 break;
    253                                
    254                         case 'F':       /* Full debug for the file with this name.  */
    255                                 #ifdef DEBUG
    256                                 fd_debug_one_file = basename(optarg);
    257                                 #else /* DEBUG */
    258                                 TRACE_DEBUG(INFO, "Error: must compile with DEBUG support to use this feature");
    259                                 return EINVAL;
    260                                 #endif /* DEBUG */
    261                                 break;
    262                                
    263                         case 'g':       /* Full debug for the function with this name.  */
    264                                 {
    265                                         int l = (int)atoi(optarg);
    266                                         if (l) {
    267                                                 gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug);
    268                                                 gnutls_global_set_log_level (l);
    269                                                 TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", l);
    270                                         }
    271                                 }
    272                                 break;
    273                                
    274                         case 'q':       /* Decrease verbosity then remove debug messages.  */
    275                                 fd_g_debug_lvl--;
    276                                 break;
    277 
    278                         case '?':       /* Invalid option.  */
    279                                 /* `getopt_long' already printed an error message.  */
    280                                 TRACE_DEBUG(INFO, "getopt_long found an invalid character");
    281                                 return EINVAL;
    282 
    283                         default:        /* bug: option not considered.  */
    284                                 TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c", c);
    285                                 ASSERT(0);
    286                                 return EINVAL;
    287                 }
    288         }
    289                
     57
     58/* freeDiameter starting point */
     59int main(int argc, char * argv[])
     60{
     61        int ret;
     62        sigset_t sig_all;
     63       
     64        /* Block all signals from the current thread and all its future children */
     65        sigfillset(&sig_all);
     66        ret = pthread_sigmask(SIG_BLOCK, &sig_all, NULL);
     67        ASSERT(ret == 0);
     68       
     69        /* Parse the command-line */
     70        ret = main_cmdline(argc, argv);
     71        if (ret != 0) {
     72                return ret;
     73        }
     74       
     75        /* Initialize the core library */
     76        ret = fd_core_initialize();
     77        if (ret != 0) {
     78                fprintf(stderr, "An error occurred during freeDiameter core library initialization.\n");
     79                return ret;
     80        }
     81       
     82        /* Set gnutls debug level ? */
     83        if (gnutls_debug) {
     84                gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug);
     85                gnutls_global_set_log_level (gnutls_debug);
     86                TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug);
     87        }
     88               
     89        /* Allow SIGINT and SIGTERM from this point to terminate the application */
     90        CHECK_POSIX( pthread_create(&signals_thr, NULL, catch_signals, NULL) );
     91       
     92        /* Parse the configuration file */
     93        CHECK_FCT( fd_core_parseconf(conffile) );
     94       
     95        /* Start the servers */
     96        CHECK_FCT( fd_core_start() );
     97       
     98        TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
     99       
     100        /* Now, just wait for termination */
     101        CHECK_FCT( fd_core_wait_shutdown_complete() );
     102       
     103        /* Just in case it was not the result of a signal, we cancel signals_thr */
     104        fd_thr_term(&signals_thr);
     105       
    290106        return 0;
    291107}
     108
    292109
    293110/* Display package version */
     
    302119                ")"
    303120#endif /* HG_VERSION */
    304                 "\n",
     121                " (libfdcore: %s)\n",
    305122                FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV
    306123#ifdef HG_VERSION
     
    310127# endif /* PACKAGE_HG_VERSION */
    311128#endif /* HG_VERSION */
    312                 );
     129                , fd_core_version());
    313130}
    314131
     
    341158}
    342159
    343 /* Terminate the application */
    344 static void fd_shutdown(int signal)
    345 {
    346         TRACE_ENTRY("%d", signal);
    347        
    348         TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", fd_sig_abbrev(signal), signal);
    349 
    350         CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), exit(2) );
    351        
    352         return;
    353 }
    354 
    355 
    356 /* Signal extensions when the framework is completly initialized */
    357 static int             is_ready = 0;
    358 static pthread_mutex_t is_ready_mtx = PTHREAD_MUTEX_INITIALIZER;
    359 static pthread_cond_t  is_ready_cnd = PTHREAD_COND_INITIALIZER;
    360 static int signal_framework_ready(void)
    361 {
    362         TRACE_ENTRY("");
    363         CHECK_POSIX( pthread_mutex_lock( &is_ready_mtx ) );
    364         is_ready = 1;
    365         CHECK_POSIX( pthread_cond_broadcast( &is_ready_cnd ) );
    366         CHECK_POSIX( pthread_mutex_unlock( &is_ready_mtx ) );
     160/* Parse the command-line */
     161static int main_cmdline(int argc, char *argv[])
     162{
     163        int c;
     164        int option_index = 0;
     165        char * locale;
     166       
     167        struct option long_options[] = {
     168                { "help",       no_argument,            NULL, 'h' },
     169                { "version",    no_argument,            NULL, 'V' },
     170                { "config",     required_argument,      NULL, 'c' },
     171                { "debug",      no_argument,            NULL, 'd' },
     172                { "quiet",      no_argument,            NULL, 'q' },
     173                { "dbglocale",  optional_argument,      NULL, 'l' },
     174                { "dbg_func",   required_argument,      NULL, 'f' },
     175                { "dbg_file",   required_argument,      NULL, 'F' },
     176                { "dbg_gnutls", required_argument,      NULL, 'g' },
     177                { NULL,         0,                      NULL, 0 }
     178        };
     179       
     180        /* Loop on arguments */
     181        while (1) {
     182                c = getopt_long (argc, argv, "hVc:dql:", long_options, &option_index);
     183                if (c == -1)
     184                        break;  /* Exit from the loop.  */
     185               
     186                switch (c) {
     187                        case 'h':       /* Print help and exit.  */
     188                                main_help();
     189                                exit(0);
     190
     191                        case 'V':       /* Print version and exit.  */
     192                                main_version();
     193                                exit(0);
     194
     195                        case 'c':       /* Read configuration from this file instead of the default location..  */
     196                                if (optarg == NULL ) {
     197                                        fprintf(stderr, "Missing argument with --config directive\n");
     198                                        return EINVAL;
     199                                }
     200                                conffile = optarg;
     201                                break;
     202
     203                        case 'l':       /* Change the locale.  */
     204                                locale = setlocale(LC_ALL, optarg?:"");
     205                                if (!locale) {
     206                                        fprintf(stderr, "Unable to set locale (%s)\n", optarg);
     207                                        return EINVAL;
     208                                }
     209                                break;
     210
     211                        case 'd':       /* Increase verbosity of debug messages.  */
     212                                fd_g_debug_lvl++;
     213                                break;
     214                               
     215                        case 'f':       /* Full debug for the function with this name.  */
     216                                #ifdef DEBUG
     217                                fd_debug_one_function = optarg;
     218                                #else /* DEBUG */
     219                                fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_func feature!\n");
     220                                return EINVAL;
     221                                #endif /* DEBUG */
     222                                break;
     223                               
     224                        case 'F':       /* Full debug for the file with this name.  */
     225                                #ifdef DEBUG
     226                                fd_debug_one_file = basename(optarg);
     227                                #else /* DEBUG */
     228                                fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_file feature!\n");
     229                                return EINVAL;
     230                                #endif /* DEBUG */
     231                                break;
     232                               
     233                        case 'g':       /* Set a debug level and function for GNU TLS calls.  */
     234                                gnutls_debug = (int)atoi(optarg);
     235                                break;
     236                               
     237                        case 'q':       /* Decrease verbosity then remove debug messages.  */
     238                                fd_g_debug_lvl--;
     239                                break;
     240
     241                        case '?':       /* Invalid option.  */
     242                                /* `getopt_long' already printed an error message.  */
     243                                fprintf(stderr, "getopt_long found an invalid character\n");
     244                                return EINVAL;
     245
     246                        default:        /* bug: option not considered.  */
     247                                fprintf(stderr, "A command-line option is missing in parser: %c\n", c);
     248                                ASSERT(0);
     249                                return EINVAL;
     250                }
     251        }
     252               
    367253        return 0;
    368254}
    369 int fd_wait_initialization_complete(void)
    370 {
    371         TRACE_ENTRY("");
    372         CHECK_POSIX( pthread_mutex_lock( &is_ready_mtx ) );
    373         pthread_cleanup_push( fd_cleanup_mutex, &is_ready_mtx );
    374         while (!is_ready) {
    375                 CHECK_POSIX( pthread_cond_wait( &is_ready_cnd, &is_ready_mtx ) );
    376         }
    377         pthread_cleanup_pop( 0 );
    378         CHECK_POSIX( pthread_mutex_unlock( &is_ready_mtx ) );
    379         return 0;
    380 }
     255
     256/* Handle some signals */
     257static void * catch_signals(void * arg)
     258{
     259        sigset_t ss;
     260        fd_log_threadname ( "signals catcher" );
     261       
     262        sigemptyset(&ss);
     263       
     264        /* Signals that terminate the daemon */
     265        sigaddset(&ss, SIGTERM);
     266        sigaddset(&ss, SIGINT);
     267       
     268        /* Signals that send an event */
     269        sigaddset(&ss, SIGUSR1);
     270        sigaddset(&ss, SIGUSR2);
     271       
     272        /* Now loop on the reception of the signal */
     273        while (1) {
     274                int sig, *ps;
     275               
     276                /* Wait to receive the next signal */
     277                CHECK_POSIX_DO( sigwait(&ss, &sig), break );
     278               
     279                TRACE_DEBUG(FULL, "Signal %d caught", sig);
     280               
     281                switch (sig) {
     282                        case SIGUSR1:
     283                        case SIGUSR2:
     284                                CHECK_MALLOC_DO( ps = malloc(sizeof(int)), goto out);
     285                                *ps = sig;
     286                                CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TRIGGER, sizeof(int), ps), goto out );
     287                                break;
     288                               
     289                        case SIGINT:
     290                        case SIGTERM:
     291                                CHECK_FCT_DO( fd_core_shutdown(), goto out );
     292
     293                }
     294        }
     295out:   
     296        /* Better way to handle this ? */
     297        ASSERT(0);
     298        return NULL;
     299}
Note: See TracChangeset for help on using the changeset viewer.