📄 xnet.c
字号:
t_errno = TINDOUT; goto error; error: if (t_errno != TLOOK && (__xnet_t_peek(fd) > 0 || __xnet_t_peek(resfd) > 0)) goto tlook; return (-1);}int__xnet_t_accept_r(int fd, int resfd, const struct t_call *call){ int ret = -1; pthread_cleanup_push_defer_np(__xnet_t_putuser, &fd); if (__xnet_t_getuser(fd)) { ret = __xnet_t_accept(fd, resfd, call); __xnet_t_putuser(&fd); } pthread_cleanup_pop_restore_np(0); return (ret);}int t_accept(int fd, int resfd, const struct t_call *call) __attribute__ ((alias("__xnet_t_accept_r")));/** * @fn int t_addleaf(int fd, int leafid, struct netbuf *addr) * @brief Add a leaf to a point to multipoint connection. * @param fd A file descriptor for the transport user endpoint. * @param leafid The identifier for the leaf. * @param addr A netbuf(3) structure describing the address of the added leaf. * * This function is NOT a thread cancellation point. * * This XTI Liubrary function is only used for ATM. It is used to add a leaf * to a point to multipoint connection. This function does not translate to * an TPI message exchange, but invokes a t_optmgmt call on an existing ATM * connection. * * t_addleaf() is NOT a thread cancellation point, but ioctl(2) is; therefore, * we disable cancellation for the duration of the call. */int__xnet_t_addleaf(int fd, int leafid, struct netbuf *addr){#if defined HAVE_XTI_ATM_H struct _t_user *user; if (!(user = __xnet_t_tstuser(fd, 0, (1 << T_COTS) | (1 << T_COTS_ORD), TSF_DATA_XFER))) goto error;#ifdef DEBUG if (!addr) goto einval; if (addr->len < 0 || (addr->len > 0 && !addr->buf)) goto einval;#endif if (!addr || addr->len < sizeof(struct t_atm_addr)) goto tbadaddr; { struct { struct t_opthdr hdr; struct t_atm_add_leaf leaf; } opts; struct t_optmgmt req, ret; req.opt.maxlen = 0; req.opt.len = sizeof(opts); req.opt.buf = (char *) &opts; req.flags = T_CURRENT; ret.opt.maxlen = sizeof(opts); ret.opt.len = 0; ret.opt.buf = (char *) &opts; ret.flags = 0; opts.hdr.len = sizeof(opts); opts.hdr.level = T_ATM_SIGNALLING; opts.hdr.name = T_ATM_ADD_LEAF; opts.hdr.status = 0; opts.leaf.leaf_ID = leafid; memcpy(&opt.leaf.leaf_address, addr->buf, addr->len); if (__xnet_t_optmgmt(fd, &req, &ret) == -1) goto error; if (ret.opt.flags == T_FAILURE) goto tproto; if (ret.opt.len < sizeof(opts) || opts.hdr.len < sizeof(opts)) goto tproto; if (opts.hdr.status != T_SUCCESS) goto tproto; if (opts.hdr.level != T_ATM_SIGNALLING || opts.hdr.name != T_ATM_ADD_LEAF) goto tproto; /** The t_addleaf function requires an operating-system specific blocking mechanism to know when to check for the leaf status indication. The most obvious approach is to have the ATM transport service provider send a signal to the stream head when an indication has arrived. What signal (SIGPOLL, SIGIO, SIGUSR) is a question. Nevertheless, we can check our open flags here and either decide to block on a poll or not to check for the indication that the addition was successful. We do not do this yet. We just always return nodata. It is the caller's responsibility to check with t_rcvleafchange(). */ goto tnodata; }#ifdef DEBUG einval: errno = EINVAL; goto tsyserr; tsyserr: t_errno = TSYSERR; goto error;#endif tnodata: t_errno = TNODATA; goto error; tbadaddr: t_errno = TBADADDR; goto error; error: return (-1);#else /* defined HAVE_XTI_ATM_H */ t_errno = TNOTSUPPORT; return (-1);#endif /* defined HAVE_XTI_ATM_H */}int__xnet_t_addleaf_r(int fd, int leafid, struct netbuf *addr){ int ret = -1; pthread_cleanup_push_defer_np(__xnet_t_putuser, &fd); if (__xnet_t_getuser(fd)) { ret = __xnet_t_addleaf(fd, leafid, addr); __xnet_t_putuser(&fd); } pthread_cleanup_pop_restore_np(0); return (ret);}int t_addleaf(int fd, int leafid, struct netbuf *addr) __attribute__ ((weak, alias("__xnet_t_addleaf_r")));/** * @fn char * t_alloc(int fd, int type, int fields) * @brief Allocate an XTI structure and initialize fields. * @param fd A file descriptor for the transport user endpoint. * @param type The type of structure to allocate. * @param fields The fields in the structure to initialize. * * This function is NOT a thread cancellation point. * * Allocate the requested library structure and initialize the requested * fields. This consists of allocating the structure itself and allocating * buffers for any of the requested fields. * * It would be more efficient if we allocated the structure and the buffers * together in a single allocation. We would probably get better memory * performance if all of the pieces were kept contiguous. However, the user * has the possibility of separately freeing the buffers and the t_free() * function does exactly that. * * t_alloc() is NOT a thread cancellation point; therefore, we defer * cancellation for the duration of the call. Note that there are no inherent * cancellation points within __xnet_t_alloc(). */char *__xnet_t_alloc(int fd, int type, int fields){ struct _t_user *user; if (!(user = __xnet_t_tstuser(fd, 0, -1, -1))) goto error; switch (type) { case T_BIND: { struct t_bind *bind; if (!(bind = (struct t_bind *) malloc(sizeof(*bind)))) goto badalloc; memset(bind, 0, sizeof(*bind)); if (fields & T_ADDR) { int len; switch ((len = user->info.addr)) { case T_INFINITE: len = _T_DEFAULT_ADDRLEN; default: if (!(bind->addr.buf = (char *) malloc(len))) { free(bind); goto badalloc; } bind->addr.maxlen = len; case 0: break; case T_INVALID: if (fields != T_ALL) { free(bind); goto einval; } break; } } return ((char *) bind); } case T_OPTMGMT: { struct t_optmgmt *opts; if (!(opts = (struct t_optmgmt *) malloc(sizeof(*opts)))) goto badalloc; memset(opts, 0, sizeof(*opts)); if (fields & T_OPT) { int len; switch ((len = user->info.options)) { case T_INFINITE: len = _T_DEFAULT_OPTLEN; default: if (!(opts->opt.buf = (char *) malloc(len))) { free(opts); goto badalloc; } opts->opt.maxlen = len; case 0: break; case T_INVALID: if (fields != T_ALL) { free(opts); goto einval; } break; } } return ((char *) opts); } case T_CALL: { struct t_call *call; if (user->info.servtype == T_CLTS) goto tnostructype; if (!(call = (struct t_call *) malloc(sizeof(*call)))) goto badalloc; memset(call, 0, sizeof(*call)); if (fields & T_ADDR) { int len; switch ((len = user->info.addr)) { case T_INFINITE: len = _T_DEFAULT_ADDRLEN; default: if (!(call->addr.buf = (char *) malloc(len))) { free(call); goto badalloc; } call->addr.maxlen = len; case 0: break; case T_INVALID: if (fields != T_ALL) { free(call); goto einval; } break; } } if (fields & T_OPT) { int len; switch ((len = user->info.options)) { case T_INFINITE: len = _T_DEFAULT_OPTLEN; default: if (!(call->opt.buf = (char *) malloc(len))) { if (call->addr.buf) free(call->addr.buf); free(call); goto badalloc; } call->opt.maxlen = len; case 0: break; case T_INVALID: if (fields != T_ALL) { if (call->addr.buf) free(call->addr.buf); free(call); goto einval; } break; } } if (fields & T_UDATA) { int len; switch ((len = user->info.connect)) { case T_INFINITE: len = _T_DEFAULT_CONNLEN; default: if (!(call->udata.buf = (char *) malloc(len))) { if (call->addr.buf) free(call->addr.buf); if (call->opt.buf) free(call->opt.buf); free(call); goto badalloc; } call->udata.maxlen = len; case 0: break; case T_INVALID: if (fields != T_ALL) { if (call->addr.buf) free(call->addr.buf); if (call->opt.buf) free(call->opt.buf); free(call); goto einval; } break; } } return ((char *) call); } case T_DIS: { struct t_discon *discon; if (user->info.servtype == T_CLTS) goto tnostructype; if (!(discon = (struct t_discon *) malloc(sizeof(*discon)))) goto badalloc; memset(discon, 0, sizeof(*discon)); if (fields & T_UDATA) { int len; 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: 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; case 0: 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -