Пример #1
0
int main ()
{
    /* log setting */
    event_set_log_callback(log_event);
    event_base_free (NULL);

    /* set to the default log behavior */
    event_set_log_callback(NULL);
    event_base_free (NULL);

}
Пример #2
0
void LibeventLog::turnOn(const char *filepath) {
	if (logfile != NULL) {
		event_set_log_callback(write_to_file_cv);
		return;
	}

	logfile = fopen(filepath, "a+");
	if (logfile == NULL) {
		event_set_log_callback(discard_log);
	} else {
		event_set_log_callback(write_to_file_cv);
	}

	event_set_fatal_callback(write_to_file_fatal_cb);
}
Пример #3
0
int main(int argc, char* argv[])
{
    SetupEnvironment();
    if (!SetupNetworking()) {
        fprintf(stderr, "Error: Initializing networking failed\n");
        return EXIT_FAILURE;
    }
    event_set_log_callback(&libevent_log_cb);

    try {
        int ret = AppInitRPC(argc, argv);
        if (ret != CONTINUE_EXECUTION)
            return ret;
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "AppInitRPC()");
        return EXIT_FAILURE;
    } catch (...) {
        PrintExceptionContinue(nullptr, "AppInitRPC()");
        return EXIT_FAILURE;
    }

    int ret = EXIT_FAILURE;
    try {
        ret = CommandLineRPC(argc, argv);
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "CommandLineRPC()");
    } catch (...) {
        PrintExceptionContinue(nullptr, "CommandLineRPC()");
    }
    return ret;
}
Пример #4
0
int
init_events()
{
  struct timeval tv;
  struct event *timer = MyMalloc(sizeof(struct event));
//  struct event *sigint = MyMalloc(sizeof(struct event));

  ev_base = event_init();

  event_set_log_callback(&libevent_log_cb);

  if(evdns_init() == -1)
  {
    ilog(L_ERROR, "libevent dns init failed");
    return FALSE;
  }

  ilog(L_DEBUG, "libevent init %p", ev_base);

  memset(&tv, 0, sizeof(tv));

  tv.tv_usec = 100;
  event_set(timer, -1, EV_PERSIST, timer_callback, timer);
  event_base_set(ev_base, timer);
  evtimer_add(timer, &tv);

/*  event_set(sigint, SIGINT, EV_SIGNAL|EV_PERSIST, sigint_callback, sigint);
  event_add(sigint, NULL);*/

  return TRUE;
}
Пример #5
0
int main() {
	struct sockaddr_in seradd;
	logger = fopen("log.txt","w");
	event_set_log_callback(logp);
	evutil_gettimeofday(&tv,NULL);
	bzero(&seradd ,sizeof(seradd));
	seradd.sin_family = AF_INET;
	inet_pton(AF_INET,"127.0.0.1",&seradd.sin_addr);
	seradd.sin_port = htons(80);

	evutil_socket_t fd = socket(PF_INET,SOCK_STREAM,0);
	if(connect(fd,(struct sockaddr *)&seradd,sizeof(seradd))<0){
		printf("Connect Error!");
	}else{
		evutil_make_socket_nonblocking(fd);
		struct event_base *base;
		struct timeval f = {5,0};
		base = event_base_new();
		struct event *sockwrite = event_new(base,fd,EV_WRITE|EV_PERSIST|EV_TIMEOUT,cb_write,NULL);
		struct event *sockread = event_new(base,fd,EV_READ|EV_PERSIST,cb_read,(void *)base);
		event_add(sockwrite,&f);
		event_add(sockread,NULL);
		event_base_dispatch(base);
	}
}
Пример #6
0
static int
basic_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
	struct basic_test_data *data = ptr;

	if (testcase->flags & TT_NO_LOGS)
		event_set_log_callback(NULL);

	if (testcase->flags & TT_NEED_SOCKETPAIR) {
		if (data->pair[0] != -1)
			evutil_closesocket(data->pair[0]);
		if (data->pair[1] != -1)
			evutil_closesocket(data->pair[1]);
	}

	if (testcase->flags & TT_NEED_DNS) {
		evdns_shutdown(0);
	}

	if (testcase->flags & TT_NEED_BASE) {
		if (data->base) {
			event_base_assert_ok(data->base);
			event_base_free(data->base);
		}
	}

	free(data);

	return 1;
}
Пример #7
0
void TcpListener::Start(
    std::function<void (bool success)> searchListenPortFinishedNotify)
{
    canceled_ = false;
    evthread_use_windows_threads();
    event_set_log_callback(EventLogCallback);
    base_ = event_base_new();
    if (base_)
    {
        unsigned short port = ntohs(addr_.sin_port);
        while ((listener_ = evconnlistener_new_bind(base_, OnAcceptCallabck,
            this, LEV_OPT_CLOSE_ON_FREE | 
            LEV_OPT_LEAVE_SOCKETS_BLOCKING | LEV_OPT_CLOSE_ON_EXEC,
            -1, (sockaddr*)&addr_, sizeof(addr_))) == nullptr)
        {
            addr_.sin_port = htons(++port);
            Sleep(50);
            if (canceled_)
                return;
        }
        if (searchListenPortFinishedNotify)
            searchListenPortFinishedNotify(true);
        if (canceled_)
            return;
        event_base_dispatch(base_);
    }
    else 
    {
        if (searchListenPortFinishedNotify)
            searchListenPortFinishedNotify(false);
    }
}
Пример #8
0
static void
libeventThreadFunc( void * veh )
{
    tr_event_handle * eh = veh;

    tr_dbg( "Starting libevent thread" );

#ifndef WIN32
    /* Don't exit when writing on a broken socket */
    signal( SIGPIPE, SIG_IGN );
#endif

    eh->h->events = eh;

    /* listen to the pipe's read fd */
    event_set( &eh->pipeEvent, eh->fds[0], EV_READ | EV_PERSIST,
               readFromPipe,
               veh );
    event_add( &eh->pipeEvent, NULL );
    event_set_log_callback( logFunc );
    event_dispatch( );

    tr_lockFree( eh->lock );
    event_base_free( eh->base );
    eh->h->events = NULL;
    tr_free( eh );
    tr_dbg( "Closing libevent thread" );
}
Пример #9
0
bool NetworkManager::init(int port)
{
    memset(m_listenAddr,0,sizeof(sockaddr_in));
    m_listenAddr->sin_family = AF_INET;
    m_listenAddr->sin_port = htons(port);
    
    m_eventBase = event_base_new();
    if(!m_eventBase)
    {
        printf("Could not initialize libevent\n");
        return false;
    }

    event_set_log_callback(&eventLog);

    m_listener = evconnlistener_new_bind(m_eventBase,evlistener,(void*)m_eventBase, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,1,(struct sockaddr*)m_listenAddr ,sizeof(sockaddr_in));
    if(!m_listener)
    {
        int errCode = EVUTIL_SOCKET_ERROR();
        const char* reason = evutil_socket_error_to_string(errCode);
        event_base_free(m_eventBase);
        printf("Could not create a listener, msg : %s\n",reason);
        return false;
    }

    evutil_gettimeofday(&m_timeval, NULL);

    struct timeval tv = {1,0};
    m_timer = event_new(m_eventBase,-1, EV_PERSIST, evtimer,this);
    event_add(m_timer, &tv);
    
    printf("network init secceed...\n");
    return true;
}
Пример #10
0
static void
levent_init(struct lldpd *cfg)
{
	/* Setup libevent */
	log_debug("event", "initialize libevent");
	event_set_log_callback(levent_log_cb);
	if (!(cfg->g_base = event_base_new()))
		fatalx("unable to create a new libevent base");
	log_info("event", "libevent %s initialized with %s method",
		  event_get_version(),
		  event_base_get_method(cfg->g_base));

	/* Setup SNMP */
#ifdef USE_SNMP
	if (cfg->g_snmp) {
		agent_init(cfg, cfg->g_snmp_agentx);
		cfg->g_snmp_timeout = evtimer_new(cfg->g_base,
		    levent_snmp_timeout,
		    cfg);
		if (!cfg->g_snmp_timeout)
			fatalx("unable to setup timeout function for SNMP");
		if ((cfg->g_snmp_fds =
			malloc(sizeof(struct ev_l))) == NULL)
			fatalx("unable to allocate memory for SNMP events");
		TAILQ_INIT(levent_snmp_fds(cfg));
	}
#endif

	/* Setup loop that will run every X seconds. */
	log_debug("event", "register loop timer");
	if (!(cfg->g_main_loop = event_new(cfg->g_base, -1, 0,
					   levent_update_and_send,
					   cfg)))
		fatalx("unable to setup main timer");
	event_active(cfg->g_main_loop, EV_TIMEOUT, 1);

	/* Setup unix socket */
	log_debug("event", "register Unix socket");
	TAILQ_INIT(&lldpd_clients);
	evutil_make_socket_nonblocking(cfg->g_ctl);
	if ((cfg->g_ctl_event = event_new(cfg->g_base, cfg->g_ctl,
		    EV_READ|EV_PERSIST, levent_ctl_accept, cfg)) == NULL)
		fatalx("unable to setup control socket event");
	event_add(cfg->g_ctl_event, NULL);

	/* Signals */
	log_debug("event", "register signals");
	signal(SIGHUP, SIG_IGN);
	evsignal_add(evsignal_new(cfg->g_base, SIGUSR1,
		levent_dump, cfg->g_base),
	    NULL);
	evsignal_add(evsignal_new(cfg->g_base, SIGINT,
		levent_stop, cfg->g_base),
	    NULL);
	evsignal_add(evsignal_new(cfg->g_base, SIGTERM,
		levent_stop, cfg->g_base),
	    NULL);
}
Пример #11
0
Файл: log.c Проект: Brijen/tmux
/* Close logging. */
void
log_close(void)
{
	if (log_file != NULL)
		fclose(log_file);
	log_file = NULL;

	event_set_log_callback(NULL);
}
Пример #12
0
bool InitHTTPServer()
{
    if (!InitHTTPAllowList())
        return false;

    if (gArgs.GetBoolArg("-rpcssl", false)) {
        uiInterface.ThreadSafeMessageBox(
            "SSL mode for RPC (-rpcssl) is no longer supported.",
            "", CClientUIInterface::MSG_ERROR);
        return false;
    }

    // Redirect libevent's logging to our own log
    event_set_log_callback(&libevent_log_cb);
    // Update libevent's log handling. Returns false if our version of
    // libevent doesn't support debug logging, in which case we should
    // clear the BCLog::LIBEVENT flag.
    if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) {
        g_logger->DisableCategory(BCLog::LIBEVENT);
    }

#ifdef WIN32
    evthread_use_windows_threads();
#else
    evthread_use_pthreads();
#endif

    raii_event_base base_ctr = obtain_event_base();

    /* Create a new evhttp object to handle requests. */
    raii_evhttp http_ctr = obtain_evhttp(base_ctr.get());
    struct evhttp* http = http_ctr.get();
    if (!http) {
        LogPrintf("couldn't create evhttp. Exiting.\n");
        return false;
    }

    evhttp_set_timeout(http, gArgs.GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT));
    evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE);
    evhttp_set_max_body_size(http, MAX_SIZE);
    evhttp_set_gencb(http, http_request_cb, nullptr);

    if (!HTTPBindAddresses(http)) {
        LogPrintf("Unable to bind any endpoint for RPC server\n");
        return false;
    }

    LogPrint(BCLog::HTTP, "Initialized HTTP server\n");
    int workQueueDepth = std::max((long)gArgs.GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
    LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);

    workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
    // transfer ownership to eventBase/HTTP via .release()
    eventBase = base_ctr.release();
    eventHTTP = http_ctr.release();
    return true;
}
Пример #13
0
/* Close logging. */
void
log_close(void)
{
	if (log_type == LOG_TYPE_FILE)
		fclose(log_file);

	event_set_log_callback(NULL);

	log_type = LOG_TYPE_OFF;
}
Пример #14
0
Файл: log.c Проект: Brijen/tmux
/* Open logging to file. */
void
log_open(const char *path)
{
	log_file = fopen(path, "w");
	if (log_file == NULL)
		return;

	setvbuf(log_file, NULL, _IOLBF, 0);
	event_set_log_callback(log_event_cb);

	tzset();
}
Пример #15
0
/* Open logging to tty. */
void
log_open_tty(int level)
{
	log_type = LOG_TYPE_TTY;
	log_level = level;

	setlinebuf(stderr);
	setlinebuf(stdout);
	event_set_log_callback(log_event_cb);

	tzset();
}
Пример #16
0
int main(const int argc, const char *argv[])
{
    event_set_log_callback(write_to_file_cb);
    event_enable_debug_mode();

    //log_level(LOG_DEBUG);
    log_fileline(LOG_FILELINE_ON);
    log_level(LOG_WARN);

    server_t *server = server_init(DEFAULT_PORT);

    if(server == NULL)
    {
        log_err(__FILE__, __LINE__, "Cannot init server.");
        exit(-1);
    }

    int power = 10;
    server->service_idx = service_index_init(power);
    char *str = NULL;

    str = calloc(sizeof(char), 5);
    memcpy(str, "aaaa", 4);
    service_t *aaaa = service_init(str);
    aaaa = service_add(server->service_idx, power, aaaa);

    server->service_first = aaaa;
    server->service_last  = aaaa;
    server->num_services++;

    str = calloc(sizeof(char), 5);
    memcpy(str, "bbbb", 4);
    service_t *bbbb = service_init(str);
    bbbb = service_add(server->service_idx, power, bbbb);

    aaaa->all_next = bbbb;
    server->service_last = bbbb;
    server->num_services++;

    str = calloc(sizeof(char), 5);
    memcpy(str, "cccc", 4);
    service_t *cccc = service_init(str);
    cccc = service_add(server->service_idx, power, cccc);

    bbbb->all_next = cccc;
    server->service_last = cccc;
    server->num_services++;

    server_event_run(server);

    return 0;
}
Пример #17
0
int logging_setup(struct module *module, config_setting_t *conf)
{
    config_setting_t *setting;
    const char *val;
    int num;

    if (config.debug < 2)
        skeeter_vlog = &skeeter_syslog;

    num = LOG_ERR;
    setting = config_setting_get_member(conf, "level");
    if (setting) {
        struct level *level;

        val = config_setting_get_string(setting);
        for (level = level_table; level->name; level++) {
            if (!strcasecmp(val, level->name))
                break;
        }
        if (!level->name) {
            skeeter_log(LOG_ERR, "Could not parse loglevel value '%s'", val);
            return 1;
        }
        num = level->level;
    }
    config.loglevel = num;

    num = LOG_MAIL;
    setting = config_setting_get_member(conf, "facility");
    if (setting) {
        struct facility *facility;

        val = config_setting_get_string(setting);
        for (facility = facility_table; facility->name; facility++) {
            if (!strcasecmp(val, facility->name))
                break;
        }
        if (!facility->name) {
            skeeter_log(LOG_ERR, "Could not parse log facility value '%s'", val);
            return 1;
        }
        num = facility->facility;
    }
    config.facility = num;

    openlog("skeeter", LOG_PID, config.facility);
    event_set_log_callback(skeeter_event_log);

    return 0;
}
Пример #18
0
LibEventInit::LibEventInit()
{
  event_set_log_callback(my_libevent_log_cb);
#ifdef OS_WIN
  evthread_use_windows_threads();
#else
  evthread_use_pthreads();
#endif
  evdns_set_log_fn(logfn);

  if (CONFIG->enableEventDebug){
    MYDEBUG("enable libevent debug");
    event_enable_debug_mode();
  }
}
Пример #19
0
/* Open logging to file. */
void
log_open_file(int level, const char *path)
{
	log_file = fopen(path, "w");
	if (log_file == NULL)
		return;

	log_type = LOG_TYPE_FILE;
	log_level = level;

	setlinebuf(log_file);
	event_set_log_callback(log_event_cb);

	tzset();
}
Пример #20
0
void LinkScheduler::run()
{
    LOG(INFO, "start");
    evthread_use_pthreads();
    event_set_log_callback(LinkScheduler::event_log_callback);
    event_set_fatal_callback(LinkScheduler::event_fatal_callback);
    _base = event_base_new();

    _printStateEvent = evtimer_new(_base, on_print_state, this);
    struct timeval t = {Conf::instance()->schedulerPrintStateInterval, 0 };
    evtimer_add(_printStateEvent, &t);

    event_base_dispatch(_base);
    abort();
}
Пример #21
0
/* Open logging to file. */
void
log_open(const char *name)
{
	char	*path;

	if (log_level == 0)
		return;
	log_close();

	xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
	log_file = fopen(path, "a");
	free(path);
	if (log_file == NULL)
		return;

	setvbuf(log_file, NULL, _IOLBF, 0);
	event_set_log_callback(log_event_cb);
}
Пример #22
0
void cNetworkSingleton::Initialise(void)
{
	// Start the lookup thread
	m_LookupThread.Start();

	// Windows: initialize networking:
	#ifdef _WIN32
		WSADATA wsaData;
		memset(&wsaData, 0, sizeof(wsaData));
		int res = WSAStartup (MAKEWORD(2, 2), &wsaData);
		if (res != 0)
		{
			int err = WSAGetLastError();
			LOGWARNING("WSAStartup failed: %d, WSAGLE = %d (%s)", res, err, evutil_socket_error_to_string(err));
			exit(1);
		}
	#endif  // _WIN32

	// Initialize LibEvent logging:
	event_set_log_callback(LogCallback);

	// Initialize threading:
	#if defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED)
		evthread_use_windows_threads();
	#elif defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
		evthread_use_pthreads();
	#else
		#error No threading implemented for EVTHREAD
	#endif

	// Create the main event_base:
	m_EventBase = event_base_new();
	if (m_EventBase == nullptr)
	{
		LOGERROR("Failed to initialize LibEvent. The server will now terminate.");
		abort();
	}

	// Create the event loop thread:
	m_HasTerminated = false;
	m_EventLoopThread = std::thread(RunEventLoop, this);
	m_StartupEvent.Wait();  // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too soon would hang, see #3228)
}
Пример #23
0
		CNetInit()
		{
#if defined _PLATFORM_WINDOWS_
			WSADATA WSAData;
			WSAStartup(0x101, &WSAData);
#elif defined _PLATFORM_LINUX_
			signal(SIGPIPE, SIG_IGN);
#endif
			event_set_log_callback(write_event_log);
			event_set_fatal_callback(write_event_fatal);

// 内存处理
//#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
//			event_set_mem_functions
//#endif // EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED

			// 2.1.1 版本后才有
			//event_enable_debug_logging();

			// 检查支持哪些后端方式
			//event_get_supported_methods
		}
