int ntttcp_server_listen()

in src/tcpstream.c [276:371]


int ntttcp_server_listen(struct ntttcp_stream_server *ss)
{
	char *log;
	int i = 0; /* hold function return value */
	int opt = 1;
	int sockfd = 0; /* socket file descriptor */
	char *local_addr_str; /* used to get local ip address */
	int ip_addr_max_size; /* used to get local ip address */
	char *port_str; /* used to get port number string for getaddrinfo() */
	struct addrinfo hints, *serv_info, *p; /* to get local sockaddr for bind() */

	/* get receiver/itself address */
	memset(&hints, 0, sizeof hints);
	hints.ai_family = ss->domain;
	hints.ai_socktype = ss->protocol;
	ASPRINTF(&port_str, "%d", ss->server_port);
	if (getaddrinfo(ss->bind_address, port_str, &hints, &serv_info) != 0) {
		PRINT_ERR("cannot get address info for receiver");
		return -1;
	}
	free(port_str);

	ip_addr_max_size = (ss->domain == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
	if ((local_addr_str = (char *)malloc(ip_addr_max_size)) == (char *)NULL) {
		PRINT_ERR("cannot allocate memory for ip address string");
		freeaddrinfo(serv_info);
		return -1;
	}

	/* get the first entry to bind and listen */
	for (p = serv_info; p != NULL; p = p->ai_next) {
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
			PRINT_ERR("cannot create socket endpoint");
			freeaddrinfo(serv_info);
			free(local_addr_str);
			return -1;
		}

		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
			ASPRINTF(&log, "cannot set socket options: %d", sockfd);
			PRINT_ERR_FREE(log);
			freeaddrinfo(serv_info);
			free(local_addr_str);
			close(sockfd);
			return -1;
		}
		if (set_socket_non_blocking(sockfd) == -1) {
			ASPRINTF(&log, "cannot set socket as non-blocking: %d", sockfd);
			PRINT_ERR_FREE(log);
			freeaddrinfo(serv_info);
			free(local_addr_str);
			close(sockfd);
			return -1;
		}
		if ((i = bind(sockfd, p->ai_addr, p->ai_addrlen)) < 0) {
			ASPRINTF(&log,
				"failed to bind the socket to local address: %s on socket: %d. return = %d",
				local_addr_str = retrive_ip_address_str((struct sockaddr_storage *)p->ai_addr, local_addr_str, ip_addr_max_size),
				sockfd, i);

			if (i == -1) /* append more info to log */
				ASPRINTF(&log, "%s. errcode = %d", log, errno);
			PRINT_DBG_FREE(log);
			continue;
		} else {
			break; /* connected */
		}
	}
	freeaddrinfo(serv_info);
	free(local_addr_str);
	if (p == NULL) {
		ASPRINTF(&log, "cannot bind the socket on address: %s", ss->bind_address);
		PRINT_ERR_FREE(log);
		close(sockfd);
		return -1;
	}

	ss->listener = sockfd;
	if (listen(ss->listener, MAX_THREADS_PER_SERVER_PORT) < 0) {
		ASPRINTF(&log, "failed to listen on address: %s: %d", ss->bind_address, ss->server_port);
		PRINT_ERR_FREE(log);
		close(ss->listener);
		return -1;
	}

	FD_ZERO(&ss->read_set);
	FD_ZERO(&ss->write_set);
	FD_SET(ss->listener, &ss->read_set);
	if (ss->listener > ss->max_fd)
		ss->max_fd = ss->listener;

	ASPRINTF(&log, "ntttcp server is listening on %s:%d", ss->bind_address, ss->server_port);
	PRINT_DBG_FREE(log);

	return ss->listener;
}