Example #1
0
struct Admin* Admin_new(Dict* config,
                        char* user,
                        struct event_base* eventBase,
                        struct ExceptionHandler* eh,
                        struct Allocator* allocator)
{
    errno = 0;
    int pipes[2][2];
    if (pipe(pipes[0]) || pipe(pipes[1])) {
        eh->exception(__FILE__ " Failed to create pipes.", errno, eh);
    }

    int pgid = getpid();
    int pid = fork();
    if (pid < 0) {
        eh->exception(__FILE__ " Failed to fork()", errno, eh);
    }

    bool isChild = (pid == 0);

    int inFd = pipes[isChild][0];
    close(pipes[!isChild][0]);

    int outFd = pipes[!isChild][1];
    close(pipes[isChild][1]);

    if (isChild) {
        // Set the process group so that children will not
        // become orphaned if the parent gets signal 11 err um 9.
        setpgid(0, pgid);

        if (user) {
            Security_setUser(user, NULL, AbortHandler_INSTANCE);
        }

        struct ChildContext context;
        memset(&context, 0, sizeof(struct ChildContext));
        context.inFd = inFd;
        context.outFd = outFd;
        context.allocator = allocator;
        event_reinit(eventBase);
        context.eventBase = eventBase;
        child(config, &context);
        exit(0);
    }

    setpgid(pid, pgid);

    struct Admin* admin = allocator->calloc(sizeof(struct Admin), 1, allocator);
    admin->inFd = inFd;
    admin->outFd = outFd;
    admin->allocator = allocator;
    admin->functionCount = 0;
    admin->eventBase = eventBase;
    admin->password = Dict_getString(config, BSTR("password"));
    admin->pipeEv = event_new(eventBase, inFd, EV_READ | EV_PERSIST, inFromChild, admin);
    event_add(admin->pipeEv, NULL);