Пример #24
0
static void
libeventThreadFunc (void * veh)
{
    struct event_base * base;
    tr_event_handle * eh = veh;

#ifndef WIN32
    /* Don't exit when writing on a broken socket */
    signal (SIGPIPE, SIG_IGN);
#endif

    /* create the libevent bases */
    base = event_base_new ();

    /* set the struct's fields */
    eh->base = base;
    eh->session->event_base = base;
    eh->session->evdns_base = evdns_base_new (base, true);
    eh->session->events = eh;

    /* listen to the pipe's read fd */
    eh->pipeEvent = event_new (base, eh->fds[0], EV_READ | EV_PERSIST, readFromPipe, veh);
    event_add (eh->pipeEvent, NULL);
    event_set_log_callback (logFunc);

    /* loop until all the events are done */
    while (!eh->die)
        event_base_dispatch (base);

    /* shut down the thread */
    tr_lockFree (eh->lock);
    event_base_free (base);
    eh->session->events = NULL;
    tr_free (eh);
    tr_logAddDebug ("Closing libevent thread");
}
Пример #25
0
void socket_init(void)
{
    addr_sock_init();
    event_set_log_callback(event_log_print);
#ifdef SOCKET_LIBEVENT_ENABLE_THREAD
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
#ifndef QJ_BOARD_ANDROID
    evthread_use_pthreads();
#endif
#else
    if(evthread_use_windows_threads()){
        log_err("evthread_use_windows_threads failed!");
    }
#endif
#endif
    g_event_base = event_base_new();
    if(NULL == g_event_base){
        log_err("event base new failed!");
        ex_assert(0);
    }

    addr_sock_set_event_base(g_event_base);
    cli_add_quit_cb(socket_quit);
}
Пример #26
0
int chassis_mainloop(void *_chas) {
    chassis *chas = _chas;
    guint i;
    struct event ev_sigterm, ev_sigint;
#ifdef SIGHUP
    struct event ev_sighup;
#endif
    chassis_event_thread_t *mainloop_thread;

    /* redirect logging from libevent to glib */
    event_set_log_callback(event_log_use_glib);


    /* add a event-handler for the "main" events */
    mainloop_thread = chassis_event_thread_new(0);
    chassis_event_threads_init_thread(mainloop_thread, chas);
    g_ptr_array_add(chas->threads, mainloop_thread);

    chas->event_base = mainloop_thread->event_base; /* all global events go to the 1st thread */

    g_assert(chas->event_base);


    /* setup all plugins all plugins */
    for (i = 0; i < chas->modules->len; i++) {
        chassis_plugin *p = chas->modules->pdata[i];

        g_assert(p->apply_config);
        if (0 != p->apply_config(chas, p->config)) {
            g_critical("%s: applying config of plugin %s failed",
                    G_STRLOC, p->name);
            return -1;
        }
    }

    signal_set(&ev_sigterm, SIGTERM, sigterm_handler, NULL);
    event_base_set(chas->event_base, &ev_sigterm);
    signal_add(&ev_sigterm, NULL);

    signal_set(&ev_sigint, SIGINT, sigint_handler, NULL);
    event_base_set(chas->event_base, &ev_sigint);
    signal_add(&ev_sigint, NULL);

#ifdef SIGHUP
    signal_set(&ev_sighup, SIGHUP, sighup_handler, chas);
    event_base_set(chas->event_base, &ev_sighup);
    if (signal_add(&ev_sighup, NULL)) {
        g_critical("%s: signal_add(SIGHUP) failed", G_STRLOC);
    }
#endif

    if (chas->event_thread_count < 1) chas->event_thread_count = 1;

    /* create the event-threads
     *
     * - dup the async-queue-ping-fds
     * - setup the events notification
     * */
    for (i = 1; i <= (guint)chas->event_thread_count; i++) { /* we already have 1 event-thread running, the main-thread */
        chassis_event_thread_t *thread = chassis_event_thread_new(i);

        chassis_event_threads_init_thread(thread, chas);

        g_ptr_array_add(chas->threads, thread);
    }

    /* start the event threads */
    chassis_event_threads_start(chas->threads);

    /**
     * handle signals and all basic events into the main-thread
     *
     * block until we are asked to shutdown
     */
    chassis_mainloop_thread_loop(mainloop_thread);

    signal_del(&ev_sigterm);
    signal_del(&ev_sigint);
#ifdef SIGHUP
    signal_del(&ev_sighup);
#endif
    return 0;
}
Пример #27
0
int chassis_mainloop(void *_chas) {
	chassis *chas = _chas;
	guint i;
	struct event ev_sigterm, ev_sigint;
#ifdef SIGHUP
	struct event ev_sighup;
#endif
	chassis_event_thread_t *mainloop_thread;

	/* redirect logging from libevent to glib */
	event_set_log_callback(event_log_use_glib);


	/* add a event-handler for the "main" events */
	mainloop_thread = chassis_event_thread_new();
	chassis_event_threads_init_thread(chas->threads, mainloop_thread, chas);
	chassis_event_threads_add(chas->threads, mainloop_thread);

	//add by Vinchn

	chas->event_base = mainloop_thread->event_base; /* all global events go to the 1st thread */

	g_assert(chas->event_base);


	/* setup all plugins all plugins */
	for (i = 0; i < chas->modules->len; i++) {
		chassis_plugin *p = chas->modules->pdata[i];

		g_assert(p->apply_config);
		if (0 != p->apply_config(chas, p->config)) {
			g_critical("%s: applying config of plugin %s failed",
					G_STRLOC, p->name);
			return -1;
		}
	}

	/*
	 * drop root privileges if requested
	 */
#ifndef _WIN32
	if (chas->user) {
		struct passwd *user_info;
		uid_t user_id= geteuid();

		/* Don't bother if we aren't superuser */
		if (user_id) {
			g_critical("can only use the --user switch if running as root");
			return -1;
		}

		if (NULL == (user_info = getpwnam(chas->user))) {
			g_critical("unknown user: %s", chas->user);
			return -1;
		}

		if (chas->log->log_filename) {
			/* chown logfile */
			if (-1 == chown(chas->log->log_filename, user_info->pw_uid, user_info->pw_gid)) {
				g_critical("%s.%d: chown(%s) failed: %s",
							__FILE__, __LINE__,
							chas->log->log_filename,
							g_strerror(errno) );

				return -1;
			}
		}

		setgid(user_info->pw_gid);
		setuid(user_info->pw_uid);
		g_debug("now running as user: %s (%d/%d)",
				chas->user,
				user_info->pw_uid,
				user_info->pw_gid );
	}
#endif

	signal_set(&ev_sigterm, SIGTERM, sigterm_handler, NULL);
	event_base_set(chas->event_base, &ev_sigterm);
	signal_add(&ev_sigterm, NULL);

	signal_set(&ev_sigint, SIGINT, sigterm_handler, NULL);
	event_base_set(chas->event_base, &ev_sigint);
	signal_add(&ev_sigint, NULL);

#ifdef SIGHUP
	signal_set(&ev_sighup, SIGHUP, sighup_handler, chas);
	event_base_set(chas->event_base, &ev_sighup);
	if (signal_add(&ev_sighup, NULL)) {
		g_critical("%s: signal_add(SIGHUP) failed", G_STRLOC);
	}
#endif

	if (chas->event_thread_count < 1) chas->event_thread_count = 1;

	/* create the event-threads
	 *
	 * - dup the async-queue-ping-fds
	 * - setup the events notification
	 * */
	for (i = 1; i < (guint)chas->event_thread_count; i++) { /* we already have 1 event-thread running, the main-thread */
		chassis_event_thread_t *event_thread;
	
		event_thread = chassis_event_thread_new();
		chassis_event_threads_init_thread(chas->threads, event_thread, chas);
		chassis_event_threads_add(chas->threads, event_thread);
	}

	/* start the event threads */
	if (chas->event_thread_count > 1) {
		chassis_event_threads_start(chas->threads);
	}

	/**
	 * handle signals and all basic events into the main-thread
	 *
	 * block until we are asked to shutdown
	 */
	chassis_event_thread_loop(mainloop_thread);

	signal_del(&ev_sigterm);
	signal_del(&ev_sigint);
#ifdef SIGHUP
	signal_del(&ev_sighup);
#endif
	return 0;
}
Пример #28
0
int
main(int argc, char **argv)
{
  int option;
  char *configfile;
  int background;
  int mdns_no_rsp;
  int mdns_no_daap;
  int loglevel;
  char *logdomains;
  char *logfile;
  char *ffid;
  char *pidfile;
  const char *gcry_version;
  sigset_t sigs;
  int sigfd;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  struct kevent ke_sigs[4];
#endif
  int ret;

  struct option option_map[] =
    {
      { "ffid",         1, NULL, 'b' },
      { "debug",        1, NULL, 'd' },
      { "logdomains",   1, NULL, 'D' },
      { "foreground",   0, NULL, 'f' },
      { "config",       1, NULL, 'c' },
      { "pidfile",      1, NULL, 'P' },
      { "version",      0, NULL, 'v' },

      { "mdns-no-rsp",  0, NULL, 512 },
      { "mdns-no-daap", 0, NULL, 513 },

      { NULL,           0, NULL, 0 }
    };

  configfile = CONFFILE;
  pidfile = PIDFILE;
  loglevel = -1;
  logdomains = NULL;
  logfile = NULL;
  background = 1;
  ffid = NULL;
  mdns_no_rsp = 0;
  mdns_no_daap = 0;

  while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1)
    {
      switch (option)
	{
	  case 512:
	    mdns_no_rsp = 1;
	    break;

	  case 513:
	    mdns_no_daap = 1;
	    break;

	  case 'b':
            ffid = optarg;
            break;

	  case 'd':
	    ret = safe_atoi32(optarg, &option);
	    if (ret < 0)
	      fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg);
	    else
	      loglevel = option;
            break;

	  case 'D':
	    logdomains = optarg;
            break;

          case 'f':
            background = 0;
            break;

          case 'c':
            configfile = optarg;
            break;

          case 'P':
	    pidfile = optarg;
            break;

          case 'v':
	    version();
            return EXIT_SUCCESS;
            break;

          default:
            usage(argv[0]);
            return EXIT_FAILURE;
            break;
        }
    }

  ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not initialize log facility\n");

      return EXIT_FAILURE;
    }

  ret = conffile_load(configfile);
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Config file errors; please fix your config\n");

      logger_deinit();
      return EXIT_FAILURE;
    }

  logger_deinit();

  /* Reinit log facility with configfile values */
  if (loglevel < 0)
    loglevel = cfg_getint(cfg_getsec(cfg, "general"), "loglevel");

  logfile = cfg_getstr(cfg_getsec(cfg, "general"), "logfile");

  ret = logger_init(logfile, logdomains, loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not reinitialize log facility with config file settings\n");

      conffile_unload();
      return EXIT_FAILURE;
    }

  /* Set up libevent logging callback */
  event_set_log_callback(logger_libevent);

  DPRINTF(E_LOG, L_MAIN, "Forked Media Server Version %s taking off\n", VERSION);

  ret = av_lockmgr_register(ffmpeg_lockmgr);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register ffmpeg lock manager callback\n");

      ret = EXIT_FAILURE;
      goto ffmpeg_init_fail;
    }

  av_register_all();
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_init();
#endif
  av_log_set_callback(logger_ffmpeg);

