⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clnt_udp.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!timerisset(&timeout)) {		if (fds != &readfds)			free(fds);		return (cu->cu_error.re_status = RPC_TIMEDOUT);	}	/*	 * sub-optimal code appears here because we have	 * some clock time to spare while the packets are in flight.	 * (We assume that this is actually only executed once.)	 */	reply_msg.acpted_rply.ar_verf = _null_auth;	reply_msg.acpted_rply.ar_results.where = resultsp;	reply_msg.acpted_rply.ar_results.proc = xresults;	gettimeofday(&start, NULL);	for (;;) {		/* XXX we know the other bits are still clear */		FD_SET(cu->cu_sock, fds);		tv = cu->cu_wait;		switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {		case 0:			timeradd(&time_waited, &cu->cu_wait, &tmp1);			time_waited = tmp1;			if (timercmp(&time_waited, &timeout, <))				goto send_again;			if (fds != &readfds)				free(fds);			return (cu->cu_error.re_status = RPC_TIMEDOUT);		case -1:			if (errno == EINTR) {				gettimeofday(&after, NULL);				timersub(&after, &start, &tmp1);				timeradd(&time_waited, &tmp1, &tmp2);				time_waited = tmp2;				if (timercmp(&time_waited, &timeout, <))					continue;				if (fds != &readfds)					free(fds);				return (cu->cu_error.re_status = RPC_TIMEDOUT);			}			cu->cu_error.re_errno = errno;			if (fds != &readfds)				free(fds);			return (cu->cu_error.re_status = RPC_CANTRECV);		}		do {			fromlen = sizeof(struct sockaddr);			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,				(int) cu->cu_recvsz, 0,				(struct sockaddr *)&from, &fromlen);		} while (inlen < 0 && errno == EINTR);		if (inlen < 0) {			if (errno == EWOULDBLOCK)				continue;			cu->cu_error.re_errno = errno;			if (fds != &readfds)				free(fds);			return (cu->cu_error.re_status = RPC_CANTRECV);		}		if (inlen < sizeof(u_int32_t))			continue;		/* see if reply transaction id matches sent id */		if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))			continue;		/* we now assume we have the proper reply */		break;	}	/*	 * now decode and validate the response	 */	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);	ok = xdr_replymsg(&reply_xdrs, &reply_msg);	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */	if (ok) {		_seterr_reply(&reply_msg, &(cu->cu_error));		if (cu->cu_error.re_status == RPC_SUCCESS) {			if (! AUTH_VALIDATE(cl->cl_auth,				&reply_msg.acpted_rply.ar_verf)) {				cu->cu_error.re_status = RPC_AUTHERROR;				cu->cu_error.re_why = AUTH_INVALIDRESP;			}			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {				xdrs->x_op = XDR_FREE;				(void)xdr_opaque_auth(xdrs,				    &(reply_msg.acpted_rply.ar_verf));			}		}  /* end successful completion */		else {			/* maybe our credentials need to be refreshed ... */			if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {				nrefreshes--;				goto call_again;			}		}  /* end of unsuccessful completion */	}  /* end of valid reply message */	else {		/*		 * It's possible for xdr_replymsg() to fail partway		 * through its attempt to decode the result from the		 * server. If this happens, it will leave the reply		 * structure partially populated with dynamically		 * allocated memory. (This can happen if someone uses		 * clntudp_bufcreate() to create a CLIENT handle and		 * specifies a receive buffer size that is too small.)		 * This memory must be free()ed to avoid a leak.		 */		int op = reply_xdrs.x_op;		reply_xdrs.x_op = XDR_FREE;		xdr_replymsg(&reply_xdrs, &reply_msg);		reply_xdrs.x_op = op;		cu->cu_error.re_status = RPC_CANTDECODERES;	}	if (fds != &readfds)		free(fds);	return (cu->cu_error.re_status);}static voidclntudp_geterr(cl, errp)	CLIENT *cl;	struct rpc_err *errp;{	register struct cu_data *cu = (struct cu_data *)cl->cl_private;	*errp = cu->cu_error;}static bool_tclntudp_freeres(cl, xdr_res, res_ptr)	CLIENT *cl;	xdrproc_t xdr_res;	caddr_t res_ptr;{	register struct cu_data *cu = (struct cu_data *)cl->cl_private;	register XDR *xdrs = &(cu->cu_outxdrs);	xdrs->x_op = XDR_FREE;	return ((*xdr_res)(xdrs, res_ptr));}static voidclntudp_abort(/*h*/)	/*CLIENT *h;*/{}static bool_tclntudp_control(cl, request, info)	CLIENT *cl;	int request;	char *info;{	register struct cu_data *cu = (struct cu_data *)cl->cl_private;	register struct timeval *tv;	int len;	switch (request) {	case CLSET_FD_CLOSE:		cu->cu_closeit = TRUE;		break;	case CLSET_FD_NCLOSE:		cu->cu_closeit = FALSE;		break;	case CLSET_TIMEOUT:		if (info == NULL)			return(FALSE);		tv = (struct timeval *)info;		cu->cu_total.tv_sec = tv->tv_sec;		cu->cu_total.tv_usec = tv->tv_usec;		break;	case CLGET_TIMEOUT:		if (info == NULL)			return(FALSE);		*(struct timeval *)info = cu->cu_total;		break;	case CLSET_RETRY_TIMEOUT:		if (info == NULL)			return(FALSE);		tv = (struct timeval *)info;		cu->cu_wait.tv_sec = tv->tv_sec;		cu->cu_wait.tv_usec = tv->tv_usec;		break;	case CLGET_RETRY_TIMEOUT:		if (info == NULL)			return(FALSE);		*(struct timeval *)info = cu->cu_wait;		break;	case CLGET_SERVER_ADDR:		if (info == NULL)			return(FALSE);		*(struct sockaddr_in *)info = cu->cu_raddr;		break;	case CLGET_FD:		if (info == NULL)			return(FALSE);		*(int *)info = cu->cu_sock;		break;	case CLGET_XID:		/*		 * use the knowledge that xid is the		 * first element in the call structure *.		 * This will get the xid of the PREVIOUS call		 */		if (info == NULL)			return(FALSE);		*(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);		break;	case CLSET_XID:		/* This will set the xid of the NEXT call */		if (info == NULL)			return(FALSE);		*(u_long *)cu->cu_outbuf =  htonl(*(u_long *)info - 1);		/* decrement by 1 as clntudp_call() increments once */	case CLGET_VERS:		/*		 * This RELIES on the information that, in the call body,		 * the version number field is the fifth field from the		 * begining of the RPC header. MUST be changed if the		 * call_struct is changed		 */		if (info == NULL)			return(FALSE);		*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +						4 * BYTES_PER_XDR_UNIT));		break;	case CLSET_VERS:		if (info == NULL)			return(FALSE);		*(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)				= htonl(*(u_long *)info);		break;	case CLGET_PROG:		/*		 * This RELIES on the information that, in the call body,		 * the program number field is the  field from the		 * begining of the RPC header. MUST be changed if the		 * call_struct is changed		 */		if (info == NULL)			return(FALSE);		*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +						3 * BYTES_PER_XDR_UNIT));		break;	case CLSET_PROG:		if (info == NULL)			return(FALSE);		*(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)				= htonl(*(u_long *)info);		break;	case CLGET_LOCAL_ADDR:		len = sizeof(struct sockaddr);		if (getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0)			return(FALSE);		break;	case CLGET_SVC_ADDR:	case CLSET_SVC_ADDR:	case CLSET_PUSH_TIMOD:	case CLSET_POP_TIMOD:	default:		return (FALSE);	}	return (TRUE);}static voidclntudp_destroy(cl)	CLIENT *cl;{	register struct cu_data *cu = (struct cu_data *)cl->cl_private;	if (cu->cu_closeit) {		(void)_RPC_close(cu->cu_sock);	}	XDR_DESTROY(&(cu->cu_outxdrs));	mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));	mem_free((caddr_t)cl, sizeof(CLIENT));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -