SVCXPRT * svc_dg_ncreatef(const int fd, const u_int sendsz, const u_int recvsz, const uint32_t flags) { SVCXPRT *xprt; struct rpc_dplx_rec *rec; struct svc_dg_xprt *su; struct __rpc_sockinfo si; u_int recvsize; u_int sendsize; u_int xp_flags; int rc; /* atomically find or create shared fd state; ref+1; locked */ xprt = svc_xprt_lookup(fd, svc_dg_xprt_setup); if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d svc_xprt_lookup failed", __func__, fd); return (NULL); } rec = REC_XPRT(xprt); xp_flags = atomic_postset_uint16_t_bits(&xprt->xp_flags, flags | SVC_XPRT_FLAG_INITIALIZED); if ((xp_flags & SVC_XPRT_FLAG_INITIALIZED)) { rpc_dplx_rui(rec); XPRT_TRACE(xprt, __func__, __func__, __LINE__); return (xprt); } if (!__rpc_fd2sockinfo(fd, &si)) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d could not get transport information", __func__, fd); return (NULL); } /* * Find the receive and the send size */ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz); recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz); if ((sendsize == 0) || (recvsize == 0)) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d transport does not support data transfer", __func__, fd); return (NULL); } __rpc_address_setup(&xprt->xp_local); rc = getsockname(fd, xprt->xp_local.nb.buf, &xprt->xp_local.nb.len); if (rc < 0) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d getsockname failed (%d)", __func__, fd, rc); return (NULL); } /* * Should be multiple of 4 for XDR. */ su = DG_DR(rec); su->su_dr.sendsz = ((sendsize + 3) / 4) * 4; su->su_dr.recvsz = ((recvsize + 3) / 4) * 4; su->su_dr.maxrec = ((MAX(sendsize, recvsize) + 3) / 4) * 4; /* duplex streams are not used by the rendezvous transport */ xdrmem_create(su->su_dr.ioq.xdrs, NULL, 0, XDR_ENCODE); svc_dg_rendezvous_ops(xprt); /* Enable reception of IP*_PKTINFO control msgs */ svc_dg_enable_pktinfo(fd, &si); /* Conditional register */ if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS) && !(flags & SVC_CREATE_FLAG_XPRT_NOREG)) || (flags & SVC_CREATE_FLAG_XPRT_DOREG)) svc_rqst_evchan_reg(__svc_params->ev_u.evchan.id, xprt, SVC_RQST_FLAG_LOCKED | SVC_RQST_FLAG_CHAN_AFFINITY); /* release */ rpc_dplx_rui(rec); XPRT_TRACE(xprt, __func__, __func__, __LINE__); #if defined(HAVE_BLKIN) __rpc_set_blkin_endpoint(xprt, "svc_dg"); #endif return (xprt); }
uint16_t x2__atomic_clear_uint16_t_bits(uint16_t *p, uint16_t v) { return atomic_clear_uint16_t_bits(p, v); }