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

📄 xnet.c

📁 This a separate release of the OpenSS7 X/Open XTI/TLI library, TLI modules (timod, tirdwr) and the I
💻 C
📖 第 1 页 / 共 5 页
字号:
					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;      tbadf:	t_errno = TBADF;	goto error;      error:	return ((char *) NULL);}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);}char *t_alloc(int fd, int type, int fields)    __attribute__ ((alias("__xnet_t_alloc_r")));/** * @fn int t_bind(int fd, const struct t_bind *req, struct t_bind *ret) * @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. * * 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);}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);}int t_bind(int fd, const struct t_bind *req, struct t_bind *ret)    __attribute__ ((alias("__xnet_t_bind_r")));/** * @fn int t_close(int fd) * @brief Close a transport endpoint. * @param fd A file descriptor for the transport endpoint to close. * * 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. * * 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);}int t_close(int fd)    __attribute__ ((alias("__xnet_t_close_r")));/** * @fn int t_connect(int fd, const struct t_call *sndcall, struct t_call *rcvcall) * @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;		req.prim.DEST_offset = add_len ? sizeof(req.prim) : 0;		req.prim.OPT_length = opt_len;		req.prim.OPT_offset = opt_len ? sizeof(req.prim) + add_len : 0;		if (add_len)			memcpy(req.addr, sndcall->addr.buf, add_len);		if (opt_len)			memcpy(req.addr + add_len, sndcall->opt.buf, opt_len);		if (dat_len)			memcpy(req.addr + add_len + opt_len, sndcall->udata.buf, dat_len);		if (__xnet_t_strioctl(fd, TI_SETPEERNAME, &req, sizeof(req)))			goto error;		__xnet_u_setstate_const(user, TS_WCON_CREQ);	}	return __xnet_t_rcvconnect(fd, rcvcall);      tlook:	t_errno = TLOOK;	goto error;#ifdef DEBUG      einval:	errno = EINVAL;	goto tsyserr;      tsyserr:	t_errno = TSYSERR;	goto error;#endif      tbadaddr:	t_errno = TBADADDR;	goto error;      tbadopt:	t_errno = TBADOPT;	goto error;      tbaddata:	t_errno = TBADDATA;	goto error;      error:	if (t_errno != TLOOK && __xnet_t_peek(fd) > 0)		goto tlook;	return (-1);}int__xnet_t_connect_r(int fd, const struct t_call *sndcall, struct t_call *rcvcall){	int ret = -1;	pthread_cleanup_push_defer_np(__xnet_t_putuser, &fd);	if (__xnet_t_getuser(fd)) {		if ((ret = __xnet_t_connect(fd, sndcall, rcvcall)) == -1)			pthread_testcancel();		__xnet_t_putuser(&fd);	} else		pthread_testcancel();	pthread_cleanup_pop_restore_np(0);	return (ret);}int t_connect(int fd, const struct t_call *sndcall, struct t_call *rcvcall)    __attribute__ ((alias("__xnet_t_connect_r")));/** * @fn int t_error(const char *errmsg) * @brief Print an error message. * @param errmsg the error message to print. * * This function is NOT a thread cancellation point. */int__xnet_t_error(const char *errmsg){	fprintf(stderr, "%s: %s\n", errmsg, __xnet_t_strerror(t_errno));}int__xnet_t_error_r(const char *errmsg){	int oldtype, ret;	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);	ret = __xnet_t_error(errmsg);	pthread_setcanceltype(oldtype, NULL);	return (ret);}int t_error(const char *errmsg)    __attribute__ ((alias("__xnet_t_error_r")));/** * @fn int t_free(void *ptr, int type) * @brief free an XTI library structure. * @param ptr a pointer to the structure to free. * @param type the type of the structure pointed to. * * This function is NOT a thread cancellation point. * * Frees the specified datastructure.  Any buffers remaining in the * datastructure (with non-NULL netbuf buf elements) will be freed using * free(2) as well.  This can be used to free a structure allocated with * malloc(2) and not necessarily allocated with t_alloc(3). */int__xnet_t_free(void *ptr, int type){	if (!ptr)		goto einval;	switch (type) {	case T_BIND:	{		struct t_bind *bind = (struct t_bind *) ptr;		if (bind->addr.buf)			free(bind->addr.buf);		free(bind);		return (0);	}	case T_OPTMGMT:	{		struct t_optmgmt *opts = (struct t_optmgmt *) ptr;		if (opts->opt.buf)			free(opts->opt.buf);		free(opts);		return (0);	}	case T_CALL:	{		struct t_call *call = (struct t_call *) ptr;		if (call->addr.buf)			free(call->addr.buf);		if (call->opt.buf)			free(call->opt.buf);		if (call->udata.buf)			free(call->udata.buf);		free(call);		return (0);	}	case T_DIS:	{		struct t_discon *discon = (struct t_discon *) ptr;		if (discon->udata.buf)			free(discon->udata.buf);		free(discon);		return (0);	}	case T_UNITDATA:	{		struct t_unitdata *unitdata = (struct t_unitdata *) ptr;		if (unitdata->addr.buf)			free(unitdata->addr.buf);		if (unitdata->opt.buf)			free(unitdata->opt.buf);		if (unitdata->udata.buf)			free(unitdata->udata.buf);		return (0);	}	case T_UDERROR:	{		struct t_uderr *uderr = (struct t_uderr *) ptr;		if (uderr->addr.buf)			free(uderr->addr.buf);		if (uderr->opt.buf)			free(uderr->opt.buf);		free(uderr);		return (0);	}	case T_INFO:	{		struct t_info *info = (struct t_info *) ptr;		free(info);		return (0);	}	default:		goto tnostructype;	}      tnostructype:	t_errno = TNOSTRUCTYPE;	goto error;      einval:	errno = EINVAL;	goto tsyserr;      tsyserr:	t_errno = TSYSERR;	goto error;      error:	return (-1);}int t_free(void *ptr, int type)    __attribute__ ((alias("__xnet_t_free")));/** * @fn int t_getinfo(int fd, struct t_info *info)

⌨️ 快捷键说明

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