<commit_before>#include "../_ft_internal.h"
#include <sys/un.h>

static void _ft_listener_on_io(struct ev_loop *loop, struct ev_io *watcher, int revents);

///

bool ft_listener_init(struct ft_listener * this, struct ft_listener_delegate * delegate, struct ft_context * context, struct addrinfo * ai)
{
	int rc;
	int fd = -1;

	assert(this != NULL);
	assert(delegate != NULL);
	assert(context != NULL);
	
	FT_TRACE(FT_TRACE_ID_LISTENER, "BEGIN fa:%d st:%d pr:%d", ai->ai_family, ai->ai_socktype, ai->ai_protocol);

	this->delegate = delegate;
	this->context = context;
	this->listening = false;
	this->data = NULL;
	this->backlog = ft_config.sock_listen_backlog;

	this->ai_family = ai->ai_family;
	this->ai_socktype = ai->ai_socktype;
	this->ai_protocol = ai->ai_protocol;
	memcpy(&this->ai_addr, ai->ai_addr, ai->ai_addrlen);
	this->ai_addrlen = ai->ai_addrlen;

	this->stats.accept_events = 0;

	char addrstr[NI_MAXHOST+NI_MAXSERV];

	if (this->ai_family == AF_UNIX)
	{
		struct sockaddr_un * un = (struct sockaddr_un *)&this->ai_addr;
		strcpy(addrstr, un->sun_path);
	}

	else
	{
		char hoststr[NI_MAXHOST];
		char portstr[NI_MAXHOST];

		rc = getnameinfo((const struct sockaddr *)&this->ai_addr, this->ai_addrlen, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
		if (rc != 0)
		{
			if (rc == EAI_FAMILY)
			{
				FT_WARN("Unsupported family: %d", this->ai_family);
				// This is not a failure
				FT_TRACE(FT_TRACE_ID_LISTENER, "END EAI_FAMILY");
				return false;
			}

			FT_WARN("Problem occured when resolving listen socket: %s", gai_strerror(rc));
			snprintf(addrstr, sizeof(addrstr)-1, "? ?");
		}

		else
			snprintf(addrstr, sizeof(addrstr)-1, "%s %s", hoststr, portstr);
	}

	// Create socket
	fd = socket(this->ai_family, this->ai_socktype, this->ai_protocol);
	if (fd < 0)
	{
		FT_ERROR_ERRNO(errno, "Failed creating listen socket");
		goto error_exit;
	}

	// Set reuse address option
	int on = 1;
	rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on));
	if (rc == -1)
	{
		FT_ERROR_ERRNO(errno, "Failed when setting option SO_REUSEADDR to listen socket");
		goto error_exit;
	}

	// Set reuse port option
	on = 1;
	rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const char *) &on, sizeof(on));
	if (rc == -1)
	{
		FT_ERROR_ERRNO(errno, "Failed when setting option SO_REUSEPORT to listen socket");
		goto error_exit;
	}

	bool res = ft_fd_nonblock(fd);
	if (!res) FT_WARN_ERRNO(errno, "Failed when setting listen socket to non-blocking mode");

#if TCP_DEFER_ACCEPT
	// See http://www.techrepublic.com/article/take-advantage-of-tcp-ip-options-to-optimize-data-transmission/
	int timeout = 1;
	rc = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int));
	if (rc == -1) FT_WARN_ERRNO(errno, "Failed when setting option TCP_DEFER_ACCEPT to listen socket");
#endif // TCP_DEFER_ACCEPT

	// Bind socket
	rc = bind(fd, (const struct sockaddr *)&this->ai_addr, this->ai_addrlen);
	if (rc != 0)
	{
		FT_ERROR_ERRNO(errno, "bind to %s ", addrstr);
		goto error_exit;
	}

	ev_io_init(&this->watcher, _ft_listener_on_io, fd, EV_READ);
	this->watcher.data = this;

	FT_DEBUG("Listening on %s", addrstr);
	FT_TRACE(FT_TRACE_ID_LISTENER, "END fd:%d", fd);
	return true;
<commit_msg>SO_REUSEPORT is now conditioned.<commit_after>#include "../_ft_internal.h"
#include <sys/un.h>

static void _ft_listener_on_io(struct ev_loop *loop, struct ev_io *watcher, int revents);