#ifdef LASTFM
  /* Initialize libcurl */
  curl_global_init(CURL_GLOBAL_DEFAULT);
#endif

  /* Initialize libgcrypt */
  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

  gcry_version = gcry_check_version(GCRYPT_VERSION);
  if (!gcry_version)
    {
      DPRINTF(E_FATAL, L_MAIN, "libgcrypt version mismatch\n");

      ret = EXIT_FAILURE;
      goto gcrypt_init_fail;
    }

  /* We aren't handling anything sensitive, so give up on secure
   * memory, which is a scarce system resource.
   */
  gcry_control(GCRYCTL_DISABLE_SECMEM, 0);

  gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

  DPRINTF(E_DBG, L_MAIN, "Initialized with gcrypt %s\n", gcry_version);

  /* Block signals for all threads except the main one */
  sigemptyset(&sigs);
  sigaddset(&sigs, SIGINT);
  sigaddset(&sigs, SIGHUP);
  sigaddset(&sigs, SIGCHLD);
  sigaddset(&sigs, SIGTERM);
  sigaddset(&sigs, SIGPIPE);
  ret = pthread_sigmask(SIG_BLOCK, &sigs, NULL);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Error setting signal set\n");

      ret = EXIT_FAILURE;
      goto signal_block_fail;
    }

  /* Daemonize and drop privileges */
  ret = daemonize(background, pidfile);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n");

      ret = EXIT_FAILURE;
      goto daemon_fail;
    }

  /* Initialize libevent (after forking) */
  evbase_main = event_init();

  DPRINTF(E_LOG, L_MAIN, "mDNS init\n");
  ret = mdns_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "mDNS init failed\n");

      ret = EXIT_FAILURE;
      goto mdns_fail;
    }

  /* Initialize the database before starting */
  DPRINTF(E_INFO, L_MAIN, "Initializing database\n");
  ret = db_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Database init failed\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Open a DB connection for the main thread */
  ret = db_perthread_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not perform perthread DB init for main\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Spawn worker thread */
  ret = worker_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Worker thread failed to start\n");

      ret = EXIT_FAILURE;
      goto worker_fail;
    }

  /* Spawn cache thread */
  ret = cache_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Cache thread failed to start\n");

      ret = EXIT_FAILURE;
      goto cache_fail;
    }

  /* Spawn file scanner thread */
  ret = filescanner_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "File scanner thread failed to start\n");

      ret = EXIT_FAILURE;
      goto filescanner_fail;
    }

