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

📄 xnet.c

📁 OpenSS7 This the fourth public release of the OpenSS7 Master Package. See README in the release for
💻 C
📖 第 1 页 / 共 5 页
字号:
			switch (user->prim) {			case -1:	/* just data */				user->moredat = ((ret & MOREDATA) != 0);				break;			case T_DATA_IND:				user->moresdu = (p->data_ind.MORE_flag != 0);				user->moredat = ((ret & MOREDATA) != 0);				break;			case T_EXDATA_IND:				user->moreedu = (p->exdata_ind.MORE_flag != 0);				user->moreexp = ((ret & MOREDATA) != 0);				break;			case T_OPTDATA_IND:				if (p->optdata_ind.DATA_flag & T_ODF_EX) {					user->moreedu =					    ((p->optdata_ind.DATA_flag & T_ODF_MORE) != 0);					user->moreexp = ((ret & MOREDATA) != 0);				} else {					user->moresdu =					    ((p->optdata_ind.DATA_flag & T_ODF_MORE) != 0);					user->moredat = ((ret & MOREDATA) != 0);				}				break;			case T_UNITDATA_IND:				user->moresdu = 0;				user->moredat = ((ret & MOREDATA) != 0);				user->moreedu = 0;				user->moreexp = 0;				break;			case T_CONN_IND:			case T_CONN_CON:			case T_DISCON_IND:			case T_ORDREL_IND:			case T_UDERROR_IND:				user->moremsg = ((ret & MOREDATA) != 0);				break;			}			if ((user->event & expect))				user->data.len = 0;	/* consumed */			else {				/* 				   didn't get what we were expecting, so we need to move any data				   from the user buffer back to the look buffer */				if (user->data.len > 0)					memcpy(user->datbuf, user->data.buf, user->data.len);				user->data.buf = user->datbuf;				udata->len = 0;			}		}	} else		goto tlook;      done:	return (user->event);      cleanup:	while (ret != -1 && (ret & (MORECTL | MOREDATA)))		ret = __xnet_t_getmsg(fd, &user->ctrl, &user->data, &flag);	goto tsync;      tlook:	t_errno = TLOOK;	goto error;      tsync:	__xnet_u_reset_event(user);	/* discard current event */	user->flags |= TUF_SYNC_REQUIRED;	goto tproto;      tproto:	t_errno = TPROTO;	goto error;      error:	return (-1);}/**  * @internal  * @brief Get the next event on the transport endpoint.  * @param fd a file descriptor for the transport endpoint.  *  * Returns the current, or obtains the current, event for the transport  * endpoing and completes elements in the user data structure representing the  * transport endpoint.  The control and data parts of any retrieved messages  * are cached in the user structure and information interpreted and  * appropriate flags set.  */static int__xnet_t_getevent(int fd){	struct _t_user *user = _t_fds[fd];	int ret, flag = 0;	union T_primitives *p = (typeof(p)) user->ctlbuf;	switch (user->event) {	case 0:		__xnet_u_reset_event(user);		if ((ret = __xnet_t_getmsg(fd, &user->ctrl, &user->data, &flag)) < 0)			goto error;		if (ret & MORECTL)			goto cleanup;		if (flag != 0 || flag == RS_HIPRI)			goto tsync;		if (user->ctrl.len || user->data.len) {			__xnet_u_setevent(user, user->ctrl.len ? p->type : -1, 0);			/* 			   There is a little extra handling for data indications */			switch (user->prim) {			case -1:	/* just data */				user->moredat = ((ret & MOREDATA) != 0);				break;			case T_DATA_IND:				user->moresdu = (p->data_ind.MORE_flag != 0);				user->moredat = ((ret & MOREDATA) != 0);				break;			case T_EXDATA_IND:				user->moreedu = (p->exdata_ind.MORE_flag != 0);				user->moreexp = ((ret & MOREDATA) != 0);				break;			case T_OPTDATA_IND:				if (p->optdata_ind.DATA_flag & T_ODF_EX) {					user->moreedu =					    ((p->optdata_ind.DATA_flag & T_ODF_MORE) != 0);					user->moreexp = ((ret & MOREDATA) != 0);				} else {					user->moresdu =					    ((p->optdata_ind.DATA_flag & T_ODF_MORE) != 0);					user->moredat = ((ret & MOREDATA) != 0);				}				break;			case T_UNITDATA_IND:				user->moresdu = 0;				user->moredat = ((ret & MOREDATA) != 0);				user->moreedu = 0;				user->moreexp = 0;				break;			case T_CONN_IND:			case T_CONN_CON:			case T_DISCON_IND:			case T_ORDREL_IND:			case T_UDERROR_IND:				user->moremsg = ((ret & MOREDATA) != 0);				break;			}		}	}	return (user->event);      cleanup:	while (ret != -1 && (ret & (MORECTL | MOREDATA)))		ret = __xnet_t_getmsg(fd, &user->ctrl, &user->data, &flag);	goto tsync;      tsync:	__xnet_u_reset_event(user);	/* discard current event */	user->flags |= TUF_SYNC_REQUIRED;	goto tproto;      tproto:	t_errno = TPROTO;	goto error;      error:	return (-1);}static pthread_rwlock_t __xnet_fd_lock = PTHREAD_RWLOCK_INITIALIZER;static inline int__xnet_lock_rdlock(pthread_rwlock_t * rwlock){	return pthread_rwlock_rdlock(rwlock);}static inline int__xnet_lock_wrlock(pthread_rwlock_t * rwlock){	return pthread_rwlock_wrlock(rwlock);}static inline void__xnet_lock_unlock(void *rwlock){	pthread_rwlock_unlock(rwlock);}static inline int__xnet_list_rdlock(void){	return __xnet_lock_rdlock(&__xnet_fd_lock);}static int__xnet_list_wrlock(void){	return __xnet_lock_wrlock(&__xnet_fd_lock);}static void__xnet_list_unlock(void *ignore){	return __xnet_lock_unlock(&__xnet_fd_lock);}#if 0static int__xnet_user_rdlock(struct _t_user *user){	return __xnet_lock_rdlock(&user->lock);}#endifstatic inline int__xnet_user_wrlock(struct _t_user *user){	return __xnet_lock_wrlock(&user->lock);}static inline void__xnet_user_unlock(struct _t_user *user){	return __xnet_lock_unlock(&user->lock);}static void__xnet_t_putuser(void *arg){	int fd = *(int *) arg;	struct _t_user *user = _t_fds[fd];	__xnet_user_unlock(user);	__xnet_list_unlock(NULL);	return;}/**  * @internal  * @brief Get a locked transport user endpoint structure.  * @param fd the file descriptor for which to get the associated endpoint.  *  * This is a range-checked array lookup of the library user structure  * associated with the specified file descriptor.  In addition, this function  * takes the necessary locks for thread-safe operation.  */static __hot struct _t_user *__xnet_t_getuser(int fd){	struct _t_user *user;	int err;	if (unlikely((err = __xnet_list_rdlock())))		goto list_lock_error;	if (unlikely(0 > fd) || unlikely(fd >= OPEN_MAX))		goto tbadf;	if (unlikely(!(user = _t_fds[fd])))		goto tbadf;	if (unlikely((err = __xnet_user_wrlock(user))))		goto user_lock_error;	return (user);      user_lock_error:	t_errno = TSYSERR;	errno = err;	__xnet_list_unlock(NULL);	goto error;      tbadf:	t_errno = TBADF;	goto error;      list_lock_error:	t_errno = TSYSERR;	errno = err;	goto error;      error:	return (NULL);}/**  * @internal  * @brief Test information about a transport endpoint.  * @param fd the file descriptor for which to test the associated endpoint.  * @param expect the event anticipated on the transport endpoint.  * @param servtype the service type anticipated on the transport endpoint.  * @param states the flag mask of the states anticipated for the transport endpoint.  *  * This is a range-checked array lookup of the library user structure  * associated with the specified file descriptor.  In addition, this function  * checks for expected events, service types and states as follows:  *  * When expect is not -1, if there is a current event on the transport  * endpoint and that event is not the same as the expected event, then the  * call will fail (return NULL) and set t_errno to @c T_LOOK.  *  * servtype is a bit mask of the service types expected for the transport  * endpoint.  If the service type of the transport endpoint is not one of the  * service types in the mask, then the call will fail (return NULL) and set  * t_errno to @c TNOTSUPPORT.  To accept any service type, set servtype to -1.  *  * states is a bit mask of the (TPI) states expected for the transport  * endpoint.  If the state of the transport endpoing is not one of the states  * in the mask, then the call will fail (return NULL) and set t_errno to  * @c TOUTSTATE.  To accept any state, set states to -1.  */static __hot struct _t_user *__xnet_t_tstuser(int fd, const int expect, const int servtype, const int states){	struct _t_user *user;	if (unlikely(0 > fd) || unlikely(fd >= OPEN_MAX))		goto tbadf;	if (unlikely(!(user = _t_fds[fd])))		goto tbadf;	if (unlikely(user->flags & TUF_SYNC_REQUIRED))		goto tproto;	if (unlikely(user->event && user->event != expect && expect != -1))		goto tlook;	if (unlikely(!((1 << user->info.servtype) & servtype)))		goto tnotsupport;	if (unlikely(!(user->statef & states)))		goto toutstate;	return (user);      toutstate:	t_errno = TOUTSTATE;	goto error;      tnotsupport:	t_errno = TNOTSUPPORT;	goto error;      tlook:	t_errno = TLOOK;	goto error;      tproto:	t_errno = TPROTO;	goto error;      tbadf:	t_errno = TBADF;	goto error;      error:	return (NULL);}/**  * @internal  * @brief A version of ioctl(2) with XTI errors.  * @param fd A file descriptor upon which to issue an IO control.  * @param cmd The IO control command.  * @param arg Argument to the IO control command.  *  * Our timod @c TI_ ioctls return the error codes (if any) in the return value  * rather than errno.  If we get a non-zero return value, it indicates that we  * need to unpack the ti and unix error codes and place them in the  * appropriate error numbers.  */static int__xnet_t_ioctl(int fd, int cmd, void *arg){	int ret;	switch ((ret = ioctl(fd, cmd, arg))) {	case 0:		return (0);	case -1:		switch (errno) {		case EBADF:		case ENOTTY:		case EINVAL:		case EPERM:			t_errno = TBADF;			break;		default:			t_errno = TSYSERR;			break;		}		return (-1);	default:		if ((t_errno = ret & 0x00ff) == TSYSERR)			if (!(errno = (ret >> 8) & 0x00ff))				errno = EINVAL;		return (-1);	}}/**  * @internal  * @brief A version of ioctl(2) with XTI errors.  * @param fd A file descriptor upon which to issue an IO control.  * @param cmd The IO control command.  * @param arg Argument to the IO control command.  * @param arglen The length of the argument.  *  * This is a simple matter of packing an otherwise tranparent IO control into  * a strioctl buffer and issuing an I_STR IO control instead.  This calls  * __xnet_t_ioctl(), so it understands how to properly unpack timod XTI and UNIX  * error codes.  */static int__xnet_t_strioctl(int fd, int cmd, void *arg, size_t arglen){	struct strioctl ioc;	ioc.ic_cmd = cmd;	ioc.ic_timout = _T_TIMEOUT;	ioc.ic_len = arglen;	ioc.ic_dp = arg;	return __xnet_t_ioctl(fd, I_STR, &ioc);}/** @brief Accept a connection indication.  * @param fd the file descriptor upon which the connection indication was received.  * @param resfd the file descriptor upon which to accept the transport connection.  * @param call a pointer to a t_call structure describing the responding transport endpoint.  */int__xnet_t_accept(int fd, int resfd, const struct t_call *call){	struct _t_user *user, *resuser;	if (!(user = __xnet_t_tstuser(fd, 0, (1 << T_COTS) | (1 << T_COTS_ORD), TSF_WRES_CIND)))		goto error;	if (fd == resfd) {		resuser = user;		if (user->ocnt > 1)			goto tindout;		if (user->ocnt < 1)			goto tproto;	} else	    if (!(resuser = __xnet_t_tstuser(resfd, 0, (1 << T_COTS) | (1 << T_COTS_ORD),					     TSF_UNBND | TSF_IDLE)))		goto error;	if (__xnet_t_peek(fd) > 0)		goto tlook;	if (__xnet_t_peek(resfd) > 0)		goto tlook;#ifdef DEBUG	if (!call)		goto einval;	if (call->addr.len < 0 || (call->addr.len > 0 && !call->addr.buf))		goto einval;	if (call->opt.len < 0 || (call->opt.len > 0 && !call->opt.buf))		goto einval;	if (call->udata.len < 0 || (call->udata.len > 0 && !call->udata.buf))		goto einval;#endif	if (call && call->addr.len > __xnet_u_max_addr(user))		goto tbadaddr;	if (call && call->opt.len > __xnet_u_max_options(user))		goto tbadopt;	if (call && call->udata.len > __xnet_u_max_connect(user))		goto tbaddata;	/* 	   Check if we need to bind the responding stream to the responding address.  This also	   rules out the case where the listening stream and the responding stream are the same	   address. */	if (resuser->statef & TSF_UNBND) {		size_t add_len = (call && call->addr.len > 0) ? call->addr.len : 0;		struct {			struct T_bind_req prim;			unsigned char addr[add_len];		} req;

⌨️ 快捷键说明

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