Example #1
0
/* 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;
}
Example #2
0
/* 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;
}