/* Create a test socket with the right properties for testing. port is the TCP port to listen or connect to. Return a socket FD and sockaddr_in. */ static void create_test_socket(int port, int *socket_fd, struct sockaddr_in *sin) { int fd; int one = 1; int buffer_size_bytes = BUF_SIZE; int flags; fd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); /* Reset the size of socket send buffer to the minimal value to facilitate buffer filling up and triggering notify_on_write */ GPR_ASSERT(grpc_set_socket_sndbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_set_socket_rcvbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); /* Make fd non-blocking */ flags = fcntl(fd, F_GETFL, 0); GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); *socket_fd = fd; /* Use local address for test */ sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(0x7f000001); GPR_ASSERT(port >= 0 && port < 65536); sin->sin_port = htons((uint16_t)port); }
/* Prepare a recently-created socket for listening. */ static int prepare_socket(grpc_socket_factory *socket_factory, int fd, const grpc_resolved_address *addr) { grpc_resolved_address sockname_temp; struct sockaddr *addr_ptr = (struct sockaddr *)addr->addr; /* Set send/receive socket buffers to 1 MB */ int buffer_size_bytes = 1024 * 1024; if (fd < 0) { goto error; } if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno)); goto error; } if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno)); goto error; } if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set ip_pktinfo."); goto error; } else if (addr_ptr->sa_family == AF_INET6) { if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo."); goto error; } } GPR_ASSERT(addr->len < ~(socklen_t)0); if (bind_socket(socket_factory, fd, addr) < 0) { char *addr_str; grpc_sockaddr_to_string(&addr_str, addr, 0); gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno)); gpr_free(addr_str); goto error; } sockname_temp.len = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, (socklen_t *)&sockname_temp.len) < 0) { goto error; } if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes", buffer_size_bytes); goto error; } if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes", buffer_size_bytes); goto error; } return grpc_sockaddr_get_port(&sockname_temp); error: if (fd >= 0) { close(fd); } return -1; }