Esempio n. 1
0
int
main (int argc, char **argv)
{
	struct event evfifo;
#ifdef WIN32
	HANDLE socket;
	WORD wVersionRequested;
	WSADATA wsaData;
	int	err;

	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );

	// Open a file. 
	socket = CreateFile("test.txt",     // open File 
			GENERIC_READ,                 // open for reading 
			0,                            // do not share 
			NULL,                         // no security 
			OPEN_EXISTING,                // existing file only 
			FILE_ATTRIBUTE_NORMAL,        // normal file 
			NULL);                        // no attr. template 

	if(socket == INVALID_HANDLE_VALUE)
		return 1;

#else
	struct stat st;
	const char *fifo = "event.fifo";
	int socket;
 
	if (lstat (fifo, &st) == 0) {
		if ((st.st_mode & S_IFMT) == S_IFREG) {
			errno = EEXIST;
			perror("lstat");
			exit (1);
		}
	}

	unlink (fifo);
	if (mkfifo (fifo, 0600) == -1) {
		perror("mkfifo");
		exit (1);
	}

	/* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
#ifdef __linux
	socket = open (fifo, O_RDWR | O_NONBLOCK, 0);
#else
	socket = open (fifo, O_RDONLY | O_NONBLOCK, 0);
#endif

	if (socket == -1) {
		perror("open");
		exit (1);
	}

	fprintf(stderr, "Write data to %s\n", fifo);
#endif
	/* Initalize the event library */
	event_init();

	/* Initalize one event */
#ifdef WIN32
	event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo);
#else
	event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);
#endif

	/* Add it to the active events, without a timeout */
	event_add(&evfifo, NULL);
	
	event_dispatch();
#ifdef WIN32
	CloseHandle(socket);
