Esempio n. 1
0
/** Initialize the common timeout that we'll use to refill the buckets every
 * time a tick elapses. */
static void
tor_libevent_set_tick_timeout(int msec_per_tick)
{
  struct event_base *base = tor_libevent_get_base();
  struct timeval tv;

  tor_assert(! one_tick);
  tv.tv_sec = msec_per_tick / 1000;
  tv.tv_usec = (msec_per_tick % 1000) * 1000;
  one_tick = event_base_init_common_timeout(base, &tv);
}
Esempio n. 2
0
File: main.c Progetto: nexie/ed2kd
int main( int argc, char *argv[] )
{
        size_t i;
        int ret, opt, longIndex = 0;
        struct event *evsig_int;
#ifdef _WIN32
        WSADATA WSAData;
#endif
        pthread_t tcp_thread, *job_threads;

        if ( evutil_secure_rng_init() < 0 ) {
                ED2KD_LOGERR("failed to seed random number generator");
                return EXIT_FAILURE;
        }

        /* parse command line arguments */
        opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
        while( opt != -1 ) {
                switch( opt ) {
                case 'v':
                        display_version();
                        return EXIT_SUCCESS;

                case 'g': {
                        unsigned char hash[ED2K_HASH_SIZE];
                        char hex_hash[sizeof(hash)*2+1];
                        get_random_user_hash(hash);
                        bin2hex(hash, hex_hash, sizeof(hex_hash));
                        puts(hex_hash);
                        return EXIT_SUCCESS;
                }

                case 'h':
                        display_usage();
                        return EXIT_SUCCESS;

                default:
                        return EXIT_FAILURE;
                }
                opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
        }

#ifdef _WIN32
        if ( 0 != WSAStartup(0x0201, &WSAData) ) {
                ED2KD_LOGERR("WSAStartup failed!");
                return EXIT_FAILURE;
        }
#endif

        if ( !server_load_config(NULL) ) {
                ED2KD_LOGERR("failed to load configuration file");
                return EXIT_FAILURE;
        }

        display_libevent_info();

#ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
        ret = evthread_use_windows_threads();
#elif EVTHREAD_USE_PTHREADS_IMPLEMENTED
        ret = evthread_use_pthreads();
#else
#error "unable to determine threading model"
#endif
        if ( ret < 0 ) {
                ED2KD_LOGERR("failed to init libevent threading model");
                return EXIT_FAILURE;
        }

        g_srv.evbase_main = event_base_new();
        if ( NULL == g_srv.evbase_main ) {
                ED2KD_LOGERR("failed to create main event loop");
                return EXIT_FAILURE;
        }
        g_srv.evbase_tcp = event_base_new();
        if ( NULL == g_srv.evbase_tcp ) {
                ED2KD_LOGERR("failed to create tcp event loop");
                return EXIT_FAILURE;
        }

        evsig_int = evsignal_new(g_srv.evbase_main, SIGINT, sigint_cb, NULL);
        evsignal_add(evsig_int, NULL);

        // common timers timevals
        g_srv.portcheck_timeout_tv = event_base_init_common_timeout(g_srv.evbase_tcp, &g_srv.cfg->portcheck_timeout_tv);
        g_srv.status_notify_tv = event_base_init_common_timeout(g_srv.evbase_tcp, &g_srv.cfg->status_notify_tv);

        if ( !db_create() ) {
                ED2KD_LOGERR("failed to create database");
                return EXIT_FAILURE;
        }

        g_srv.thread_count = omp_get_num_procs() + 1;

        pthread_cond_init(&g_srv.job_cond, NULL);
        pthread_mutex_init(&g_srv.job_mutex, NULL);
        TAILQ_INIT(&g_srv.jqueue);

        job_threads = (pthread_t *)malloc(g_srv.thread_count * sizeof(*job_threads));

        // start tcp worker threads
        for ( i=0; i<g_srv.thread_count; ++i ) {
                pthread_create(&job_threads[i], NULL, server_job_worker, NULL);
        }

        // start tcp dispatch thread
        pthread_create(&tcp_thread, NULL, server_base_worker, g_srv.evbase_tcp);

        // start tcp listen loop
        if ( !server_listen() ) {
                ED2KD_LOGERR("failed to start server listener");
                server_stop();
        }

        pthread_join(tcp_thread, NULL);

        while ( EBUSY == pthread_cond_destroy(&g_srv.job_cond) ) {
                pthread_cond_broadcast(&g_srv.job_cond);
                //pthread_yield();
        }

        pthread_mutex_destroy(&g_srv.job_mutex);

        for ( i=0; i<g_srv.thread_count; ++i ) {
                pthread_join(job_threads[i], NULL);
        }

        free(job_threads);

        // todo: free job queue items

        evconnlistener_free(g_srv.tcp_listener);
        event_free(evsig_int);
        event_base_free(g_srv.evbase_tcp);
        event_base_free(g_srv.evbase_main);

        if ( db_destroy() < 0 ) {
                ED2KD_LOGERR("failed to destroy database");
        }

        server_free_config();

        return EXIT_SUCCESS;
}
Esempio n. 3
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));
	if (bevs == NULL || states == NULL) {
		printf("Unable to allocate memory...\n");
		return 1;
	}

	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. 4
