/* Set a reuseport bind on a socket. */ int ci_udp_reuseport_bind(citp_socket* ep, ci_fd_t fd, const struct sockaddr* sa, socklen_t sa_len) { int rc; ci_uint32 laddr_be32 = ci_get_ip4_addr(ep->s->domain, sa); int lport_be16 = ((struct sockaddr_in*)sa)->sin_port; ci_assert_nequal(ep->s->s_flags & CI_SOCK_FLAG_REUSEPORT, 0); /* We cannot support binding to port 0 as the kernel would assign * the socket a port number. We must move the socket before binding * the OS socket and we don't have a port number to look up * clusters. */ if( lport_be16 == 0 ) { LOG_UC(ci_log("%s: Binding to port 0 with reuseport set not supported", __FUNCTION__)); RET_WITH_ERRNO(ENOSYS); } if( (rc = ci_tcp_ep_reuseport_bind(fd, CITP_OPTS.cluster_name, CITP_OPTS.cluster_size, CITP_OPTS.cluster_restart_opt, laddr_be32, lport_be16)) != 0 ) { errno = -rc; return -1; } return rc; }
/* Set a reuseport bind on a socket. */ int ci_tcp_reuseport_bind(ci_sock_cmn* sock, ci_fd_t fd) { int rc; /* With legacy reuseport we delay the __ci_bind actions to avoid errors * when trying to re-use a port for the os socket, so won't have set the * PORT_BOUND flag yet. */ ci_assert(((sock->s_flags & CI_SOCK_FLAG_PORT_BOUND) != 0) || ((sock->s_flags & CI_SOCK_FLAG_REUSEPORT_LEGACY) != 0)); ci_assert_nequal(sock->s_flags & CI_SOCK_FLAG_REUSEPORT, 0); if ( (rc = ci_tcp_ep_reuseport_bind(fd, CITP_OPTS.cluster_name, CITP_OPTS.cluster_size, CITP_OPTS.cluster_restart_opt, sock_laddr_be32(sock), sock_lport_be16(sock))) != 0 ) { errno = -rc; return -1; } return 0; }