📄 xnet.c
字号:
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 + -