///

bool ft_listener_init(struct ft_listener * this, struct ft_listener_delegate * delegate, struct ft_context * context, struct addrinfo * ai)
{
	int rc;
	int fd = -1;

	assert(this != NULL);
	assert(delegate != NULL);
	assert(context != NULL);
	
	FT_TRACE(FT_TRACE_ID_LISTENER, "BEGIN fa:%d st:%d pr:%d", ai->ai_family, ai->ai_socktype, ai->ai_protocol);

	this->delegate = delegate;
	this->context = context;
	this->listening = false;
	this->data = NULL;
	this->backlog = ft_config.sock_listen_backlog;

	this->ai_family = ai->ai_family;
	this->ai_socktype = ai->ai_socktype;
	this->ai_protocol = ai->ai_protocol;
	memcpy(&this->ai_addr, ai->ai_addr, ai->ai_addrlen);
	this->ai_addrlen = ai->ai_addrlen;

	this->stats.accept_events = 0;

	char addrstr[NI_MAXHOST+NI_MAXSERV];

	if (this->ai_family == AF_UNIX)
	{
		struct sockaddr_un * un = (struct sockaddr_un *)&this->ai_addr;
		strcpy(addrstr, un->sun_path);
	}

	else
	{
		char hoststr[NI_MAXHOST];
		char portstr[NI_MAXHOST];

		rc = getnameinfo((const struct sockaddr *)&this->ai_addr, this->ai_addrlen, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
		if (rc != 0)
		{
			if (rc == EAI_FAMILY)
			{
				FT_WARN("Unsupported family: %d", this->ai_family);
				// This is not a failure
				FT_TRACE(FT_TRACE_ID_LISTENER, "END EAI_FAMILY");
				return false;
			}

			FT_WARN("Problem occured when resolving listen socket: %s", gai_strerror(rc));
			snprintf(addrstr, sizeof(addrstr)-1, "? ?");
		}

		else
			snprintf(addrstr, sizeof(addrstr)-1, "%s %s", hoststr, portstr);
	}

	// Create socket
	fd = socket(this->ai_family, this->ai_socktype, this->ai_protocol);
	if (fd < 0)
	{
		FT_ERROR_ERRNO(errno, "Failed creating listen socket");
		goto error_exit;
	}

	// Set reuse address option
	int on = 1;
	rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on));
	if (rc == -1)
	{
		FT_ERROR_ERRNO(errno, "Failed when setting option SO_REUSEADDR to listen socket");
		goto error_exit;
	}

#ifdef SO_REUSEPORT
	// Set reuse port option
	on = 1;
	rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const char *) &on, sizeof(on));
	if (rc == -1)
	{
		FT_ERROR_ERRNO(errno, "Failed when setting option SO_REUSEPORT to listen socket");
		goto error_exit;
	}
#endif

	bool res = ft_fd_nonblock(fd);
	if (!res) FT_WARN_ERRNO(errno, "Failed when setting listen socket to non-blocking mode");

#if TCP_DEFER_ACCEPT
	// See http://www.techrepublic.com/article/take-advantage-of-tcp-ip-options-to-optimize-data-transmission/
	int timeout = 1;
	rc = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int));
	if (rc == -1) FT_WARN_ERRNO(errno, "Failed when setting option TCP_DEFER_ACCEPT to listen socket");
#endif // TCP_DEFER_ACCEPT

	// Bind socket
	rc = bind(fd, (const struct sockaddr *)&this->ai_addr, this->ai_addrlen);
	if (rc != 0)
	{
		FT_ERROR_ERRNO(errno, "bind to %s ", addrstr);
		goto error_exit;
	}

	ev_io_init(&this->watcher, _ft_listener_on_io, fd, EV_READ);
	this->watcher.data = this;

	FT_DEBUG("Listening on %s", addrstr);
	FT_TRACE(FT_TRACE_ID_LISTENER, "END fd:%d", fd);
	return true;

{'fraction_non_alphanumeric': 0.14483282674772036, 'fraction_numerical': 0.003951367781155016, 'mean_word_length': 4.586587436332767, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5353748', 'n_tokens_mistral': 2664, 'n_tokens_neox': 2503, 'n_words': 576}