Changeset 658:f198d16fa7f4 in freeDiameter for freeDiameterd/main.c
- Timestamp:
- Jan 14, 2011, 3:15:23 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
freeDiameterd/main.c
r628 r658 34 34 *********************************************************************************************************/ 35 35 36 #include "fD.h" 36 #include <freeDiameter/freeDiameter-host.h> 37 #include <freeDiameter/libfdcore.h> 37 38 38 39 #include <signal.h> 39 40 #include <getopt.h> 40 41 #include <locale.h> 41 #include <gcrypt.h> 42 42 43 43 44 /* forward declarations */ 44 static void fd_shutdown(int signal);45 45 static 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 } 46 static void * catch_signals(void * arg); 47 static pthread_t signals_thr; 48 49 static char *conffile = NULL; 50 static int gnutls_debug = 0; 183 51 184 52 /* gnutls debug */ … … 187 55 } 188 56 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 */ 59 int 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 290 106 return 0; 291 107 } 108 292 109 293 110 /* Display package version */ … … 302 119 ")" 303 120 #endif /* HG_VERSION */ 304 " \n",121 " (libfdcore: %s)\n", 305 122 FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV 306 123 #ifdef HG_VERSION … … 310 127 # endif /* PACKAGE_HG_VERSION */ 311 128 #endif /* HG_VERSION */ 312 );129 , fd_core_version()); 313 130 } 314 131 … … 341 158 } 342 159 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 */ 161 static 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 367 253 return 0; 368 254 } 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 */ 257 static 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 } 295 out: 296 /* Better way to handle this ? */ 297 ASSERT(0); 298 return NULL; 299 }
Note: See TracChangeset
for help on using the changeset viewer.