#endif
	return (0);
}
Esempio n. 2
0
static struct http_connection * http_connection_new(struct http_server *hs,
		int fd, struct sockaddr *sin)
{
	struct http_connection *hc = NULL;
	hc = (struct http_connection *)malloc(sizeof(struct http_connection));
	if (!hc) {
		printf("Could not create new http connection\n");
		return NULL;
	}

	memset(hc, 0, sizeof(struct http_connection));

	hc->hs = hs;
	hc->fd = fd;
	memcpy(&(hc->sin), sin, sizeof(struct sockaddr_in));
	hc->connection_status = HTTP_CONNECTION_STATUS_READ_HEADER;
	hc->status = HTTP_OK;

	if (fd >= 0) {	/* init head node with fd<0 */
		/* create a event for this fd */
		hc->ev_read = event_new(hs->base, fd, EV_READ | EV_PERSIST, http_read_cb, hc);
		if (!hc->ev_read) {
			printf("Could not create event for http connection(fd %d)\n", fd);
			goto failed;
		}

		hc->ev_write = event_new(hs->base, fd, EV_WRITE, http_404_cb, hc);
		if (!hc->ev_write) {
			printf("Could not create event for http connection(fd %d)\n", fd);
			goto failed;
		}

		/* create a event buffer for read data */
		hc->evbin = evbuffer_new();
		if (!hc->evbin) {
			printf("Could not create input evbuffer for http connection(fd %d)\n", fd);
			goto failed;
		}

		/* create a event buffer for read data */
		hc->evbout = evbuffer_new();
		if (!hc->evbout) {
			printf("Could not create output evbuffer for http connection(fd %d)\n", fd);
			goto failed;
		}

		int i = 1;
		setsockopt(hc->fd, SOL_TCP, TCP_NODELAY, &i, sizeof(i));

		/* close connection if not data received in 3 seconds */
		struct timeval timeout = {10, 0};
		event_add(hc->ev_read, &timeout);
	}

	/* init list node */
	hc->prev = hc;
	hc->next = hc;

	dbprintf("http connection new %p\n", hc);

	return hc;
failed:
	if (hc->evbout)
		evbuffer_free(hc->evbout);
	if (hc->evbin)
		evbuffer_free(hc->evbin);
	if (hc->ev_write)
		event_free(hc->ev_write);
	if (hc->ev_read)
		event_free(hc->ev_read);
	if (hc)
		free(hc);
	return NULL;
}
Esempio n. 3
0
int
main(int argc, char *argv[])
{
	struct stat st;
	char *server = NULL;
	int c, fd, port = 0, use_ssl = 0;

	ctx->channel = "flood";
	ctx->type = "text/html";
	ctx->send_tv.tv_sec = 1;
	ctx->stats_tv.tv_sec = 5;
	
	while ((c = getopt(argc, argv, "c:f:l:p:r:sh?")) != -1) {
		switch (c) {
		case 'c':
			ctx->channel = optarg;
			break;
		case 'f':
			if ((fd = open(optarg, O_RDONLY, 0)) != -1) {
				if (fstat(fd, &st) == -1)
					err(1, "fstat");
				ctx->len = st.st_size;
				ctx->data = malloc(st.st_size);
				if (read(fd, ctx->data, ctx->len) != ctx->len)
					err(1, "read");
				close(fd);
			} else
				err(1, "open");
			break;
		case 'l':
			server = optarg;
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'r':
			ctx->send_tv.tv_sec = 0;
			ctx->send_tv.tv_usec = 1000000 / atoi(optarg);
			break;
		case 's':
			use_ssl = 1;
			break;
		case 't':
			ctx->type = optarg;
			break;
		default:
			usage();
			break;
		}
	}
	argc -= optind;
	argv += optind;

	if (argc > 0)
		usage();
	
	putenv("EVENT_SHOW_METHOD=1");
	event_init();

	evmsg_open(server, port, use_ssl);
	evmsg_set_auth(getenv("USER"), "foobar");
	
	evtimer_set(&ctx->send_ev, send_msg, NULL);
	event_add(&ctx->send_ev, &ctx->send_tv);

	evtimer_set(&ctx->stats_ev, print_stats, NULL);
	event_add(&ctx->stats_ev, &ctx->stats_tv);
	
	event_dispatch();
	
	evmsg_close();
	
	exit(0);
}
Esempio n. 4
0
//********************************************************************************
// Main
//********************************************************************************
int main(int argc, char **argv)
{
	struct event_base *base;
	struct evconnlistener *listener;
	struct event *signal_event;

	struct sockaddr_in sin;
#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
#endif

    // Setup libevent
    printf("Setting up\n");fflush(stdout);
	base = event_base_new();
	if (!base)
    {
		fprintf(stderr, "Could not initialize libevent!\n");
		return 1;
	}

    // Init RVM
    initRVM();

    // Init group structure (TODO: how to do thisn, and to ensure it's only once.
    //theGroup = initRVMGroup();

    // Init socket
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);

    // Setup listener for socket connections
    printf("Setting up listener\n");fflush(stdout);
	listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
	                                   LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
                                       (struct sockaddr*)&sin,
	                                   sizeof(sin));
	if (!listener)
    {
		fprintf(stderr, "Could not create a listener!\n");
		return 1;
	}

    // Setup signal event listener
	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
	if (!signal_event || event_add(signal_event, NULL)<0)
    {
		fprintf(stderr, "Could not create/add a signal event!\n");
		return 1;
	}

    // Start libevent
	event_base_dispatch(base);

    // Free resources when done
	evconnlistener_free(listener);
	event_free(signal_event);
	event_base_free(base);

	printf("done\n");
	return 0;
}
Esempio n. 5
0
static int
test_ratelimiting(void)
{
	struct event_base *base;
	struct sockaddr_in sin;
	struct evconnlistener *listener;

	struct sockaddr_storage ss;
	ev_socklen_t slen;

	int i;

	struct timeval tv;

	ev_uint64_t total_received;
	double total_sq_persec, total_persec;
	double variance;
	double expected_total_persec = -1.0, expected_avg_persec = -1.0;
	int ok = 1;
	struct event_config *base_cfg;
	struct event *periodic_level_check;
	struct event *group_drain_event=NULL;

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
	sin.sin_port = 0; /* unspecified port */

	if (0)
		event_enable_debug_mode();

	base_cfg = event_config_new();

#ifdef _WIN32
	if (cfg_enable_iocp) {
		evthread_use_windows_threads();
		event_config_set_flag(base_cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
	}
#endif

	base = event_base_new_with_config(base_cfg);
	event_config_free(base_cfg);
	if (! base) {
		fprintf(stderr, "Couldn't create event_base");
		return 1;
	}

	listener = evconnlistener_new_bind(base, echo_listenercb, base,
	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
	    (struct sockaddr *)&sin, sizeof(sin));
	if (! listener) {
		fprintf(stderr, "Couldn't create listener");
		return 1;
	}

	slen = sizeof(ss);
	if (getsockname(evconnlistener_get_fd(listener), (struct sockaddr *)&ss,
		&slen) < 0) {
		perror("getsockname");
		return 1;
	}

	if (cfg_connlimit > 0) {
		conn_bucket_cfg = ev_token_bucket_cfg_new(
			cfg_connlimit, cfg_connlimit * 4,
			cfg_connlimit, cfg_connlimit * 4,
			&cfg_tick);
		assert(conn_bucket_cfg);
	}

	if (cfg_grouplimit > 0) {
		group_bucket_cfg = ev_token_bucket_cfg_new(
			cfg_grouplimit, cfg_grouplimit * 4,
			cfg_grouplimit, cfg_grouplimit * 4,
			&cfg_tick);
		group = ratelim_group = bufferevent_rate_limit_group_new(
			base, group_bucket_cfg);
		expected_total_persec = cfg_grouplimit - (cfg_group_drain / seconds_per_tick);
		expected_avg_persec = cfg_grouplimit / cfg_n_connections;
		if (cfg_connlimit > 0 && expected_avg_persec > cfg_connlimit)
			expected_avg_persec = cfg_connlimit;
		if (cfg_min_share >= 0)
			bufferevent_rate_limit_group_set_min_share(
				ratelim_group, cfg_min_share);
	}

	if (expected_avg_persec < 0 && cfg_connlimit > 0)
		expected_avg_persec = cfg_connlimit;

	if (expected_avg_persec > 0)
		expected_avg_persec /= seconds_per_tick;
	if (expected_total_persec > 0)
		expected_total_persec /= seconds_per_tick;

	bevs = calloc(cfg_n_connections, sizeof(struct bufferevent *));
	states = calloc(cfg_n_connections, sizeof(struct client_state));

	for (i = 0; i < cfg_n_connections; ++i) {
		bevs[i] = bufferevent_socket_new(base, -1,
		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE);
		assert(bevs[i]);
		bufferevent_setcb(bevs[i], discard_readcb, loud_writecb,
		    write_on_connectedcb, &states[i]);
		bufferevent_enable(bevs[i], EV_READ|EV_WRITE);
		bufferevent_socket_connect(bevs[i], (struct sockaddr *)&ss,
		    slen);
	}

	tv.tv_sec = cfg_duration - 1;
	tv.tv_usec = 995000;

	event_base_loopexit(base, &tv);

	tv.tv_sec = 0;
	tv.tv_usec = 100*1000;
	ms100_common = event_base_init_common_timeout(base, &tv);

	periodic_level_check = event_new(base, -1, EV_PERSIST, check_group_bucket_levels_cb, NULL);
	event_add(periodic_level_check, ms100_common);

	if (cfg_group_drain && ratelim_group) {
		group_drain_event = event_new(base, -1, EV_PERSIST, group_drain_cb, NULL);
		event_add(group_drain_event, &cfg_tick);
	}

	event_base_dispatch(base);

	ratelim_group = NULL; /* So no more responders get added */
	event_free(periodic_level_check);
	if (group_drain_event)
		event_del(group_drain_event);

	for (i = 0; i < cfg_n_connections; ++i) {
		bufferevent_free(bevs[i]);
	}
	evconnlistener_free(listener);

	/* Make sure no new echo_conns get added to the group. */
	ratelim_group = NULL;

	/* This should get _everybody_ freed */
	while (n_echo_conns_open) {
		printf("waiting for %d conns\n", n_echo_conns_open);
		tv.tv_sec = 0;
		tv.tv_usec = 300000;
		event_base_loopexit(base, &tv);
		event_base_dispatch(base);
	}

	if (group)
		bufferevent_rate_limit_group_free(group);

	if (total_n_bev_checks) {
		printf("Average read bucket level: %f\n",
		    (double)total_rbucket_level/total_n_bev_checks);
		printf("Average write bucket level: %f\n",
		    (double)total_wbucket_level/total_n_bev_checks);
		printf("Highest read bucket level: %f\n",
		    (double)max_bucket_level);
		printf("Highest write bucket level: %f\n",
		    (double)min_bucket_level);
		printf("Average max-to-read: %f\n",
		    ((double)total_max_to_read)/total_n_bev_checks);
		printf("Average max-to-write: %f\n",
		    ((double)total_max_to_write)/total_n_bev_checks);
	}
	if (total_n_group_bev_checks) {
		printf("Average group read bucket level: %f\n",
		    ((double)total_group_rbucket_level)/total_n_group_bev_checks);
		printf("Average group write bucket level: %f\n",
		    ((double)total_group_wbucket_level)/total_n_group_bev_checks);
	}

	total_received = 0;
	total_persec = 0.0;
	total_sq_persec = 0.0;
	for (i=0; i < cfg_n_connections; ++i) {
		double persec = states[i].received;
		persec /= cfg_duration;
		total_received += states[i].received;
		total_persec += persec;
		total_sq_persec += persec*persec;
		printf("%d: %f per second\n", i+1, persec);
	}
	printf("   total: %f per second\n",
	    ((double)total_received)/cfg_duration);
	if (expected_total_persec > 0) {
		double diff = expected_total_persec -
		    ((double)total_received/cfg_duration);
		printf("  [Off by %lf]\n", diff);
		if (cfg_grouplimit_tolerance > 0 &&
		    fabs(diff) > cfg_grouplimit_tolerance) {
			fprintf(stderr, "Group bandwidth out of bounds\n");
			ok = 0;
		}
	}

	printf(" average: %f per second\n",
	    (((double)total_received)/cfg_duration)/cfg_n_connections);
	if (expected_avg_persec > 0) {
		double diff = expected_avg_persec - (((double)total_received)/cfg_duration)/cfg_n_connections;
		printf("  [Off by %lf]\n", diff);
		if (cfg_connlimit_tolerance > 0 &&
		    fabs(diff) > cfg_connlimit_tolerance) {
			fprintf(stderr, "Connection bandwidth out of bounds\n");
			ok = 0;
		}
	}

	variance = total_sq_persec/cfg_n_connections - total_persec*total_persec/(cfg_n_connections*cfg_n_connections);

	printf("  stddev: %f per second\n", sqrt(variance));
	if (cfg_stddev_tolerance > 0 &&
	    sqrt(variance) > cfg_stddev_tolerance) {
		fprintf(stderr, "Connection variance out of bounds\n");
		ok = 0;
	}

	event_base_free(base);
	free(bevs);
	free(states);

	return ok ? 0 : 1;
}
Esempio n. 6
0
static int
http_map_finish (struct rspamd_http_connection *conn,
		struct rspamd_http_message *msg)
{
	struct http_callback_data *cbd = conn->ud;
	struct rspamd_map *map;
	struct rspamd_map_backend *bk;
	guchar *aux_data, *in = NULL;
	gsize inlen = 0, dlen = 0;

	map = cbd->map;
	bk = cbd->bk;

	if (msg->code == 200) {

		if (cbd->check) {
			cbd->periodic->need_modify = TRUE;
			/* Reset the whole chain */
			cbd->periodic->cur_backend = 0;
			rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
			MAP_RELEASE (cbd, "http_callback_data");

			return 0;
		}

		if (cbd->stage == map_load_file) {
			if (msg->last_modified) {
				cbd->data->last_checked = msg->last_modified;
			}
			else {
				cbd->data->last_checked = msg->date;
			}

			/* Maybe we need to check signature ? */
			if (bk->is_signed) {

				if (bk->trusted_pubkey) {
					/* No need to load key */
					cbd->stage = map_load_signature;
					cbd->pk = rspamd_pubkey_ref (bk->trusted_pubkey);
				}
				else {
					cbd->stage = map_load_pubkey;
				}

				cbd->shmem_data = rspamd_http_message_shmem_ref (msg);
				cbd->data_len = msg->body_buf.len;
				rspamd_http_connection_reset (cbd->conn);
				write_http_request (cbd);
				MAP_RELEASE (cbd, "http_callback_data");

				return 0;
			}
			else {
				/* Unsinged version - just open file */
				cbd->shmem_data = rspamd_http_message_shmem_ref (msg);
				cbd->data_len = msg->body_buf.len;

				goto read_data;
			}
		}
		else if (cbd->stage == map_load_pubkey) {
			/* We now can load pubkey */
			cbd->shmem_pubkey = rspamd_http_message_shmem_ref (msg);
			cbd->pubkey_len = msg->body_buf.len;

			aux_data = rspamd_shmem_xmap (cbd->shmem_pubkey->shm_name,
					PROT_READ, &inlen);

			if (aux_data == NULL) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				goto err;
			}

			if (inlen < cbd->pubkey_len) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			cbd->pk = rspamd_pubkey_from_base32 (aux_data, cbd->pubkey_len,
					RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);
			munmap (aux_data, inlen);

			if (cbd->pk == NULL) {
				msg_err_map ("cannot load pubkey file %s: bad pubkey",
						cbd->shmem_pubkey->shm_name);
				goto err;
			}

			cbd->stage = map_load_signature;
			rspamd_http_connection_reset (cbd->conn);
			write_http_request (cbd);
			MAP_RELEASE (cbd, "http_callback_data");

			return 0;
		}
		else if (cbd->stage == map_load_signature) {
			/* We can now check signature */
			cbd->shmem_sig = rspamd_http_message_shmem_ref (msg);
			cbd->sig_len = msg->body_buf.len;

			aux_data = rspamd_shmem_xmap (cbd->shmem_sig->shm_name,
					PROT_READ, &inlen);

			if (aux_data == NULL) {
				msg_err_map ("cannot map signature file %s: %s",
						cbd->shmem_sig->shm_name, strerror (errno));
				goto err;
			}

			if (inlen < cbd->sig_len) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen);

			if (in == NULL) {
				msg_err_map ("cannot read tempfile %s: %s",
						cbd->shmem_data->shm_name,
						strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			if (!rspamd_map_check_sig_pk_mem (aux_data, cbd->sig_len, map, in,
					cbd->data_len, cbd->pk)) {
				munmap (aux_data, inlen);
				munmap (in, dlen);
				goto err;
			}

			munmap (in, dlen);
		}

read_data:
		g_assert (cbd->shmem_data != NULL);

		in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen);

		if (in == NULL) {
			msg_err_map ("cannot read tempfile %s: %s",
					cbd->shmem_data->shm_name,
					strerror (errno));
			goto err;
		}

		map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
		msg_info_map ("read map data from %s", cbd->data->host);

		/*
		 * We know that a map is in the locked state
		 */
		if (g_atomic_int_compare_and_exchange (&map->cache->available, 0, 1)) {
			/* Store cached data */
			struct rspamd_http_map_cached_cbdata *cache_cbd;
			struct timeval tv;

			rspamd_strlcpy (map->cache->shmem_name, cbd->shmem_data->shm_name,
					sizeof (map->cache->shmem_name));
			map->cache->len = cbd->data_len;
			map->cache->last_checked = cbd->data->last_checked;
			cache_cbd = g_slice_alloc0 (sizeof (*cache_cbd));
			cache_cbd->shm = cbd->shmem_data;
			cache_cbd->map = map;
			MAP_RETAIN (cache_cbd->shm, "shmem_data");
			event_set (&cache_cbd->timeout, -1, EV_TIMEOUT, rspamd_map_cache_cb,
					cache_cbd);
			event_base_set (cbd->ev_base, &cache_cbd->timeout);
			double_to_tv (map->poll_timeout, &tv);
			event_add (&cache_cbd->timeout, &tv);
		}

		cbd->periodic->cur_backend ++;
		munmap (in, dlen);
		rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	}
	else if (msg->code == 304 && (cbd->check && cbd->stage == map_load_file)) {
		msg_debug_map ("data is not modified for server %s",
				cbd->data->host);

		if (msg->last_modified) {
			cbd->data->last_checked = msg->last_modified;
		}
		else {
			cbd->data->last_checked = msg->date;
		}

		cbd->periodic->cur_backend ++;
		rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	}
	else {
		msg_info_map ("cannot load map %s from %s: HTTP error %d",
				bk->uri, cbd->data->host, msg->code);
	}

	MAP_RELEASE (cbd, "http_callback_data");
	return 0;

err:
	cbd->periodic->errored = 1;
	rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	MAP_RELEASE (cbd, "http_callback_data");

	return 0;
}
Esempio n. 7
0
void init(int argc, char **argv){
	if(argc < 2){
		usage(argc, argv);
		exit(0);
	}
	signal(SIGPIPE, SIG_IGN);

	{
		struct timeval tv;
		if(gettimeofday(&tv, NULL) == -1){
			srand(time(NULL) + getpid());
		}else{
			srand(tv.tv_sec + tv.tv_usec + getpid());
		}
	}

	bool is_daemon = false;
	const char *conf_file = NULL;
	for(int i=1; i<argc; i++){
		if(strcmp(argv[i], "-d") == 0){
			is_daemon = true;
		}else{
			conf_file = argv[i];
		}
	}

	if(conf_file == NULL){
		usage(argc, argv);
		exit(0);
	}

	if(!is_file(conf_file)){
		fprintf(stderr, "'%s' is not a file or not exists!\n", conf_file);
		exit(0);
	}

	conf = Config::load(conf_file);
	if(!conf){
		fprintf(stderr, "error loading conf file: '%s'\n", conf_file);
		exit(0);
	}
	{
		std::string conf_dir = real_dirname(conf_file);
		if(chdir(conf_dir.c_str()) == -1){
			fprintf(stderr, "error chdir: %s\n", conf_dir.c_str());
			exit(0);
		}
	}


	std::string log_output;
	int log_rotate_size = 0;
	{ // logger
		int log_level = Logger::get_level(conf->get_str("logger.level"));
		log_rotate_size = conf->get_num("logger.rotate.size");
		if(log_rotate_size < 1024 * 1024){
			log_rotate_size = 1024 * 1024;
		}
		log_output = conf->get_str("logger.output");
		if(log_output == ""){
			log_output = "stdout";
		}
		if(log_open(log_output.c_str(), log_level, true, log_rotate_size) == -1){
			fprintf(stderr, "error open log file: %s\n", log_output.c_str());
			exit(0);
		}
	}

	check_pidfile();
	if(is_daemon){
		daemonize();
	}

	log_info("starting icomet %s...", ICOMET_VERSION);
	log_info("config file: %s", conf_file);
	log_info("log_level       : %s", conf->get_str("logger.level"));
	log_info("log_output      : %s", log_output.c_str());
	log_info("log_rotate_size : %d", log_rotate_size);


	evbase = event_base_new();
	if(!evbase){
		fprintf(stderr, "create evbase error!\n");
		exit(0);
	}
	admin_http = evhttp_new(evbase);
	if(!admin_http){
		fprintf(stderr, "create admin_http error!\n");
		exit(0);
	}
	front_http = evhttp_new(evbase);
	if(!front_http){
		fprintf(stderr, "create front_http error!\n");
		exit(0);
	}
	
	sigint_event = evsignal_new(evbase, SIGINT, signal_cb, NULL);
	if(!sigint_event || event_add(sigint_event, NULL)<0){
		fprintf(stderr, "Could not create/add a signal event!\n");
		exit(0);
	}
	sigterm_event = evsignal_new(evbase, SIGTERM, signal_cb, NULL);
	if(!sigterm_event || event_add(sigterm_event, NULL)<0){
		fprintf(stderr, "Could not create/add a signal event!\n");
		exit(0);
	}
	timer_event = event_new(evbase, -1, EV_PERSIST, timer_cb, NULL);
	{
		struct timeval tv;
		tv.tv_sec = CHANNEL_CHECK_INTERVAL;
		tv.tv_usec = 0;
		if(!timer_event || evtimer_add(timer_event, &tv)<0){
			fprintf(stderr, "Could not create/add a timer event!\n");
			exit(0);
		}
	}
}
Esempio n. 8
0
/* Thread: main */
int
remote_pairing_init(void)
{
  int ret;

  remote_list = NULL;

#ifdef USE_EVENTFD
  pairing_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
  if (pairing_efd < 0)
    {
      DPRINTF(E_FATAL, L_REMOTE, "Could not create eventfd: %s\n", strerror(errno));

      return -1;
    }
#else
# if defined(__linux__)
  ret = pipe2(pairing_pipe, O_CLOEXEC | O_NONBLOCK);
# else
  ret = pipe(pairing_pipe);
# endif
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_REMOTE, "Could not create pairing pipe: %s\n", strerror(errno));

      return -1;
    }