#ifdef HAVE_SPOTIFY_H
  /* Spawn Spotify thread */
  ret = spotify_init();
  if (ret < 0)
    {
      DPRINTF(E_INFO, L_MAIN, "Spotify thread not started\n");;
    }
#endif

  /* Spawn player thread */
  ret = player_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Player thread failed to start\n");

      ret = EXIT_FAILURE;
      goto player_fail;
    }

  /* Spawn HTTPd thread */
  ret = httpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n");

      ret = EXIT_FAILURE;
      goto httpd_fail;
    }

#ifdef MPD
  /* Spawn MPD thread */
  ret = mpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "MPD thread failed to start\n");

      ret = EXIT_FAILURE;
      goto mpd_fail;
    }
#endif

  /* Start Remote pairing service */
  ret = remote_pairing_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Remote pairing service failed to start\n");

      ret = EXIT_FAILURE;
      goto remote_fail;
    }

  /* Register mDNS services */
  ret = register_services(ffid, mdns_no_rsp, mdns_no_daap);
  if (ret < 0)
    {
      ret = EXIT_FAILURE;
      goto mdns_reg_fail;
    }

#if defined(__linux__)
  /* Set up signal fd */
  sigfd = signalfd(-1, &sigs, SFD_NONBLOCK | SFD_CLOEXEC);
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup signalfd: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  event_set(&sig_event, sigfd, EV_READ, signal_signalfd_cb, NULL);

