FreeBSD/sys/rpc/clnt_dg.c
/*
 * Connection less client creation returns with client handle parameters.
 * Default options are set, which the user can change using clnt_control().
 * fd should be open and bound.
 * NB: The rpch->cl_auth is initialized to null authentication.
 * 	Caller may wish to set this something more useful.
 *
 * sendsz and recvsz are the maximum allowable packet sizes that can be
 * sent and received. Normally they are the same, but they can be
 * changed to improve the program efficiency and buffer allocation.
 * If they are 0, use the transport default.
 *
 * If svcaddr is NULL, returns NULL.
 */
Connection less client creation returns with client handle parameters.
Default options are set, which the user can change using clnt_control().
fd should be open and bound.
NB: The rpch->cl_auth is initialized to null authentication.
Caller may wish to set this something more useful.

sendsz and recvsz are the maximum allowable packet sizes that can be
sent and received. Normally they are the same, but they can be
changed to improve the program efficiency and buffer allocation.
If they are 0, use the transport default.

If svcaddr is NULL, returns NULL.
Connection less client creation returns with client handle parameters . Default options are set which the user can change using clnt_control () . fd should be open and bound . NB : The rpch - > cl_auth is initialized to null authentication . Caller may wish to set this something more useful . sendsz and recvsz are the maximum allowable packet sizes that can be sent and received . Normally they are the same but they can be changed to improve the program efficiency and buffer allocation . If they are 0 use the transport default . If svcaddr is NULL returns NULL .
CLIENT *
clnt_dg_create(
	struct socket *so,
	struct sockaddr *svcaddr,	
	rpcprog_t program,		
	rpcvers_t version,		
	size_t sendsz,			
	size_t recvsz)			
{
	CLIENT *cl = NULL;		
	struct cu_data *cu = NULL;	
	struct cu_socket *cs = NULL;
	struct sockbuf *sb;
	struct timeval now;
	struct rpc_msg call_msg;
	struct __rpc_sockinfo si;
	XDR xdrs;
	int error;
	if (svcaddr == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
		return (NULL);
	}
	if (!__rpc_socket2sockinfo(so, &si)) {
		rpc_createerr.cf_stat = RPC_TLIERROR;
		rpc_createerr.cf_error.re_errno = 0;
		return (NULL);
	}
	sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
	recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
	if ((sendsz == 0) || (recvsz == 0)) {
		rpc_createerr.cf_stat = RPC_TLIERROR; 
		rpc_createerr.cf_error.re_errno = 0;
		return (NULL);
	}
	cl = mem_alloc(sizeof (CLIENT));
	sendsz = rounddown(sendsz + 3, 4);
	recvsz = rounddown(recvsz + 3, 4);
	cu = mem_alloc(sizeof (*cu));
	cu->cu_threads = 0;
	cu->cu_closing = FALSE;
	cu->cu_closed = FALSE;
	(void) memcpy(&cu->cu_raddr, svcaddr, (size_t)svcaddr->sa_len);
	cu->cu_rlen = svcaddr->sa_len;
	cu->cu_wait.tv_sec = 3;	
	cu->cu_wait.tv_usec = 0;
	cu->cu_total.tv_sec = -1;
	cu->cu_total.tv_usec = -1;
	cu->cu_sendsz = sendsz;
	cu->cu_recvsz = recvsz;
	cu->cu_async = FALSE;
	cu->cu_connect = FALSE;
	cu->cu_connected = FALSE;
	cu->cu_waitchan = "rpcrecv";
	cu->cu_waitflag = 0;
	cu->cu_cwnd = MAXCWND / 2;
	cu->cu_sent = 0;
	cu->cu_cwnd_wait = FALSE;
	(void) getmicrotime(&now);
	cu->cu_xid = __RPC_GETXID(&now);
	call_msg.rm_xid = cu->cu_xid;
	call_msg.rm_call.cb_prog = program;
	call_msg.rm_call.cb_vers = version;
	xdrmem_create(&xdrs, cu->cu_mcallc, MCALL_MSG_SIZE, XDR_ENCODE);
	if (! xdr_callhdr(&xdrs, &call_msg)) {
		rpc_createerr.cf_stat = RPC_CANTENCODEARGS;  
		rpc_createerr.cf_error.re_errno = 0;
		goto err2;
	}
	cu->cu_mcalllen = XDR_GETPOS(&xdrs);
	cu->cu_closeit = FALSE;
	cu->cu_socket = so;
	error = soreserve(so, (u_long)sendsz, (u_long)recvsz);
	if (error != 0) {
		rpc_createerr.cf_stat = RPC_FAILED;
		rpc_createerr.cf_error.re_errno = error;
		goto err2;
	}
	sb = &so->so_rcv;
	SOCKBUF_LOCK(&so->so_rcv);
recheck_socket:
	if (sb->sb_upcall) {
		if (sb->sb_upcall != clnt_dg_soupcall) {
			SOCKBUF_UNLOCK(&so->so_rcv);
			printf("clnt_dg_create(): socket already has an incompatible upcall\n");
			goto err2;
		}
		cs = (struct cu_socket *) sb->sb_upcallarg;
		mtx_lock(&cs->cs_lock);
		cs->cs_refs++;
		mtx_unlock(&cs->cs_lock);
	} else {
		SOCKBUF_UNLOCK(&so->so_rcv);
		cs = mem_alloc(sizeof(*cs));
		SOCKBUF_LOCK(&so->so_rcv);
		if (sb->sb_upcall) {
			mem_free(cs, sizeof(*cs));
			goto recheck_socket;
		}
		mtx_init(&cs->cs_lock, "cs->cs_lock", NULL, MTX_DEF);
		cs->cs_refs = 1;
		cs->cs_upcallrefs = 0;
		TAILQ_INIT(&cs->cs_pending);
		soupcall_set(so, SO_RCV, clnt_dg_soupcall, cs);
	}
	SOCKBUF_UNLOCK(&so->so_rcv);
	cl->cl_refs = 1;
	cl->cl_ops = &clnt_dg_ops;
	cl->cl_private = (caddr_t)(void *)cu;
	cl->cl_auth = authnone_create();
	cl->cl_tp = NULL;
	cl->cl_netid = NULL;
	return (cl);
err2:
	mem_free(cl, sizeof (CLIENT));
	mem_free(cu, sizeof (*cu));
	return (NULL);
}
CLIENT * clnt_dg_create ( struct socket * so , struct sockaddr * svcaddr , rpcprog_t program , rpcvers_t version , size_t sendsz , size_t recvsz ) { CLIENT * cl = NULL ; struct cu_data * cu = NULL ; struct cu_socket * cs = NULL ; struct sockbuf * sb ; struct timeval now ; struct rpc_msg call_msg ; struct __rpc_sockinfo si ; XDR xdrs ; int error ; if ( svcaddr == NULL ) { rpc_createerr . cf_stat = RPC_UNKNOWNADDR ; return ( NULL ) ; } if ( ! __rpc_socket2sockinfo ( so , & si ) ) { rpc_createerr . cf_stat = RPC_TLIERROR ; rpc_createerr . cf_error . re_errno = 0 ; return ( NULL ) ; } sendsz = __rpc_get_t_size ( si . si_af , si . si_proto , ( int ) sendsz ) ; recvsz = __rpc_get_t_size ( si . si_af , si . si_proto , ( int ) recvsz ) ; if ( ( sendsz == 0 ) || ( recvsz == 0 ) ) { rpc_createerr . cf_stat = RPC_TLIERROR ; rpc_createerr . cf_error . re_errno = 0 ; return ( NULL ) ; } cl = mem_alloc ( sizeof ( CLIENT ) ) ; sendsz = rounddown ( sendsz + 3 , 4 ) ; recvsz = rounddown ( recvsz + 3 , 4 ) ; cu = mem_alloc ( sizeof ( * cu ) ) ; cu -> cu_threads = 0 ; cu -> cu_closing = FALSE ; cu -> cu_closed = FALSE ; ( void ) memcpy ( & cu -> cu_raddr , svcaddr , ( size_t ) svcaddr -> sa_len ) ; cu -> cu_rlen = svcaddr -> sa_len ; cu -> cu_wait . tv_sec = 3 ; cu -> cu_wait . tv_usec = 0 ; cu -> cu_total . tv_sec = -1 ; cu -> cu_total . tv_usec = -1 ; cu -> cu_sendsz = sendsz ; cu -> cu_recvsz = recvsz ; cu -> cu_async = FALSE ; cu -> cu_connect = FALSE ; cu -> cu_connected = FALSE ; cu -> cu_waitchan = " " ; cu -> cu_waitflag = 0 ; cu -> cu_cwnd = MAXCWND / 2 ; cu -> cu_sent = 0 ; cu -> cu_cwnd_wait = FALSE ; ( void ) getmicrotime ( & now ) ; cu -> cu_xid = __RPC_GETXID ( & now ) ; call_msg . rm_xid = cu -> cu_xid ; call_msg . rm_call . cb_prog = program ; call_msg . rm_call . cb_vers = version ; xdrmem_create ( & xdrs , cu -> cu_mcallc , MCALL_MSG_SIZE , XDR_ENCODE ) ; if ( ! xdr_callhdr ( & xdrs , & call_msg ) ) { rpc_createerr . cf_stat = RPC_CANTENCODEARGS ; rpc_createerr . cf_error . re_errno = 0 ; goto err2 ; } cu -> cu_mcalllen = XDR_GETPOS ( & xdrs ) ; cu -> cu_closeit = FALSE ; cu -> cu_socket = so ; error = soreserve ( so , ( u_long ) sendsz , ( u_long ) recvsz ) ; if ( error != 0 ) { rpc_createerr . cf_stat = RPC_FAILED ; rpc_createerr . cf_error . re_errno = error ; goto err2 ; } sb = & so -> so_rcv ; SOCKBUF_LOCK ( & so -> so_rcv ) ; recheck_socket : if ( sb -> sb_upcall ) { if ( sb -> sb_upcall != clnt_dg_soupcall ) { SOCKBUF_UNLOCK ( & so -> so_rcv ) ; printf ( " \n " ) ; goto err2 ; } cs = ( struct cu_socket * ) sb -> sb_upcallarg ; mtx_lock ( & cs -> cs_lock ) ; cs -> cs_refs ++ ; mtx_unlock ( & cs -> cs_lock ) ; } else { SOCKBUF_UNLOCK ( & so -> so_rcv ) ; cs = mem_alloc ( sizeof ( * cs ) ) ; SOCKBUF_LOCK ( & so -> so_rcv ) ; if ( sb -> sb_upcall ) { mem_free ( cs , sizeof ( * cs ) ) ; goto recheck_socket ; } mtx_init ( & cs -> cs_lock , " " , NULL , MTX_DEF ) ; cs -> cs_refs = 1 ; cs -> cs_upcallrefs = 0 ; TAILQ_INIT ( & cs -> cs_pending ) ; soupcall_set ( so , SO_RCV , clnt_dg_soupcall , cs ) ; } SOCKBUF_UNLOCK ( & so -> so_rcv ) ; cl -> cl_refs = 1 ; cl -> cl_ops = & clnt_dg_ops ; cl -> cl_private = ( caddr_t ) ( void * ) cu ; cl -> cl_auth = authnone_create ( ) ; cl -> cl_tp = NULL ; cl -> cl_netid = NULL ; return ( cl ) ; err2 : mem_free ( cl , sizeof ( CLIENT ) ) ; mem_free ( cu , sizeof ( * cu ) ) ; return ( NULL ) ; }
Connection less client creation returns with client handle parameters.
Connection less client creation returns with client handle parameters .
/* servers address */ /* program number */ /* version number */ /* buffer recv size */ /* buffer send size */ /* client handle */ /* private data */ /*
	 * Find the receive and the send size
	 */ /* XXX */ /*
	 * Should be multiple of 4 for XDR.
	 */ /* Other values can also be set through clnt_control() */ /* heuristically chosen */ /* XXX */ /*
	 * By default, closeit is always FALSE. It is users responsibility
	 * to do a close on it, else the user may use clnt_control
	 * to let clnt_destroy do it for him/her.
	 */ /*
		 * We are the first on this socket - allocate the
		 * structure and install it in the socket.
		 */ /*
			 * We have lost a race with some other client.
			 */