# ifndef __linux__
  ret = fcntl(pairing_pipe[0], F_SETFL, O_NONBLOCK);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_REMOTE, "Could not set O_NONBLOCK: %s\n", strerror(errno));

      goto pairing_pipe_fail;
    }
# endif
#endif /* USE_EVENTFD */

  ret = mdns_browse("_touch-remote._tcp", touch_remote_cb);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_REMOTE, "Could not browse for Remote services\n");

      goto mdns_browse_fail;
    }

#ifdef USE_EVENTFD
  event_set(&pairingev, pairing_efd, EV_READ, pairing_cb, NULL);
#else
  event_set(&pairingev, pairing_pipe[0], EV_READ, pairing_cb, NULL);
#endif
  event_base_set(evbase_main, &pairingev);
  event_add(&pairingev, NULL);

  return 0;

#ifndef __linux__
 pairing_pipe_fail:
#endif
 mdns_browse_fail:
#ifdef USE_EVENTFD
  close(pairing_efd);
#else
  close(pairing_pipe[0]);
  close(pairing_pipe[1]);
#endif

  return -1;
}
Esempio n. 9
0
int
main (int argc, gchar **argv)
{
	GOptionContext *context;
	GError *error = NULL;
	struct event_base *ev_base;
	GString *b32_key;
	pid_t *sfd;
	rspamd_inet_addr_t *addr;
	struct event term_ev, int_ev;
	struct in_addr ina = {INADDR_ANY};

	rspamd_init_libs ();

	context = g_option_context_new (
			"rspamd-http-server - test server for benchmarks");
	g_option_context_set_summary (context,
			"Summary:\n  Rspamd test HTTP server "
					RVERSION
					"\n  Release id: "
					RID);
	g_option_context_add_main_entries (context, entries, NULL);

	if (!g_option_context_parse (context, &argc, &argv, &error)) {
		rspamd_fprintf (stderr, "option parsing failed: %s\n", error->message);
		g_error_free (error);
		exit (1);
	}

	maps = g_hash_table_new (g_int_hash, g_int_equal);

	if (key == NULL) {
		server_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
				openssl_mode ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
		b32_key = rspamd_keypair_print (server_key,
				RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32);
		rspamd_printf ("key: %v\n", b32_key);
	}
	else {
		/* TODO: add key loading */
	}

	if (cache_size > 0) {
		c = rspamd_keypair_cache_new (cache_size);
	}

	sfd = g_alloca (sizeof (*sfd) * nworkers);
	addr = rspamd_inet_address_new (AF_INET, &ina);
	rspamd_inet_address_set_port (addr, port);
	rspamd_http_start_servers (sfd, addr);

	/* Just wait for workers */
	ev_base = event_init ();

	event_set (&term_ev, SIGTERM, EV_SIGNAL, rspamd_http_server_term, sfd);
	event_base_set (ev_base, &term_ev);
	event_add (&term_ev, NULL);
	event_set (&int_ev, SIGINT, EV_SIGNAL, rspamd_http_server_term, sfd);
	event_base_set (ev_base, &int_ev);
	event_add (&int_ev, NULL);

	event_base_loop (ev_base, 0);

	return 0;
}
Esempio n. 10
0
int 
NetReactor::NetReactor::init()
{
    event_init();

    Log::NOTICE("Listen Port %d", _port);

    _listenFd = net_tcplisten(_port, 100);
    set_fd_noblock(_listenFd);

    event_set(&_listener, _listenFd, EV_READ|EV_PERSIST, ReactorAccept, this);
    event_add(&_listener, NULL);

    /********test app conn ********/

    NetConnManager * cMag = NetConnManager::getInstance();
    string appSvrIp("127.0.0.1");
    struct sockaddr_in svr_address1, svr_address2;
    set_tcp_sockaddr(appSvrIp.c_str(),
                     1090,
                     &svr_address1);
    set_tcp_sockaddr(appSvrIp.c_str(),
                     1090,
                     &svr_address2);

    int appFd1 = socket(AF_INET, SOCK_STREAM, 0);
    int appFd2 = socket(AF_INET, SOCK_STREAM, 0);
    int res = net_connect_to_ms(appFd1,
                               (struct sockaddr *)&svr_address1,
                                sizeof(svr_address1),
                                1000, 1); 
    if(res < 0)
    {
        Log::ERROR("INIT ERROR: CAN not connect to appSvr");
        close(appFd1);
        return -1;
    }
    res = net_connect_to_ms(appFd2,
                           (struct sockaddr *)&svr_address2,
                            sizeof(svr_address2),
                            1000, 1); 
    if(res < 0)
    {
        Log::ERROR("INIT ERROR: CAN not connect to appSvr");
        close(appFd2);
        return -1;
    }
    vector<int> fdVec;
    vector<struct sockaddr_in> fdAddr;
    fdVec.push_back(appFd1);
    fdVec.push_back(appFd2);
    fdAddr.push_back(svr_address1);
    fdAddr.push_back(svr_address2);

    for(int i = 0; i < fdVec.size(); i++)
    {
        printf("init conn  %d %d \n", fdVec[0],fdVec[1]);
        struct bufferevent * bev;
        bev = bufferevent_new(fdVec[i],
                              EvReadCallback,
                              NULL,
                              EvErrorCallback,
                              this);
        bev->timeout_read = 1800;
        bev->timeout_write = 1800;
        bufferevent_enable(bev, EV_READ|EV_WRITE);

        
        std::unique_ptr<Iconn> con(new AppConn(this, bev, appSvrIp, 1090)); 
        cMag->setConn(fdVec[i], std::move(con));
        cMag->addAppConnFd(fdVec[i]); 
    }
    Log::NOTICE("Connect to App Svr succ"); 

    /* end  test app conn*/
}
Esempio n. 11
0
bool LibEventHttpClient::send(const std::string &url,
                              const std::vector<std::string> &headers,
                              int timeoutSeconds, bool async,
                              const void *data /* = NULL */,
                              int size /* = 0 */) {
  clear();
  m_url = url;

  if (m_conn == NULL) {
    m_conn = evhttp_connection_new(m_address.c_str(), m_port);
    evhttp_connection_set_closecb(m_conn, on_connection_closed, this);
    evhttp_connection_set_base(m_conn, m_eventBase);
  }
  m_request = evhttp_request_new(on_request_completed, this);

  // REVIEW: libevent never sends a Host header (nor does it properly send HTTP
  // 400 for HTTP/1.1 requests without such a header), in blatent violation of
  // RFC2616; this should perhaps be fixed in the library proper.
  if (m_port == 80) {
    evhttp_add_header(m_request->output_headers, "Host", m_address.c_str());
  } else {
    std::ostringstream ss;
    ss << m_address << ":" << m_port;
    evhttp_add_header(m_request->output_headers, "Host", ss.str().c_str());
  }

  // request headers
  bool keepalive = true;
  for (unsigned int i = 0; i < headers.size(); i++) {
    const std::string &header = headers[i];
    size_t pos = header.find(':');
    if (pos != string::npos && header[pos + 1] == ' ') {
      string name = header.substr(0, pos);
      if (strcasecmp(name.c_str(), "Connection") == 0) {
        keepalive = false;
      }
      int ret = evhttp_add_header(m_request->output_headers,
                                  name.c_str(), header.c_str() + pos + 2);
      if (ret >= 0) {
        continue;
      }
    }
    Logger::Error("invalid request header: [%s]", header.c_str());
  }
  if (keepalive) {
    evhttp_add_header(m_request->output_headers, "Connection", "keep-alive");
  }

  // post data
  if (data && size) {
    evbuffer_add(m_request->output_buffer, data, size);
  }

  // url
  evhttp_cmd_type cmd = data ? EVHTTP_REQ_POST : EVHTTP_REQ_GET;
  int ret = evhttp_make_request(m_conn, m_request, cmd, url.c_str());
  if (ret != 0) {
    Logger::Error("evhttp_make_request failed");
    return false;
  }

  if (timeoutSeconds > 0) {
    struct timeval timeout;
    timeout.tv_sec = timeoutSeconds;
    timeout.tv_usec = 0;

    event_set(&m_eventTimeout, -1, 0, timer_callback, m_eventBase);
    event_base_set(m_eventBase, &m_eventTimeout);
    event_add(&m_eventTimeout, &timeout);
  }

  if (async) {
    m_thread = new AsyncFunc<LibEventHttpClient>
      (this, &LibEventHttpClient::sendImpl);
    m_thread->start();
  } else {
    sendImpl();
  }
  return true;
}
Esempio n. 12
0
void client::handle_event(short evtype)
{
    // connect() returning to us?  normally we expect EV_WRITE, but for UNIX domain
    // sockets we workaround since connect() returned immediately, but we don't want
    // to do any I/O from the client::connect() call...
    if (!m_connected && (evtype == EV_WRITE || m_unix_sockaddr != NULL)) {
        int error = -1;
        socklen_t errsz = sizeof(error);

        if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, (void *) &error, &errsz) == -1) {
            benchmark_error_log("connect: error getting connect response (getsockopt): %s\n", strerror(errno));
            return;
        }

        if (error != 0) {
            benchmark_error_log("connect: connection failed: %s\n", strerror(error));
            return;
        }

        m_connected = true;
        if (!m_reqs_processed) {
            process_first_request();
        } else {
            benchmark_debug_log("reconnection complete, proceeding with test\n");
            fill_pipeline();
        }
    }
   
    assert(m_connected == true);
    if ((evtype & EV_WRITE) == EV_WRITE && evbuffer_get_length(m_write_buf) > 0) {
        if (evbuffer_write(m_write_buf, m_sockfd) < 0) {
            if (errno != EWOULDBLOCK) {
                benchmark_error_log("write error: %s\n", strerror(errno));
                disconnect();

                return;
            }
        }
    }

    if ((evtype & EV_READ) == EV_READ) {
        int ret = 1;
        while (ret > 0) {
            ret = evbuffer_read(m_read_buf, m_sockfd, -1); 
        }

        if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
            benchmark_error_log("read error: %s\n", strerror(errno));
            disconnect();

            return;
        }
        if (ret == 0) {
            benchmark_error_log("connection dropped.\n");
            disconnect();

            return;
        }
        
        if (evbuffer_get_length(m_read_buf) > 0) {
            process_response();

            // process_response may have disconnected, in which case
            // we just abort and wait for libevent to call us back sometime
            if (!m_connected) {
                return;
            }
                
        }
    }

    // update event
    short new_evtype = 0;
    if (!finished()) {
        new_evtype = EV_READ;
    }
    if (evbuffer_get_length(m_write_buf) > 0) {
        assert(finished() == false);
        new_evtype |= EV_WRITE;
    }

    if (new_evtype) {
        int ret = event_assign(m_event, m_event_base,
            m_sockfd, new_evtype, client_event_handler, (void *)this);
        assert(ret == 0);

        ret = event_add(m_event, NULL);
        assert(ret == 0);
    } else {
        benchmark_debug_log("nothing else to do, test is finished.\n");
        m_stats.set_end_time(NULL);
    }
}
Esempio n. 13
0
int client::connect(void)
{
    struct connect_info addr;

    // clean up existing socket/buffers
    if (m_sockfd != -1)
        close(m_sockfd);
    evbuffer_drain(m_read_buf, evbuffer_get_length(m_read_buf));
    evbuffer_drain(m_write_buf, evbuffer_get_length(m_write_buf));

    if (m_unix_sockaddr != NULL) {
        m_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
        if (m_sockfd < 0) {
            return -errno;
        }
    } else {
        if (m_config->server_addr->get_connect_info(&addr) != 0) {
            benchmark_error_log("connect: resolve error: %s\n", m_config->server_addr->get_last_error());
            return -1;
        }

        // initialize socket
        m_sockfd = socket(addr.ci_family, addr.ci_socktype, addr.ci_protocol);
        if (m_sockfd < 0) {
            return -errno;
        }

        // configure socket behavior
        struct linger ling = {0, 0};
        int flags = 1;
        int error = setsockopt(m_sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
        assert(error == 0);

        error = setsockopt(m_sockfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
        assert(error == 0);

        error = setsockopt(m_sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
        assert(error == 0);
    }
    
    // set non-blocking behavior
    int flags = 1;
    if ((flags = fcntl(m_sockfd, F_GETFL, 0)) < 0 ||
        fcntl(m_sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
            benchmark_error_log("connect: failed to set non-blocking flag.\n");
            close(m_sockfd);
            m_sockfd = -1;
            return -1;
    }

    // set up event
    if (!m_event) {
        m_event = event_new(m_event_base,
            m_sockfd, EV_WRITE, client_event_handler, (void *)this);    
        assert(m_event != NULL);
    } else {
        int ret = event_del(m_event);
        assert(ret == 0);

        ret = event_assign(m_event, m_event_base,
            m_sockfd, EV_WRITE, client_event_handler, (void *)this);
        assert(ret == 0);
    }
    
    int ret = event_add(m_event, NULL);
    assert(ret == 0);

    // call connect
    if (::connect(m_sockfd, 
        m_unix_sockaddr ? (struct sockaddr *) m_unix_sockaddr : addr.ci_addr,
        m_unix_sockaddr ? sizeof(struct sockaddr_un) : addr.ci_addrlen) == -1) {
        if (errno == EINPROGRESS || errno == EWOULDBLOCK)            
            return 0;
        benchmark_error_log("connect failed, error = %s\n", strerror(errno));
        return -1;
    }
    
    return 0;
}
Esempio n. 14
0
File: work.c Progetto: alk/moxi
/** A work queue is a mechanism to allow thread-to-thread
 *  communication in a libevent-based, multithreaded system.
 *
 *  One thread can send work to another thread.  The receiving thread
 *  should be libevent-based, with a processing loop handled by
 *  libevent.
 *
 *  Use work_queue_init() to initialize a work_queue structure,
 *  where the work_queue structure memory is owned by the caller.
 *
 *  Returns true on success.
 */
bool work_queue_init(work_queue *m, struct event_base *event_base) {
    assert(m != NULL);

    memset(m, 0, sizeof(work_queue));

    pthread_mutex_init(&m->work_lock, NULL);

    m->work_head = NULL;
    m->work_tail = NULL;

    m->num_items = 0;
    m->tot_sends = 0;
    m->tot_recvs = 0;

    m->event_base = event_base;
    assert(m->event_base != NULL);

    int fds[2] = {0};
#ifdef WIN32
    struct sockaddr_in serv_addr;
    int sockfd;

    if ((sockfd = createLocalListSock(&serv_addr)) < 0 ||
        createLocalSocketPair(sockfd,fds,&serv_addr) == -1)
    {
        fprintf(stderr, "Can't create notify pipe: %s", strerror(errno));
        return false;
    }
#else
    if (pipe(fds)) {
        perror("Can't create notify pipe");
        return false;
    }
#endif

    m->recv_fd = fds[0];
    m->send_fd = fds[1];

    event_set(&m->event, m->recv_fd,
              EV_READ | EV_PERSIST, work_recv, m);
    event_base_set(m->event_base, &m->event);

    if (event_add(&m->event, 0) == 0) {
#ifdef WORK_DEBUG
            moxi_log_write("work_queue_init %x %x %x %d %d %u %llu\n",
                    (int) pthread_self(),
                    (int) m,
                    (int) m->event_base,
                    m->send_fd,
                    m->recv_fd,
                    m->work_head != NULL,
                    m->tot_sends);
#endif

        return true;
    }

#ifdef WORK_DEBUG
    moxi_log_write("work_queue_init error\n");
#endif

    return false;
}
Esempio n. 15
0
int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only)
{
	char* json = (char*)json_dumps(req->payload, JSON_COMPACT);

	char* ns;
	size_t bytes;
	bytes = netstring_encode_new(&ns, json, (size_t)strlen(json));

	bool sent = false;
	jsonrpc_server_group_t* c_grp = NULL;
	if(global_server_group != NULL)
		c_grp = *global_server_group;
	jsonrpc_server_group_t* p_grp = NULL;
	jsonrpc_server_group_t* w_grp = NULL;
	jsonrpc_server_t* s = NULL;
	server_list_t* tried_servers = NULL;
	DEBUG("SENDING DATA\n");
	for(; c_grp != NULL; c_grp = c_grp->next) {

		if(strncmp(conn.s, c_grp->conn.s, c_grp->conn.len) != 0) continue;

		for(p_grp = c_grp->sub_group; p_grp != NULL; p_grp = p_grp->next)
		{
			w_grp = p_grp->sub_group;
			while(!sent) {
				loadbalance_by_weight(&s, w_grp, tried_servers);
				if (s == NULL || s->status != JSONRPC_SERVER_CONNECTED) {
					break;
				}

				if(bufferevent_write(s->bev, ns, bytes) == 0) {
					sent = true;
					if(!notify_only) {
						s->req_count++;
						if (s->hwm > 0 && s->req_count >= s->hwm) {
							WARN("%.*s:%d in connection group %.*s has exceeded its high water mark (%d)\n",
									STR(s->addr), s->port,
									STR(s->conn), s->hwm);
						}
					}
					req->server = s;
					break;
				} else {
					addto_server_list(s, &tried_servers);
				}
			}

			if (sent) {
				break;
			}

			WARN("Failed to send to priority group, %d\n", p_grp->priority);
			if(p_grp->next != NULL) {
				INFO("Proceeding to next priority group, %d\n",
						p_grp->next->priority);
			}
		}

		if (sent) {
			break;
		}

	}

	if(!sent) {
		WARN("Failed to send to connection group, \"%.*s\"\n",
				STR(conn));
		if(schedule_retry(req)<0) {
			fail_request(JRPC_ERR_RETRY, req, "Failed to schedule retry");
		}
	}

	free_server_list(tried_servers);
	if(ns) pkg_free(ns);
	if(json) free(json);

	if (sent && notify_only == false) {

		const struct timeval tv = ms_to_tv(req->timeout);

		req->timeout_ev = evtimer_new(global_ev_base, timeout_cb, (void*)req);
		if(event_add(req->timeout_ev, &tv)<0) {
			ERR("event_add failed while setting request timer (%s).",
					strerror(errno));
			return -1;
		}
	}

	return sent;
}
Esempio n. 16
0
int
main(int argc, char *argv[])
{
	const char *cause = NULL;
	int ch, nsocks = 0, save_errno = 0;
	int inet4 = 0, inet6 = 0;
	char group[ICB_MAXGRPLEN], *grplist = NULL;
	char *ptr = NULL;

	/* init group lists before calling icb_addgroup */
	icb_init();

	while ((ch = getopt(argc, argv, "46CdG:M:nL:S:v")) != -1)
		switch (ch) {
		case '4':
			inet4++;
			break;
		case '6':
			inet6++;
			break;
		case 'C':
			creategroups++;
			break;
		case 'd':
			foreground++;
			break;
		case 'G':
			grplist = optarg;
			break;
		case 'L':
			strlcpy(logprefix, optarg, sizeof logprefix);
			dologging++;
			break;
		case 'M':
			strlcpy(modtabpath, optarg, sizeof modtabpath);
			break;
		case 'n':
			dodns = 0;
			break;
		case 'S':
			strlcpy(srvname, optarg, sizeof srvname);
			break;
		case 'v':
			verbose++;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	argc -= optind;
	argv += optind;

	/* add group "1" as it's a login group for most of the clients */
	if (icb_addgroup(NULL, "1") == NULL)
		err(EX_UNAVAILABLE, NULL);

	if (grplist) {
		while (icb_token(grplist, strlen(grplist), &ptr, group,
		    ICB_MAXGRPLEN, ',', 0) > 0)
			if (icb_addgroup(NULL, group) == NULL)
				err(EX_UNAVAILABLE, NULL);
	}

	if (argc == 0)
		argc++;

	if (inet4 && inet6)
		errx(EX_USAGE, "Can't specify both -4 and -6");

	tzset();
	(void)setlocale(LC_ALL, "C");

	if (foreground)
		openlog("icbd", LOG_PID | LOG_PERROR, LOG_DAEMON);
	else
		openlog("icbd", LOG_PID | LOG_NDELAY, LOG_DAEMON);

	if (!foreground && daemon(0, 0) < 0)
		err(EX_OSERR, NULL);

	(void)event_init();

	for (ch = 0; ch < argc; ch++) {
		struct addrinfo hints, *res, *res0;
		struct icbd_listener *l;
		char *addr, *port;
		int error, s, on = 1;

		addr = port = NULL;
		if (argv[ch] != NULL) {
			if (argv[ch][0] != ':')
				addr = argv[ch];
			if ((port = strrchr(argv[ch], ':')) != NULL)
				*port++ = '\0';
		}

		bzero(&hints, sizeof hints);
		if (inet4 || inet6)
			hints.ai_family = inet4 ? PF_INET : PF_INET6;
		else
			hints.ai_family = PF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_PASSIVE;
		if ((error = getaddrinfo(addr, port ? port : "icb", &hints,
		    &res0)) != 0) {
			syslog(LOG_ERR, "%s", gai_strerror(error));
			return (EX_UNAVAILABLE);
		}

		for (res = res0; res != NULL; res = res->ai_next) {
			if ((s = socket(res->ai_family, res->ai_socktype,
			    res->ai_protocol)) < 0) {
				cause = "socket";
				save_errno = errno;
				continue;
			}

			if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on,
			    sizeof on) < 0) {
				cause = "SO_REUSEADDR";
				save_errno = errno;
				(void)close(s);
				continue;
			}

			if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
				cause = "bind";
				save_errno = errno;
				(void)close(s);
				continue;
			}

			(void)listen(s, TCP_BACKLOG);

			if ((l = calloc(1, sizeof *l)) == NULL)
				err(EX_UNAVAILABLE, NULL);
			event_set(&l->ev, s, EV_READ | EV_PERSIST,
			    icbd_accept, l);
			if (event_add(&l->ev, NULL) < 0) {
				syslog(LOG_ERR, "event_add: %m");
				return (EX_UNAVAILABLE);
			}
			evtimer_set(&l->pause, icbd_paused, l);

			nsocks++;
		}

		freeaddrinfo(res0);
	}

	if (nsocks == 0) {
		errno = save_errno;
		syslog(LOG_ERR, "%s: %m", cause);
		return (EX_UNAVAILABLE);
	}

	/* start the logger service */
	logger_init();

	/* initialize resolver */
	res_init();

	icbd_restrict();

	icbd_modupdate();

	(void)signal(SIGPIPE, SIG_IGN);

	(void)event_dispatch();

	syslog(LOG_ERR, "event_dispatch: %m");

	return (EX_UNAVAILABLE);
}
Esempio n. 17
0
/* 从对端 server 的 data 链路收到数据,把它放到对应的 kmod 节点中 */
void node_data_handler(evutil_socket_t fd, short event, void *args)
{
	struct node *node;
	struct daemon *daemon;
	struct device_list *dev_list;
	struct device *dev;
	struct packet *pkt;
	struct packet *pkt_clone;
	int i, ret, full;
	cb_fn *cb;

	node = (struct node *)args;
	daemon = node->daemon;
	dev_list = daemon->dev_list;

	pkt = handler_recv(node->dfd);
	if (!pkt) {
		node_del_data_event(node);
		log_error("receive data from server node %d failed", node->id);
		return;
	}

	/* FIXME 如果某个device的queue满了,在这里就会等待,从而造成两个问题:
	 *	1. 这是event的call back函数,如果等待会造成event base的阻塞
	 *	2. 单个device队列满而影响到所有其它device,不公平
	 * 是否可以这样?
	 *   提前获取队列一个空位,如果失败的话,直接返回,
	 *   当队列有剩余空间时再加入该event
	 * 但是,device互相影响的问题还是没能解决,满了直接断连?
	 */
	full = 0;
	for (i = 0; i < dev_list->dev_num; i++) {
		//FIXME 查找效率很低,可考虑序号对应下标,并且判读是否是只有单个device
		dev = dev_list->devs[i];
		if (!device_is_target(dev, pkt->kmod_to))
			continue;
		if (!device_want_recv(dev))
			continue;
		pkt_clone = packet_clone(pkt);
		if (!pkt_clone) {
			log_error("send to kmod node %d failed: no memory", dev->id);
			free_packet(pkt_clone);
			goto out;
		}
		cb = full ? NULL : node_data_handle_force_cb;
		ret = dev_put_data_packet_force(dev, pkt_clone, cb, node);
		if (ret < 0) {
			log_error("kmod node %d data queue is NOT start", dev->id);
			goto out;
		} else if (ret > 0) {
			log_info("%s force handle for node %d", __func__, node->id);
			full = 1;
		}
	}

out:
	free_packet(pkt);
	if (!full) {
		ret = event_add(node->data_event, NULL);
		if (ret < 0) {
			log_error("failed to add data event on node %d", node->id);
			node_del_data_event(node);
		}
	}
}
Esempio n. 18
0
//Main
int main(int argc, char *argv[])
{
    //Get args
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <snapshot_file>\n", argv[0]);
        return 1;
    }
    snap_path = argv[1];

    //Allocate memory
    fprintf(stderr, "Allocating arena with size %.2f MBytes ...\n", (float)m / CHAR_BIT / MEGA);
    Bloom = malloc( (m + ( CHAR_BIT - 1)) / CHAR_BIT ); // Ceil byte length: bytes = bits + 7 / 8


    //Load or create snapshot file
    if (!access(snap_path, F_OK)) {
        fputs("Loading snapshot...\n", stderr);
        if (LoadSnap(Bloom, snap_path)) {
            fputs("Unable to load snapshot!\n", stderr);
            return -1;
        }
        fputs("Snapshot loaded.\n", stderr);
    } else {
        fputs("Initializing new file storage...\n", stderr);
        size_t shouldwrite = (m + (CHAR_BIT - 1)) / CHAR_BIT;
        memset(Bloom, 0, shouldwrite); 

        if (SaveSnap(Bloom, snap_path)) {
            fputs("Unable to save initial snapshot!\n", stderr);
            return -1;
        }
        fputs("Initial snapshot written.\n", stderr);
    }


    void OnReq(struct evhttp_request *req, void *arg)
    {
        struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req);
        if (!OutBuf) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        struct evkeyvalq *Headers = evhttp_request_get_output_headers(req);
        if (!Headers) {
            evhttp_send_reply(req, HTTP_INTERNAL, "Internal Error", OutBuf);
            return;
        }
        const struct evhttp_uri *HTTPURI =  evhttp_request_get_evhttp_uri(req);
        if (!HTTPURI) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        const char *path =  evhttp_uri_get_path(HTTPURI);
        if (!path) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
        }
        const char *query_string = evhttp_uri_get_query(HTTPURI);
        if (!query_string) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }
        struct evkeyvalq params;
        evhttp_parse_query_str(query_string, &params);
        const char *element = evhttp_find_header(&params, "e");
        if (!element) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }

        int i;
        const char* (*Operation)(bloom_cell *, size_t []) = NULL;
        for (i=0; i< sizeof HandlerTable/ sizeof HandlerTable[0] ; i++)
            if (strncmp(HandlerTable[i][0], path, STR_MAX) == 0) {
                Operation = HandlerTable[i][1];
                break;
            }
        if (!Operation) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", OutBuf);
            return;
        }

        const char *response = Operation(Bloom, Hashes(element));

        evhttp_add_header(Headers, MIME_TYPE);
        evbuffer_add_printf(OutBuf, response);
        evhttp_send_reply(req, HTTP_OK, "OK", OutBuf);
        evhttp_clear_headers(&params);
    };

    if (!(base = event_base_new()))
        crash("Couldn't create an event_base: exiting\n", -1);

    if (!(http = evhttp_new(base)))
        crash("Couldn't create evhttp. Exiting.\n", -1);
    evhttp_set_gencb(http, OnReq, NULL);

    if (!(handle = evhttp_bind_socket_with_handle(http, BIND_ADDRESS, BIND_PORT)))
        crash("couldn't bind to port 8888. Exiting.\n", -1);

    if (signal(SIGINT, term_handler) == SIG_ERR)
        crash("Unable to set SIGINT handler!", -1);

    if (signal(SIGTERM, term_handler) == SIG_ERR)
        crash("Unable to set SIGTERM handler!", -1);

    if (signal(SIGCHLD, child_collector) == SIG_ERR)
        crash("Unable to set SIGCHLD handler!", -1);
    
    //This signal handled by event loop in order to avoid malloc deadlock
    if ((dump_event = evsignal_new(base, SIGUSR1, dump_handler, NULL)) == NULL)
        crash("Unable to create SIGUSR1 handler!", -1);
    else 
        if (event_add(dump_event, NULL) == -1)
            crash("Unable to add SIGUSR1 handler!", -1);

    if (event_base_dispatch(base) == -1)
        crash("Failed to run message loop.\n", -1);

    fputs("Exiting...\n", stderr);
    SaveSnap(Bloom, snap_path);
    evhttp_del_accept_socket(http, handle);
    evhttp_free(http);
    event_free(dump_event);
    event_base_free(base);
    free(Bloom);
    return 0;
}
Esempio n. 19
0
void time_cb(int fd, short event, void* argc)
{
	printf("timer wakeup\n");
	event_add(&ev, &tv);
}
Esempio n. 20
0
/**
 * @name c_app_write_event_sched
 * @brief Schedule a write event
 */