#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  sigfd = kqueue();
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup kqueue: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  EV_SET(&ke_sigs[0], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[1], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[2], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[3], SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);

  ret = kevent(sigfd, ke_sigs, 4, NULL, 0, NULL);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register signal events: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  event_set(&sig_event, sigfd, EV_READ, signal_kqueue_cb, NULL);
#endif

  event_base_set(evbase_main, &sig_event);
  event_add(&sig_event, NULL);

  /* Run the loop */
  event_base_dispatch(evbase_main);

  DPRINTF(E_LOG, L_MAIN, "Stopping gracefully\n");
  ret = EXIT_SUCCESS;

  /*
   * On a clean shutdown, bring mDNS down first to give a chance
   * to the clients to perform a clean shutdown on their end
   */
  DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
  mdns_deinit();

 signalfd_fail:
 mdns_reg_fail:
  DPRINTF(E_LOG, L_MAIN, "Remote pairing deinit\n");
  remote_pairing_deinit();

 remote_fail:
  DPRINTF(E_LOG, L_MAIN, "HTTPd deinit\n");
  httpd_deinit();

 httpd_fail:
  DPRINTF(E_LOG, L_MAIN, "TCPd deinit\n");
#ifdef MPD
  DPRINTF(E_LOG, L_MAIN, "MPD deinit\n");
  mpd_deinit();
 mpd_fail:
#endif

  DPRINTF(E_LOG, L_MAIN, "Player deinit\n");
  player_deinit();

 player_fail:
