FreeBSD/sys/rpc/clnt_bck.c
/*
 * Create a client handle for a connection.
 * Default options are set, which the user can change using clnt_control()'s.
 * This code handles the special case of an NFSv4.1 session backchannel
 * call, which is sent on a TCP connection created against the server
 * by a client.
 */
Create a client handle for a connection.
Default options are set, which the user can change using clnt_control()'s.
This code handles the special case of an NFSv4.1 session backchannel
call, which is sent on a TCP connection created against the server
by a client.
Create a client handle for a connection . Default options are set which the user can change using clnt_control () ' s . This code handles the special case of an NFSv4 . 1 session backchannel call which is sent on a TCP connection created against the server by a client .
void *
clnt_bck_create(
	struct socket *so,		
	const rpcprog_t prog,		
	const rpcvers_t vers)		
{
	CLIENT *cl;			
	struct ct_data *ct = NULL;	
	struct timeval now;
	struct rpc_msg call_msg;
	static uint32_t disrupt;
	XDR xdrs;
	if (disrupt == 0)
		disrupt = (uint32_t)(long)so;
	cl = (CLIENT *)mem_alloc(sizeof (*cl));
	ct = (struct ct_data *)mem_alloc(sizeof (*ct));
	mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF);
	ct->ct_threads = 0;
	ct->ct_closing = FALSE;
	ct->ct_closed = FALSE;
	ct->ct_upcallrefs = 0;
	ct->ct_closeit = FALSE;
	ct->ct_wait.tv_sec = -1;
	ct->ct_wait.tv_usec = -1;
	getmicrotime(&now);
	ct->ct_xid = ((uint32_t)++disrupt) ^ __RPC_GETXID(&now);
	call_msg.rm_xid = ct->ct_xid;
	call_msg.rm_direction = CALL;
	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	call_msg.rm_call.cb_prog = (uint32_t)prog;
	call_msg.rm_call.cb_vers = (uint32_t)vers;
	xdrmem_create(&xdrs, ct->ct_mcallc, MCALL_MSG_SIZE,
	    XDR_ENCODE);
	if (!xdr_callhdr(&xdrs, &call_msg))
		goto err;
	ct->ct_mpos = XDR_GETPOS(&xdrs);
	XDR_DESTROY(&xdrs);
	ct->ct_waitchan = "rpcbck";
	ct->ct_waitflag = 0;
	cl->cl_refs = 1;
	cl->cl_ops = &clnt_bck_ops;
	cl->cl_private = ct;
	cl->cl_auth = authnone_create();
	TAILQ_INIT(&ct->ct_pending);
	return (cl);
err:
	mtx_destroy(&ct->ct_lock);
	mem_free(ct, sizeof (struct ct_data));
	mem_free(cl, sizeof (CLIENT));
	return (NULL);
}
void * clnt_bck_create ( struct socket * so , const rpcprog_t prog , const rpcvers_t vers ) { CLIENT * cl ; struct ct_data * ct = NULL ; struct timeval now ; struct rpc_msg call_msg ; static uint32_t disrupt ; XDR xdrs ; if ( disrupt == 0 ) disrupt = ( uint32_t ) ( long ) so ; cl = ( CLIENT * ) mem_alloc ( sizeof ( * cl ) ) ; ct = ( struct ct_data * ) mem_alloc ( sizeof ( * ct ) ) ; mtx_init ( & ct -> ct_lock , " " , NULL , MTX_DEF ) ; ct -> ct_threads = 0 ; ct -> ct_closing = FALSE ; ct -> ct_closed = FALSE ; ct -> ct_upcallrefs = 0 ; ct -> ct_closeit = FALSE ; ct -> ct_wait . tv_sec = -1 ; ct -> ct_wait . tv_usec = -1 ; getmicrotime ( & now ) ; ct -> ct_xid = ( ( uint32_t ) ++ disrupt ) ^ __RPC_GETXID ( & now ) ; call_msg . rm_xid = ct -> ct_xid ; call_msg . rm_direction = CALL ; call_msg . rm_call . cb_rpcvers = RPC_MSG_VERSION ; call_msg . rm_call . cb_prog = ( uint32_t ) prog ; call_msg . rm_call . cb_vers = ( uint32_t ) vers ; xdrmem_create ( & xdrs , ct -> ct_mcallc , MCALL_MSG_SIZE , XDR_ENCODE ) ; if ( ! xdr_callhdr ( & xdrs , & call_msg ) ) goto err ; ct -> ct_mpos = XDR_GETPOS ( & xdrs ) ; XDR_DESTROY ( & xdrs ) ; ct -> ct_waitchan = " " ; ct -> ct_waitflag = 0 ; cl -> cl_refs = 1 ; cl -> cl_ops = & clnt_bck_ops ; cl -> cl_private = ct ; cl -> cl_auth = authnone_create ( ) ; TAILQ_INIT ( & ct -> ct_pending ) ; return ( cl ) ; err : mtx_destroy ( & ct -> ct_lock ) ; mem_free ( ct , sizeof ( struct ct_data ) ) ; mem_free ( cl , sizeof ( CLIENT ) ) ; return ( NULL ) ; }
Create a client handle for a connection.
Create a client handle for a connection .
/* Server transport socket. */ /* program number */ /* version number */ /* client handle */ /* client handle */ /*
	 * Set up private data struct
	 */ /*
	 * Initialize call message
	 */ /*
	 * pre-serialize the static part of the call msg and stash it away
	 */