static void
c_app_write_event_sched(void *conn_arg)
{
    c_conn_t *conn = conn_arg;
    event_add((struct event *)(conn->wr_event), NULL);
}
Esempio n. 21
0
int
main(int argc, char **argv)
{
	struct event* ev;
	struct event* timeout;
	struct event_base* base;

	evutil_socket_t pair[2];
	struct timeval tv;
	struct cpu_usage_timer timer;

	double usage, secPassed, secUsed;

#ifdef WIN32
	WORD wVersionRequested;
	WSADATA wsaData;

	wVersionRequested = MAKEWORD(2, 2);

	(void) WSAStartup(wVersionRequested, &wsaData);
#endif
	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
		return (1);

	/* Initalize the event library */
	base = event_base_new();

	/* Initalize a timeout to terminate the test */
	timeout = evtimer_new(base,timeout_cb,&timeout);
	/* and watch for writability on one end of the pipe */
	ev = event_new(base,pair[1],EV_WRITE | EV_PERSIST, write_cb, &ev);

	tv.tv_sec  = 5;
	tv.tv_usec = 0;

	evtimer_add(timeout, &tv);

	event_add(ev, NULL);

	start_cpu_usage_timer(&timer);

	event_base_dispatch(base);

	event_free(ev);
	event_free(timeout);
	event_base_free(base);

	get_cpu_usage(&timer, &secPassed, &secUsed, &usage);

	/* attempt to calculate our cpu usage over the test should be
	   virtually nil */

	printf("usec used=%d, usec passed=%d, cpu usage=%.2f%%\n",
	    (int)(secUsed*1e6),
	    (int)(secPassed*1e6),
	    usage*100);

	if (usage > 50.0) /* way too high */
	  return 1;

	return 0;
}
inline
static
void setup_relays(void)
{
    if(!*options.relay_ports)
    {
        debug("relays: missing ports");
        teardown_control();
        return;
    }

    const char *w = options.relay_ports;
    for(context.relays_count = 1; *w; ++ w)
        context.relays_count += *w == ',';

    debug("relays: setting up tcp channels port");
    evconnlistener_set_cb(  context.listener.tcp,
                            accept_tcp_channel,
                            NULL);

    debug("relays: setting up %d relay ports", context.relays_count);
    context.relays =
        (struct RelayListener *) malloc(
            context.relays_count * sizeof(struct RelayListener));

    w = options.relay_ports;
    struct RelayListener *cur = context.relays;
    uint8_t udp = 0;
    for(int c = 0; c < context.relays_count; ++ c)
    {
        char        proto[4];
        int32_t     bytes;

        if(sscanf(w, "%[^:]:%hu,%n", proto, &cur->port, &bytes) != 2)
        {
            debug("relays: invalid relay ports format");
            context.relays_count = c;
            teardown_control();
            return;
        }

        if(!strcmp(proto, "tcp"))
        {
            debug("relays: setting up tcp relay %d", cur->port);

            cur->proto = IPPROTO_TCP;
            struct sockaddr_in  relay; memset(&relay, 0, sizeof(relay));
            relay.sin_family = AF_INET;
            if(options.address)
            {
                debug("relays: binding to address %s", options.address);
                inet_pton(AF_INET, options.address, &relay.sin_addr);
            }

            else
                relay.sin_addr.s_addr = INADDR_ANY;

            relay.sin_port = htons(cur->port);

            cur->tcp_listener = evconnlistener_new_bind(
                context.events,
                accept_tcp_peer, cur,
                LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
                (struct sockaddr *) &relay, sizeof(relay));

            if(!cur->tcp_listener)
            {
                perror("evconnlistener_new_bind");
                context.relays_count = c;
                teardown_control();
                return;
            }

            if(options.interface)
            {
                evutil_socket_t fd =
                    evconnlistener_get_fd(cur->tcp_listener);

                debug(  "relays: binding fd:%d to interface %s",
                        fd,
                        options.interface);

                assert(fd != -1);
                struct ifreq ifr; memset(&ifr, 0, sizeof(ifr));
                strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name));
                if(setsockopt(  fd,
                                SOL_SOCKET,
                                SO_BINDTODEVICE,
                                &ifr,
                                sizeof(ifr)) == -1)
                {
                    perror("setsockopt");
                    context.relays_count = c;
                    teardown_control();
                    return;
                }
            }

            evconnlistener_set_error_cb(cur->tcp_listener,
                                        error_on_tcp_peer_listener);

            ++ cur;
            w += bytes;
        }

        else if(!strcmp(proto, "udp"))
        {
            udp = 1;
            debug("relays: setting up udp relay %d", cur->port);

            cur->proto = IPPROTO_UDP;
            struct sockaddr_in  relay; memset(&relay, 0, sizeof(relay));
            relay.sin_family = AF_INET;
            if(options.address)
            {
                debug("relays: binding to address %s", options.address);
                inet_pton(AF_INET, options.address, &relay.sin_addr);
            }

            else
                relay.sin_addr.s_addr = INADDR_ANY;

            relay.sin_port = htons(cur->port);

            evutil_socket_t ufd = socket(AF_INET, SOCK_DGRAM, 0);
            assert(ufd != -1);
            //evutil_make_socket_nonblocking(ufd); maybe?
            if(options.interface)
            {
                debug(  "relays: binding fd:%d to interface %s",
                        ufd,
                        options.interface);

                struct ifreq ifr; memset(&ifr, 0, sizeof(ifr));
                strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name));
                if(setsockopt(  ufd,
                                SOL_SOCKET,
                                SO_BINDTODEVICE,
                                &ifr,
                                sizeof(ifr)) == -1)
                {
                    perror("setsockopt");
                    context.relays_count = c;
                    teardown_control();
                    return;
                }
            }

            if(bind(ufd, (struct sockaddr *) &relay, sizeof(relay)) == -1)
            {
                perror("bind");
                context.relays_count = c;
                teardown_control();
                return;
            }

            cur->udp_listener = event_new(  context.events,
                                            ufd,
                                            EV_READ | EV_PERSIST,
                                            read_udp_peer,
                                            cur);

            event_add(cur->udp_listener, NULL);

            ++ cur;
            w += bytes;
        }

        else
        {
            debug("relays: unsupported protocol %s", proto);
            context.relays_count = c;
            teardown_control();
            return;
        }
    }

    if(udp)
    {
        debug("relays: setting up udp channels port");
        struct sockaddr_in relay; memset(&relay, 0, sizeof(relay));
        relay.sin_family = AF_INET;
        if(options.address)
        {
            debug("relays: binding to address %s", options.address);
            inet_pton(AF_INET, options.address, &relay.sin_addr);
        }

        else
            relay.sin_addr.s_addr = INADDR_ANY;

        relay.sin_port = htons(options.control_port);

        evutil_socket_t ufd = socket(AF_INET, SOCK_DGRAM, 0);
        //evutil_make_socket_nonblocking(ufd); maybe?
        if(options.interface)
        {
            debug(  "relays: binding fd:%d to interface %s",
                    ufd,
                    options.interface);

            struct ifreq ifr; memset(&ifr, 0, sizeof(ifr));
            strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name));
            if(setsockopt(  ufd,
                            SOL_SOCKET,
                            SO_BINDTODEVICE,
                            &ifr,
                            sizeof(ifr)) == -1)
            {
                perror("setsockopt");
                teardown_control();
                return;
            }
        }

        if(bind(ufd, (struct sockaddr *) &relay, sizeof(relay)) == -1)
        {
            perror("bind");
            teardown_control();
            return;
        }

        context.listener.udp = event_new(   context.events,
                                            ufd,
                                            EV_READ | EV_PERSIST,
                                            read_udp_channel,
                                            NULL);

        event_add(context.listener.udp, NULL);
    }
}
Esempio n. 23
0
int main(int argc, char **argv)
{
    char *sip = NULL;
    char *cip = NULL;
    int i, opt;
    int ipver = 0;
    int port = 0;
    int buf_len = 0;
    int delay = DEF_DELAY;
    time_t tm_out = 0;
    int icount = DEF_INSTANCES;
    int len;
    int transport = 0;
    int background = 0;

    struct sockaddr_in sin;
    struct sockaddr_in6 sin6;
    struct event_base *e_base = NULL;
    struct event e_ki;

    event_timeout e_timeout;
    connection c;
    Client cl;
    connection *cons_p;

    /*traffic_gw tg;*/

    while((opt = getopt(argc, argv, "4:6:p:t:S:d:T:i:hb")) != -1)
    {
        switch(opt) {
            case '4':
                ipver = AF_INET;
                if(get_ip_subopt(&sip, &cip, optarg) != 0) {
                    print_usage(argv[0]);
                    return (1);
                }
                break;

            case '6':
                ipver = AF_INET6;
                if(get_ip_subopt(&sip, &cip, optarg) != 0) {
                    print_usage(argv[0]);
                    return (1);
                }
                break;

            case 'p':
                port = (int) strtol(optarg, (char **)NULL, 10);
                break;

            case 'S':
                buf_len = (int) strtol(optarg, (char **)NULL, 10);
                break; 

            case 'd':
                delay = (int) strtol(optarg, (char **)NULL, 10);
                break;

            case 't':
                len = strlen(argv[optind - 1]);

                if(!strncmp(argv[optind - 1], "tcp", len))
                    transport = SOCK_STREAM;
                else if(!strncmp(argv[optind - 1], "udp", len))
                    transport = SOCK_DGRAM;
                break;

            case 'T':
                tm_out = (time_t) strtol(optarg, (char **)NULL, 10);
                break;

            case 'i':
                icount = (int) strtol(optarg, (char **)NULL, 10);
                break;

            case 'b':
                background = 1;
                break;

            case 'h':
                print_usage(argv[0]);
                return (0);
                break;
     
            default:
                print_usage(argv[0]);
                return (1);
                break;
        }
    }

    if(cip == NULL || sip == NULL || port == 0 ||
         buf_len == 0 || transport == 0) {
        DPRINT(DPRINT_ERROR,"parameters are not valid\n");
        print_usage(argv[0]);
        return (1);
    } 

    memset(&c, 0, sizeof(connection));
    c.buffer = NULL;
    c.buf_len = buf_len;
    c.delay = delay;
    c.ipver = ipver;
    c.transport = transport;

    if(c.ipver == AF_INET) {
        memset(&sin, 0, sizeof(struct sockaddr_in));

        sin.sin_family = AF_INET;
        if(inet_pton(AF_INET, sip, (void *)&sin.sin_addr) < 0) 
        {
            DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", 
                __FUNCTION__, sip);
            return (1);
        }
        sin.sin_port = htons(port);
        memcpy(&c.servAddr, &sin, sizeof(struct sockaddr_storage));

        if(inet_pton(AF_INET, cip, (void *)&sin.sin_addr) < 0) {
            DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", 
                __FUNCTION__, cip);
            return (1);
        }

        sin.sin_port = htons(0);
        memcpy(&c.bindAddr, &sin, sizeof(struct sockaddr_storage));

        c.bindAddrSize = sizeof(struct sockaddr_in);
    }
    else if (c.ipver == AF_INET6) {
        memset(&sin6, 0, sizeof(struct sockaddr_in6));

        sin6.sin6_family = AF_INET6;
        if(inet_pton(AF_INET6, sip, (void *)&sin6.sin6_addr) < 0) {
            DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", 
                __FUNCTION__, sip);
            return (1);
        }
        sin6.sin6_port = htons(port);
        memcpy(&c.servAddr, &sin6, sizeof(struct sockaddr_storage));

        if(inet_pton(AF_INET6, cip, (void *)&sin6.sin6_addr) < 0) {
            DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", 
                __FUNCTION__, cip);
            return (1);
        }
        sin6.sin6_port = htons(0);
        memcpy(&c.bindAddr, &sin6, sizeof(struct sockaddr_storage));

        c.bindAddrSize = sizeof(struct sockaddr_in6);
    }

    if (background)
        daemon(0,0);

    e_base = event_base_new();
    if(e_base == NULL) {
        DPRINT(DPRINT_ERROR, "[%s] unable to initialize event base\n", 
            __FUNCTION__);
        return (1);
    }

    if(!background) {
    /* initialize keyboard interupt event handler */
        event_set(&e_ki, STDIN_FILENO, (EV_READ | EV_PERSIST), 
            cb_keyboard_int, e_base);
        event_base_set(e_base, &e_ki);
        event_add(&e_ki, NULL);
    }

    /* initialize timeout event handler */
    e_timeout.tv.tv_usec = 0;
    e_timeout.tv.tv_sec = tm_out;
    event_set(&e_timeout.e, -1, 0, cb_timeout, e_base);
    event_base_set(e_base, &e_timeout.e);
    event_add(&e_timeout.e, &e_timeout.tv);

    bzero(&cl, sizeof(Client));

    cl.cons = (connection *) calloc(icount, sizeof(connection));
    cons_p = cl.cons;

    for(i = 0; i < icount; ++i) {
        memcpy(&cons_p[i], &c, sizeof(connection));

        if(prep_connection(&cons_p[i]) < 0) {
            DPRINT(DPRINT_ERROR, "[%s] [%d] connection failed \n",
                __FUNCTION__, i);
        }
        else {
            ++cl.estcount;
            cons_p[i].established = 1;
            cons_p[i].buffer = (char *) malloc(cons_p[i].buf_len);

            event_set(&cons_p[i].r_event, cons_p[i].s,
                (EV_READ | EV_PERSIST), cb_rw, &cons_p[i]);
            event_base_set(e_base, &cons_p[i].r_event);
            event_add(&cons_p[i].r_event, NULL);

            event_set(&cons_p[i].w_event, cons_p[i].s,
                (EV_WRITE | EV_PERSIST), cb_rw, &cons_p[i]);
            event_base_set(e_base, &cons_p[i].w_event);
            event_add(&cons_p[i].w_event, NULL);
        }
    }

    DPRINT(DPRINT_DEBUG, "[%s] %d connections established\n", __FUNCTION__,
        cl.estcount);

    event_base_dispatch(e_base);

    DPRINT(DPRINT_DEBUG, "[%s] cleaning up...\n", __FUNCTION__);

    /* clean up */
    event_del(&e_timeout.e);
    event_del(&e_ki);

    for(i = 0; i < icount; ++i) {
        if(cons_p[i].established) {
            event_del(&cons_p[i].r_event);
            event_del(&cons_p[i].w_event);
            close(cons_p[i].s);
            free(cons_p[i].buffer);
        }
    }

    event_base_free(e_base);
    free(cons_p);
    return (0);
}
Esempio n. 24
0
// only in child
static void child(struct sockaddr_storage* addr,
                  int addrLen,
                  char* user,
                  struct ChildContext* context)
{
    context->dataFromParent =
        event_new(context->eventBase,
                  context->inFd,
                  EV_READ | EV_PERSIST,
                  incomingFromParent,
                  context);

