📄 xnet.c
字号:
/***************************************************************************** @(#) xnet.c,v openss7-0_9_2_E(0.9.2.9) 2006/10/02 11:31:30 ----------------------------------------------------------------------------- Copyright (c) 2001-2006 OpenSS7 Corporation <http://www.openss7.com/> Copyright (c) 1997-2000 Brian F. G. Bidulock <bidulock@openss7.org> All Rights Reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----------------------------------------------------------------------------- U.S. GOVERNMENT RESTRICTED RIGHTS. If you are licensing this Software on behalf of the U.S. Government ("Government"), the following provisions apply to you. If the Software is supplied by the Department of Defense ("DoD"), it is classified as "Commercial Computer Software" under paragraph 252.227-7014 of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any successor regulations) and the Government is acquiring only the license rights granted herein (the license rights customarily provided to non-Government users). If the Software is supplied to any unit or agency of the Government other than DoD, it is classified as "Restricted Computer Software" and the Government's rights in the Software are defined in paragraph 52.227-19 of the Federal Acquisition Regulations ("FAR") (or any successor regulations) or, in the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR (or any successor regulations). ----------------------------------------------------------------------------- Commercial licensing and support of this software is available from OpenSS7 Corporation at a fee. See http://www.openss7.com/ ----------------------------------------------------------------------------- Last Modified 2006/10/02 11:31:30 by brian *****************************************************************************/#ident "@(#) xnet.c,v openss7-0_9_2_E(0.9.2.9) 2006/10/02 11:31:30"static char const ident[] = "xnet.c,v openss7-0_9_2_E(0.9.2.9) 2006/10/02 11:31:30";/* This file can be processed with doxygen(1). *//** @weakgroup xnet OpenSS7 XNET Library * @{ *//** @file * OpenSS7 X/Open Networking Library (XNET) implementation file. */#define _XOPEN_SOURCE 600#define _REENTRANT#define _THREAD_SAFE#if 0#define __USE_UNIX98#define __USE_XOPEN2K#define __USE_GNU#endif/** @name System Configuration Names * These are system configuration names for use with t_sysconf(). Note that * _SC_T_IOV_MAX is already set to 1 by glibc header files in <unistd.h>. * Well, used to, not any more, it is some really big number. * @{ *///#define _SC_T_IOV_MAX 1 /**< IOV maximum. */#define _SC_T_DEFAULT_ADDRLEN 2 /**< Default address length. */#define _SC_T_DEFAULT_CONNLEN 3 /**< Default connect data length. */#define _SC_T_DEFAULT_DISCLEN 4 /**< Default disconnect data length. */#define _SC_T_DEFAULT_OPTLEN 5 /**< Default option length. */#define _SC_T_DEFAULT_DATALEN 6 /**< Default data length. *//** @} *//** @name System Configuration Values Defaults * These are the default values for the corresponding system configuration names and are the default * values returned by t_sysconf(). * @{ */#define _T_DEFAULT_ADDRLEN 128 /**< Default address length. */#define _T_DEFAULT_CONNLEN 256 /**< Default connect data length. */#define _T_DEFAULT_DISCLEN 256 /**< Default disconnect data length. */#define _T_DEFAULT_OPTLEN 256 /**< Default options length. */#define _T_DEFAULT_DATALEN 16384 /**< Default user data length. */#define _T_TIMEOUT -1 /**< Default timeout value for library ioctl. */#define _T_IOV_MAX 16 /**< IOV maximum. *//** @} */#define NEED_T_USCALAR_T 1#include <stdlib.h>#include "gettext.h"#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#include <sys/stropts.h>#include <sys/poll.h>#include <fcntl.h>#if 0#pragma weak getpmsg#pragma weak putpmsg#pragma weak getmsg#pragma weak putmsg#pragma weak isastream#endif#ifdef HAVE_INTTYPES_H# include <inttypes.h>#else# ifdef HAVE_STDINT_H# include <stdint.h># endif#endif#ifndef __EXCEPTIONS#define __EXCEPTIONS 1#endif#include <unistd.h>#include <errno.h>#include <stddef.h>#include <stdio.h>#include <string.h>#include <stropts.h>#include <pthread.h>#include <linux/limits.h>#include <values.h>#ifndef __P#define __P(__prototype) __prototype#endif#include <xti.h>#include <tihdr.h>#include <timod.h>#if defined __i386__ || defined __x86_64__ || defined __k8__#define fastcall __attribute__((__regparm__(3)))#else#define fastcall#endif#define __hot __attribute__((section(".text.hot")))#define __unlikely __attribute__((section(".text.unlikely")))#if __GNUC__ < 3#define inline inline fastcall __hot#define noinline extern fastcall __unlikely#else#define inline inline __attribute__((always_inline)) fastcall __hot#define noinline static __attribute__((noinline)) fastcall __unlikely#endif#define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)#undef min#define min(a, b) (a < b ? a : b)/** * This manual contains documentation of the OpenSS7 XNS/XTI Library functions * that are generated automatically from the source code with doxygen. This * documentation is intended to be used for maintainers of the OpenSS7 XNS/XTI * Library and is not intended for users of the OpenSS7 XNS/XTI Library. * Users should consult the documentation found in the user manual pages * beginning with xti(3). * * <h2>Thread Safety</h2> * The OpenSS7 XNS/XTI Library is design to be thread-safe. This is * accomplished in a number of ways. Thread-safety depends on the use of * glibc2 and the pthreads library. * * Glibc2 provides lightweight thread-specific data for errno and h_errno. * Because h_errno uses communications function orthoginal to the XTI Library * services, we borrow h_errno and use it for t_errno. This does not cause a * problem because neither h_errno nor t_errno need to maintain their value * accross any other system call. * * Glibc2 also provides some weak undefined aliases for POSIX thread functions * to peform its own thread-safety. When the pthread library (libpthread) is * linked with glibc2, these functions call libpthread functions instead * of internal dummy routines. The same approach is taken for the OpenSS7 * XNS/XTI Library. The library uses weak defined and undefined aliases that * automatically invoke libpthread functions when libpthread is (dynamically) * linked and uses dummy functions when it is not. This maintains maximum * efficiency when libpthread is not dynamically linked, but provides full * thread safety when it is. * * Libpthread behaves in some strange ways with regards to thread * cancellation. Because libpthread uses Linux clone processes for threads, * cancellation of a thread is accomplished by sending a signal to the thread * process. This does not directly result in cancellation, but will result in * the failure of a system call with the EINTR error code. It is necessary to * test for cancellation upon error return from system calls to perform the * actual cancellation of the thread. * * The XTI sepcification (OpenGroup XNS 5.2) lists the following functions as * being thread cancellation points: t_close(), t_connect(), t_listen(), * t_rcv(), t_rcvconnect(), t_rcvrel(), t_rcvreldata(), t_rcvudata(), t_rcvv, * t_rcvvudata(), t_snd(), t_sndrel(), t_sndreldata(), t_sndudata(), t_sndv(), * t_sndvudata(). * * The OpenSS7 XNS/XTI Library adds the following functions that operate on * data or expedited data with options that are not present in the XNS 5.2 * specifications, that are also thread cancellation points: t_rcvopt(), * t_rcvvopt(), t_sndopt(), t_sndvopt(). * * Other XTI functions are not permitted by XNS 5.2 to be thread cancellation * points. Any function that cannot be a thread cancellation point needs to * have its cancellation status deferred if it internally invokes a function * that permits thread cancellation. Functions that do not permit thread * cancellation are: t_accept(), t_addleaf(), t_alloc(), t_bind(), t_error(), * t_free(), t_getinfo(), t_getprotaddr(), t_getstate(), t_look(), t_open(), * t_optmgmt(), t_rcvdis(), t_rcvleafchange(), t_rcvuderr(), t_removeleaf(), * t_snddis(), t_strerror(), t_sync(), t_sysconf(), t_unbind(). * * Locks and asynchronous thread cancellation present challenges: * * Functions that act as thread cancellation points must push routines onto * the function stack executed at exit of the thread to release the locks held * by the function. These are performed with weak definitions of POSIX thread * library functions. * * Functions that do not act as thread cancellation points must defer thread * cancellation before taking locks and then release locks before thread * canceallation is restored. * * The above are the techniques used by glibc2 for the same purpose and is the * same technique that is used by the OpenSS7 XNS/XTI library. */struct __xnet_tsd { int terrno;};/* * Once condition for Thread-Specific Data key creation. */static pthread_once_t __xnet_tsd_once = PTHREAD_ONCE_INIT;/* * XNET library Thread-Specific Data key. */static pthread_key_t __xnet_tsd_key = 0;static void__xnet_tsd_free(void *buf){ pthread_setspecific(__xnet_tsd_key, NULL); free(buf);}static void__xnet_tsd_alloc(void){ int ret; void *buf; ret = pthread_key_create(&__xnet_tsd_key, __xnet_tsd_free); buf = malloc(sizeof(struct __xnet_tsd)); bzero(buf, sizeof(*buf)); ret = pthread_setspecific(__xnet_tsd_key, buf); return;}static struct __xnet_tsd *__xnet_get_tsd(void){ pthread_once(&__xnet_tsd_once, __xnet_tsd_alloc); return (struct __xnet_tsd *) pthread_getspecific(__xnet_tsd_key);};/** @brief #t_errno location function. * @version XNET_1.0 * @par Alias: * This function is an implementation of _t_errno(). */int *__xnet__t_errno(void){ return &(__xnet_get_tsd()->terrno);}/** @fn int *_t_errno(void) * @version XNET_1.0 * @par Alias: * This symbol is a strong alias of __xnet__t_errno(). * * This function provides the location of the integer that contains the XTI/TLI * error number returned by the last XTI function that failed. This is * normally used to provide #t_errno in a thread-safe way as follows: * * @code * #define t_errno (*(_t_errno())) * @endcode */__asm__(".symver __xnet__t_errno,_t_errno@@XNET_1.0");struct _t_user { pthread_rwlock_t lock; /**< lock for this structure */ int refs; /**< number of references to this structure */ int event; /**< pending t_look() events */ int flags; /**< user flags */ int fflags; /**< file flags */ int gflags; /**< getmsg flags */ int state; /**< XTI state */ int statef; /**< TPI state flag */ int prim; /**< last received TLI primitive */ int qlen; /**< length of the listen queue */ int ocnt; /**< outstanding connection indications */ u_int8_t moredat; /**< more data in T_DATA_IND/T_OPTDATA_IND */ u_int8_t moresdu; /**< more tsdu */ u_int8_t moreexp; /**< more data in T_EXDATA_IND/T_OPTDATA_IND */ u_int8_t moreedu; /**< more etsdu */ u_int8_t moremsg; /**< more data with dis/con/rel message */ int ctlmax; /**< maximum size of ctlbuf */ char *ctlbuf; /**< ctrl part buffer */ int datmax; /**< maximum size of datbuf */ char *datbuf; /**< data part buffer */ uint token; /**< acceptor id */ struct strbuf ctrl; /**< ctrl part of received message */ struct strbuf data; /**< data part of received message */ struct t_info info; /**< information structure */};/** @name Transport User Flags * Flags for the _t_user::flags member of the struct _t_user structure. * @{ */#define TUF_FLOW_NORM 01 /**< Was flow controlled for normal messages. */#define TUF_FLOW_EXP 02 /**< Was flow controlled for expedited messages. */#define TUF_SYNC_REQUIRED 04 /**< t_sync() required. */#define TUF_WACK_INFO 010 /**< Waiting for T_INFO_ACK. */#define TUF_WACK_OPTMGMT 020 /**< Waiting for T_OPTMGMT_ACK. */#define TUF_WACK_ADDR 040 /**< Waiting for T_ADDR_ACK. */#define TUF_WACK_CAPABILITY 0100 /**< Waitinf for T_CAPABILITY_ACK. */#define TUF_WACK_GETADDR 0200 /**< Waiting for T_GETADDR_ACK. */#define TUF_WACK_OK 0400 /**< Waiting for T_OK_ACK. */#define TUF_WACK_BIND 01000 /**< Waiting for T_BIND_ACK. */#define TUF_MORE_DATA 02000 /**< More data left on receive queue. *//** @} */#ifndef T_ACK#define T_ACK (-2) /**< for now */#endifstatic struct _t_user *_t_fds[OPEN_MAX] = { NULL, };/** @name Transport State Flags * Efficiency for avoiding case statements with two results for multiple * states. * @{ */#define TSF_UNBND (1 << TS_UNBND ) /**< Unbound state. */#define TSF_WACK_BREQ (1 << TS_WACK_BREQ ) /**< Waiting for a T_BIND_ACK. */#define TSF_WACK_UREQ (1 << TS_WACK_UREQ ) /**< Waiting for a T_OK_ACK. */#define TSF_IDLE (1 << TS_IDLE ) /**< Idle state. */#define TSF_WACK_OPTREQ (1 << TS_WACK_OPTREQ ) /**< Waiting to receive a T_OPTMGMT_ACK. */#define TSF_WACK_CREQ (1 << TS_WACK_CREQ ) /**< Waiting to receive a T_OK_ACK. */#define TSF_WCON_CREQ (1 << TS_WCON_CREQ ) /**< Waiting to receive a T_CONN_CON. */#define TSF_WRES_CIND (1 << TS_WRES_CIND ) /**< Waiting to send a T_CONN_RES. */#define TSF_WACK_CRES (1 << TS_WACK_CRES ) /**< Waiting to send a T_OK_ACK. */#define TSF_DATA_XFER (1 << TS_DATA_XFER ) /**< Data Transfer state. */#define TSF_WIND_ORDREL (1 << TS_WIND_ORDREL ) /**< Waiting to receive a T_ORDREL_IND. */#define TSF_WREQ_ORDREL (1 << TS_WREQ_ORDREL ) /**< Waiting to send a T_ORDREL_REQ. */#define TSF_WACK_DREQ6 (1 << TS_WACK_DREQ6 ) /**< Waiting to receive a T_OK_ACK. */#define TSF_WACK_DREQ7 (1 << TS_WACK_DREQ7 ) /**< Waiting to receive a T_OK_ACK. */#define TSF_WACK_DREQ9 (1 << TS_WACK_DREQ9 ) /**< Waiting to receive a T_OK_ACK. */#define TSF_WACK_DREQ10 (1 << TS_WACK_DREQ10 ) /**< Waiting to receive a T_OK_ACK. */#define TSF_WACK_DREQ11 (1 << TS_WACK_DREQ11 ) /**< Waiting to receive a T_OK_ACK. *//** @} *//** @internal * @brief Set the state of the endpoint to a constant state. * @param user a pointer to the _t_user structure for this endpoint. * @param state the constant state value to set. * * This inline function sets the state of the the transport endpoint in the * user structure to the constate state specified. This function is an inline * accepting a constant so that the compiler can inline just the appropriate * case value. */static inline void__xnet_u_setstate_const(struct _t_user *user, const int state){ user->statef = (1 << state); switch (state) { case TS_UNBND: case TS_WACK_BREQ: user->state = T_UNBND; break; case TS_WACK_UREQ: case TS_IDLE: case TS_WACK_CREQ: user->state = T_IDLE; break; case TS_WCON_CREQ: case TS_WACK_DREQ6: user->state = T_OUTCON; break; case TS_WRES_CIND: case TS_WACK_CRES: case TS_WACK_DREQ7: user->state = T_INCON; break; case TS_DATA_XFER: case TS_WACK_DREQ9: user->state = T_DATAXFER; break; case TS_WIND_ORDREL: case TS_WACK_DREQ10: user->state = T_OUTREL; break; case TS_WREQ_ORDREL: case TS_WACK_DREQ11: user->state = T_INREL; break; default: user->state = T_UNINIT; }}/** @internal * @brief Set the state of the endpoint to a variable state. * @param user a pointer to the _t_user structure for this endpoint. * @param state the variable state value to set. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -