int lagscope_server_select()

in src/main.c [451:581]


int lagscope_server_select(struct lagscope_test_server *server)
{
	int err_code = NO_ERR;
	char *log = NULL;
	struct lagscope_test *test = server->test;
	bool verbose_log = test->verbose;

	int n_fds = 0, newfd, current_fd = 0;
	char *buffer; //receive buffer
	int msg_actual_size; //the buffer actual size = msg_size * sizeof(char)
	long nbytes; //bytes read
	fd_set read_set, write_set;

	struct sockaddr_storage peer_addr, local_addr; //for remote peer, and local address
	socklen_t peer_addr_size, local_addr_size;
	char *ip_address_str;
	int ip_address_max_size;

	msg_actual_size = test->msg_size * sizeof(char);
	if ((buffer = (char *)malloc(msg_actual_size)) == (char *)NULL) {
		PRINT_ERR("cannot allocate memory for receive message");
		return ERROR_MEMORY_ALLOC;
	}
	ip_address_max_size = (test->domain == AF_INET? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
	if ((ip_address_str = (char *)malloc(ip_address_max_size)) == (char *)NULL) {
		PRINT_ERR("cannot allocate memory for ip address of peer");
		free(buffer);
		return ERROR_MEMORY_ALLOC;
	}

	/* accept new client, receive data from client */
	while (1) {
		memcpy(&read_set, &server->read_set, sizeof(fd_set));
		memcpy(&write_set, &server->write_set, sizeof(fd_set));

		/* we are notified by select() */
		n_fds = select(server->max_fd + 1, &read_set, NULL, NULL, NULL);
		if (n_fds < 0 && errno != EINTR) {
			PRINT_ERR("error happened when select()");
			err_code = ERROR_SELECT;
			continue;
		}

		/*run through the existing connections looking for data to be read*/
		for (current_fd = 0; current_fd <= server->max_fd; current_fd++) {
			if (!FD_ISSET(current_fd, &read_set))
				continue;

			/* then, we got one fd to handle */
			/* a NEW connection coming */

			if (current_fd == server->listener) {
 				/* handle new connections */
				peer_addr_size = sizeof(peer_addr);
				if ((newfd = accept(server->listener, (struct sockaddr *) &peer_addr, &peer_addr_size)) < 0) {
					err_code = ERROR_ACCEPT;
					break;
				}

				/* then we got a new connection */
/*				if (set_socket_non_blocking(newfd) == -1) {
					ASPRINTF(&log, "cannot set the new socket as non-blocking: %d", newfd);
					PRINT_DBG_FREE(log);
				}
*/
				FD_SET(newfd, &server->read_set); /* add the new one to read_set */
				if (newfd > server->max_fd) {
					/* update the maximum */
					server->max_fd = newfd;
				}

				/* print out new connection info */
				local_addr_size = sizeof(local_addr);
				if (getsockname(newfd, (struct sockaddr *) &local_addr, &local_addr_size) != 0) {
					ASPRINTF(&log, "failed to get local address information for the new socket: %d", newfd);
					PRINT_DBG_FREE(log);
				}
				else {
					ASPRINTF(&log, "New connection: %s:%d --> local:%d [socket %d]",
							ip_address_str = retrive_ip_address_str(&peer_addr, ip_address_str, ip_address_max_size),
							ntohs(test->domain == AF_INET ?
									((struct sockaddr_in *)&peer_addr)->sin_port
									:((struct sockaddr_in6 *)&peer_addr)->sin6_port),
							ntohs(test->domain == AF_INET ?
									((struct sockaddr_in *)&local_addr)->sin_port
									:((struct sockaddr_in6 *)&local_addr)->sin6_port),
							newfd);
					PRINT_INFO_FREE(log);
				}
				turn_on_light();
			}
			/* handle data from an EXISTING client */
			else {
				memset(buffer, 0, msg_actual_size);

				/* got error or connection closed by client */
				if ((nbytes = n_read(current_fd, buffer, msg_actual_size)) <= 0) {
					if (nbytes == 0) {
						ASPRINTF(&log, "socket closed: %d", current_fd);
						PRINT_DBG_FREE(log);
					}
					else {
						ASPRINTF(&log, "error: cannot read data from socket: %d", current_fd);
						PRINT_INFO_FREE(log);
						err_code = ERROR_NETWORK_READ;
						/* need to continue test and check other socket, so don't end the test */
					}
					CLOSE(current_fd);
					FD_CLR(current_fd, &server->read_set); /* remove from master set when finished */
				}
				/* report ping request eceived */
				else {
					if ((nbytes = n_write(current_fd, buffer, msg_actual_size)) != msg_actual_size) {
						ASPRINTF(&log, "error: cannot write echo data to client from socket: %d", current_fd);
						PRINT_ERR_FREE(log);
					}
					ASPRINTF(&log, "Received from %s: bytes=%ld",
							ip_address_str = retrive_ip_address_str(&peer_addr, ip_address_str, ip_address_max_size),
							nbytes);
					PRINT_DBG_FREE(log);
				}
			}
		}
	}

	free(buffer);
	free(ip_address_str);
	CLOSE(server->listener);
	WSACLEAN();
	return err_code;
}