mirror of
https://github.com/haiwen/ccnet-server.git
synced 2025-05-09 07:36:20 +00:00
* use searpc-named-pipe-transport * delete unused files * remove not threaded rpc * use NamedPipeClient * remove not threaded rpc * remove unused code * remove unused rpc function * remove unused code and source files * Add name of rpc named pipe to ccent.h.
374 lines
9.3 KiB
C
374 lines
9.3 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
#include "common.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <getopt.h>
|
|
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
#include <event2/dns.h>
|
|
#else
|
|
#include <evdns.h>
|
|
#endif
|
|
|
|
#include "server-session.h"
|
|
#include "user-mgr.h"
|
|
#include "rpc-service.h"
|
|
#include "log.h"
|
|
|
|
char *pidfile = NULL;
|
|
CcnetSession *session;
|
|
|
|
|
|
#ifndef WIN32
|
|
struct event sigint;
|
|
struct event sigterm;
|
|
struct event sigusr1;
|
|
|
|
static void sigintHandler (int fd, short event, void *user_data)
|
|
{
|
|
ccnet_session_on_exit (session);
|
|
exit (1);
|
|
}
|
|
|
|
static void sigusr1Handler (int fd, short event, void *user_data)
|
|
{
|
|
ccnet_log_reopen ();
|
|
}
|
|
|
|
static void setSigHandlers ()
|
|
{
|
|
signal (SIGPIPE, SIG_IGN);
|
|
|
|
event_set(&sigint, SIGINT, EV_SIGNAL, sigintHandler, NULL);
|
|
event_add(&sigint, NULL);
|
|
|
|
/* same as sigint */
|
|
event_set(&sigterm, SIGTERM, EV_SIGNAL, sigintHandler, NULL);
|
|
event_add(&sigterm, NULL);
|
|
|
|
/* redesign as reopen log */
|
|
event_set(&sigusr1, SIGUSR1, EV_SIGNAL | EV_PERSIST, sigusr1Handler, NULL);
|
|
event_add(&sigusr1, NULL);
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
remove_pidfile (const char *pidfile)
|
|
{
|
|
if (pidfile) {
|
|
g_unlink (pidfile);
|
|
}
|
|
}
|
|
|
|
static int
|
|
write_pidfile (const char *pidfile_path)
|
|
{
|
|
if (!pidfile_path)
|
|
return -1;
|
|
|
|
pid_t pid = getpid();
|
|
|
|
FILE *pidfile = fopen(pidfile_path, "w");
|
|
if (!pidfile) {
|
|
ccnet_warning ("Failed to fopen() pidfile %s: %s\n",
|
|
pidfile_path, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
char buf[32];
|
|
snprintf (buf, sizeof(buf), "%d\n", pid);
|
|
if (fputs(buf, pidfile) < 0) {
|
|
ccnet_warning ("Failed to write pidfile %s: %s\n",
|
|
pidfile_path, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
fflush (pidfile);
|
|
fclose (pidfile);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
on_ccnet_exit(void)
|
|
{
|
|
if (pidfile)
|
|
remove_pidfile (pidfile);
|
|
}
|
|
|
|
|
|
static const char *short_options = "hvdta:c:D:f:P:M:F:";
|
|
static struct option long_options[] = {
|
|
{ "help", no_argument, NULL, 'h', },
|
|
{ "version", no_argument, NULL, 'v', },
|
|
{ "config-dir", required_argument, NULL, 'c' },
|
|
{ "add-admin", required_argument, NULL, 'a' },
|
|
{ "central-config-dir", required_argument, NULL, 'F' },
|
|
{ "logfile", required_argument, NULL, 'f' },
|
|
{ "debug", required_argument, NULL, 'D' },
|
|
{ "daemon", no_argument, NULL, 'd' },
|
|
{ "pidfile", required_argument, NULL, 'P' },
|
|
{ "max-users", required_argument, NULL, 'M' },
|
|
{ "test-config", required_argument, NULL, 't' },
|
|
{ NULL, 0, NULL, 0, },
|
|
};
|
|
|
|
|
|
static void usage()
|
|
{
|
|
fputs(
|
|
"usage: ccnet-server [OPTIONS]\n\n"
|
|
"Supported OPTIONS are:\n"
|
|
" -c CONFDIR\n"
|
|
" Specify the ccnet configuration directory. Default is ~/.ccnet\n"
|
|
" -d\n"
|
|
" Run ccnet as a daemon\n"
|
|
" -D FLAGS\n"
|
|
" Specify debug flags for logging, for example\n"
|
|
" Peer,Processor\n"
|
|
" supported flags are\n"
|
|
" Peer,Processor,Netio,\n"
|
|
" Message,Connection,Other\n"
|
|
" or ALL to enable all debug flags\n"
|
|
" -f LOG_FILE\n"
|
|
" Log file path\n"
|
|
" -P PIDFILE\n"
|
|
" Specify the file to store pid\n"
|
|
" -M MAX_USERS\n"
|
|
" Specify the max users for login\n"
|
|
" -t\n"
|
|
" test ccnet configuration and exit\n",
|
|
stdout);
|
|
}
|
|
|
|
int test_ccnet_config(const char *central_config_dir, const char *config_dir, int max_users)
|
|
{
|
|
#if !GLIB_CHECK_VERSION(2, 36, 0)
|
|
g_type_init ();
|
|
#endif
|
|
|
|
config_dir = ccnet_expand_path (config_dir);
|
|
if (central_config_dir) {
|
|
central_config_dir = ccnet_expand_path (central_config_dir);
|
|
}
|
|
|
|
if (ccnet_log_init ("-", "debug") < 0) {
|
|
fprintf (stderr, "ccnet_log_init error: %s\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
srand (time(NULL));
|
|
|
|
session = (CcnetSession *)ccnet_server_session_new ();
|
|
if (!session) {
|
|
fprintf (stderr, "Error: failed to create ccnet session\n");
|
|
return -1;
|
|
}
|
|
|
|
event_init ();
|
|
evdns_init ();
|
|
ccnet_user_manager_set_max_users (((struct CcnetServerSession *)session)->user_mgr, max_users);
|
|
if (ccnet_session_prepare(session, central_config_dir, config_dir, TRUE) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int c;
|
|
char *config_dir;
|
|
char *admin_passwd = NULL;
|
|
char *central_config_dir = NULL;
|
|
char *log_file = 0;
|
|
const char *debug_str = 0;
|
|
int daemon_mode = 0;
|
|
int max_users = 0;
|
|
const char *log_level_str = "debug";
|
|
gboolean test_config = FALSE;
|
|
|
|
config_dir = DEFAULT_CONFIG_DIR;
|
|
|
|
#ifdef WIN32
|
|
argv = get_argv_utf8 (&argc);
|
|
#endif
|
|
while ((c = getopt_long (argc, argv, short_options,
|
|
long_options, NULL)) != EOF) {
|
|
switch (c) {
|
|
case 'h':
|
|
usage();
|
|
exit(0);
|
|
break;
|
|
case 'v':
|
|
exit (1);
|
|
break;
|
|
case 'c':
|
|
config_dir = optarg;
|
|
break;
|
|
case 'F':
|
|
central_config_dir = optarg;
|
|
break;
|
|
case 'f':
|
|
log_file = optarg;
|
|
break;
|
|
case 'D':
|
|
debug_str = optarg;
|
|
break;
|
|
case 'd':
|
|
daemon_mode = 1;
|
|
break;
|
|
case 'P':
|
|
pidfile = optarg;
|
|
break;
|
|
case 'M':
|
|
max_users = atoi(optarg);
|
|
break;
|
|
case 't':
|
|
test_config = TRUE;
|
|
break;
|
|
case 'a':
|
|
admin_passwd = optarg;
|
|
break;
|
|
default:
|
|
fprintf (stderr, "unknown option \"-%c\"\n", (char)c);
|
|
usage();
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if (config_dir == NULL) {
|
|
fprintf (stderr, "Missing config dir\n");
|
|
exit (1);
|
|
}
|
|
|
|
if (test_config) {
|
|
/* test ccnet configuration and exit */
|
|
return test_ccnet_config (central_config_dir, config_dir, max_users);
|
|
}
|
|
|
|
#ifndef WIN32
|
|
if (daemon_mode) {
|
|
#ifndef __APPLE__
|
|
daemon (1, 0);
|
|
#else /* __APPLE */
|
|
/* daemon is deprecated under APPLE
|
|
* use fork() instead
|
|
* */
|
|
switch (fork ()) {
|
|
case -1:
|
|
ccnet_warning ("Failed to daemonize");
|
|
exit (-1);
|
|
break;
|
|
case 0:
|
|
/* all good*/
|
|
break;
|
|
default:
|
|
/* kill origin process */
|
|
exit (0);
|
|
}
|
|
#endif /* __APPLE */
|
|
}
|
|
#else /* WIN32 */
|
|
WSADATA wsadata;
|
|
WSAStartup(0x0101, &wsadata);
|
|
#endif
|
|
|
|
#if !GLIB_CHECK_VERSION(2, 36, 0)
|
|
g_type_init ();
|
|
#endif
|
|
|
|
/* log */
|
|
if (!debug_str)
|
|
debug_str = g_getenv("CCNET_DEBUG");
|
|
ccnet_debug_set_flags_string (debug_str);
|
|
|
|
config_dir = ccnet_expand_path (config_dir);
|
|
|
|
if (!log_file) {
|
|
char *logdir = g_build_filename (config_dir, "logs", NULL);
|
|
checkdir_with_mkdir (logdir);
|
|
g_free (logdir);
|
|
log_file = g_build_filename (config_dir, "logs", "ccnet.log", NULL);
|
|
}
|
|
if (ccnet_log_init (log_file, log_level_str) < 0) {
|
|
fprintf (stderr, "ccnet_log_init error: %s, %s\n", strerror(errno),
|
|
log_file);
|
|
exit (1);
|
|
}
|
|
|
|
srand (time(NULL));
|
|
|
|
session = (CcnetSession *)ccnet_server_session_new ();
|
|
if (!session) {
|
|
fputs ("Error: failed to start ccnet session, "
|
|
"see log file for the detail.\n", stderr);
|
|
return -1;
|
|
}
|
|
|
|
event_init ();
|
|
evdns_init ();
|
|
ccnet_user_manager_set_max_users (((struct CcnetServerSession *)session)->user_mgr, max_users);
|
|
if (ccnet_session_prepare(session, central_config_dir, config_dir, FALSE) < 0) {
|
|
fputs ("Error: failed to start ccnet session, "
|
|
"see log file for the detail.\n", stderr);
|
|
return -1;
|
|
}
|
|
if (admin_passwd) {
|
|
|
|
int ret = 0;
|
|
char **admin_pass = g_strsplit(admin_passwd, "/", 2);
|
|
|
|
if (g_strv_length (admin_pass) < 2 ) {
|
|
fprintf (stderr, "Error: Missing parameter, failed to add admin\n");
|
|
ret = -1;
|
|
} else if (!strcmp(admin_pass[0], "") || !strcmp(admin_pass[1], "")) {
|
|
fprintf (stderr, "Error: Username or password can't be null, failed to add admin\n");
|
|
ret = -1;
|
|
} else if (ccnet_user_manager_add_emailuser (((struct CcnetServerSession *)session)->user_mgr,
|
|
admin_pass[0],
|
|
admin_pass[1],
|
|
1, 1)) {
|
|
|
|
fprintf (stderr, "Error: Failed to add admin\n");
|
|
ret = -1;
|
|
}
|
|
|
|
g_strfreev (admin_pass);
|
|
return ret;
|
|
}
|
|
|
|
/* write pidfile after session_prepare success, if there is
|
|
* another instance of ccnet session_prepare will failed.
|
|
*/
|
|
if (pidfile) {
|
|
if (write_pidfile (pidfile) < 0) {
|
|
ccnet_message ("Failed to write pidfile\n");
|
|
return -1;
|
|
}
|
|
}
|
|
atexit (on_ccnet_exit);
|
|
|
|
#ifndef WIN32
|
|
setSigHandlers();
|
|
#endif
|
|
|
|
ccnet_session_start (session);
|
|
if(ccnet_start_rpc(session) < 0) {
|
|
ccnet_warning ("Failed to start ccnet rpc server.\n");
|
|
exit (-1);
|
|
}
|
|
|
|
/* actually enter the event loop */
|
|
event_dispatch ();
|
|
|
|
return 0;
|
|
}
|
|
|