FreeBSD/sys/rpc/svc_vc.c
/*
 * Create a new transport for a socket optained via soaccept().
 */
Create a new transport for a socket optained via soaccept().
Create a new transport for a socket optained via soaccept () .
SVCXPRT *
svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
{
	SVCXPRT *xprt;
	struct cf_conn *cd;
	struct sockaddr* sa = NULL;
	struct sockopt opt;
	int one = 1;
	int error;
	bzero(&opt, sizeof(struct sockopt));
	opt.sopt_dir = SOPT_SET;
	opt.sopt_level = SOL_SOCKET;
	opt.sopt_name = SO_KEEPALIVE;
	opt.sopt_val = &one;
	opt.sopt_valsize = sizeof(one);
	error = sosetopt(so, &opt);
	if (error) {
		return (NULL);
	}
	if (so->so_proto->pr_protocol == IPPROTO_TCP) {
		bzero(&opt, sizeof(struct sockopt));
		opt.sopt_dir = SOPT_SET;
		opt.sopt_level = IPPROTO_TCP;
		opt.sopt_name = TCP_NODELAY;
		opt.sopt_val = &one;
		opt.sopt_valsize = sizeof(one);
		error = sosetopt(so, &opt);
		if (error) {
			return (NULL);
		}
	}
	cd = mem_alloc(sizeof(*cd));
	cd->strm_stat = XPRT_IDLE;
	xprt = svc_xprt_alloc();
	sx_init(&xprt->xp_lock, "xprt->xp_lock");
	xprt->xp_pool = pool;
	xprt->xp_socket = so;
	xprt->xp_p1 = cd;
	xprt->xp_p2 = NULL;
	xprt->xp_ops = &svc_vc_ops;
	xprt->xp_idletimeout = 6 * 60;
	memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len);
	CURVNET_SET(so->so_vnet);
	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
	CURVNET_RESTORE();
	if (error)
		goto cleanup_svc_vc_create;
	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
	free(sa, M_SONAME);
	xprt_register(xprt);
	SOCKBUF_LOCK(&so->so_rcv);
	xprt->xp_upcallset = 1;
	soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt);
	SOCKBUF_UNLOCK(&so->so_rcv);
	sx_xlock(&xprt->xp_lock);
	xprt_active(xprt);
	sx_xunlock(&xprt->xp_lock);
	return (xprt);
cleanup_svc_vc_create:
	sx_destroy(&xprt->xp_lock);
	svc_xprt_free(xprt);
	mem_free(cd, sizeof(*cd));
	return (NULL);
}
SVCXPRT * svc_vc_create_conn ( SVCPOOL * pool , struct socket * so , struct sockaddr * raddr ) { SVCXPRT * xprt ; struct cf_conn * cd ; struct sockaddr * sa = NULL ; struct sockopt opt ; int one = 1 ; int error ; bzero ( & opt , sizeof ( struct sockopt ) ) ; opt . sopt_dir = SOPT_SET ; opt . sopt_level = SOL_SOCKET ; opt . sopt_name = SO_KEEPALIVE ; opt . sopt_val = & one ; opt . sopt_valsize = sizeof ( one ) ; error = sosetopt ( so , & opt ) ; if ( error ) { return ( NULL ) ; } if ( so -> so_proto -> pr_protocol == IPPROTO_TCP ) { bzero ( & opt , sizeof ( struct sockopt ) ) ; opt . sopt_dir = SOPT_SET ; opt . sopt_level = IPPROTO_TCP ; opt . sopt_name = TCP_NODELAY ; opt . sopt_val = & one ; opt . sopt_valsize = sizeof ( one ) ; error = sosetopt ( so , & opt ) ; if ( error ) { return ( NULL ) ; } } cd = mem_alloc ( sizeof ( * cd ) ) ; cd -> strm_stat = XPRT_IDLE ; xprt = svc_xprt_alloc ( ) ; sx_init ( & xprt -> xp_lock , " " ) ; xprt -> xp_pool = pool ; xprt -> xp_socket = so ; xprt -> xp_p1 = cd ; xprt -> xp_p2 = NULL ; xprt -> xp_ops = & svc_vc_ops ; xprt -> xp_idletimeout = 6 * 60 ; memcpy ( & xprt -> xp_rtaddr , raddr , raddr -> sa_len ) ; CURVNET_SET ( so -> so_vnet ) ; error = so -> so_proto -> pr_usrreqs -> pru_sockaddr ( so , & sa ) ; CURVNET_RESTORE ( ) ; if ( error ) goto cleanup_svc_vc_create ; memcpy ( & xprt -> xp_ltaddr , sa , sa -> sa_len ) ; free ( sa , M_SONAME ) ; xprt_register ( xprt ) ; SOCKBUF_LOCK ( & so -> so_rcv ) ; xprt -> xp_upcallset = 1 ; soupcall_set ( so , SO_RCV , svc_vc_soupcall , xprt ) ; SOCKBUF_UNLOCK ( & so -> so_rcv ) ; sx_xlock ( & xprt -> xp_lock ) ; xprt_active ( xprt ) ; sx_xunlock ( & xprt -> xp_lock ) ; return ( xprt ) ; cleanup_svc_vc_create : sx_destroy ( & xprt -> xp_lock ) ; svc_xprt_free ( xprt ) ; mem_free ( cd , sizeof ( * cd ) ) ; return ( NULL ) ; }
Create a new transport for a socket optained via soaccept().
Create a new transport for a socket optained via soaccept () .
/*
	 * See http://www.connectathon.org/talks96/nfstcp.pdf - client
	 * has a 5 minute timer, server has a 6 minute timer.
	 */ /*
	 * Throw the transport into the active list in case it already
	 * has some data buffered.
	 */