    event_add(context->dataFromParent, NULL);

    if (!addr->ss_family) {
        addr->ss_family = AF_INET;
        // Apple gets mad if the length is wrong.
        addrLen = sizeof(struct sockaddr_in);
    }

    evutil_socket_t listener = socket(addr->ss_family, SOCK_STREAM, 0);

    if (listener < 0) {
        perror("socket()");
    }

    evutil_make_listen_socket_reuseable(listener);

    if (bind(listener, (struct sockaddr*) addr, addrLen) < 0) {
        perror("bind()");
        return;
    }

    if (getsockname(listener, (struct sockaddr*) addr, (socklen_t*) &addrLen)) {
        perror("getsockname()");
    }

    if (listen(listener, 16)<0) {
        perror("listen");
        return;
    }

    evutil_make_socket_nonblocking(listener);

    context->socketEvent =
        event_new(context->eventBase, listener, EV_READ | EV_PERSIST, acceptConn, context);
    event_add(context->socketEvent, NULL);

    if (!context->eventBase) {
        exit(-1);
    }

    // Write back the sockaddr_storage struct so the other end knows our port.
    uint8_t buff[sizeof(struct sockaddr_storage) + sizeof(int) + 8];
    Bits_memcpyConst(buff, "abcd", 4);
    Bits_memcpyConst(&buff[4], &addrLen, sizeof(int));
    Bits_memcpyConst(&buff[4 + sizeof(int)], addr, sizeof(struct sockaddr_storage));
    Bits_memcpyConst(&buff[4 + sizeof(int) + sizeof(struct sockaddr_storage)], "wxyz", 4);
    write(context->outFd, buff, sizeof(buff));

