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

📄 xnet.c

📁 OpenSS7 This the fourth public release of the OpenSS7 Master Package. See README in the release for
💻 C
📖 第 1 页 / 共 5 页
字号:
			switch ((len = user->info.discon)) {			case T_INFINITE:				len = _T_DEFAULT_DISCLEN;;			default:				if (!(discon->udata.buf = (char *) malloc(len))) {					free(discon);					goto badalloc;				}				discon->udata.maxlen = len;			case 0:				break;			case T_INVALID:				if (fields != T_ALL) {					free(discon);					goto einval;				}				break;			}		}		return ((char *) discon);	}	case T_UNITDATA:	{		struct t_unitdata *udata;		if (user->info.servtype != T_CLTS)			goto tnostructype;		if (!(udata = (struct t_unitdata *) malloc(sizeof(*udata))))			goto badalloc;		memset(udata, 0, sizeof(*udata));		if (fields & T_ADDR) {			int len;			switch ((len = user->info.addr)) {			case T_INFINITE:				len = _T_DEFAULT_ADDRLEN;			default:				if (!(udata->addr.buf = (char *) malloc(len))) {					free(udata);					goto badalloc;				}				udata->addr.maxlen = len;			case 0:				break;			case T_INVALID:				if (fields != T_ALL) {					free(udata);					goto einval;				}				break;			}		}		if (fields & T_OPT) {			int len;			switch ((len = user->info.options)) {			case T_INFINITE:				len = _T_DEFAULT_OPTLEN;			default:				if (!(udata->opt.buf = (char *) malloc(len))) {					if (udata->addr.buf)						free(udata->addr.buf);					free(udata);					goto badalloc;				}				udata->opt.maxlen = len;			case 0:				break;			case T_INVALID:				if (fields != T_ALL) {					if (udata->addr.buf)						free(udata->addr.buf);					free(udata);					goto einval;				}				break;			}		}		if (fields & T_UDATA) {			int len;			switch ((len = user->info.tsdu)) {			case T_INFINITE:			case 0:				len = _T_DEFAULT_DATALEN;			default:				if (!(udata->udata.buf = (char *) malloc(len))) {					if (udata->addr.buf)						free(udata->addr.buf);					if (udata->opt.buf)						free(udata->opt.buf);					free(udata);					goto badalloc;				}				udata->udata.maxlen = len;				break;			case T_INVALID:				if (fields != T_ALL) {					if (udata->addr.buf)						free(udata->addr.buf);					if (udata->opt.buf)						free(udata->opt.buf);					free(udata);					goto einval;				}				break;			}		}		return ((char *) udata);	}	case T_UDERROR:	{		struct t_uderr *uderr;		if (user->info.servtype != T_CLTS)			goto tnostructype;		if (!(uderr = (struct t_uderr *) malloc(sizeof(*uderr))))			goto badalloc;		memset(uderr, 0, sizeof(*uderr));		if (fields & T_ADDR) {			int len;			switch ((len = user->info.addr)) {			case T_INFINITE:				len = _T_DEFAULT_ADDRLEN;			default:				if (!(uderr->addr.buf = (char *) malloc(len))) {					free(uderr);					goto badalloc;				}				uderr->addr.maxlen = len;			case 0:				break;			case T_INVALID:				if (fields != T_ALL) {					free(uderr);					goto einval;				}				break;			}		}		if (fields & T_OPT) {			int len;			switch ((len = user->info.options)) {			case T_INFINITE:				len = _T_DEFAULT_OPTLEN;			default:				if (!(uderr->opt.buf = (char *) malloc(len))) {					if (uderr->addr.buf)						free(uderr->addr.buf);					free(uderr);					goto badalloc;				}				uderr->opt.maxlen = len;			case 0:				break;			case T_INVALID:				if (fields != T_ALL) {					if (uderr->addr.buf)						free(uderr->addr.buf);					free(uderr);					goto einval;				}				break;			}		}		return ((char *) uderr);	}	case T_INFO:	{		struct t_info *inf;		if (!(inf = (struct t_info *) malloc(sizeof(*inf))))			goto badalloc;		memset(inf, 0, sizeof(*inf));		return ((char *) inf);	}	default:		goto tnostructype;	}      tnostructype:	t_errno = TNOSTRUCTYPE;	goto error;      einval:	t_errno = TSYSERR;	errno = EINVAL;	goto error;      badalloc:	t_errno = TSYSERR;	goto error;      error:	return ((char *) NULL);}/** The reentrant version of __xnet_t_alloc(). */char *__xnet_t_alloc_r(int fd, int type, int fields){	char *ret = NULL;	pthread_cleanup_push_defer_np(__xnet_t_putuser, &fd);	if (__xnet_t_getuser(fd)) {		ret = __xnet_t_alloc(fd, type, fields);		__xnet_t_putuser(&fd);	}	pthread_cleanup_pop_restore_np(0);	return (ret);}__asm__(".symver __xnet_t_alloc_r,t_alloc@@XNET_1.0");/** @brief Bind an address to a transport endpoint.  * @param fd A file descriptor indicating the transport endpoint to bind.  * @param req A t_bind structure indicating the bind parameters.  * @param ret A t_bind structure to return the bind result.  * @version XNET_1.0  * @par Alias:  * This function is an implementation of t_bind().  *  * This function is NOT a thread cancellation point.  * t_bind() is NOT a thread cancellation point; however, ioctl(2) might be;  * therefore, we disable cancellation for the duration of the call.  */int__xnet_t_bind(int fd, const struct t_bind *req, struct t_bind *ret){	struct _t_user *user;	if (!(user = __xnet_t_tstuser(fd, 0, -1, TSF_UNBND)))		goto error;#ifdef DEBUG	if (req && (req->addr.len < 0 || (req->addr.len > 0 && !req->addr.buf)))		goto einval;	if (ret && (req->addr.maxlen < 0 || (ret->addr.maxlen > 0 && !ret->addr.buf)))		goto einval;#endif	if (req && req->addr.len > __xnet_u_max_addr(user))		goto tbadaddr;	{		size_t add_len = (req && req->addr.len > 0) ? req->addr.len : 0;		size_t add_max = min(__xnet_u_max_addr(user), _T_DEFAULT_ADDRLEN);		size_t qlen = (req && req->qlen > 0) ? req->qlen : 0;		union {			struct {				struct T_bind_req prim;				unsigned char addr[add_len];			} req;			struct {				struct T_bind_ack prim;				unsigned char addr[add_max];			} ack;		} buf;		buf.req.prim.PRIM_type = T_BIND_REQ;		buf.req.prim.ADDR_length = add_len;		buf.req.prim.ADDR_offset = add_len ? sizeof(buf.req.prim) : 0;		buf.req.prim.CONIND_number = qlen;		if (add_len)			memcpy(buf.req.addr, req->addr.buf, add_len);		if (__xnet_t_strioctl(fd, TI_BIND, &buf, sizeof(buf)) != 0)			goto error;		__xnet_u_setstate_const(user, TS_IDLE);		user->qlen = buf.ack.prim.CONIND_number;		if (ret) {			if (ret->addr.maxlen > 0) {				if (ret->addr.maxlen < buf.ack.prim.ADDR_length)					goto tbufovflw;				if ((ret->addr.len = buf.ack.prim.ADDR_length))					memcpy(ret->addr.buf,					       ((char *) &buf) + buf.ack.prim.ADDR_offset,					       ret->addr.len);			}			ret->qlen = buf.ack.prim.CONIND_number;		}		return (0);	}      tbufovflw:	t_errno = TBUFOVFLW;	goto error;      tbadaddr:	t_errno = TBADADDR;	goto error;#ifdef DEBUG      einval:	errno = EINVAL;	goto tsyserr;      tsyserr:	t_errno = TSYSERR;	goto tsyserr;#endif      error:	return (-1);}/** The reentrant version of __xnet_t_bind(). */int__xnet_t_bind_r(int fd, const struct t_bind *req, struct t_bind *ret){	int rtv = -1;	pthread_cleanup_push_defer_np(__xnet_t_putuser, &fd);	if (__xnet_t_getuser(fd)) {		rtv = __xnet_t_bind(fd, req, ret);		__xnet_t_putuser(&fd);	}	pthread_cleanup_pop_restore_np(0);	return (rtv);}__asm__(".symver __xnet_t_bind_r,t_bind@@XNET_1.0");/** @brief Close a transport endpoint.  * @param fd A file descriptor for the transport endpoint to close.  * @version XNET_1.0  *  * This function is a thread cancellation point.  t_close() is a thread  * cancellation point, and so it close(2); therefore, we defer cancellation  * until the call completes.  */int__xnet_t_close(int fd){	struct _t_user *user;	int ret;	if (!(user = __xnet_t_tstuser(fd, -1, -1, -1)))		goto error;	if ((ret = close(fd)) == 0 || errno != EINTR) {		if (--user->refs == 0) {			_t_fds[fd] = NULL;			pthread_rwlock_destroy(&user->lock);			if (user->ctlbuf)				free(user->ctlbuf);			if (user->datbuf)				free(user->datbuf);			free(user);		}	}	if (ret == 0)		return (0);	if (errno == EINTR)		t_errno = TSYSERR;      error:	return (-1);}/**  * @brief Recursive t_close function.  * @param fd A file descriptor for the transport endpoint to close.  * @version XNET_1.0  * @par Alias:  * This function is an implementation of t_close().  *  * This is again a little different that most of the _r wrappers: we take a  * write lock on the _t_fds list so that we are able to delete the file  * descriptor from the list.  This will block most other threads from  * performing functions on the list, also, we must wait for a quiet period  * until all other functions that read lock the list are not being used.  If  * you are sure that the close will only be performed by one thread and that  * no other thread will act on the file descriptor until close returns, use  * the non-recursive version.  */int__xnet_t_close_r(int fd){	int err, ret = -1;	pthread_cleanup_push_defer_np(__xnet_list_unlock, NULL);	if ((err = __xnet_list_wrlock()) == 0) {		ret = __xnet_t_close(fd);		__xnet_list_unlock(NULL);	} else {		t_errno = TSYSERR;		errno = err;	}	pthread_cleanup_pop_restore_np(0);	return (ret);}__asm__(".symver __xnet_t_close_r,t_close@@XNET_1.0");/** @brief Establish a transport connection.  * @param fd the transport endpoint to connect.  * @param sndcall a pointer to a t_call structure specifying the peer addres, options and data.  * @param rcvcall a pointer to a t_call structure returning the responding address, options and data.  *  * This function is a thread cancellation point.  */int__xnet_t_connect(int fd, const struct t_call *sndcall, struct t_call *rcvcall){	struct _t_user *user;	if (!(user = __xnet_t_tstuser(fd, 0, (1 << T_COTS) | (1 << T_COTS_ORD), TSF_IDLE)))		goto error;	if (__xnet_t_peek(fd) > 0)		goto tlook;#ifdef DEBUG	if (!sndcall)		goto einval;	if (sndcall->addr.len < 0 || (sndcall->addr.len > 0 && !sndcall->addr.buf))		goto einval;	if (sndcall->opt.len < 0 || (sndcall->opt.len > 0 && !sndcall->opt.buf))		goto einval;	if (sndcall->udata.len < 0 || (sndcall->udata.len > 0 && !sndcall->udata.buf))		goto einval;	if (rcvcall	    && (rcvcall->addr.maxlen < 0 || (rcvcall->addr.maxlen > 0 && !rcvcall->addr.buf)))		goto einval;	if (rcvcall && (rcvcall->opt.maxlen < 0 || (rcvcall->opt.maxlen > 0 && !rcvcall->opt.buf)))		goto einval;	if (rcvcall	    && (rcvcall->udata.maxlen < 0 || (rcvcall->udata.maxlen > 0 && !rcvcall->udata.buf)))		goto einval;#endif	if (sndcall && sndcall->addr.len > __xnet_u_max_addr(user))		goto tbadaddr;	if (sndcall && sndcall->opt.len > __xnet_u_max_options(user))		goto tbadopt;	if (sndcall && sndcall->udata.len > __xnet_u_max_connect(user))		goto tbaddata;	{		size_t add_len = (sndcall && sndcall->addr.len > 0) ? sndcall->addr.len : 0;		size_t opt_len = (sndcall && sndcall->opt.len > 0) ? sndcall->opt.len : 0;		size_t dat_len = (sndcall && sndcall->udata.len > 0) ? sndcall->udata.len : 0;		struct {			struct T_conn_req prim;			unsigned char addr[add_len];			unsigned char opt[opt_len];			unsigned char udata[dat_len];		} req;		req.prim.PRIM_type = T_CONN_REQ;		req.prim.DEST_length = add_len

⌨️ 快捷键说明

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