0
/* Testing code for event_base_dump_events().

   Notes that just because we have code to exercise this function,
   doesn't mean that *ANYTHING* about the output format is guaranteed to
   remain in the future.
 */
int
main(int argc, char **argv)
{
#define N_EVENTS 13
	int i;
	struct event *ev[N_EVENTS];
	evutil_socket_t pair1[2];
	evutil_socket_t pair2[2];
	struct timeval tv_onesec = {1,0};
	struct timeval tv_two5sec = {2,500*1000};
	const struct timeval *tv_onesec_common;
	const struct timeval *tv_two5sec_common;
	struct event_base *base;
	struct timeval now;

#ifdef _WIN32
	WORD wVersionRequested;
	WSADATA wsaData;

	wVersionRequested = MAKEWORD(2, 2);

	WSAStartup(wVersionRequested, &wsaData);
#endif

#ifdef _WIN32
#define LOCAL_SOCKETPAIR_AF AF_INET
#else
#define LOCAL_SOCKETPAIR_AF AF_UNIX
#endif

	if (evutil_make_internal_pipe_(pair1) < 0 ||
	    evutil_make_internal_pipe_(pair2) < 0) {
		sock_perror("evutil_make_internal_pipe_");
		return 1;
	}

	if (!(base = event_base_new())) {
		fprintf(stderr,"Couldn't make event_base\n");
		return 2;
	}

	tv_onesec_common = event_base_init_common_timeout(base, &tv_onesec);
	tv_two5sec_common = event_base_init_common_timeout(base, &tv_two5sec);

	ev[0] = event_new(base, pair1[0], EV_WRITE, callback1, NULL);
	ev[1] = event_new(base, pair1[1], EV_READ|EV_PERSIST, callback1, NULL);
	ev[2] = event_new(base, pair2[0], EV_WRITE|EV_PERSIST, callback2, NULL);
	ev[3] = event_new(base, pair2[1], EV_READ, callback2, NULL);

	/* For timers */
	ev[4] = evtimer_new(base, callback1, NULL);
	ev[5] = evtimer_new(base, callback1, NULL);
	ev[6] = evtimer_new(base, callback1, NULL);
	ev[7] = event_new(base, -1, EV_PERSIST, callback2, NULL);
	ev[8] = event_new(base, -1, EV_PERSIST, callback2, NULL);
	ev[9] = event_new(base, -1, EV_PERSIST, callback2, NULL);

	/* To activate */
	ev[10] = event_new(base, -1, 0, callback1, NULL);
	ev[11] = event_new(base, -1, 0, callback2, NULL);

	/* Signals */
	ev[12] = evsignal_new(base, SIGINT, callback2, NULL);

	event_add(ev[0], NULL);
	event_add(ev[1], &tv_onesec);
	event_add(ev[2], tv_onesec_common);
	event_add(ev[3], tv_two5sec_common);

	event_add(ev[4], tv_onesec_common);
	event_add(ev[5], tv_onesec_common);
	event_add(ev[6], &tv_onesec);
	event_add(ev[7], tv_two5sec_common);
	event_add(ev[8], tv_onesec_common);
	event_add(ev[9], &tv_two5sec);

	event_active(ev[10], EV_READ, 1);
	event_active(ev[11], EV_READ|EV_WRITE|EV_TIMEOUT, 1);
	event_active(ev[1], EV_READ, 1);

	event_add(ev[12], NULL);

	evutil_gettimeofday(&now,NULL);
	puts("=====expected");
	printf("Now= %ld.%06d\n",(long)now.tv_sec,(int)now.tv_usec);
	puts("Inserted:");
	printf("  %p [fd  %ld] Write\n",ev[0],(long)pair1[0]);
	printf("  %p [fd  %ld] Read Persist Timeout=T+1\n",ev[1],(long)pair1[1]);
	printf("  %p [fd  %ld] Write Persist Timeout=T+1\n",ev[2],(long)pair2[0]);
	printf("  %p [fd  %ld] Read Timeout=T+2.5\n",ev[3],(long)pair2[1]);
	printf("  %p [fd  -1] Timeout=T+1\n",ev[4]);
	printf("  %p [fd  -1] Timeout=T+1\n",ev[5]);
	printf("  %p [fd  -1] Timeout=T+1\n",ev[6]);
	printf("  %p [fd  -1] Persist Timeout=T+2.5\n",ev[7]);
	printf("  %p [fd  -1] Persist Timeout=T+1\n",ev[8]);
	printf("  %p [fd  -1] Persist Timeout=T+2.5\n",ev[9]);
	printf("  %p [sig %d] Signal Persist\n", ev[12], (int)SIGINT);

	puts("Active:");
	printf("  %p [fd  -1, priority=0] Read active\n", ev[10]);
	printf("  %p [fd  -1, priority=0] Read Write Timeout active\n", ev[11]);
	printf("  %p [fd  %ld, priority=0] Read active\n", ev[1], (long)pair1[1]);

	puts("======received");
	event_base_dump_events(base, stdout);

	for (i = 0; i < N_EVENTS; ++i) {
		event_free(ev[i]);
	}
	event_base_free(base);

	return 0;
}