ONC+ Developer's Guide

Server Side of the Expert-Level Interface

Example 4–13 shows the server side of Example 4–12. It is called svcudp_create(). The server side uses svc_tli_create().

svc_tli_create() is used when the application needs a fine degree of control, particularly to:

Use rpcb_set() to register the service with rpcbind.


Example 4–13 Server for RPC Lower Level

#include <stdio.h>

#include <rpc/rpc.h>
#include <netconfig.h>

#include <netinet/in.h>
 
SVCXPRT *
svcudp_create(fd)
	register int fd;
{
	struct netconfig *nconf;
	SVCXPRT *svc;
	int madefd = FALSE;
	int port;
	void *handlep;
	struct  t_info tinfo;
 
	/* If no transports available */
	if ((handlep = setnetconfig() ) == (void *) NULL) {
		nc_perror("server");
		return((SVCXPRT *) NULL);
	}
	/*
	 * Try all the transports until it gets one which is
	 * connectionless, family is INET and, name is UDP
	 */
	while (nconf = getnetconfig( handlep)) {
		if ((nconf->nc_semantics == NC_TPI_CLTS) &&

		    (strcmp( nconf->nc_protofmly, NC_INET) == 0 )&&
		    (strcmp( nconf->nc_proto, NC_UDP) == 0 ))
			break;
	}
	if (nconf == (struct netconfig *) NULL) {
		endnetconfig(handlep);
		return((SVCXPRT *) NULL);
	}
	if (fd == RPC_ANYFD) {
		fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
		if (fd == -1) {
			(void) endnetconfig();
			return((SVCXPRT *) NULL);
		}
		madefd = TRUE;
	} else
		t_getinfo(fd, &tinfo);
	svc = svc_tli_create(fd, nconf, (struct t_bind *) NULL,
	                      tinfo.tsdu, tinfo.tsdu);
	(void) endnetconfig(handlep);
	if (svc == (SVCXPRT *) NULL) {
		if (madefd)
			(void) t_close(fd);
		return((SVCXPRT *)NULL);
	}
	return (svc);
}

The network selection here is accomplished similar to clntudp_create(). The file descriptor is not bound explicitly to a transport address because svc_tli_create() does that.

svcudp_create() can use an open fd. It opens one itself using the selected netconfig structure if none is provided.