#ifdef HAVE_SPOTIFY_H
  DPRINTF(E_LOG, L_MAIN, "Spotify deinit\n");
  spotify_deinit();
#endif
  DPRINTF(E_LOG, L_MAIN, "File scanner deinit\n");
  filescanner_deinit();

 filescanner_fail:
  DPRINTF(E_LOG, L_MAIN, "Cache deinit\n");
  cache_deinit();

 cache_fail:
  DPRINTF(E_LOG, L_MAIN, "Worker deinit\n");
  worker_deinit();

 worker_fail:
  DPRINTF(E_LOG, L_MAIN, "Database deinit\n");
  db_perthread_deinit();
  db_deinit();

 db_fail:
  if (ret == EXIT_FAILURE)
    {
      DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
      mdns_deinit();
    }

 mdns_fail:
 daemon_fail:
  if (background)
    {
      ret = seteuid(0);
      if (ret < 0)
	DPRINTF(E_LOG, L_MAIN, "seteuid() failed: %s\n", strerror(errno));
      else
	{
	  ret = unlink(pidfile);
	  if (ret < 0)
	    DPRINTF(E_LOG, L_MAIN, "Could not unlink PID file %s: %s\n", pidfile, strerror(errno));
	}
    }

 signal_block_fail:
 gcrypt_init_fail:
#ifdef LASTFM
  curl_global_cleanup();