    event_base_dispatch(context->eventBase);
}
Esempio n. 25
0
static void
lua_tcp_write_helper (struct lua_tcp_cbdata *cbd)
{
	struct iovec *start;
	guint niov, i;
	gint flags = 0;
	gsize remain;
	gssize r;
	struct iovec *cur_iov;
	struct msghdr msg;

	if (cbd->pos == cbd->total) {
		goto call_finish_handler;
	}

	start = &cbd->iov[0];
	niov = cbd->iovlen;
	remain = cbd->pos;
	/* We know that niov is small enough for that */
	cur_iov = alloca (niov * sizeof (struct iovec));
	memcpy (cur_iov, cbd->iov, niov * sizeof (struct iovec));

	for (i = 0; i < cbd->iovlen && remain > 0; i++) {
		/* Find out the first iov required */
		start = &cur_iov[i];
		if (start->iov_len <= remain) {
			remain -= start->iov_len;
			start = &cur_iov[i + 1];
			niov--;
		}
		else {
			start->iov_base = (void *)((char *)start->iov_base + remain);
			start->iov_len -= remain;
			remain = 0;
		}
	}

	memset (&msg, 0, sizeof (msg));
	msg.msg_iov = start;
	msg.msg_iovlen = MIN (IOV_MAX, niov);
	g_assert (niov > 0);
#ifdef MSG_NOSIGNAL
	flags = MSG_NOSIGNAL;
#endif
	r = sendmsg (cbd->fd, &msg, flags);

	if (r == -1) {
		lua_tcp_push_error (cbd, "IO write error while trying to write %d "
				"bytes: %s", (gint)remain, strerror (errno));
		lua_tcp_maybe_free (cbd);
		return;
	}
	else {
		cbd->pos += r;
	}

	if (cbd->pos >= cbd->total) {
		goto call_finish_handler;
	}
	else {
		/* Want to write more */
		event_add (&cbd->ev, &cbd->tv);
	}

	return;

call_finish_handler:

	if (!cbd->partial) {
		cbd->in = g_string_sized_new (BUFSIZ);
		rspamd_mempool_add_destructor (cbd->pool, rspamd_gstring_free_hard,
				cbd->in);
	}

	if (cbd->do_shutdown) {
		/* Half close the connection */
		shutdown (cbd->fd, SHUT_WR);
	}

	event_del (&cbd->ev);
#ifdef EV_CLOSED
	event_set (&cbd->ev, cbd->fd, EV_READ|EV_PERSIST|EV_CLOSED,
				lua_tcp_handler, cbd);
#else
	event_set (&cbd->ev, cbd->fd, EV_READ|EV_PERSIST, lua_tcp_handler, cbd);
#endif
	event_base_set (cbd->ev_base, &cbd->ev);
	event_add (&cbd->ev, &cbd->tv);
}
Esempio n. 26
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;
}
Esempio n. 27
0
int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg)
{
	event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);

	return event_add(ev, 0);
}
Esempio n. 28
0
static void
didaktik_set_intrq( struct wd_fdc *f )
{
  if( aux_register & INTRQ_ENABLED )
    event_add( 0, z80_nmi_event );
}
Esempio n. 29
0
int init_socket(async_http_worker_t *worker)
{
	worker->socket_event = event_new(worker->evbase, worker->notication_socket[0], EV_READ|EV_PERSIST, notification_socket_cb, worker);
	event_add(worker->socket_event, NULL);
	return (0);
}
Esempio n. 30
0
/***
 * @function rspamd_redis.make_request({params})
 * Make request to redis server, params is a table of key=value arguments in any order
 * @param {task} task worker task object
 * @param {ip} host server address
 * @param {function} callback callback to be called in form `function (task, err, data)`
 * @param {string} cmd command to be sent to redis
 * @param {table} args numeric array of strings used as redis arguments
 * @param {number} timeout timeout in seconds for request (1.0 by default)
 * @return {boolean} `true` if a request has been scheduled
 */