    return admin;
}
Example #2
0
static void
thread_basic(void *arg)
{
	THREAD_T threads[NUM_THREADS];
	struct event ev;
	struct timeval tv;
	int i;
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;

	struct event *notification_event = NULL;
	struct event *sigchld_event = NULL;

	EVTHREAD_ALLOC_LOCK(count_lock, 0);
	tt_assert(count_lock);

	tt_assert(base);
	if (evthread_make_base_notifiable(base)<0) {
		tt_abort_msg("Couldn't make base notifiable!");
	}

#ifndef WIN32
	if (data->setup_data && !strcmp(data->setup_data, "forking")) {
		pid_t pid;
		int status;
		sigchld_event = evsignal_new(base, SIGCHLD, sigchld_cb, base);
		/* This piggybacks on the th_notify_fd weirdly, and looks
		 * inside libevent internals.  Not a good idea in non-testing
		 * code! */
		notification_event = event_new(base,
		    base->th_notify_fd[0], EV_READ|EV_PERSIST, notify_fd_cb,
		    NULL);
		event_add(sigchld_event, NULL);
		event_add(notification_event, NULL);

		if ((pid = fork()) == 0) {
			event_del(notification_event);
			if (event_reinit(base) < 0) {
				TT_FAIL(("reinit"));
				exit(1);
			}
			event_assign(notification_event, base,
			    base->th_notify_fd[0], EV_READ|EV_PERSIST,
			    notify_fd_cb, NULL);
			event_add(notification_event, NULL);
	 		goto child;
		}

		event_base_dispatch(base);

		if (waitpid(pid, &status, 0) == -1)
			tt_abort_perror("waitpid");
		TT_BLATHER(("Waitpid okay\n"));

		tt_assert(got_sigchld);
		tt_int_op(notification_fd_used, ==, 0);

		goto end;
	}
Example #3
0
int
server_start(struct server *s) {

	int i, ret;

	/* initialize libevent */
	s->base = event_base_new();

	if(s->cfg->daemonize) {
		server_daemonize(s->cfg->pidfile);

		/* sometimes event mech gets lost on fork */
		if(event_reinit(s->base) != 0) {
			fprintf(stderr, "Error: event_reinit failed after fork");
		}
	}

	/* ignore sigpipe */
#ifdef SIGPIPE
	signal(SIGPIPE, SIG_IGN);
#endif

	slog_init(s);

	/* install signal handlers */
	server_install_signal_handlers(s);

	/* start worker threads */
	for(i = 0; i < s->cfg->http_threads; ++i) {
		worker_start(s->w[i]);
	}

	/* create socket */
	s->fd = socket_setup(s, s->cfg->http_host, s->cfg->http_port);
	if(s->fd < 0) {
		return -1;
	}
	
	/*set keepalive socket option to do with half connection*/
        int keep_alive = 1;
        setsockopt(s->fd , SOL_SOCKET, SO_KEEPALIVE, (void*)&keep_alive, sizeof(keep_alive));

	/* start http server */
	event_set(&s->ev, s->fd, EV_READ | EV_PERSIST, server_can_accept, s);
	event_base_set(s->base, &s->ev);
	ret = event_add(&s->ev, NULL);

	if(ret < 0) {
		slog(s, WEBDIS_ERROR, "Error calling event_add on socket", 0);
		return -1;
	}

	slog(s, WEBDIS_INFO, "Webdis " WEBDIS_VERSION " up and running", 0);
	event_base_dispatch(s->base);

	return 0;
}
Example #4
0
int
main(int argc, char **argv)
{
    int r, l;
    struct event_base *ev_base;
    struct job binlog_jobs = {};

    progname = argv[0];
    opts(argc, argv);

    if (detach && binlog_dir) {
        if (binlog_dir[0] != '/') {
            warnx("The -b option requires an absolute path when used with -d.");
            usage("Path is not absolute", binlog_dir);
        }
    }

    job_init();
    prot_init();

    /* We want to make sure that only one beanstalkd tries to use the binlog
     * directory at a time. So acquire a lock now and never release it. */
    if (binlog_dir) {
        r = binlog_lock();
        if (!r) twarnx("failed to lock binlog dir %s", binlog_dir), exit(10);
    }

    r = make_server_socket(host_addr, port);
    if (r == -1) twarnx("make_server_socket()"), exit(111);
    l = r;

    if (user) su(user);
    ev_base = event_init();
    set_sig_handlers();
    nudge_fd_limit();

    r = listen(l, 1024);
    if (r == -1) twarn("listen()");
    accept_handler = (evh)h_accept;
    unbrake();

    binlog_jobs.prev = binlog_jobs.next = &binlog_jobs;
    binlog_init(&binlog_jobs);
    prot_replay_binlog(&binlog_jobs);

    if (detach) {
        daemonize();
        event_reinit(ev_base);
    }

    event_dispatch();
    twarnx("event_dispatch error");
    binlog_shutdown();
    return 0;
}
int server_start(struct server *s) {
    int i, ret;


    /* setrlimit */
    server_setrlimit(8192);

    /* daemonize */
    if (s->cfg->daemonize) {
        server_daemonize(s->cfg->pid);

        /* sometimes event mech gets lost on fork */
        if (event_reinit(s->base) != 0) {
            fprintf(stderr, "Error: event_reinit failed after fork");
        }
    }

    /* ignore sigpipe */
#ifdef SIGPIPE
    signal(SIGPIPE, SIG_IGN);
#endif

    /* lose root privileges if we have them */
    /*ret = server_setuid(s->cfg->user);
    if(ret < 0) {
        return -1;
    }*/

    /* slog init */
    slog_init(s);

    /* install signal handlers */
    server_install_signal_handlers(s);

    /* initialize libevent */
    s->base = event_base_new();

    /* start worker threads */
    for (i = 0; i < s->cfg->worker_processes; ++i) {
        worker_start(s->w[i]);
    }

    /* create socket */
	ret = socket_setup(s, s->cfg->http.servers);
    if(ret < 0) {
		return -1;
	}

    /* dispatch */
    slog(s, LOG_INFO, "pbiws " PBIWS_VERSION " up and running", 0);
    event_base_dispatch(s->base);

    return 0;
}
Example #6
0
struct tmuxproc *
proc_start(const char *name, struct event_base *base, int forkflag,
    void (*signalcb)(int))
{
	struct tmuxproc	*tp;
	struct utsname	 u;

#ifdef TMATE_SLAVE
	if (forkflag)
		fatal("can't fork");
#else
	if (forkflag) {
		switch (fork()) {
		case -1:
			fatal("fork failed");
		case 0:
			break;
		default:
			return (NULL);
		}
		if (daemon(1, 0) != 0)
			fatal("daemon failed");

		clear_signals(0);
		if (event_reinit(base) != 0)
			fatalx("event_reinit failed");
	}
	log_open(name);
#endif

#ifdef HAVE_SETPROCTITLE
	setproctitle("%s (%s)", name, socket_path);
#endif

	if (uname(&u) < 0)
		memset(&u, 0, sizeof u);

	log_debug("%s started (%ld): socket %s, protocol %d", name,
	    (long)getpid(), socket_path, PROTOCOL_VERSION);
	log_debug("on %s %s %s; libevent %s (%s)", u.sysname, u.release,
	    u.version, event_get_version(), event_get_method());

	tp = xcalloc(1, sizeof *tp);
	tp->name = xstrdup(name);

#ifndef TMATE_SLAVE
	tp->signalcb = signalcb;
	set_signals(proc_signal_cb, tp);
#endif

	return (tp);
}
Example #7
0
int
server_start(struct server *s) {

	int i, ret;

	/* initialize libevent */
	s->base = event_base_new();

	if(s->cfg->daemonize) {
		server_daemonize();

		/* sometimes event mech gets lost on fork */
		if(event_reinit(s->base) != 0) {
			fprintf(stderr, "Error: event_reinit failed after fork");
		}
	}

	/* ignore sigpipe */
#ifdef SIGPIPE
	signal(SIGPIPE, SIG_IGN);
#endif

	slog_init(s);

	/* start worker threads */
	for(i = 0; i < s->cfg->http_threads; ++i) {
		worker_start(s->w[i]);
	}

	/* create socket */
	s->fd = socket_setup(s->cfg->http_host, s->cfg->http_port);
	if(s->fd < 0) {
		return -1;
	}

	/* start http server */
	event_set(&s->ev, s->fd, EV_READ | EV_PERSIST, server_can_accept, s);
	event_base_set(s->base, &s->ev);
	ret = event_add(&s->ev, NULL);

	if(ret < 0) {
		slog(s, WEBDIS_ERROR, "Error calling event_add on socket", 0);
		return -1;
	}

	event_base_dispatch(s->base);

	return 0;
}
Example #8
0
int CXtReactor::Reinit(void)
{
	/* Call for after fork */
	int nRet = FUN_RET_OK;
	
	if ( m_pEvtBase == NULL )
	{
		return FUN_RET_ERR_ILLEGAL_CALL;
	}

	nRet = event_reinit( m_pEvtBase );
	if ( nRet < 0 )
	{
		return XT_REACT_INIT_FAIL;
	}
	return FUN_RET_OK;	
}
Example #9
0
File: proc.c Project: icetan/tmux
struct tmuxproc *
proc_start(const char *name, struct event_base *base, int forkflag,
    void (*signalcb)(int))
{
	struct tmuxproc	*tp;

	if (forkflag) {
		switch (fork()) {
		case -1:
			fatal("fork failed");
		case 0:
			break;
		default:
			return (NULL);
		}
		if (daemon(1, 0) != 0)
			fatal("daemon failed");

		clear_signals(0);
		if (event_reinit(base) != 0)
			fatalx("event_reinit failed");
	}

	logfile(name);

#ifdef HAVE_SETPROCTITLE
	setproctitle("%s (%s)", name, socket_path);
#endif

	log_debug("%s started (%ld): socket %s, protocol %d", name,
	    (long)getpid(), socket_path, PROTOCOL_VERSION);

	tp = xcalloc(1, sizeof *tp);
	tp->name = xstrdup(name);

	tp->signalcb = signalcb;
	set_signals(proc_signal_cb, tp);

	return (tp);
}
Example #10
0
struct rspamd_worker *
rspamd_fork_worker (struct rspamd_main *rspamd_main,
		struct rspamd_worker_conf *cf,
		guint index,
		struct event_base *ev_base)
{
	struct rspamd_worker *wrk;
	gint rc;
	struct rlimit rlim;

	/* Starting worker process */
	wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));

	if (!rspamd_socketpair (wrk->control_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	if (!rspamd_socketpair (wrk->srv_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	wrk->srv = rspamd_main;
	wrk->type = cf->type;
	wrk->cf = cf;
	REF_RETAIN (cf);
	wrk->index = index;
	wrk->ctx = cf->ctx;
	wrk->finish_actions = g_ptr_array_new ();

	wrk->pid = fork ();

	switch (wrk->pid) {
	case 0:
		/* Update pid for logging */
		rspamd_log_update_pid (cf->type, rspamd_main->logger);

		/* Init PRNG after fork */
		rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
		if (rc != OTTERY_ERR_NONE) {
			msg_err_main ("cannot initialize PRNG: %d", rc);
			abort ();
		}

		rspamd_random_seed_fast ();
#ifdef HAVE_EVUTIL_RNG_INIT
		evutil_secure_rng_init ();
#endif

		/* Remove the inherited event base */
		event_reinit (rspamd_main->ev_base);
		event_base_free (rspamd_main->ev_base);

		/* Drop privilleges */
		rspamd_worker_drop_priv (rspamd_main);
		/* Set limits */
		rspamd_worker_set_limits (rspamd_main, cf);
		/* Re-set stack limit */
		getrlimit (RLIMIT_STACK, &rlim);
		rlim.rlim_cur = 100 * 1024 * 1024;
		rlim.rlim_max = rlim.rlim_cur;
		setrlimit (RLIMIT_STACK, &rlim);

		setproctitle ("%s process", cf->worker->name);
		rspamd_pidfile_close (rspamd_main->pfh);
		/* Do silent log reopen to avoid collisions */
		rspamd_log_close (rspamd_main->logger);
		rspamd_log_open (rspamd_main->logger);
		wrk->start_time = rspamd_get_calendar_ticks ();

#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30))
# if (GLIB_MINOR_VERSION > 20)
		/* Ugly hack for old glib */
		if (!g_thread_get_initialized ()) {
			g_thread_init (NULL);
		}
# else
		g_thread_init (NULL);
# endif
#endif
		msg_info_main ("starting %s process %P (%d)", cf->worker->name,
				getpid (), index);
		/* Close parent part of socketpair */
		close (wrk->control_pipe[0]);
		close (wrk->srv_pipe[0]);
		rspamd_socket_nonblocking (wrk->control_pipe[1]);
		rspamd_socket_nonblocking (wrk->srv_pipe[1]);
		/* Execute worker */
		cf->worker->worker_start_func (wrk);
		exit (EXIT_FAILURE);
		break;
	case -1:
		msg_err_main ("cannot fork main process. %s", strerror (errno));
		rspamd_pidfile_remove (rspamd_main->pfh);
		exit (-errno);
		break;
	default:
		/* Close worker part of socketpair */
		close (wrk->control_pipe[1]);
		close (wrk->srv_pipe[1]);
		rspamd_socket_nonblocking (wrk->control_pipe[0]);
		rspamd_socket_nonblocking (wrk->srv_pipe[0]);
		rspamd_srv_start_watching (wrk, ev_base);
		/* Insert worker into worker's table, pid is index */
		g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER (
				wrk->pid), wrk);
		break;
	}

	return wrk;
}
Example #11
0
void HttpServer::start(int port, int workers){
    struct event_base *base;
    struct sockaddr_in sin;
    struct evconnlistener *listener;
    
    if(!port){
        port = DEFAULT_PORT;
    }
    
    if(!workers){
        workers = WORKERS_COUNT;
    }
    
    base = event_base_new();
    
    if (!base) {
        throw std::runtime_error("Can't create base");
    }
    
    memset(&sin, 0, sizeof(sin));
    
    // setting IPv4 family addresses and localhost
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr("127.0.0.1");
    // setting port
    sin.sin_port = htons(port);
    
    /*
     struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
        evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
        const struct sockaddr *sa, int socklen);
     */
    
    listener = evconnlistener_new_bind(base, connectionCallback, nullptr, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 1024, (struct sockaddr*) &sin, sizeof(sin));
    
    if(listener == NULL){
        event_base_free(base);
        throw std::runtime_error("Couldn't bind port");
    }
    
    /* Fork mechanism */
    for(int i=0; i<workers-1; i++){
        pid_t pid = fork();
        
        if (pid == 0)
        {
            std::cout<<"child process started. pid: " << getpid() << std::endl;
            event_reinit(base);
            
        } else if (pid > 0) {
            // parent process
            break;
            
        } else {
            // fork failed
            std::cout<<"fork failed!\n";
        }
    }
    
    evconnlistener_set_error_cb(listener, errorCallback);
    event_base_dispatch(base);
    
    event_base_free(base);
    return;
}
Example #12
0
void Admin_sendMessage(Dict* message, String* txid, struct Admin* admin)
{
    if (!admin) {
        return;
    }
    Assert_true(txid);

    uint8_t buff[MAX_API_REQUEST_SIZE + TXID_LEN];

    // Write the inter-process txid.
    Bits_memcpyConst(buff, txid->bytes, TXID_LEN);

    uint8_t allocBuff[256];
    struct Allocator* allocator = BufferAllocator_new(allocBuff, 256);

    // Bounce back the user-supplied txid.
    String userTxid = { .bytes = txid->bytes + TXID_LEN, .len = txid->len - TXID_LEN };
    if (txid->len > TXID_LEN) {
        Dict_putString(message, TXID, &userTxid, allocator);
    }

    struct Writer* w = ArrayWriter_new(buff + TXID_LEN, MAX_API_REQUEST_SIZE, allocator);
    StandardBencSerializer_get()->serializeDictionary(w, message);

    write(admin->outFd, buff, w->bytesWritten(w) + TXID_LEN);
}

struct Admin* Admin_new(struct sockaddr_storage* addr,
                        int addrLen,
                        String* password,
                        char* user,
                        struct event_base* eventBase,
                        struct ExceptionHandler* eh,
                        struct Log* logger,
                        struct Allocator* allocator)
{
    errno = 0;
    int pipes[2][2];
    if (pipe(pipes[0]) || pipe(pipes[1])) {
        eh->exception(__FILE__ " Failed to create pipes.", errno, eh);
    }

    int pgid = getpid();
    int pid = fork();
    if (pid < 0) {
        eh->exception(__FILE__ " Failed to fork()", errno, eh);
    }

    bool isChild = (pid == 0);

    int inFd = pipes[isChild][0];
    close(pipes[!isChild][0]);

    int outFd = pipes[!isChild][1];
    close(pipes[isChild][1]);

    if (isChild) {
        // Set the process group so that children will not
        // become orphaned if the parent gets signal 11 err um 9.
        setpgid(0, pgid);

        if (user) {
            Security_setUser(user, NULL, AbortHandler_INSTANCE);
        }

        struct ChildContext context;
        memset(&context, 0, sizeof(struct ChildContext));
        context.inFd = inFd;
        context.outFd = outFd;
        context.allocator = allocator;
        event_reinit(eventBase);
        context.eventBase = eventBase;
        child(addr, addrLen, user, &context);
        fprintf(stderr, "Admin process exiting.");
        exit(0);
    }

    setpgid(pid, pgid);

    struct Admin* admin = allocator->calloc(sizeof(struct Admin), 1, allocator);
    admin->inFd = inFd;
    admin->outFd = outFd;
    admin->allocator = allocator;
    admin->logger = logger;
    admin->functionCount = 0;
    admin->eventBase = eventBase;
    admin->password = password;
    Bits_memcpyConst(&admin->address, addr, sizeof(struct sockaddr_storage));
    admin->addressLength = addrLen;
    admin->pipeEv = event_new(eventBase, inFd, EV_READ | EV_PERSIST, inFromChild, admin);
    event_add(admin->pipeEv, NULL);

    event_base_dispatch(eventBase);

    return admin;
}
Example #13
0
static void
libevent_ctx_reinitialize(void *priv)
{
    event_reinit(priv);
}
Example #14
0
static gint
lua_worker_spawn_process (lua_State *L)
{
	struct rspamd_worker *w = lua_check_worker (L, 1);
	struct rspamd_lua_process_cbdata *cbdata;
	struct rspamd_abstract_worker_ctx *actx;
	struct rspamd_srv_command srv_cmd;
	const gchar *cmdline = NULL, *input = NULL;
	gsize inputlen = 0;
	pid_t pid;
	GError *err = NULL;
	gint func_cbref, cb_cbref;

	if (!rspamd_lua_parse_table_arguments (L, 2, &err,
			"func=F;exec=S;stdin=V;*on_complete=F", &func_cbref,
			&cmdline, &inputlen, &input, &cb_cbref)) {
		msg_err ("cannot get parameters list: %e", err);

		if (err) {
			g_error_free (err);
		}

		return 0;
	}

	cbdata = g_malloc0 (sizeof (*cbdata));
	cbdata->cb_cbref = cb_cbref;
	cbdata->func_cbref = func_cbref;

	if (input) {
		cbdata->out_buf = g_string_new_len (input, inputlen);
		cbdata->out_pos = 0;
	}

	if (rspamd_socketpair (cbdata->sp, TRUE) == -1) {
		msg_err ("cannot spawn socketpair: %s", strerror (errno));
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
		g_free (cbdata);

		return 0;
	}

	actx = w->ctx;
	cbdata->wrk = w;
	cbdata->L = L;
	cbdata->ev_base = actx->ev_base;
	cbdata->sz = (guint64)-1;

	pid = fork ();

	if (pid == -1) {
		msg_err ("cannot spawn process: %s", strerror (errno));
		close (cbdata->sp[0]);
		close (cbdata->sp[1]);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
		g_free (cbdata);

		return 0;
	}
	else if (pid == 0) {
		/* Child */
		gint rc;
		gchar inbuf[4];

		rspamd_log_update_pid (w->cf->type, w->srv->logger);
		rc = ottery_init (w->srv->cfg->libs_ctx->ottery_cfg);

		if (rc != OTTERY_ERR_NONE) {
			msg_err ("cannot initialize PRNG: %d", rc);
			abort ();
		}
		rspamd_random_seed_fast ();
#ifdef HAVE_EVUTIL_RNG_INIT
		evutil_secure_rng_init ();
#endif

		close (cbdata->sp[0]);
		/* Here we assume that we can block on writing results */
		rspamd_socket_blocking (cbdata->sp[1]);
		event_reinit (cbdata->ev_base);
		g_hash_table_remove_all (w->signal_events);
		rspamd_worker_unblock_signals ();
		rspamd_lua_execute_lua_subprocess (L, cbdata);

		/* Wait for parent to reply and exit */
		rc = read (cbdata->sp[1], inbuf, sizeof (inbuf));

		if (memcmp (inbuf, "\0\0\0\0", 4) == 0) {
			exit (EXIT_SUCCESS);
		}
		else {
			msg_err ("got invalid reply from parent");

			exit (EXIT_FAILURE);
		}

	}

	cbdata->cpid = pid;
	cbdata->io_buf = g_string_sized_new (8);
	/* Notify main */
	memset (&srv_cmd, 0, sizeof (srv_cmd));
	srv_cmd.type = RSPAMD_SRV_ON_FORK;
	srv_cmd.cmd.on_fork.state = child_create;
	srv_cmd.cmd.on_fork.cpid = pid;
	srv_cmd.cmd.on_fork.ppid = getpid ();
	rspamd_srv_send_command (w, cbdata->ev_base, &srv_cmd, -1, NULL, NULL);

	close (cbdata->sp[1]);
	rspamd_socket_nonblocking (cbdata->sp[0]);
	/* Parent */
	rspamd_worker_set_signal_handler (SIGCHLD, w, cbdata->ev_base,
			rspamd_lua_cld_handler,
			cbdata);

	/* Add result pipe waiting */
	event_set (&cbdata->ev, cbdata->sp[0], EV_READ | EV_PERSIST,
			rspamd_lua_subprocess_io, cbdata);
	event_base_set (cbdata->ev_base, &cbdata->ev);
	/* TODO: maybe add timeout? */
	event_add (&cbdata->ev, NULL);

	return 0;
}
Example #15
0
int worker(struct event_base *ev_base) {
  event_reinit(ev_base);
  event_base_dispatch(ev_base);
}
Example #16
0
int main(int argc, char **argv) {

  init_config(argc, argv);

  open_authorizations("r");

  init_webfinger();

  /** OPEN MAGIC DATABASE **/

  magic_cookie = magic_open(MAGIC_MIME);
  if(magic_load(magic_cookie, RS_MAGIC_DATABASE) != 0) {
    log_error("Failed to load magic database: %s", magic_error(magic_cookie));
    exit(EXIT_FAILURE);
  }

  log_info("starting process: main");

  if(prctl(PR_SET_NAME, "rs-serve [main]", 0, 0, 0) != 0) {
    log_error("Failed to set process name: %s", strerror(errno));
  }

  /** SETUP EVENT BASE **/

  rs_event_base = event_base_new();
  ASSERT_NOT_NULL(rs_event_base, "event_base_new()");
  log_debug("libevent method: %s", event_base_get_method(rs_event_base));
  event_set_log_callback(log_event_base_message);

  // TODO: add error cb to base

  /** SETUP AUTH TOKENS HASH TABLE **/

  auth_sessions = sm_new(1024); // FIXME: this a hardcoded value.

  /** SETUP MAIN LISTENER **/

  struct sockaddr_in sin;
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(0);
  sin.sin_port = htons(RS_PORT);

  evhtp_t *server = evhtp_new(rs_event_base, NULL);

  if(RS_USE_SSL) {
    evhtp_ssl_cfg_t ssl_config = {
      .pemfile = RS_SSL_CERT_PATH,
      .privfile = RS_SSL_KEY_PATH,
      .cafile = RS_SSL_CA_PATH,
      // what's this???
      .capath = NULL,
      .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW",
      .ssl_opts = SSL_OP_NO_SSLv2,
      .ssl_ctx_timeout = 60*60*48,
      .verify_peer = SSL_VERIFY_PEER,
      .verify_depth = 42,
      .x509_verify_cb = dummy_ssl_verify_callback,
      .x509_chk_issued_cb = dummy_check_issued_cb,
      .scache_type = evhtp_ssl_scache_type_internal,
      .scache_size = 1024,
      .scache_timeout = 1024,
      .scache_init = NULL,
      .scache_add = NULL,
      .scache_get = NULL,
      .scache_del = NULL
    };

    if(evhtp_ssl_init(server, &ssl_config) != 0) {
      log_error("evhtp_ssl_init() failed");
      exit(EXIT_FAILURE);
    }
  }

  /* WEBFINGER */

  evhtp_callback_cb webfinger_cb = (RS_WEBFINGER_ENABLED ?
                                    handle_webfinger : reject_webfinger);
  evhtp_set_cb(server, "/.well-known/webfinger", webfinger_cb, NULL);
  // support legacy webfinger clients (we don't support XRD though):
  evhtp_set_cb(server, "/.well-known/host-meta", webfinger_cb, NULL);
  evhtp_set_cb(server, "/.well-known/host-meta.json", webfinger_cb, NULL);

  /* REMOTESTORAGE */

  evhtp_callback_t *storage_cb = evhtp_set_regex_cb(server, "^/storage/([^/]+)/.*$", handle_storage, NULL);

  evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL);

  if(evhtp_bind_sockaddr(server, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) {
    log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno));
    exit(EXIT_FAILURE);
  }

  /** SETUP AUTH LISTENER **/

  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(0);
  sin.sin_port = htons(RS_AUTH_PORT);

  evhtp_t *server_auth = evhtp_new(rs_event_base, NULL);

  if(RS_USE_SSL) {
    evhtp_ssl_cfg_t ssl_config = {
      .pemfile = RS_SSL_CERT_PATH,
      .privfile = RS_SSL_KEY_PATH,
      .cafile = RS_SSL_CA_PATH,
      // what's this???
      .capath = NULL,
      .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW",
      .ssl_opts = SSL_OP_NO_SSLv2,
      .ssl_ctx_timeout = 60*60*48,
      .verify_peer = SSL_VERIFY_PEER,
      .verify_depth = 42,
      .x509_verify_cb = dummy_ssl_verify_callback,
      .x509_chk_issued_cb = dummy_check_issued_cb,
      .scache_type = evhtp_ssl_scache_type_internal,
      .scache_size = 1024,
      .scache_timeout = 1024,
      .scache_init = NULL,
      .scache_add = NULL,
      .scache_get = NULL,
      .scache_del = NULL
    };

    if(evhtp_ssl_init(server_auth, &ssl_config) != 0) {
      log_error("evhtp_ssl_init() failed");
      exit(EXIT_FAILURE);
    }
  }

  /* AUTH */

  evhtp_set_cb(server_auth, "/authenticate", handle_authenticate, NULL);
  evhtp_set_cb(server_auth, "/authorizations", handle_authorizations, NULL);

  evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL);

  if(evhtp_bind_sockaddr(server_auth, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) {
    log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno));
    exit(EXIT_FAILURE);
  }

  /** SETUP SIGNALS **/

  sigset_t sigmask;
  sigemptyset(&sigmask);
  sigaddset(&sigmask, SIGINT);
  sigaddset(&sigmask, SIGTERM);
  sigaddset(&sigmask, SIGCHLD);
  ASSERT_ZERO(sigprocmask(SIG_BLOCK, &sigmask, NULL), "sigprocmask()");
  int sfd = signalfd(-1, &sigmask, SFD_NONBLOCK);
  ASSERT_NOT_EQ(sfd, -1, "signalfd()");

  struct event *signal_event = event_new(rs_event_base, sfd, EV_READ | EV_PERSIST,
                                         handle_signal, NULL);
  event_add(signal_event, NULL);

  /** RUN EVENT LOOP **/

  if(RS_DETACH) {
    int pid = fork();
    if(pid == 0) {
      event_reinit(rs_event_base);

      if(RS_LOG_FILE == stdout) {
        log_warn("No --log-file option given. Future output will be lost.");
        freopen("/dev/null", "r", stdout);
        freopen("/dev/null", "r", stderr);
      }

      return event_base_dispatch(rs_event_base);
    } else {
      printf("rs-serve detached with pid %d\n", pid);
      if(RS_PID_FILE) {
        fprintf(RS_PID_FILE, "%d", pid);
        fflush(RS_PID_FILE);
      }
      _exit(EXIT_SUCCESS);
    }
  } else {
    if(RS_PID_FILE) {
      fprintf(RS_PID_FILE, "%d", getpid());
      fflush(RS_PID_FILE);
    }
    return event_base_dispatch(rs_event_base);
  }
}