#endif
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_deinit();
#endif
  av_lockmgr_register(NULL);

 ffmpeg_init_fail:
  DPRINTF(E_LOG, L_MAIN, "Exiting.\n");
  conffile_unload();
  logger_deinit();

  return ret;
}
Пример #29
0
int main(int argc, char *argv[])
{
	mmatic *mm = mmatic_create();
	mmatic *mmtmp = mmatic_create();
	struct mg *mg;
	int i;

	/*
	 * initialize and parse config
	 */

	mg = mmatic_zalloc(mm, sizeof(struct mg));
	mg->mm = mm;
	mg->mmtmp = mmtmp;
	apply_defaults(mg);

	/* get my id number from hostname */
	fetch_myid(mg);

	/* parse command line options */
	if (parse_argv(mg, argc, argv))
		return 1;

	/* parse configuration file options */
	if (mg->options.conf_file) {
		if (parse_config(mg))
			return 4;
	}

	/*
	 * config syntax looks OK, see if it is feasible
	 */

	/* initialize random number generator */
	srand48(mg->options.myid);

	/* init libevent */
	mg->evb = event_init();
	event_set_log_callback(libevent_log);

	/* init stats structures so mgstats_aggregator_add() used somewhere below works */
	mgstats_init(mg);

	/* attach to raw interfaces */
	if (mgi_init(mg, handle_packet) <= 0) {
		dbg(0, "no available interfaces found\n");
		return 2;
	}

	/* parse traffic file */
	if (parse_traffic(mg))
		return 3;

	/*
	 * all OK, prepare to start
	 */

	/* synchronize time reference point on all nodes */
	mgc_sync(mg);

	/* schedule stats writing */
	mgstats_start(mg);

	/* attach global stats */
	_stats_init(mg);

	/* schedule heartbeat and disk sync signals */
	heartbeat_init(mg);
	sync_init(mg);

	/* schedule the real work of this node: line generators */
	for (i = 1; i < TRAFFIC_LINE_MAX; i++) {
		if (!(mg->lines[i] && mg->lines[i]->my))
			continue;

		/* this will schedule first execution */
		mgs_sleep(mg->lines[i], NULL);
		mg->running++;
	}

	/* suppose last frame was received now */
	gettimeofday(&mg->last, NULL);

	/*
	 * start!
	 */

	dbg(0, "Starting\n");
	event_base_dispatch(mg->evb);

	/*******************************/

	/*
	 * cleanup after end of libevent loop
	 */

	event_base_free(mg->evb);
	mmatic_free(mg->mm);
	mmatic_free(mg->mmtmp);

	fflush(NULL);
	sync();

	return 0;
}
Пример #30
0
int main(int argc, char** argv)
{
	/* Set the CWD */
	char *home = getenv("HOME");
	if (!home) {
		printf("Failed to load data directory\n");
		return EXIT_FAILURE;
	}
	
	char *datadir = malloc(strlen(home) + 10);
	snprintf(datadir, strlen(home) + 10, "%s/.bitpeer", home);
	
	if (chdir(datadir) < 0) {
		if (mkdir(datadir, 0777) < 0) {
			printf("Failed to create data directory.\n");
			return EXIT_FAILURE;
		}
		
		if (chdir(datadir) < 0) {
			printf("Failed to chdir\n");
			return EXIT_FAILURE;
		}
	}
	
	free(datadir);
	
	/* For safety we do these protocol struct assertions */
	assert(sizeof(bp_proto_message_s) == 24);
	assert(sizeof(bp_proto_net_addr_s) == 26);
	assert(sizeof(bp_proto_net_addr_full_s) == 30);
	assert(sizeof(bp_proto_version_s) == 80);
	assert(sizeof(bp_proto_inv_s) == 36);
	assert(sizeof(bp_btcblock_header_s) == 80);
	
	/* Set the settings */
	bp_program_s program;
	memset(&program, 0, sizeof(program));
	program.addrpool_size = 20480;
	program.min_connections = 8;
	program.max_connections = 4096;
	program.reindex_blocks = 0;
	program.relay_transactions = 1;
	program.relay_blocks = 1;
	program.txpool_size = 1024;
	program.blocks_per_getblocks = 500;
	
	/* Interpret the command line */
	if (argc < 2) {
		printf("Invalid command line arguments.\n");
		printf("Usage:  bitpeer [listen_port] [public_ip] -n [seed_node]\n");
		printf("public_ip and seed_node may optionally contain a port number.\n");
		return EXIT_FAILURE;
	}
	
	unsigned short listen_port = atoi(argv[1]);
	if (listen_port == 0) {
		printf("Invalid port number specified. Valid ports go from 1 to 65535.\n");
		return EXIT_FAILURE;
	}
	
	struct sockaddr_in6 sockaddr;
	int sockaddr_len = sizeof(struct sockaddr_in6);
	if (evutil_parse_sockaddr_port(argv[2], (struct sockaddr*)&sockaddr, &sockaddr_len) < 0) {
		printf("Invalid public_ip specified\n");
		return EXIT_FAILURE;
	}
	if (sockaddr.sin6_family == AF_INET) {
		sockaddr = bp_in4to6((struct sockaddr_in*)&sockaddr);
		sockaddr_len = sizeof(struct sockaddr_in6);
	}
	if (sockaddr.sin6_port == 0) {
		sockaddr.sin6_port = ntohs(listen_port);
	}
	
	int nodecount = 0;
	struct sockaddr_in6 *nodeaddrs = NULL;
	int *nodelens = NULL;
	int *nodeperm = NULL;
	
	/* Now interpret the optional arguments */
	// Quick preprocessor macro to go to the next argv
	
#define NEXT_I() {i++; if (i >= argc) { printf("Argument for %s missing\n", argv[i-1]); return EXIT_FAILURE; }}
	for (int i = 3; i < argc; i++) {
		if (strcmp(argv[i], "--reindex") == 0) {
			program.reindex_blocks = 1;
		}
		else if (strcmp(argv[i], "--addnode") == 0  || strcmp(argv[i], "-n") == 0 ||
				 strcmp(argv[i], "--addpnode") == 0 || strcmp(argv[i], "-p") == 0) {
			NEXT_I();
			nodeaddrs = realloc(nodeaddrs, (nodecount+1) * sizeof(struct sockaddr_in6));
			nodelens = realloc(nodelens, (nodecount+1) * sizeof(int));
			nodeperm = realloc(nodeperm, (nodecount+1) * sizeof(int));
			nodelens[nodecount] = sizeof(struct sockaddr_in6);
			nodeperm[nodecount] = 0;
			
			if (strcmp(argv[i-1], "--addpnode") == 0 || strcmp(argv[i-1], "-p") == 0) {
				printf("Adding a permanent node\n");
				nodeperm[nodecount] = 1;
			}
			
			struct sockaddr_in6 *addr = &nodeaddrs[nodecount];
			memset(addr, 0, sizeof(struct sockaddr_in6));
			
			if (evutil_parse_sockaddr_port(argv[i], (struct sockaddr*)addr, nodelens+nodecount) < 0) {
				printf("Invalid node address specified: %s %d\n", argv[i], nodelens[nodecount]);
				return EXIT_FAILURE;
			}
			if (addr->sin6_family == AF_INET) {
				*addr = bp_in4to6((struct sockaddr_in*)addr);
				nodelens[nodecount] = sizeof(struct sockaddr_in6);
			}
			assert(addr->sin6_family == AF_INET6);
			
			if (addr->sin6_port == 0) addr->sin6_port = ntohs(8333);
			
			nodecount += 1;
		}
		else if (strcmp(argv[i], "--txpool") == 0) {
			NEXT_I();
			program.txpool_size = atoi(argv[i]);
			if (program.txpool_size <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--addrpool") == 0) {
			NEXT_I();
			program.addrpool_size = atoi(argv[i]);
			if (program.addrpool_size <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--getblocks-limit") == 0) {
			NEXT_I();
			program.blocks_per_getblocks = atoi(argv[i]);
			if (program.blocks_per_getblocks == 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--no-tx") == 0) {
			program.relay_transactions = 0;
		}
		else if (strcmp(argv[i], "--no-blocks") == 0) {
			program.relay_blocks = 0;
		}
		else if (strcmp(argv[i], "--minconn") == 0) {
			NEXT_I();
			program.min_connections = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "--maxconn") == 0) {
			NEXT_I();
			program.max_connections = atoi(argv[i]);
			if (program.max_connections <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--evdebug") == 0) {
#ifdef EVENT_DBG_ALL
			event_enable_debug_logging(EVENT_DBG_ALL);
#endif
			event_set_log_callback(log_cb);
			event_enable_debug_mode();
		}
		else {
			printf("Unknown argument '%s'\n", argv[i]);
			return EXIT_FAILURE;
		}
	}
	
	/* Ignore SIGPIPE */
	struct sigaction act;
	act.sa_handler = SIG_IGN;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGPIPE, &act, NULL);
	
	/* Create the main loop */
	bp_program_init(&program);
	
	program.eventbase = event_base_new();

	/* Set up the signal handler */
	struct event *signal_event = evsignal_new(program.eventbase, SIGINT, signal_cb, &program);
	evsignal_add(signal_event, NULL);
	
	/* Create a server */
	bp_server_s server;
	program.server = &server;
	bp_server_init(&server, &program, (char*)&sockaddr.sin6_addr, ntohs(sockaddr.sin6_port));
	if (bp_server_listen(&server, listen_port) < 0) {
		return EXIT_FAILURE;
	}
	
	/* We need to connect to one initial node in order to seed everything.
	   We will not do this initial discovery ourselves. */
	for (int i = 0; i < nodecount; i++) {
		bp_connection_s *seed_connection = malloc(sizeof(bp_connection_s));
		int status = bp_connection_connect(seed_connection, &server, &nodeaddrs[i], nodelens[i]);
		if (status < 0) {
			printf("Connecting failed\n");
		}
		seed_connection->is_seed = 1;
		seed_connection->is_permanent = nodeperm[i];
	}
	
	free(nodeaddrs);
	free(nodelens);
	free(nodeperm);
	
	/* Run the loop */
	event_base_loop(program.eventbase, 0);
	printf("Entering clean shutdown state\n");

	/* It would appear that our loop ended, so clean up */
	event_free(signal_event);
	bp_server_deinit(&server);
	
	bp_program_deinit(&program);
	event_base_free(program.eventbase);
	
	return EXIT_SUCCESS;
}