static int
lua_redis_make_request (lua_State *L)
{
	struct lua_redis_userdata *ud;
	struct rspamd_lua_ip *addr = NULL;
	struct rspamd_task *task = NULL;
	const gchar *cmd = NULL;
	gint top, cbref = -1;
	struct timeval tv;
	gboolean ret = FALSE;
	gdouble timeout = REDIS_DEFAULT_TIMEOUT;

	if (lua_istable (L, 1)) {
		/* Table version */
		lua_pushstring (L, "task");
		lua_gettable (L, -2);
		if (lua_type (L, -1) == LUA_TUSERDATA) {
			task = lua_check_task (L, -1);
		}
		lua_pop (L, 1);

		lua_pushstring (L, "callback");
		lua_gettable (L, -2);
		if (lua_type (L, -1) == LUA_TFUNCTION) {
			/* This also pops function from the stack */
			cbref = luaL_ref (L, LUA_REGISTRYINDEX);
		}
		else {
			msg_err ("bad callback argument for lua redis");
			lua_pop (L, 1);
		}

		lua_pushstring (L, "cmd");
		lua_gettable (L, -2);
		cmd = lua_tostring (L, -1);
		lua_pop (L, 1);

		lua_pushstring (L, "host");
		lua_gettable (L, -2);
		if (lua_type (L, -1) == LUA_TUSERDATA) {
			addr = lua_check_ip (L, -1);
		}
		lua_pop (L, 1);

		lua_pushstring (L, "timeout");
		lua_gettable (L, -2);
		timeout = lua_tonumber (L, -1);
		lua_pop (L, 1);

		if (task != NULL && addr != NULL && cbref != -1 && cmd != NULL) {
			ud =
					rspamd_mempool_alloc (task->task_pool,
							sizeof (struct lua_redis_userdata));
			ud->task = task;
			ud->L = L;
			ud->cbref = cbref;
			lua_pushstring (L, "args");
			lua_redis_parse_args (L, -1, cmd, ud);
			ret = TRUE;
		}
		else {
			if (cbref != -1) {
				luaL_unref (L, LUA_REGISTRYINDEX, cbref);
			}

			msg_err ("incorrect function invocation");
		}
	}
	else if ((task = lua_check_task (L, 1)) != NULL) {
		addr = lua_check_ip (L, 2);
		top = lua_gettop (L);
		/* Now get callback */
		if (lua_isfunction (L, 3) && addr != NULL && addr->addr && top >= 4) {
			/* Create userdata */
			ud =
				rspamd_mempool_alloc (task->task_pool,
					sizeof (struct lua_redis_userdata));
			ud->task = task;
			ud->L = L;

			/* Pop other arguments */
			lua_pushvalue (L, 3);
			/* Get a reference */
			ud->cbref = luaL_ref (L, LUA_REGISTRYINDEX);

			cmd = luaL_checkstring (L, 4);
			if (top > 4) {
				lua_redis_parse_args (L, 5, cmd, ud);
			}
			else {
				lua_redis_parse_args (L, 0, cmd, ud);
			}

			ret = TRUE;
		}
		else {
			msg_err ("incorrect function invocation");
		}
	}

	if (ret) {
		ud->terminated = 0;
		ud->ctx = redisAsyncConnect (rspamd_inet_address_to_string (addr->addr),
				rspamd_inet_address_get_port (addr->addr));
		redisAsyncSetConnectCallback (ud->ctx, lua_redis_connect_cb);

		if (ud->ctx == NULL || ud->ctx->err) {
			ud->terminated = 1;
			redisAsyncFree (ud->ctx);
			lua_redis_free_args (ud);
			luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref);
			lua_pushboolean (L, FALSE);

			return 1;
		}
		redisLibeventAttach (ud->ctx, ud->task->ev_base);
		ret = redisAsyncCommandArgv (ud->ctx,
					lua_redis_callback,
					ud,
					ud->nargs,
					(const gchar **)ud->args,
					NULL);
		if (ret == REDIS_OK) {
			rspamd_session_add_event (ud->task->s,
					lua_redis_fin,
					ud,
					g_quark_from_static_string ("lua redis"));

			double_to_tv (timeout, &tv);
			event_set (&ud->timeout, -1, EV_TIMEOUT, lua_redis_timeout, ud);
			event_base_set (ud->task->ev_base, &ud->timeout);
			event_add (&ud->timeout, &tv);
		}
		else {
			msg_info ("call to redis failed: %s", ud->ctx->errstr);
			ud->terminated = 1;
			lua_redis_free_args (ud);
			redisAsyncFree (ud->ctx);
			luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref);
		}
	}

	lua_pushboolean (L, ret);

	return 1;
}