Oracle网络TNS协议介绍(revised)

在开发源工具解决Oracle中的问题时,必须了解TNS协议。在努力理解TNS协议的时候,Oracle JDBC驱动程序(classes12.zip)会是一个很有用的资源

TNS头

每个TNS包都有一个8字节的包头。包最前面的两个字节用来表示包的长度–不包括包头的大小。和所有的值一样,大小是大端字节的方式存储的。如果进行了校验,那么校验和会被存放在下一个字(WORD)内–默认情况下会对校验和进行校验,该字(WORD)的值为0x0000。下面的一个字节用来表示包的类型–例如,最常见的类型如下所示:

Connect packet Type        1
Accept packet    Type       2
Ack  packet          Type      3
Refuse Packet     Type      4
Redirect Packet    Type   5
Data   Packet         Type    6
NULL Packet          Type    7
Abort  Packet          Type   9
Resend    Packet       Type 11
Marker   Packet         Type 12
Attention Packet       Type 13
Control   Packet        Type 14

要连接Oracle的时候,在TNS级,客户机向服务器发送一个链接包(类型1),这个包会指定客户将要访问的服务器名称。假定Listener知道这样的服务,那么接下来有两种可能:Listener可能会发送一个接收包(类型2)或者它可能用一个重定向包(类型5)将客户机指定向到另一个端口。如果出现的是前一种情况,那么客户机将尝试进行身份验证。如果出现的是后一种情况,那么客户机会向自己被重定向的端口发送一个连接包并请求访问该服务。如果一切顺利的话,服务器会发出一个接收包并开始进行身份验证。所有的身份验证包都是类型为6的数据包。

如果Listener不知道客户机要求访问那个服务,那么它就会发送一个拒绝包–类型4。一旦通过身份验证,查询包和结果包都是数据包。偶尔您会看到类型为12(oxoC的包)–这是用来中断的标记包。例如,如果服务器希望客户机停止发送数据,那么它会向客户机发送一个标记包。

接下来继续介绍TNS包头的细节,下面的一个字节是包头标志位(header flag)。一般这些包头标志位是不使用的,不过在10g中客户机可能会将它的值设定为0x04。

最后的两个字节构成一个字(WORD),他用来存放头校验和–在默认情况下不使用这个字并将其设为0x000:

WORD   00 00  Pocket Size
WORD   00 00  Packet Checksum
Byte     00  Packet Type
Byte     00   Flags
Word     00 00 Header Checksum

在对包进行深入研究前,观察一下拒绝包(类型4)应该会有所帮助。拒绝包表示某种错误–例如,一个因“用户名/密码无效”而被拒绝登陆的错误–即ORA-01017。根绝这些错误,第54个字节指出了问题所在:A3代表无效的密码,a2表明没有这样的用户。很明显,即使从拒绝包中也可以得到可能有用的信息。

发现这篇文章被网友转载了:地址;而且因为163 blog的权重比这里高导致原帖变成了”转帖”,真是很令人头痛的事情,
转载请注明出处:www.askmac.cn  谢谢!


Posted

in

by

Tags:

Comments

7 responses to “Oracle网络TNS协议介绍(revised)”

  1. admin Avatar
    admin

    Oracle Net “Connect Time” Performance Tuning

    Applies to:

    Oracle Net Services – Version: 8.0.1.0.0 to 11.2.0.1 – Release: to 11.2
    Information in this document applies to any platform.
    Purpose

    In many application architectures, such as a three-tiered architecture, Clients (such as middle tier or web servers) require quick connect times in order to optimize the whole web sites response time requirements. The process of the Client connecting to the database is well documented in the Oracle Net Administrator’s Guide. This document is intended to illustrate the optimal settings for Oracle Net to accomplish quick connect times. Though these suggestions are valid to increase connect times, they may not be valid for a particular architecture, so testing of these suggestions is highly recommended to assure actual performance and availability gains.

    The connection process includes several steps. The first part involves the resolution of the connect descriptor. The next steps contributing to the time taken for Client connection include:
    1. The time taken for the network protocol to connect the Client host to the Listener host
    2. For the Listener to create either a dedicated server process or determine which Dispatcher is to be used
    3. The time it takes for the Client process to complete the TNS connect to the Server process.
    The timings used in this article are drawn from Oracle Net trace files with time stamping enabled. To eliminate as many variables as possible, the examples used throughout this article consistently denote particular sections of trace files used. That is, from the beginning of the trace file to a specific location within the trace file that denotes the global memory used during the connection process.
    Scope and Application

    This article is primarily intended for Application Designers and Database Administrators.
    Oracle Net “Connect Time” Performance Tuning

    ORACLE NET CONNECT TIME PERFORMANCE TUNING

    RESOLVING THE CONNECT DESCRIPTOR

    In the examples below, the first time stamp is from the beginning of the Oracle Net trace file. The second time stamp is from a point in the trace file where the connect descriptor has been looked up and resolved into the network protocol requirements but before the actual connection is made. This allows for a good measurement for the resolution of the descriptor and removes any delays that might occur on a network.

    The fastest method for a Client to resolve the connect descriptor is not to have to resolve the connect descriptor into protocol-specific information. This is done by placing the entire connect descriptor directly on the command line:

    E:\Temp>sqlplus scott/tiger@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS= / (PROTOCOL=TCP)(HOST=kareardo-pc)(PORT=1521))) / (CONNECT_DATA=(SERVICE_NAME=iasdb.kareardo_pc.us.oracle.com)))

    [04-OCT-2002 19:37:41:919] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [04-OCT-2002 19:37:41:919] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 0 ms.

    This method might be the fastest way to resolve the connect descriptor, but may require hard coding the connect information into the Client software. This becomes a major problem for maintaining systems and Client software. This is not a recommended method, but illustrated here merely for completeness.

    The next method is placing the connect descriptor in a TNSNAMES.ORA file and connecting without using the NAMES.DEFAULT_DOMAIN extension: scott/tiger@iasdb

    [09-OCT-2002 11:05:52:323] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 11:05:52:343] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 20 ms.

    If we use the connect descriptor using the NAMES.DEFAULT_DOMAIN extension: scott/[email protected]

    [09-OCT-2002 11:05:11:664] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 11:05:11:684] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 20 ms. As can be seen here, there is no additional time involved in using the default domain.
    NAMES.DIRECTORY_PATH

    A simple configuration gain is to change the way the Client looks up the connect descriptor. This connect descriptor must be translated by Oracle Net into the network protocol location of the database (IP address and port number) and the name of the database service.

    There are a variety of methods to store this information, such as in a TNSNAMES.ORA (TNSNAMES) file, Oracle Internet Directory (OID – LDAP), Oracle Names (ONAMES) or using the Host Naming Adapter. For this article, only TNSNAMES and LDAP naming resolutions are examined.

    The default connect descriptor lookup path is to first look in the local naming file TNSNAMES.ORA, then to try the well-known Oracle Names servers, and then finally to try the Host Naming Adapter. The parameter that influences this lookup order is NAMES.DIRECTORY_PATH parameter in the SQLNET.ORA file.

    Using external naming methods, like Oracle Internet Directory, usually requires network round trips to the external naming resource. Timing tests against these external sources is highly subjective and may be influenced by network bandwidth availability, latency and number of requests per second on the system used. To reduce this variability, the following tests were run where the OID server was located on the same system as the Client. Thus any network variability was removed.

    Setting NAMES.DIRECTORY_PATH so that a local TNSNAMES.ORA file with the connect descriptor information in it is queried first would be the fastest time to resolve.

    NAMES.DIRECTORY_PATH = (TNSNAMES, LDAP)

    Looking for a connect descriptor that is in TNSNAMES.ORA and with the TNSNAMES.ORA file first in the lookup order:

    [09-OCT-2002 10:18:30:026] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 10:18:30:096] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 70 ms. For the directory lookup with OID appearing first, but no valid entry in it, yet with the valid entry appearing in the TNSNAMES.ORA file:

    [09-OCT-2002 10:22:22:170] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 10:22:22:280] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 110 ms.

    If the policy of the Enterprise is to have a central naming authority, like OID, placing the TNSNAMES entry first in NAMES.DIRECTORY_PATH would only delay the Client from resolving the connect descriptor if it did not contain a valid entry.

    [09-OCT-2002 10:25:37:160] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 10:25:37:240] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 80 ms. However, placing the OID server first in the NAMES.DIRECTORY_PATH:

    [09-OCT-2002 10:24:36:052] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [09-OCT-2002 10:24:36:122] niotns: setting up interrupt handler…

    This method resolved the connect descriptor in 70 ms.
    SHARED SERVER OR DEDICATED

    Once Oracle Net has resolved the connect descriptor to network protocol-specific information, it now has to connect to the Oracle Listener. Network protocols have built-in mechanisms to respond to and handle failures, such as a non-responsive or failed process. For TCP/IP, these are the retransmission interval, the time TCP/IP will wait for an acknowledgment before re-transmitting a packet. A second parameter governs the number of packets that will be resent without acknowledgment before giving up.

    Granted, each operating system’s (OS) TCP/IP stack differ slightly in which parameter governs what, so platform-specific details are discussed in this article. For example, the Sun Solaris operating system has separate parameters governing this behavior during TCP/IP’s three-way connect handshake as compared to the parameters governing the normal retransmission interval. Keep in mind that changing these parameters may have unexpected effects on other services on the Client or server, so care must be taken when changing from any default parameters.

    After the network protocol has established its connection to the Oracle Listener, the Listener continues the connection process. The Oracle Listener performs many tasks, but the ones that play a role in the connection process are the creation of the dedicated server process, or the redirection to a dispatcher process. Creation of any process on a computer consumes memory and CPU, but as it pertains to this article, it consumes time.

    When the database is configured to allow only dedicated connections, the Listener receives a connect request and passes the task of creating the dedicated server process to the operating system. Once the time to create this process has elapsed, the Listener can then redirect the Client to it. A redirect packet is then sent to the Client if the dedicated server process did not inherit the same port number then the Listener, otherwise a resend packet is sent. The Client then connects to the dedicated server process and continues with the login to the database.

    This Listener connection process can be sped up if the server process can be pre-created. If the process can be created prior to the connection request, the Listener will not have to wait to send the redirect or resend packets, but send them right after the connect request comes in. This is possible if the Oracle Database is configured for Shared Server. In a Shared Server configuration, processes called dispatchers are created by the process monitor (PMON) and register their network protocol information with the Listener. By making themselves available, the Listener will redirect the connect request to the dispatcher rather then wait to create a dedicated server process. Such a configuration can decrease the connect time considerably. A simple test using SQL*Plus from a Windows 2000 workstation going to a Sun Sparc20 server revealed the following results. The timing was from the start of the trace file to the reception of the Oracle Net Accept packet.

    Dedicated server configuration:

    [02-OCT-2002 20:36:12:367] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [02-OCT-2002 20:36:12:567] nscon: got NSPTAC packet

    This method received the accept packet in 200 ms.

    Shared Server configuration:

    [02-OCT-2002 20:36:23:633] — TRACE CONFIGURATION INFORMATION FOLLOWS —

    [02-OCT-2002 20:36:23:723] nscon: got NSPTAC packet

    This method received the accept packet in 90 ms.
    LISTENER QUEUE SIZE AND MULTIPLE LISTENERS

    The next bottleneck the Listener could encounter is too many concurrent connection requests. The Listener process, like any other has limits – it is constrained by CPU speed and available memory. Although system growth is usually faster than Moore’s Law (that PCs double in processing power every few years), there are techniques that can assist in scaling the Listener. The first is to adjust the request queue-size (QUEUESIZE) of the Listener process, the second is to increase the number of Listeners.

    The QUEUESIZE parameter represents the maximum possible number of concurrent connections the Listener may receive – this does not refer the number of requests per second the Listener may handle. The Listener queue-size is dependent on corresponding underlying network protocol parameters (e.g. SOMAXCONN, SNS_MAXCONN, TCP_CONN_REQ_MAX_Q, etc.) that define the maximum, concurrent connections per port or socket. Therefore, the Listener queue-size value cannot exceed the underlying protocol parameter value.

    Oracle Net protocol adapters (e.g. IPC, TCP) maintain their own queue-sizes, for which the default values differ depending on protocol adapter, version and platform. The use of IPC’s queuesize is very version dependent. For instance, in Oracle9i (9.2.0), only TCP/IP queue-size is tunable. In Oracle10g and later, IPC’s queuesize can be changed in Unix only as it uses Domain Sockets. Windows, uses Named Pipes for the IPC protocol, and NamedPipes does not have a concept of a queue. For TCP, the default queue-size for Unix and Windows NT Workstations is in the order of 20, whereas on Windows NT Server/Enterprise it is 50. By analyzing the Listener log file, if the number of requests per second exceeds the queue-size values, increasing the queue-size recommended.

    The next method is to increase the number of Listener processes. This also has the advantage of increasing Listener availability. Many large systems have multiple CPU’s and the operating systems take up the responsibility of placing processes on each CPU. This increases the possibility for two Listener processes to act simultaneously, thus places an upper bound of twice the connect throughput then one Listener. From a system design perspective, there are two ways to configure the Client to take advantage of dual Listeners. The first configuration is to slave a set of Clients to one Listener, and the other half to the other. This configuration is necessary when more control is needed.

    This is a very good solution when the system architecture consists of truly independent Clients. Client-side connection load balancing is covered in the Oracle Net Administrators Manual. This Client side configuration allows the Oracle Net Client to randomly choose between two or more possible Listener addresses. As long as these addresses represent independent Listener processes, then overloading a single Listener process is reduced. It is a common error to configure a Listener with two different TCP/IP ports thinking that this represents a ‘second’ Listener. In the configuration outlined here, there are two different Listener processes, not two different Listener addresses.
    CONCLUSION

    There are many areas where a slight change in a configuration can result in significant gains in performance. Each area needs to be examined closely and tuned to fit the architectural and service level requirements of a particular application or system.

  2. admin Avatar
    admin

    SQL*NET PACKET STRUCTURE: NS PACKET HEADER

    Problem Description:
    ====================

    This entry contains information about the SQL*Net packet structure and the NS
    packet headers (protocol independent layer).

    These packet types appear in the SQL*Net trace. The help explain how the
    client and server are synchronized and what they are doing.

    Search words:
    packets tracing file trc tns sqlnet

    Solution Description:
    =====================

    ================
    NS PACKET HEADER
    ================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPHDTYP | reserved | NSPHDHSM |
    —————————————————————–
    NSPHDLEN: Packet length – number of bytes in the entire packet.
    NSPHDPSM: Packet checksum – the 16-bit ones complement of the 16-bit
    ones complement sum of the entire packet.
    NSPHDTYP: Packet type
    Code Decimal HEX Description
    ———– ——- ——- ——————————
    NSPTCN 01 1 connect
    NSPTAC 02 2 accept
    NSPTAK 03 3 acknowledge
    NSPTRF 04 4 refuse
    NSPTRD 05 5 redirect
    NSPTDA 06 6 data
    NSPTNL 07 7 “null” – empty data, no flags
    NSPTAB 09 9 abort
    NSPTRS 11 B re-send
    NSPTMK 12 C marker
    NSPTAT 13 D attention
    NSPTCNL 14 E control information
    NSPTHI 19 12 highest legal packet type

    NSPHDHSM: Header checksum – the 16-bit ones complement of the 16-bit
    ones complement sum of the packet header.
    NSPSIZHD: size of packet header

    =================
    NS CONNECT PACKET
    =================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |——————————————————- ——-|
    | NSPTCN (1) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPCNVSN | NSPCNLOV |
    |—————————————————————|
    | NSPCNOPT | NSPCNSDU |
    |—————————————————————|
    | NSPCNTDU | NSPCNNTC |
    |—————————————————————|
    | NSPCNTNA | NSPCNONE |
    |—————————————————————|
    | NSPCNLEN | NSPCNOFF |
    |—————————————————————|
    | NSPCNMXC |
    |—————————————————————|
    | NSPCNFL0 | NSPCNFL1 |//////////////////////////////|
    |—————————————————————|
    | (expansion) |
    |—————————————————————|
    | NSPCNDAT, NSPCNV3DAT, NSPCNV2DAT (data) |
    —————————————————————–

    NSPCNVSN Packet version number.
    NSPCNLOV Lowest version number that sender can be compatible with.
    NSPCNOPT Global service options supported (see NSGBLXXXX in nsi.h).
    NSPCNSDU My SDU (session data unit) size.
    NSPCNTDU Maximum TDU (transport data unit) size for NT driver.
    NSPCNNTC NT protocol characteristics (see NTCXXX in ti.h).
    NSPCNTNA Line turnaround value (=> max consecutive packet sends
    allowed before a packet recv must occur).
    NSPCNONE The value ‘1’ in my hardware byte order
    NSPCNLEN Length of connect data (not necessarily in this packet).
    NSPCNOFF Offset to start of connect data.
    NSPCNMXC Maximum connect data that can be received.
    NSPCNFL0 Connect flags (from nsinfflg).
    NSPCNFL1 Connect flags (from nsinfflg).

    **** The following are added for Oracle Trace functionality (expansion)
    NSPCNCF1 cross facility item 1
    NSPCNCF2 cross facility item 2
    NSPCNCID unique connection id
    **** End of update for Oracle trace

    NSPCNDAT start of connect data (V3.6 packet)
    NSPCNV3DAT start of connect data (V3 packet)
    NSPCNV2DAT start of connect data, V2 packet

    ================
    NS ACCEPT PACKET
    ================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTAC (2) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPACVSN | NSPACOPT |
    |—————————————————————|
    | NSPACSDU | NSPACTDU |
    |—————————————————————|
    | NSPACONE | NSPACLEN |
    |—————————————————————|
    | NSPACOFF | NSPACFL0 | NSPACFL1 |
    |—————————————————————|
    | (expansion) |
    |—————————————————————|
    | NSPACDAT, NSPACV2DAT (data) |
    —————————————————————–

    NSPACVSN Version that this connection is to run at.
    NSPACOPT Global service options in place for this connection.
    NSPACSDU SDU (session data unit) size for this connection.
    NSPACTDU Maximum TDU (transport data unit) for this connection.
    NSPACONE The value ‘1’ in my hardware byte order
    NSPACLEN Length of connect data (not necessarily in this packet).
    NSPACOFF Offset to start of connect data.
    NSPACFL0 Connect flags (from nsctxinf).
    NSPACFL1 Connect flags (from nsctxinf).
    NSPACDAT Start of connect data (V3/V3.6 packet)
    NSPACV2DAT Start of connect data, V2 packet

    ================
    NS RESEND PACKET
    ================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTRS (11) | reserved | NSPHDHSM |
    —————————————————————–

    ================
    NS REFUSE PACKET
    ================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTRF (4) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPRFURS | NSPRFSRS | NSPRFLEN |
    |—————————————————————|
    | NSPRFDAT (data) |
    —————————————————————–

    NSPRFURS User (application) reason for refusal.
    NSPRFSRS System (NS) reason for refusal.
    NSPRFLEN Length of refuse data (not necessarily in this packet).
    NSPRFDAT Start of connect data

    ==================
    NS REDIRECT PACKET
    ==================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTRD (5) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPRDLEN | NSPRDDAT (data) |
    |——————————— |
    | |
    —————————————————————–

    NSPRDLEN Length of redirect data (not necessarily in this packet).
    NSPRDDAT Start of connect data

    ==============
    NS DATA PACKET
    ==============
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |———————————————————————-|
    | NSPTDA (6) | reserved | NSPHDHSM |
    |———————————————————————-|
    | NSPDAFLG | NSPDADAT (data) |
    |———————————————————————-|

    NSPDAFLG flags:
    Code Value Description
    ———– ———– ——————————
    NSPDAFZER 0
    NSPDAFTKN 1 the hdx (send) token
    NSPDAFRCF 2 request confirmation
    NSPDAFCFM 4 confirmation
    NSPDAFRSV 8 RESERVED (for hdx flag)
    NSPDAFMOR 20 more data to come
    NSPDAFEOF 40 “end of file”
    NSPDAFIMM 80 do immediate confirmation
    NSPDAFRTS 100 request-to-send
    NSPDAFRNT 200 request NT trailer
    NSPDADAT start of data

    ================
    NS MARKER PACKET
    ================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTMK (12) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPMKTYP | NSPMKODT | NSPMKDAT |
    —————————————————————-

    NSPMKTYP marker type
    Code Value Description
    ———– ———– ——————————
    NSPMKTD0 0 data marker – 0 data bytes
    NSPMKTD1 1 data marker – 1 data byte
    NSPMKTAT 2 attention marker => ATTENTION packet
    NSPMKODT old (pre-V3.05) data byte
    NSPMKDAT data byte – For V3.05 we want NSPMKDAT to be the same
    as
    NSPDADAT – this fixes a bug to do with reading a
    marker via
    the NSBRECV interface where the MARKER packet
    co-resides in
    the same SDU buffer as a another packet (“leftover”
    condition).

    ===================
    NS ATTENTION PACKET
    ===================
    (there isn’t one, it’s a special case of a MARKER packet, see above)

    ===============
    NS ABORT PACKET
    ===============

    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTAB (9) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPABURS | NSPABSRS | NSPABDAT (data) |
    |——————————— |
    | |
    —————————————————————–

    NSPABURS User (application) reason for abort.
    NSPABSRS System (NS) reason for abort.
    NSPABDAT Start of abort data

    =================
    NS CONTROL PACKET
    =================
    0 1 2 3
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    —————————————————————–
    | NSPHDLEN | NSPHDPSM |
    |—————————————————————|
    | NSPTCNL (14) | reserved | NSPHDHSM |
    |—————————————————————|
    | NSPTCNLCMD | data |
    |——————————— |
    | |
    —————————————————————–

    * The control command passed. Initially the only command would be for
    Oracle trace.

    NSPCTLCMD valid commands are:

    Code Value Description
    ———– ———– ————————–
    NSPCTL_OT 1 Oracle trace command

  3. admin Avatar
    admin

    Oracle Net Diagnostics
    Applies to:

    Oracle Net Services – Version: 9.2.0.1 to 11.1.0.7
    Information in this document applies to any platform.
    Purpose

    The aim of this document is to provide diagnostics Guidance for Oracle Net issues, covering the areas:

    Client Connection Issues
    Server Connection Issues
    TNS listener
    Connection Manager
    Oracle Names

    Last Review Date

    May 29, 2009
    Instructions for the Reader

    A Troubleshooting Guide is provided to assist in debugging a specific issue. When possible, diagnostic tools are included in the document to assist in troubleshooting.
    Troubleshooting Details

    Oracle Net Diagnostics

    Oracle Net connections problems can be placed into the following areas

    Client connection issues: Issue from a physical client platform, middle tier or an application running, located on server where the database is installed.Where the connection is unable to commicate with the database server, has naming resolution or connection handshake failure, configuration and or setup issue or conflict with database.

    Server connection issues: Issue establishing session to database, due to backend process failure, setup and / or configuration failure.

    TNS Listener issues: Issue with the TNS listener connection handshake, Peformance on the listener, process crash, memory leak or CPU spin with the TNSLSNR process.

    Each area requires a specfic diagnostic path to be followed, which always requires Oracle Net tracing to be enabled. The following section explains how to enable tracing and shows the notes with all the parameters available for Oracle Net tracing:

    Oracle Net Tracing

    Note 219968.1SQL*Net, Net8, Oracle Net Services – Tracing and Logging at a Glance

    Note 395525.1How to Enable Oracle SQLNet Client, Server, Listener, Kerberos and External procedure Tracing from Net Manager.

    Please note, that enabling Oracle Net server tracing can produce large amounts of trace, in a very short time frame. Even with cyclic tracing, each process will have the TRACE_FILENO_SERVER value amount of traces produced. Optimal tracing workflow should be to enable tracing, reproduce problem and then disable tracing. Thus limiting amount of time tracing is enabled. If unable to enable trace due to high connection volume, then the following article can assist.

    Note 401134.1How To Limit Connections Generating Trace when Oracle Net Server Enabled.

    Other options are to enable tracing when the system is quieter or out of normal business hours.

    Ensure only matching client and server traces are uploaded. Following article explains how to achieve this.Note 374116.1 How to Match Oracle Net Client and Server Trace Files.

    Diagnosing Oracle Net traces

    When analyzing Oracle Net traces, key features / steps in the trace need to be reviewed, to narrow down the point of failure / issue. Ensure to review the trace to understand how and what is used for the connection. Points to look for are:

    SQLNET.ORA parameters.
    Naming resolution method (local, onames, ldap, ezconnect, host)
    Correct TNSNAMES file used if local naming resolution selected
    Connection model. (Dedicated or shared server)
    Connection handshake completion.(Connect, Resend or Redirect, Connect and Accept packets)
    Cross-reference client and server packet flow, checking Packet sizes send, received / sent information, timings between client and server processes.
    Ensure completion codes are not mistaken for errors.
    Full details on how to diagnose Oracle Net traces can be found in Note 156485.1 Examining Oracle Net, Net8, SQL*Net Trace Files.

    Please note that a multithread application will show thread id before the time stamp column of a net trace. Match the thread id’s to follow the correct flow of information in the trace.Ensure completion codes reported in traces are not mistaken for error codes.

    General Problem Analysis

    Attempt to establish all possible facts to narrow down the causes to a minimumm, using the concept / method of :

    What is the problem / what is not a problem?
    When is the problem seen / when is the problem not seen?
    Where is the problem / Where is the problem not?
    What has changed?

    Initial questions that need to be asked are along the lines of the following:

    What Client and Server platforms reproduce the problem?
    What Client and Server platforms work?

    What 5-digit version of Oracle software reproduces the problem?
    What 5-digit version of Oracle software works?
    (Windows platform confirm patch number bundle used)

    What products reproduce the issue?
    What products do not reproduce the issue?
    (Ensure SQL*plus is tested)

    Is this standalone database?
    Is this RAC?

    Is the problem is constant?
    Is the problem reported intermittently?
    Is there any pattern to the failure?

    What resolves the problem?
    How long does the problem last?

    What physical network topology affects the problem?
    What settings, if any allow the connection(s) to work?

    Problem reproduces on another node / server?
    Problem reproduces against another RDBMS?

    Has this ever worked or is this a fresh installation / setup?
    When did the problem start fail?
    What changes happened around time the first failure / problem was reported?

    Client Connection Issues

    Confirm the underlying physical network under Oracle Net is functioning correctly.
    What are the results of testing TCP/IP communications from client to server?
    Use Telnet / FTP from same failing client to the server, what is the result?

    Attempt to narrow down problem further, to a specfic client, range of clients and / or platforms being used:
    Is the problem limited to one client and / or cetain platform?
    If so, what is the impact on the problem when physcially moving that client on the network?
    Which clients report the problem?
    Which clients do not report a problem?
    What do those clients have in common?

    What is the result of the command TNSping ?

    TNSping command will show if the alias can be read correctly. This is important, as the net admin files are sensitive to manual editing. Bracket placement, white spaces, control characters, etc, in the files can cause Oracle net to fail.Any failure here should be resolved by removing the entry via net manager tool and adding back via the same tool.

    C:\tnsping sample.oracle.com

    TNS Ping Utility for 32-bit Windows: Version 10.2.0.4.0 -Production on 15-APR-2009 09:45:14
    Copyright (c) 1997, 2007, Oracle. All rights reserved.

    Used parameter files:
    C:\Oracle\RDBMS102\network\admin\sqlnet.ora

    Used TNSNAMES adapter to resolve the alias
    Attempting to contact (DESCRIPTION = (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP (HOST = sample.oracle.com)(SERVICE_NAME = orcl.oracle.com)))
    OK (90 msec)

    Check the output to ensure the following was the expected:

    Naming resolution method selected.
    Version of of Oracle software was used.
    SQLNET.ORA file used.

    TNSping does NOT check if the service is available. It only goes as far as checking the TNS listener can be reached from the client. A TNSping trace will show refuse packet for successful resolution. Futher information on TNSping see Note:787848.1Intended Usage of the ‘tnsping’ Tool.

    Net Manager (NetMGR) Or Net Configuration Assistant (NetCA) GUI tools show the alias correctly? If the alias is not viewed correctly in via the GUI tools, rename the TNSNAMES.ORA and SQLNET.ORA files to .OLD. Rebuild the alias and re-test.

    Understand the setup / enviroment and the effects on the connection.
    Is there Multiple Oracle Software versions installed on the client?
    What enviroment path order is set for the client?
    Has enviroment varaible ORACLE_HOME been set?
    Has enviroment varaible TNS_ADMIN been set?

    For Windows platform,ensure the required ORACLE_HOME is first on the path. Use the Oracle Universal Installer (OUI) to ensure the path and registry is set to required values. Older clients will use the Oracle home selector tool.
    GUI tools will read the properties and start in values from the shortcut, find the correct Oracle Key and know the registry location to use.Using tools from command line, require the path to be set correctly, meaning the correct Oracle key file will be picked up.The Oracle key file holds the registry location, for example >> SOFTWARE\ORACLE\KEY_RDBMS102

    What other software is installed on the client that could be interfering with the network connections? Anti virus, Firewall and other software, such as networking probing can be known to effect Oracle Net connections. Features such as Firewall filters, Access control lists, Packet Inspection, should be disabled and connections re-tested.

    Check the SQLNET.ORA file for parameters and values that might effect the connection, such as timeout or ASO settings. Test connection with basic settings. If the connection works, retest, adding values back 1 at time, to confirm which is the problem parameter.

    If the sofware has never worked or there has been software patch installed, it might have corrupted the client installation. Is there a chance of re-installation of the client software to test Oracle binaries are okay?

    Client Diagnostics :

    Oracle Net Level 16 Client trace, capturing the failure / issue.
    If certain clients work or the problem is intermittent, capture working trace to capare against the failing / problem connection.

    If the issue / problem in the traces confirms TNS listener connection problem, Oracle Net Level 16 Client trace capturing the failure / issue with matching TNS listener level 16 trace, will be required. Along with further TNS listener diagnostics, as per the TNS listener diagnostics section.
    Sqlnet.log from the client. Default location is ORACLE_HOME/network/log.
    Capture client environment settings and all Oracle Net admin files via RDA
    Please note JDBC thin client connections can not be Oracle Net Client traced, but the Oracle Net packet flow can now be JavaNet traced. Note 793415.1 How to Perform the Equivalent of Sqlnet Client Tracing with Oracle JDBC Thin Driver.

    Server Connection Issues:

    Understanding the connection model being used and setup, can offer possible workaround / solution to the problem. Check items such as :
    Is the Connection model Dedicated or shared server?
    What happens if the opposite connection model is used?
    Is the connection routing via connection manager?

    Is the problem limited to one database in the Oracle home?
    Does the problem reproduce on other servers?
    Does the problem reproduce for other Oracle homes?

    What is the outcome when testing from the database Oracle home via bequeath connection?
    What is the outcome when testing from the database Oracle home via local connection?

    (Bequeath example is “sqlplus username/password”)
    (Local example is “sqlplus username/password@alias”)

    Is Valid Node checking in use? (see sqlnet.ora file on server)
    What are the results after disabling node checking?

    These tests help confirm if the problem is with the network between client and server. Helps to narrow down possible common area for the failure.

    Server Diagnostics :

    Oracle Net level 16 Client and Server traces.
    Sqlnet.log from the server and client. Default location is the ORACLE_HOME/Network/log
    Capture enviroment and database settings relative to net via RDA
    For Shared Server diagnostics follow Note 1005259.6 Shared Server (MTS) Diagnostics and Note 981615.1 Diagnostics Available for Shared Server (Formally known as MTS)
    The SQLNET.ORA file is only read once on creation of a process. RDBMS Background process and shared server dispatchers will need to be restarted for parameter changes in the SQLNET.ORA to be picked up. Once a process has started to be traced, tracing will not stop untill that the process stops.

    TNS listener

    Check if the TNS listener issue is limted to :
    Single TNS listener affected on server?
    Multiple TNS listeners affected on server?
    Symptons / Problem reproduces for TNS listener on another node?
    Understand the symptons, may allow for a second TNS listener to be started and let connections continue on second listener.

    Is the problem / issue due to values used for the TNS Listener? ie TCP/IP port number, IPC Key or Host name used ?

    Is there any Software installed that is effecting the connections?
    Such as Firewall software installed,Network packet-checking inplace,Port probing software running, software accelarators, GPRS, etc?

    When the problem / issue is reproducing
    Listener control shows listener status?
    Listener control shows Database service status ready?

    Understand the enviroment / setup, such as
    Listener process running from the account owning the Oracle binaries?
    Database running from the same account owning Oracle binaries?
    Permissions on binaries / sockets directories been amended / changed ?
    Sockets directory being cleaned up / changed ?

    TNS listener Diagnostics :

    Oracle Net level 16 Listener tracing. The workflow should be to capture ssue is to enable tracing, capture the failure and disable tracing, as quickly as possible.
    RDA output.
    Listener.log. Covering time period of the problem and a few hours before. Default location is the ORACLE_HOME/network/log/ Following articles have further diagnostics steps for certain situations
    Crashing TNS Listener : Note 793844.1Troubleshooting a TNS listener crash.

    Slow TNS listener connections : Note 557416.1How to Diagnose Slow TNS listener / Connection Performance

    Hanging TNS listener situations : Note 230156.1TNS Listener Hanging Inforamation to Get For Resolving or Troubleshooting.

    To further restrict the amount of time the TNS listener is traced, follow method described in Note 751432.1Further TNS Listener Tracing can be used.

    Connection Manager (CMAN)

    Issues with connection manager can be with the cman processes or the functionality of cman, access control, registeration, etc.

    Connections going via CMAN

    Narrow down the issue by confirming:
    Issue reproduces for all clients to the database via cman?
    Issue reproduces for all databases via cman?
    Has the CMAN.ora migrated from 9i version?
    Is the CMAN Multiplexing option enabled? Disable option, check results
    CMAN Access control parameters (rules) is use? Disable rules, check results

    CMAN Diagnostics :

    Connection manager can have tracing and logging setup.Following note covers the connection manager diagnostic required for each version of cman, as cman changed between versions 9 and 10g

    Note 579660.1 Troubleshooting Connection Manager.
    Note 733421.1Troubleshooting Guide: TNS-04012: Unable to Start Oracle Connection Manager Instance
    Note 298916.1A Guide to CMAN Configuration for 10g and Newer Releases

    Oracle Names (ONAMES)

    Issues with Oracle names can be with naming resolution method or the names server process.

    Oracle Names Naming Resolution

    Does the issue effects all aliases stored in the names server? Check / comparing working entry to failing entry.
    Alias stored can be resolved via namesctl? Otherwise could be bad entry in the names server.
    Alias created via Net Manager? Use the tool to ensure incorrect data not being used.
    All clients have issue with the alias? Issue could be with cleint, rather than the names server.
    Issue affects all Oracle Names servers? Incorrectly replicated data ?

    Oracle Names Diagnostics :

    Oracle Net level 16-client trace with matching Level 16 Oracle Names server trace.
    Names.log and Sqlnet.log (ORACLE_HOME/network/log)
    RDA output from ORACLE_HOME running Oracle Names
    Oracle Names Startup Issues

    When was the last time the startup worked successfully?
    Is the region database and TNS listener up and running?
    Are the checkpoint files available?(ORACLE_HOME/network/names)
    Running the namesctl startup command as the owner of the Oracle Binaries

    Startup Issues Diagnostics :

    Level-16 Oracle Names Server and namesctl trace of the startup failing
    Truss of start up failing can also assist.

    truss -feao /tmp/truss.log namesctl start
    Names.log(ORACLE_HOME/network/log)
    RDA for Oracle home where Onames is running from.
    Oracle Names Crash / Hang:

    How often is the Hang/crash seen?
    Is there any pattern to the crash (Date/time/peak load) for example?
    Any core file generated on crash?
    CPU / Memory leak for the process? Use tools like TOP / Pmap to montior usage.

    Hang / Crash Diagnostics :

    Level-16 Oracle Names server trace.
    Pstack and/or truss of Oracle names process that is hung

    pstack
    truss -feao /tmp/truss.log -P
    Level-16 Oracle Net client trace for connection attempting naming resolution when onames server hung.
    RDA for Oracle home where Onames is running from.

  4. admin Avatar
    admin

    Troubleshooting Oracle Net
    Applies to:

    Oracle Net Services – Version: 9.2.0.1.0
    Information in this document applies to any platform.
    Purpose

    The aim of this document is to provide a Troubleshooting Guide for Oracle Net, including :

    Client Connection Issues
    Server Connection Issues
    TNS listener
    With Referances to best practices for

    Oracle Net tracing
    Diagnosing Oracle Net Traces
    Last Review Date

    April 30, 2009
    Instructions for the Reader

    A Troubleshooting Guide is provided to assist in debugging a specific issue. When possible, diagnostic tools are included in the document to assist in troubleshooting.
    Troubleshooting Details

    Oracle Net Troubleshooting

    Instructions for the Reader
    The Oracle Net Troubleshooting Guide is provided to assist you in solving Oracle Net issues in a structured manner. The method is based on Oracle Diagnostic Methodology and helps you to avoid trial and error approach. It guides you through a step-by-step method. Diagnostic tools are included in the document to assist in the different troubleshooting steps.

    Step by step approach

    ISSUE CLARIFICATION

    In the issue clarification section it is important to describe the problem as best as possible. What is the problem you need to solve? At the end of the process you should be able to come back to this section to verify if the root cause was found and the solution was provided.

    WHAT IS the problem we are looking at?

    Examples of problem descriptions:

    Connections from 10.2.0.1 Windows clients to standalone 11.1.0.7 RDBMS on Solaris, are not possible via F&A application, erroring with the message TNS-12154. Connection from same client, using SQL*plus is successful from the same ORACLE_HOME.
    Connections to application using Oracle client 10.2.0.4 on Linux, become extremely slow in the afternoon and eventually hang. At the time of the hang, connections directly on the Linux server to the RAC 10.2.0.4 RDBMS also hang. Database has to be re-started to resolve the problem.
    Some users can connect to the 11.1.0.6 database, some not. ORA-12545 received for the 11.1.0.6 Windows SQL*plus clients.
    Note: The problems can be caused due to client connection issues, server connection issues, listener issues or other problems. If this is known already at this stage, it is good to mention this. Otherwise next steps will clarify where the problem exactly resides.

    ISSUE VERIFICATION

    When you have a starting problem description it is time to collect facts in a structured way. First step would be to get an overview of all the facts we have. What information do we have readily available?
    The answers to the following Oracle Net specific questions can potentially help you to solve the problem:

    Please note that for Oracle Net, questions can be more relevant to certain areas, than others. For these reasons the following Key / guidelines can be followed:

    (C) Questions related to client connection issues.
    Issue from a physical client platform, middle tier or an application running, located on server where the database is installed. Where the connection is unable to communicate with the database server, via TCP/IP, has naming resolution or connection handshake failure is started, configuration / setup conflict with RDBMS settings.
    (S) Questions related to server issues.
    Issues establishing session to database, due to backend process failure, setup and / or configuration failures.
    (L) Questions related to TNS Listener issues.
    Issue with the TNS listener connection handshake, process crash, memory leak or CPU spin with the TNSLSNR process.

    What is the problem / what is not a problem?

    What are the symptoms?
    What are the different errors generated?
    What Client and Server platforms reproduce the problem?
    What Client and Server platforms work?
    What 5-digit version of Oracle software reproduces the problem?
    What 5-digit version of Oracle software works?
    (For Windows platform confirm patch number bundle used)
    What products reproduce the issue?
    What products do not reproduce the issue?
    What is the result of TNSping with the same connect string?
    Is this standalone database?
    Is this RAC?

    When is the problem seen / when is the problem not seen?

    Is the problem constant?
    Is the problem reported intermittently?
    Is there any pattern to the failure?
    What resolves the problem?
    How long does the problem last?
    Has this ever worked or is this a fresh installation / setup?
    When did the problem start to fail?

    Where is the problem / Where is the problem not?

    What physical network topology affects the problem?
    What settings, if any allow the connection(s) to work?
    Problem reproduces on another node / server?
    Problem reproduces against another RDBMS?
    (C)Is there other, working TCP/IP communications from effected machines?
    (C)What is the impact on the problem when physically moving client on the network?
    (C)Which clients report the problem?
    (C)Which clients do not report a problem?
    (C)What do the clients have in common?
    Is the Connection model used Dedicated or Shared Server?
    What happens if the opposite connection model is used?
    (S)Is the problem limited to one database in the Oracle home?
    (S)Does the problem reproduce on other servers?
    (S)Is the connection from the database Oracle home via Bequeath working?
    (S)Is the Local connection from the database Oracle home working?
    (S)Is Valid Node checking in use?
    (L)Single or multiple TNS listener affected on server?
    (L)Symptoms / Problem reproduces for TNS listener on another node?
    (L)Is there specific software installed on the non-working node compared to the working node?

    CAUSE DETERMINATION

    The facts listed in the ISSUE VERIFICATION are the starting point for the CAUSE DETERMINATION:
    There are 3 main approaches to take here:

    Use your experience to list possible causes. List the assumptions which needs to be checked in this case
    Start searching for possible causes in My Oracle Support or other Oracle knowledge bases. Use the facts collected above to refine your search criteria.
    Analyze the facts on differences between the working situation and non working situation: Depending on the answers from the questioning above and further investigation from the troubleshooting guides you should be able to list what is different, special, unique between the IS and the IS NOT and also see what is changed and when.

    Examples
    What changes happened around time the first failure / problem was reported?

    New software installed?
    Upgrade done?
    New hardware?
    Network configuration changes?
    What is different between the clients who can connect and those that cannot?
    What changed and could have an impact between the working situation and the current situation?
    What is different to the working Alias and the non-working Alias?
    The output will be a list of potential reasons causing the symptoms: can be a bug, a configuration setting, a conflict with other software, …

    CAUSE JUSTIFICATION

    Evaluate the causes: check the causes against the facts (the IS and the IS NOT observations). This also includes checking the symptoms of the problem against any bug rediscoveries identifying a problem. List potential assumptions you have made. Determine the most probable cause (often the one with the least assumptions or with the most reasonable assumptions).

    For the most probable cause, verify the assumptions and turn them into facts (document them in the Issue Verification part). Some examples:

    If bug XXX then we expect an upgrade from version x to y happened before the symptoms started
    If the configuration file is wrong on client x, and right on client y, we expect it to work if we copy the file
    This looks like same issue as described in note XXX but then we expect also a virus checker installed on the Windows server
    If this cause would be true then another sequence of actions would result in a different outcome: let’s test this via an internal test case

    If the verification fails, go to the next probable cause and repeat the verification.

    If no potential cause stands the justification process, go back to the issue verification and collect more detailed facts. Further diagnostics can be verified. See below in the section Diagnostic Tools)

    POTENTIAL SOLUTIONS

    A brief description of the corrective actions that will remove the cause of the problem: in some cases there is only 1 solution linked to the cause. But in many cases, there are more. Example: install a patch to remove the bug from the system, avoid the problem by working differently, or avoid the problem by setting some parameters.

    POTENTIAL SOLUTION JUSTIFICATION

    Explain why the proposed solution solves the problem.

    Diagnostic Tools

    Each area requires a specific diagnostic path to be followed, which always requires Oracle Net tracing to be enabled. The following notes contain all the parameters available for Oracle Net tracing:

    Generic Oracle Net Tracing

    Note 219968.1SQL*Net, Net8, Oracle Net Services – Tracing and Logging at a Glance
    Note 395525.1How to Enable Oracle SQLNet Client, Server, Listener, Kerberos and External procedure Tracing from Net Manager

    Please note, that enabling Oracle Net Server tracing can produce large amounts of trace, in a very short time frame. Even with cyclic tracing, each process will have the TRACE_FILENO_SERVER value amount of traces produced. Optimal tracing workflow should be to enable tracing, reproduce problem and then disable tracing. Thus limiting amount of time tracing is enabled. If unable to enable trace due to high connection volume, then the following article can assist.

    Note 401134.1How To Limit Connections Generating Trace when Oracle Net Server Enabled

    Other options are to enable tracing when the system is quieter or out of normal business hours.

    Ensure only matching client and server traces are uploaded. Following article explains how to achieve this. Note 374116.1 How to Match Oracle Net Client and Server Trace Files

    Diagnosing Oracle Net traces

    When analyzing Oracle Net traces, key features / steps in the trace need to be reviewed, to narrow down the point of failure / issue. Ensure to review the trace to understand how and what is used for the connection. Points to look for are:

    SQLNET.ORA parameters.
    TNSNAMES.ORA file used.
    Naming resolution method (local, onames, ldap, ezconnect, host)
    Connection model. (Dedicated or shared server)
    Connection handshake completion (Connect, Resend or Redirect, Connect and Accept packets)
    Cross-reference client and server packet flow, checking packet sizes send, received / sent information, timings between client and server processes.
    Ensure completion codes are not mistaken for errors.

    Full details on how to diagnose Oracle Net traces can be found in Note 156485.1 Examining Oracle Net, Net8, SQL*Net Trace Files.

    Please note that multithread application will show thread id before the time stamp column of a net trace. Match the thread id’s to follow the correct flow of information in the trace. Ensure completion codes reported in traces are not mistaken for error codes.

    Client Connection Diagnostics:

    If the problem is specific to client area, Oracle Net Level 16 Client trace capturing the failure / issue.
    If the problem is specific to client and TNS listener handshake failure, Oracle Net Level 16 Client trace capturing the failure / issue with matching TNS listener level 16 trace.
    Sqlnet.log from the client. Default location is ORACLE_HOME/network/log
    Capture environment settings and all net admin files, etc via RDA.

    Please note that JDBC thin client connections cannot be Oracle Net Client traced, but the Oracle Net packet flow can now be JavaNet traced. Note 793415.1 How to Perform the Equivalent of Sqlnet Client Tracing with Oracle JDBC Thin Driver

    Common Client Error Codes:

    Articles to be followed when diagnosing the common error codes:

    Note 114085.1TROUBLESHOOTING GUIDE TNS-12154 TNS could not resolve service name:
    Note 77640.1SERVICE_NAME Parameter – Resolving The ORA-12514 Error
    Note 553328.1Troubleshooting ORA-12545 / TNS-12545 Connect failed because target host or object does not exist

    Server Diagnostics:

    Oracle Net level 16 Client and Server traces.
    Sqlnet.log from the server and client. Default location ORACLE_HOME/Network/log
    Capture environment settings, status, RDBMS information, net admin files, etc via RDA
    Shared server diagnostics follow Note 1005259.6 Shared Server (MTS)
    Diagnostics

    Important note:

    The SQLNET.ORA file is only read once on creation of a process. RDBMS Background process and shared server dispatchers will need to be restarted for parameter changes in the SQLNET.ORA to be picked up. Once a process has started to be traced, tracing will not stop until that the process stops.

    TNS Listener diagnostics

    Oracle Net level 16 Listener tracing. The workflow should be to enable tracing, capture the failure and disable tracing, as quickly as possible.
    RDA output from the ORACLE_HOME where TNS listener is running.
    Listener.log. Covering time period of the problem and a few hours before. Default location is ORACLE_HOME/network/log/.

    Further diagnostics maybe required, see following guides:

    For Crashing TNS Listener follow:
    Note 793844.1Troubleshooting a TNS listener crash

    For Slow TNS listener connections follow:
    Note 557416.1How to Diagnose Slow TNS listener / Connection Performance

    For Hanging TNS listener situations follow:
    Note 230156.1TNSListener Hanging Information to Get For Resolving or Troubleshooting.

    If issues arise from TNS listener tracing at busy / peak times, To further restrict the amount of time the TNS listener is traced, follow method described in Note 751432.1 Further TNS Listener Tracing can be used.

  5. admin Avatar
    admin

    Examples of Troubleshooting Slow Oracle Net Connections
    Applies to:

    Oracle Net Services – Version: 10.2.0.1 and later [Release: 10.2 and later ]
    Information in this document applies to any platform.
    Purpose

    Examples of diagnosing slow connections to database
    Last Review Date

    March 22, 2010
    Instructions for the Reader

    A Troubleshooting Guide is provided to assist in debugging a specific issue. When possible, diagnostic tools are included in the document to assist in troubleshooting.
    Troubleshooting Details

    Reported is slow connections to the database, from remote and bequeath connections.
    Oracle Net client trace, Some points to look for in the trace
    Time gap time stamp column
    Check the start time of the trace.
    Check if the handshake is completed, ie connection has passed the TNS listener?
    When time gap found, check the packets before / after the slowness is seen. What type of packets are they? What information do the packets show?
    What is the function names where the time is lost?
    Example 1

    Oracle Net client trace

    o Starts [22-FEB-2010 03:44:01:127]
    o Connection handshake completed by this point >>

    [22-FEB-2010 03:44:01:321] nscon: got NSPTAC packet
    [22-FEB-2010 03:44:01:321] nsconneg: entry
    [22-FEB-2010 03:44:01:321] nsconneg: vsn=314, gbl=0xa01, sdu=8192, tdu=8192
    [22-FEB-2010 03:44:01:322] nsconneg: normal exit
    [22-FEB-2010 03:44:01:322] nscon: no connect data
    [22-FEB-2010 03:44:01:322] nscon: connect handshake is complete

    o This means no issue with TNS listener
    o 41 second delay here >>

    [22-FEB-2010 03:44:01:361] nsbasic_bsd: 00 00 00 00 30 10 41 55 |….0.AU|
    [22-FEB-2010 03:44:01:361] nsbasic_bsd: 54 48 5F 46 41 49 4C 4F |TH_FAILO|
    [22-FEB-2010 03:44:01:361] nsbasic_bsd: 56 45 52 5F 49 44 00 00 |VER_ID..|
    [22-FEB-2010 03:44:01:361] nsbasic_bsd: 00 00 00 00 00 00 |…… |
    [22-FEB-2010 03:44:01:361] nsbasic_bsd: exit (0)
    [22-FEB-2010 03:44:01:361] nsbasic_brc: entry: oln/tot=0
    [22-FEB-2010 03:44:41:563] nsbasic_brc: type=6, plen=1756
    [22-FEB-2010 03:44:41:563] nsbasic_brc: what=1, tot =1756
    [22-FEB-2010 03:44:41:563] nsbasic_brc: packet dump
    [22-FEB-2010 03:44:41:563] nsbasic_brc: 06 DC 00 00 06 00 00 00 |……..|
    [22-FEB-2010 03:44:41:563] nsbasic_brc: 00 00 08 00 26 00 00 00 |….&…|
    [22-FEB-2010 03:44:41:563] nsbasic_brc: 13 13 41 55 54 48 5F 56 |..AUTH_V|
    [22-FEB-2010 03:44:41:563] nsbasic_brc: 45 52 53 49 4F 4E 5F 53 |ERSION_S|

    o Thats client sending packet (nsbasic_bsd) to the server and waits to receive packet back (nsbasic_brc)
    o This is user authentication issue. Inside the packets at the time of the delay, helps to show the stage the the connection is at
    o Client is sending authentication information

    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 27 0D 41 55 54 48 5F 54 |’.AUTH_T|
    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 45 52 4D 49 4E 41 4C 00 |ERMINAL.|

    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 2D 0F 41 55 54 48 5F 50 |-.AUTH_P|
    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 52 4F 47 52 41 4D 5F 4E |ROGRAM_N|
    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 4D 00 00 00 54 1C 73 71 |M…T.sq|

    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 00 24 0C 41 55 54 48 5F |.$.AUTH_|
    [22-FEB-2010 03:44:01:360] nsbasic_bsd: 4D 41 43 48 49 4E 45 00 |MACHINE.|

    Oracle Net server trace, matched to client via Connection ID value

    o Before delay seen, the server receives packet from the client in timely manner

    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 27 0D 41 55 54 48 5F 54 |’.AUTH_T|
    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 45 52 4D 49 4E 41 4C 00 |ERMINAL.|

    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 2D 0F 41 55 54 48 5F 50 |-.AUTH_P|
    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 52 4F 47 52 41 4D 5F 4E |ROGRAM_N|
    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 4D 00 00 00 54 1C 73 71 |M…T.sq|

    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 00 24 0C 41 55 54 48 5F |.$.AUTH_|
    [000001 22-FEB-2010 03:44:01:360] nsbasic_brc: 4D 41 43 48 49 4E 45 00 |MACHINE.|

    o But then the time loss is shown between these functions

    [000001 22-FEB-2010 03:44:01:370] nassky: entry
    [000001 22-FEB-2010 03:44:01:370] nassky: exit
    [000001 22-FEB-2010 03:44:01:370] nszssk: exit
    [000001 22-FEB-2010 03:44:41:562] nioqsn: entry
    [000001 22-FEB-2010 03:44:41:562] nioqsn: exit
    [000001 22-FEB-2010 03:44:41:562] nioqrc: entry

    Truss of the same slow sqlplus connection, with time stamp.
    Example was taken from HP machine using command
    $tusc -faepo /tmp/tusc.out -T %H:%M:%S sqlplus username/password@net-service-name
    07:15:41 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:15:41 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_1.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:15:55 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:15:55 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_2.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:15:58 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:15:58 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_3.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:06 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:16:06 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_4.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:08 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_5.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:11 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:16:11 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_6.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:12 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_7.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:13 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_8.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:15 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_9.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:16 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_a.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:17 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_b.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:17 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_c.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:19 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_d.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:19 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_e.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:16:29 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:16:29 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_f.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) = 20

    Investigating the error code reported, files, lines, etc in the truss / tusc output:
    o Time lost for audit files

    07:15:41 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_1.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST
    07:15:55 [20162] open(0x9fffffffffff3b20, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ……………………………………. [running]
    07:15:55 [20162] open(“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_2.aud”, O_RDWR|O_CREAT|O_EXCL|0x800, 0660) ERR#17 EEXIST

    $ cat /usr/include/sys/errno.h | grep EEXIST
    #define EEXIST 17 /* File exists */

    o In this case the Error 17 is due to Oracle trying create the audit file, which already exists in the directory. Oracle will not overwrite the old audit file and therefore it trying to create new audit file.

    o Oracle trying to create following audit file

    (“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_1.aud”

    o Since this audit file exist already OS throw err 17
    o And Oracle tries to create with following file

    (“/u01/app/oracle/admin/ORCL/adump/orcl_ora_20162_2.aud”

    o This file already exist, this pattern is repeated as Oracle keeps trying prefix _n (1 to 9) then it will start prefixing (a to z)
    Solutions here included purge of the old audit files, disabling auditing, etc

    Example 2
    Oracle Net client trace

    o Client trace starts here

    [12-MAR-2010 11:00:19:569]

    o Accept packet seen in the trace, NSPTAC is accept packet.

    [12-MAR-2010 11:00:19:600] nsprecv: packet dump
    [12-MAR-2010 11:00:19:600] nsprecv: 00 20 00 00 02 00 00 00 |……..|
    [12-MAR-2010 11:00:19:600] nsprecv: 01 38 00 00 08 00 7F FF |.8……|
    [12-MAR-2010 11:00:19:600] nsprecv: 01 00 00 00 00 20 41 41 |……AA|
    [12-MAR-2010 11:00:19:600] nsprecv: 00 00 00 00 00 00 00 00 |……..|
    [12-MAR-2010 11:00:19:600] nsprecv: normal exit
    [12-MAR-2010 11:00:19:600] nscon: got NSPTAC packet

    o This is important section of the trace to review, as it means the TNS listener is not the problem.Connection handshake has been completed at this point.

    o After accept packet, a time gap is seen for nttrd,which is basic TCP read >>

    [12-MAR-2010 11:00:19:600] nttrd: entry
    [12-MAR-2010 11:00:22:772] nttrd: socket 1856 had bytes read=215

    o So looking at bigger picture, what is going on at the around the time gap?
    o Packet sent by the client, before delay (full packet removed, just so note not filled to wasted information)

    [12-MAR-2010 11:00:19:600] nspsend: 00 25 00 00 06 00 00 00 |.%……|
    [12-MAR-2010 11:00:19:600] nspsend: 00 00 01 06 05 04 03 02 |……..|
    [12-MAR-2010 11:00:19:600] nspsend: 01 00 49 42 4D 50 43 2F |..IBMPC/|
    [12-MAR-2010 11:00:19:600] nspsend: 57 49 4E 5F 4E 54 2D 38 |WIN_NT-8|
    [12-MAR-2010 11:00:19:600] nspsend: 2E 31 2E 30 00 |.1.0. |

    o Receiving packet after time gap >>

    [12-MAR-2010 11:00:22:772] nsprecv: 00 D7 00 00 06 00 00 00 |……..|
    [12-MAR-2010 11:00:22:772] nsprecv: 00 00 01 06 00 78 38 36 |…..x86|
    [12-MAR-2010 11:00:22:772] nsprecv: 5F 36 34 2F 4C 69 6E 75 |_64/Linu|
    [12-MAR-2010 11:00:22:772] nsprecv: 78 20 32 2E 34 2E 78 78 |x.2.4.xx|
    [12-MAR-2010 11:00:22:772] nsprecv: 00 67 03 01 0A 00 66 03 |.g….f.|
    [12-MAR-2010 11:00:22:772] nsprecv: 40 03 01 40 03 66 03 01 |@[email protected]..|
    [12-MAR-2010 11:00:22:772] nsprecv: 66 03 48 03 01 48 03 66 |f.H..H.f|
    [12-MAR-2010 11:00:22:772] nsprecv: 03 01 66 03 52 03 01 52 |..f.R..R|
    [12-MAR-2010 11:00:22:772] nsprecv: 03 66 03 01 66 03 61 03 |.f..f.a.|
    [12-MAR-2010 11:00:22:772] nsprecv: 01 61 03 66 03 01 66 03 |.a.f..f.|
    [12-MAR-2010 11:00:22:772] nsprecv: 1F 03 08 1F 03 66 03 01 |…..f..|
    [12-MAR-2010 11:00:22:772] nsprecv: 00 64 00 00 00 60 01 24 |.d…`.$|
    [12-MAR-2010 11:00:22:772] nsprecv: 0F 05 0B 0C 03 0C 0C 05 |……..|
    [12-MAR-2010 11:00:22:772] nsprecv: 04 05 0D 06 09 07 08 05 |……..|
    [12-MAR-2010 11:00:22:772] nsprecv: 05 05 05 05 0F 05 05 05 |……..|
    [12-MAR-2010 11:00:22:772] nsprecv: 05 05 0A 05 05 05 05 05 |……..|
    [12-MAR-2010 11:00:22:772] nsprecv: 04 05 06 07 08 08 23 47 |……#G|
    [12-MAR-2010 11:00:22:772] nsprecv: 23 47 08 11 23 08 11 41 |#G..#..A|

    o The delay is client waiting for information from the database to be returned. ie here we see linux version inside the data packet
    o We then start to investigate what the database / server is doing and monitor RDBMS performance, etc
    o Here the issue turned out to be CPU issue on the server, which was a lack of resources on the server.
    Example 3

    Oracle Net client trace

    Trace starts here >>

    [17-APR-2010 15:15:00:336]

    o Start of the connection handshake and the client sends connect packet to TNS listener. NSPTCN is the connect packet

    [17-APR-2010 15:15:00:370] nscon: doing connect handshake…
    [17-APR-2010 15:15:00:370] nscon: sending NSPTCN packet

    o Time gap is then see between connect and resend packets. So the client is waiting to hear back from the TNS listener.

    [17-APR-2010 15:15:00:371] nsprecv: reading from transport…
    [17-APR-2010 15:15:00:371] nttrd: entry
    [17-APR-2010 15:15:05:725] nttrd: socket 9 had bytes read=8
    [17-APR-2010 15:15:05:725] nttrd: exit
    [17-APR-2010 15:15:05:725] nsprecv: 8 bytes from transport
    [17-APR-2010 15:15:05:726] nsprecv: tlen=8, plen=8, type=11
    [17-APR-2010 15:15:05:726] nsprecv: packet dump
    [17-APR-2010 15:15:05:726] nsprecv: 00 08 00 00 0B 00 00 00 |……..|
    [17-APR-2010 15:15:05:726] nsprecv: normal exit
    [17-APR-2010 15:15:05:726] nscon: got NSPTRS packet

    NSPTRS is resend packet, depending on connection model, version and platform, this can be a redirect packet (NSPTRD). In this case, we now need to investigate what the TNS listener is doing. More than likley the bequeath of the shadow process is the the problem.

  6. admin Avatar
    admin

    Solving Firewall Problems on Windows

    PURPOSE

    This article describes how to get around firewall problems with SQL*Net/Net*8
    on Windows Servers

    SCOPE & APPLICATION

    External

    RELATED DOCUMENTS

    Note:62528.1 Using Connection Manager as a MultiProtocol Interchange

    A firewall is a secure gateway that controls the traffic into and out of a
    company’s internal network. Firewalls can cause problems when a SQL*Net client
    inside the firewall tries to connect to an Oracle database on NT outside the
    firewall, or vice versa.

    Listeners on NT commonly listen on port 1521. It is a common misconception
    that if you allow access in to and out of the firewall by enabling access
    through port 1521, that SQL*Net clients will be able to connect. To understand
    why the connect will fail, it is necessary to understand how a SQL*Net
    connection on NT works.

    When a client initiates a connect, a TCP connection is established with port
    1521. A TNS CONNECT packet is then sent to the listener. On UNIX systems the
    listener process will fork a new Oracle process to deal with the new incoming
    connection. With UNIX, forked processes will inherit the resources owned by the
    parent process, in other words file handles and TCP sockets.

    Earlier releases of SQL*Net for Windows NT used the WINSOCK V1.1 API. With this
    version of WINSOCK there is no capabaility of passing a TCP socket between two
    processes, and no way to inherit a TCP socket. To work around this restriction
    a new thread of execution is created by the main Oracle process and a local
    connection is made between the listener and this new thread. The newly created
    Oracle thread randomly selects a new TCP port, for example port 1087, to use
    for the connection request and informs the listener of the new port to be used.

    The listener now needs to inform the client that they need to REDIRECT the
    connection attempt to this newly selected networking endpoint. The listener
    now sends a TNS REDIRECT packet to the client with details of the new port to
    reconnect to. The client drops the existing TCP connection and then issues a
    TCP Connect sequence to the new TCP port, and this is then followed by a TNS
    Connect packet. If all is well and the Oracle server is able to process the
    incoming connection request, then the server thread will respond with a TNS
    ACCEPT packet and data will begin to flow.

    So, if you enable connects through port 1521 on your firewall, you can now see
    that after the REDIRECT packet has been sent to the client, the connect will
    fail as port 1087 is not enabled in the firewall. As the REDIRECT port that
    gets generated is entirely at random, you cannot enable access through multiple
    ports in the firewall as you have no idea which ports will get allocated.

    To workaround this problem there are several options:

    1. This step should only be performed by the firewall administrator and only
    if they feel this is a viable workaround for their company. Otherwise,
    skip to step 2.

    Configure the firewall to limit IP addresses rather than port numbers. This
    is not a very secure option.

    2. Use Connection Manager so the TNS CONNECT following the REDIRECT happens
    at the server side of the firewall.
    For further information on Connection Manager and how to configure it,
    refer to Note:62528.1.

    3. If you are on Oracle 8 or higher, you can use a WINSOCK V2 API feature called
    Shared Sockets. This allows a socket to be shared (or passed) between multiple
    processes. To use this functionality in a single Oracle Home enviroment, set
    USE_SHARED_SOCKET = TRUE in the HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE section
    of the registry. If you are using Multiple Oracle Homes, change to the
    desired Oracle 8 Home and view the oracle.key file in ORACLE_HOME\BIN to
    find which registry key to add USE_SHARED_SOCKET to.

    Please see Note:124140.1 for greater detail on this Windows feature.

    Also, there is a WARNING when using this method:
    Please note that as WINSOCK V2 allows a socket to be shared between multiple
    processes, you cannot restart the listener without taking the database down
    first (termination of all existing connections).

  7. maclean Avatar
    maclean

    /*
    $Header: tnsapi.c 30-dec-97.22:19:11 scotmac Exp $
    */

    /*
    NAME
    tnsapi – Transport Network Session Application Program Interface.

    DESCRIPTION
    TNS engine.

    PUBLIC FUNCTIONS
    tnsapi()

    PRIVATE FUNCTIONS
    tnsdopen()
    tnsdclose()
    tnsdsend()
    tnsdrecv()
    tnsdcntl()

    MODIFIED
    hnellore 08/14/98 – prt_exception-709339-change tnsapi func decalration un
    scotmac 11/18/97 – Handle is ALWAYS allocated on open and deallocated on
    mberner 08/21/97 – fixup log information
    smckinle 07/08/97 – OSD reference shouldn’t be in generic file.
    mberner 06/26/97 – fix bug #490613
    mberner 06/18/97 – fix bug #491875
    mhill 06/12/97 – clean up rcs header
    jchangav 09/27/96 – Merged from NETWORK_3.0.2.0.0_SOLARIS_960926
    aswang 11/25/96 – porting exception for bug#425421
    jgraham 09/23/96 – fix compilation error
    jgraham 09/20/96 – bug 355689
    jchangav 09/10/96 – Merge NT changes from 3.0.1
    */

    /*************************************************************************/
    /* Include headers */
    /*************************************************************************/

    #include

    #ifndef TNSAPI_BEFORE_V23
    # ifndef SLTS_ORACLE
    # include
    # endif
    #endif

    #ifndef SNLSTD
    #include
    #endif

    #ifndef NL
    # include
    #endif

    #ifndef NSI
    # include
    #endif

    #ifndef NSGBL
    # include
    #endif

    #ifndef NNCI
    # include
    #endif

    #ifndef NNFS_ORACLE
    # include
    #endif

    #ifndef NRI
    # include
    #endif

    #ifndef TNSAPI0
    # include
    #endif

    #ifndef TNSAPI
    # include
    #endif

    /*************************************************************************/
    /* Local function prototypes */
    /*************************************************************************/
    /* DISABLE check_naming */
    /*
    * These are just mirror images of
    * tnsopen()
    * tnsclose()
    * tnssend()
    * tnsrecv()
    *
    * It is for the sake of implementation. We don’t want to implement everything
    * in just one function. See tns.h for the usage and descriptions of these
    * functions.
    */

    /*
    TNS Do Open: initialize the connection handle
    */
    STATICF sword tnsdopen ( /*_ tnshdl **handlep, const text *name _*/ );

    /*
    TNS Do Close: close the connection handle
    */
    STATICF sword tnsdclose(/*_ tnshdl **handlep _*/);

    /*
    TNS Do Send: send data to the connection handle
    */
    STATICF sword tnsdsend(/*_ tnshdl *handle, ub1 *data, size_t *length _*/);

    /*
    TNS Do Receive: receive data from the conneciton handle
    */
    STATICF sword tnsdrecv(/*_ tnshdl *handle, ub1 *data, size_t *length _*/);

    /*
    TNS Do Cntl: control functions
    */
    STATICF sword tnsdcntl VAFP((sword operation, tnshdl *hdl, … ));

    /*
    TNS Do init: Initialize the NL global area
    */
    STATICF dvoid *tnsdinit(/*_ void _*/);

    /*
    TNS Do Global Initialization: Initialize TNS API context in NPD global area
    */
    STATICF void tnsdingbl(/*_ dvoid *npd, dvoid *gbhp _*/);

    /*
    TNS Do Terminate: symmetric to tnsdinit()
    */
    STATICF void tnsdtrm(/*_ dvoid *npd _*/);

    /*
    TNS Do global terminate: symmetric to tnsdingbl()
    */
    STATICF void tnsdtrgbl(/*_ tnsgblctx ** _*/);

    /*************************************************************************/
    /* Public Functions */
    /*************************************************************************/

    /*
    TNS API: execute the TNS control operation. This is the TNS engine.
    */

    #if defined(A_OSF) || defined(HPUX)
    int tnsapi (operation)
    int operation;
    #else
    int tnsapi VAFD((operation VAAELLIPSIS))
    int operation VAFDAD
    VAFDELLIPSIS
    #endif /* A_OSF || HPUX */
    {
    va_list list;
    tnshdl **hdlp;
    tnshdl *hdl;
    text *name;
    sword ret;
    ub1 *data;
    size_t *len;
    sword cmd;

    VASTART(list, operation);
    /*
    * depending on the operation, the number and data type of argements are
    * different
    */
    switch(operation)
    {
    case TNSAPIOOPEN:
    hdlp = va_arg(list, tnshdl **);
    name = (text *)va_arg(list, char *);
    /* sanity check. The user should not pass in a NULL tnsp */
    if (hdlp)
    {
    ret = tnsdopen(hdlp, (text *)name);
    }
    else
    {
    ret = NULHDL_TNSAPIE;
    }
    break;

    case TNSAPIOCLOSE:
    hdlp = va_arg(list, tnshdl **);
    /* sanity check. The user should not pass in a NULL tnsp */
    if (hdlp)
    {
    ret = tnsdclose(hdlp);
    }
    else
    {
    ret = NULHDL_TNSAPIE;
    }
    break;

    case TNSAPIOSEND:
    hdl = va_arg(list, tnshdl *);
    data = va_arg(list, ub1 *);
    len = va_arg(list, size_t *);
    /* sanity check. The user should not pass in a NULL tnsp */
    if (hdl)
    {
    ret = tnsdsend(hdl, data, len);
    }
    else
    {
    ret = NULHDL_TNSAPIE;
    }
    break;

    case TNSAPIORECV:
    hdl = va_arg(list, tnshdl *);
    data = va_arg(list, ub1 *);
    len = va_arg(list, size_t *);
    /* sanity check. The user should not pass in a NULL tnsp */
    if (hdl)
    {
    ret = tnsdrecv(hdl, data, len);
    }
    else
    {
    ret = NULHDL_TNSAPIE;
    }
    break;

    /*
    * Added to test listen/anser automatically, should be removed
    * in the first release
    */
    /* case TNSAPIOLSN:
    hdl = va_arg(list, tnshdl *);
    if (hdl)
    ret = tnsdcntl(TNSAPIOLSN, hdl);
    else
    ret = NULHDL_TNSAPIE;
    break;
    */
    /* end of added code */

    case TNSAPICTL:
    hdl = va_arg(list, tnshdl *);
    cmd = va_arg(list, sword);
    if (hdl)
    {
    ret = tnsdcntl(cmd, hdl);
    }
    else
    {
    ret = NULHDL_TNSAPIE;
    }
    break;

    default:
    /*
    * Addtional control function calls, e.g., nonblocking, flushing, will
    * be added in future releases.
    */
    ret = INVOP_TNSAPIE;
    break;
    }

    va_end(list);
    return ((int)ret);
    }

    /*
    */
    STATICF sword tnsdopen(handlep, name)
    tnshdl **handlep;
    const text *name;
    {
    tnshdl *hdl = *handlep;
    dvoid *npd = NULL; /* NPD global */
    dvoid *gbhp = NULL; /* NS per-user global */
    size_t addbufl;
    size_t canbufl;
    sword ecode;
    uword retcode = 0;
    size_t namelen;
    text namebuf[NNCIDNMAX];
    text addbuf[NNCIDNMAX];
    text canbuf[NNCIDNMAX];

    /*
    * Allocate the handle.
    */
    if ( (hdl = (tnshdl *)snlmalc(1, sizeof(tnshdl))) == (tnshdl *)NULL)
    {
    return((sword)MALFAIL_TNSAPIE);
    }
    else
    {
    CLRSTRUCT(*hdl);
    *handlep = hdl;
    }

    /*
    * Check the tnsapi_nlstdgd in NPD global, if it is null, then this is
    * the first connection handle of this user. We need
    * to allocate the tnsapi global in NPD global area
    */
    /*
    * Initialization for, e.g. trace in NL global area, and get the NPD
    * global
    */
    if (!(npd = tnsdinit()) )
    {
    tnsdtrm(npd);
    snlmfre((dvoid *)hdl);
    *handlep = (tnshdl *)NULL;
    return((sword)NLINIFAIL_TNSAPIE);
    }

    TNSLOCKMUTEX(npd);
    if ( (hdl->gbl_tnshdl = (dvoid *)TNSGCTX(npd)) == NULL)
    {
    /*
    * This is the first connection handle of this user
    * so we need to allocate the NPD global
    */
    if ( (hdl->gbl_tnshdl = (dvoid *)snlmal(sizeof(tnsgblctx))) == NULL)
    {
    snlmfre((dvoid *)hdl);
    *handlep = (tnshdl *)NULL;
    TNSUNLOCKMUTEX(npd);
    return ((sword)MALFAIL_TNSAPIE);
    }
    TNSSCTX(npd, hdl->gbl_tnshdl);

    /* Initialize the NS per-user global area, check for errors */
    nsgblini(npd, &gbhp, NULLP(nsind));

    /* Initialize TNS API global area, check for errors */
    tnsdingbl(npd, gbhp);
    }
    TNSUNLOCKMUTEX(npd);

    /* start connection out in blocking mode */
    hdl->io_tnshdl = IO_TNSHDL_BLOCKING;

    /* enable the tracing */
    {
    NLTRDEFINE(“tnsopen”, npd, NLDTTNSAPI, NLDTTDUMMY, NLDTTDUMMY);
    NLTRENTER();

    /*
    * check if this is a client or a server, create the NV binding
    * if necessary
    */
    if (!name)
    {
    hdl->svr_tnshdl = TRUE;
    hdl->service_tnshdl = NULLP(text);
    }
    else
    {
    namelen = strlen((char *)name);
    /*
    * In the first release, we will specify that listener has to be
    * running in order to make a connection. In future enhancement,
    * we are going to support the case in which the listener is not
    * available. The implementation to accomodate both cases is done
    * for the purpose of testing, however.
    *
    * If name is not NULL, it could be either client or server,
    * In the case of a server, name is the listening end point.
    */

    /* resolve the NV string */
    if ( *name == NLNVBEGDE)
    {
    /* it is an explicit NVstring, so use it directly */
    NLTRUSR((NLTRTRC, “Name is already an NVstring.\n”));
    if( (hdl->service_tnshdl = (text *)snlmal(namelen +1))
    == (text *)NULL)
    {
    retcode = MALFAIL_TNSAPIE;
    }
    else
    {
    DISCARD strcpy((char *)hdl->service_tnshdl,
    (const char *)name);
    NLTRUSR((NLTRTRC, “Name is %s.\n”, hdl->service_tnshdl));
    /*
    * in the first release, not null name always indiate that
    * this is the client
    */
    hdl->svr_tnshdl = FALSE;
    }
    }
    else
    {
    /* try to resolve it */
    if (namelen >= NNCIDNMAX)
    {
    NLTRFTL((NLTRTRC, “Service name is too long.\n”));
    retcode = NMTOOLONG_TNSAPIE;
    }
    else
    {
    DISCARD memcpy((dvoid *)namebuf, (const dvoid *)name,
    namelen + 1);

    if (ecode = nnfsn2a(npd,
    namebuf, (size_t)NNCIDNMAX, &namelen,
    addbuf, (size_t)NNCIADMAX, &addbufl,
    canbuf, (size_t)NNCIDNMAX, &canbufl))
    {
    /* Signal error, write error into trace steam*/
    NLTRFTL((NLTRTRC,
    “Failed to resolve service name.\n”));
    retcode = NMRESFAIL_TNSAPIE;
    }
    else
    {
    if ((hdl->service_tnshdl =
    (text *)snlmal(strlen((const char *)addbuf)+1) )
    == (text *)NULL)
    {
    retcode = MALFAIL_TNSAPIE;
    }
    else
    {
    DISCARD strcpy((char *)hdl->service_tnshdl,
    (const char *)addbuf);
    NLTRUSR((NLTRTRC,
    “Name is %s.\n”, hdl->service_tnshdl));
    /*
    * in the first release, not null name
    * always indiate that this is the client
    */
    hdl->svr_tnshdl = FALSE;
    }
    } /* if nnfsn2a */
    } /* if namelen */
    } /* if *name == NLNVBEDGE */
    } /* if !name */

    /* Increase the count in con_tnsgblctx */
    if (retcode == 0)
    {
    TNSLOCKMUTEX(npd);
    ((tnsgblctx *)(hdl->gbl_tnshdl))->con_tnsgblctx++;
    TNSUNLOCKMUTEX(npd);

    if ((hdl->res_tnshdl=(tnsres *)snlmal(sizeof(tnsres)))
    != (tnsres *)NULL)
    CLRSTRUCT(*(hdl->res_tnshdl));
    else
    {
    retcode = MALFAIL_TNSAPIE;
    }
    }

    if (retcode != 0 )
    {
    if (hdl->service_tnshdl)
    {
    snlmfre((dvoid *)hdl->service_tnshdl);
    }

    snlmfre((dvoid *)hdl);
    *handlep = (tnshdl *)NULL;
    }
    NLTREXIT();
    }
    return((sword)retcode);
    }

    /*
    * Initialize TNS API context in NPD global area
    */
    STATICF void tnsdingbl(npd, gbhp)
    dvoid *npd;
    dvoid *gbhp;
    {
    tnsgblctx *ctx;

    /* sanity check */
    if (npd)
    {
    ctx = TNSGCTX(npd);
    /* This should have been allocated already */
    if (ctx)
    {
    /*
    * assign the NS per user global to the corresponding field in ctx
    * and initialize the number of open connectins of this user to 0
    */
    ctx->gbh_tnsgblctx = (nsgbu *)gbhp;
    ctx->con_tnsgblctx = 0;
    ctx->npd_tnsgblctx = npd;
    }
    }
    return;
    }

    /*
    * Initialize the NL global area for, e.g., tracing
    * return the NPD global pointer
    */
    STATICF dvoid *tnsdinit()
    {
    dvoid *npd = NULL;
    size_t curdirl;
    serc se;
    size_t actesize = 0;
    nlstdatt init;
    text curdir[TNSAPI_MFN];
    text reason[TNSAPI_ERRBUFL];

    /* clear the init structure */
    CLRSTRUCT(init);

    /* initialize parameter files: system and local, trace, … */
    init.mask_nlstdatt = NLSTDATT_SYSPARMS | NLSTDATT_TRACE |
    NLSTDATT_PF_ERRORS_OK;

    /* system sqlnet.ora */
    init.syspdesc_nlstdatt.nlfnsname = (text *)TNSAPI_PFILENAME;
    init.syspdesc_nlstdatt.nlfnssize = TNSAPI_PFILENAMEL;
    init.syspdesc_nlstdatt.nlfnename = (text *)TNSAPI_PEXT;
    init.syspdesc_nlstdatt.nlfnesize = TNSAPI_PEXTL;

    /* trace unique */
    bis(init.trcdesc_nlstdatt.nlfnflag, NLFNUNIQUE);

    /* trace extension */
    init.trcdesc_nlstdatt.nlfnename = (text *)TNSAPI_TEXT;
    init.trcdesc_nlstdatt.nlfnesize = TNSAPI_TEXTL;

    /*
    * since we could not distinguish the client and the server at this stage,
    * we could not name the client and server trace differently by setting up
    * trcdesc_nlstdatt.nlfnsname field. The traces will be distinguished by
    * their uniqueness. The default trace file would be: tnsapi.trc_
    */
    init.trcdesc_nlstdatt.nlfnsname = (text *)TNSAPI_TFILENAME;
    init.trcdesc_nlstdatt.nlfnssize = TNSAPI_TFILENAMEL;

    /* default trace file directory is the current directory*/
    DISCARD snlfncdir(&se, curdir, sizeof(curdir), &curdirl);
    init.trcdesc_nlstdatt.nlfndname = (text *)curdir;
    init.trcdesc_nlstdatt.nlfndsize = curdirl;
    init.trcparms_nlstdatt[NLSTDGO_TRACE_FILE] = (text *)TNSAPI_TRCFNAME;
    init.trcparms_nlstdatt[NLSTDGO_TRACE_DIR] = (text *)TNSAPI_TRCDNAME;
    init.trcparms_nlstdatt[NLSTDGO_TRACE_LEVEL] = (text *)TNSAPI_TRCLEVEL;

    #ifndef TNSAPI_BEFORE_V23
    /* by default, it is thread safe */
    init.threadsafe_nlstdatt = NLSTDATT_THREAD_SAFE;
    #endif

    if (nlstdgg(&npd, &init, reason, TNSAPI_ERRBUFL, &actesize))
    {
    return ((dvoid *)0);
    }

    return(npd);
    }

    /*
    * Close the tns connection, reset the tns api handle.
    */
    STATICF sword tnsdclose(handlep)
    tnshdl **handlep;
    {
    tnshdl *hdl = *handlep;
    tnsgblctx *ctx;
    dvoid *npd;

    /* sanity check */
    if (hdl)
    {
    if (! (ctx = (tnsgblctx *)hdl->gbl_tnshdl))
    {
    return((sword)HDLUNINI_TNSAPIE);
    }
    npd = ctx->npd_tnsgblctx;

    {
    NLTRDEFINE(“tnsclose”, npd, NLDTTNSAPI, NLDTTDUMMY, NLDTTDUMMY);
    NLTRENTER();
    /*
    * check if the connections is open.
    */
    if (hdl->cxd_tnshdl)
    {
    /* close down this connection, and reset cxd_tnshdl */
    DISCARD nsdisc(hdl->cxd_tnshdl, NSFIMM);
    snlmfre((dvoid *)hdl->cxd_tnshdl);
    hdl->cxd_tnshdl = (nscxd *)NULL;
    }

    /*
    * free up the memory: service, error stack
    */
    if (hdl->service_tnshdl)
    snlmfre((dvoid *)hdl->service_tnshdl);
    if (hdl->res_tnshdl)
    snlmfre((dvoid *)hdl->res_tnshdl);

    /*
    * If tnsopen() succeeded but the first tnssend()/tnsrecv()
    * failed, nsgbltrm(), nlstdstp() still need to be called.
    */
    /* We will get a ctx back if tnsopen() succeeded */

    TNSLOCKMUTEX(npd);

    /* if there are other open connections of this user */
    if (–ctx->con_tnsgblctx >= 0)
    {
    /* if this is the last open connection of this user */
    if (ctx->con_tnsgblctx == 0)
    {
    /* Terminate NS per user global context */
    nsgbltrm((dvoid *)ctx->gbh_tnsgblctx);

    /* Reset the global area of TNS API in nlstdgd */
    TNSSCTX(ctx->npd_tnsgblctx, NULL);

    /* Terminate TNS API global context */
    tnsdtrgbl((tnsgblctx **)(&(hdl->gbl_tnshdl)));

    NLTREXIT();
    /* Shutdown the NL facilities initialized with nlstdgg() */
    tnsdtrm(npd);
    npd = 0;
    }
    /* this is not the last open connection */
    else
    {
    /* only decrease the global counter of pointers to
    the NPD global */
    nlstdtrm(&(ctx->npd_tnsgblctx));
    NLTREXIT();
    }
    }
    if (npd)
    TNSUNLOCKMUTEX(npd);

    /*
    * Free the handle and reset
    */
    snlmfre((dvoid *)hdl);
    *handlep = (tnshdl *)NULL;
    }
    return(0);
    }
    }

    /*
    * call nlstdstp, symmetric to nlstdgg() in tnsdinit()
    */
    STATICF void tnsdtrm(npd)
    dvoid *npd;
    {
    nlstdstp(npd);
    return;
    }

    /*
    * Free up the memory, reset the pointer
    */
    STATICF void tnsdtrgbl(tnsgbl)
    tnsgblctx **tnsgbl;
    {
    snlmfre((dvoid *)(*tnsgbl));
    *tnsgbl = (tnsgblctx *)NULL;
    return;
    }

    /*
    * Send data over the handle. Connection is first establised
    * on the client side before data is sent. It is an error for
    * the server to call tnssend() right after tnsopen()
    */
    STATICF sword tnsdsend(hdl, data, length)
    tnshdl *hdl;
    ub1 *data;
    size_t *length;
    {
    tnsgblctx *ctx = (tnsgblctx *)hdl->gbl_tnshdl; /* TNS API global context */
    nscxd *cxd; /* NS context */
    text *address = hdl->service_tnshdl; /* service name */
    tnsres *tres = hdl->res_tnshdl; /* error stack */
    dvoid *gbhp; /* NS per user global */
    dvoid *npd; /* NPD global */
    sword retcode = 0;

    /* if the global handle has not been allocated, can not call this
    function */
    if ( ctx == (tnsgblctx *)NULL)
    {
    /* Signal error, write error message into trace stream */
    return((sword)HDLUNINI_TNSAPIE);
    }

    gbhp = (dvoid *)ctx->gbh_tnsgblctx;
    npd = ctx->npd_tnsgblctx;

    {
    NLTRDEFINE(“tnssend”, npd, NLDTTNSAPI, NLDTTDUMMY, NLDTTDUMMY);
    NLTRENTER();

    /*
    * if this is the first call to tnssend(), no cxd has been
    * allocated yet
    */
    if ( hdl->cxd_tnshdl == (nscxd *)NULL)
    {

    /*
    * Check if this is the client or the server,
    * Client: try to establish the connection
    * Server: it is an error since server must first call tnsrecv()
    */

    if ( !hdl->svr_tnshdl )
    {
    /* This is the client */

    if ((cxd = (nscxd *)snlmal(sizeof(nscxd))) == (nscxd *)NULL)
    {
    retcode = MALFAIL_TNSAPIE;
    }
    else
    {
    nsinfo info;
    nscnd cndo, cndi;
    text buf[TNSAPI_CONBUFL];
    buf[0] = ”;
    /*
    * initialize the structures: cxd, tres
    */
    CLRSTRUCT(*cxd);

    CLRSTRUCT(info);
    CLRSTRUCT(cndo);
    CLRSTRUCT(cndi);

    NSSETCND(&cndo, address);
    NSINICND(&cndi, buf, sizeof(buf));
    NSINFENABLENA(&info);

    /* making connection, with routing */
    if (nricall(gbhp,
    cxd,
    &cndo,
    &cndi,
    &info,
    &(cxd->nscxdres)) nscxdres
    * snlmfre((dvoid *)cxd);
    */
    NLTRUSR((NLTRTRC, “Client connect request failed.\n”));
    CPSTRUCT(tres->ns_tnsres, cxd->nscxdres);
    snlmfre((dvoid *)cxd);
    retcode = tres->res_tnsres = CONFAIL_TNSAPIE;
    }
    else
    {
    hdl->cxd_tnshdl = cxd;
    }
    }
    } /* if !hdl->svr_tnshdl */
    else
    {
    /*
    * I am the server
    * server should NOT call tnsapi_send() until the connection is
    * established.
    * write the error message in to trace stream
    * set (tnsres *res) to indicate the error
    */
    NLTRUSR((NLTRTRC,
    “Server should call tnsrecv() first to establish connection.\n”));
    retcode = tres->res_tnsres = INVSVROP_TNSAPIE;
    }
    }

    /* Set connection into nonblocking mode if it has been requested
    by a call before the connection was actually established –
    the default was blocking */
    if (!retcode && (hdl->io_tnshdl == IO_TNSHDL_NONBLOCKING))
    {
    retcode = tnsdcntl(TNSAPICNONBLOCKING, hdl);
    }

    if ( !retcode )
    {
    /*
    * Connection has been established, client/server wants to
    * send data. Flush the data to transport, since the
    * default flush mode in NS is not flushing on send
    */
    if ((retcode =
    nssend(hdl->cxd_tnshdl, NSWDATA, data, length, NSFFLUSH))
    != 0)
    {
    if (hdl->cxd_tnshdl->nscxdres.nsresns == NSEWOULDBLOCK)
    {
    /* we’re in nonblocking mode and would block… */
    retcode = tres->res_tnsres = WOULDBLOCK_TNSAPIE;
    }
    else
    {
    /*
    * Send failed, set the TNS API error and the NS error
    */
    NLTRUSR((NLTRTRC, “Underlying send command failed.\n”))
    retcode = tres->res_tnsres = SDFAIL_TNSAPIE;
    }
    CPSTRUCT(tres->ns_tnsres, hdl->cxd_tnshdl->nscxdres);
    }
    }
    NLTREXIT();
    }
    return(retcode);
    }

    /*
    * Receive data over connection handle. Connection is first established
    * on the server side before data is received. It is an error for the
    * client to call tnsrecv() after tnsopen().
    */
    STATICF sword tnsdrecv(hdl, data, length)
    tnshdl *hdl;
    ub1 *data;
    size_t *length;
    {
    tnsgblctx *ctx = (tnsgblctx *)hdl->gbl_tnshdl; /* TNS API global context */
    nscxd *cxd; /* NS context */
    text *address = hdl->service_tnshdl; /* service name */
    tnsres *tres = hdl->res_tnshdl; /* error stack */
    dvoid *gbhp; /* NS per user global */
    sword retcode = 0;
    dvoid *npd; /* NPD global */
    ub1 what;

    /* if the global handle has not been allocated, can’t call this function */
    if ( ctx == (tnsgblctx *)NULL)
    {
    /* Signal error, write error message into trace stream */
    return((sword)HDLUNINI_TNSAPIE);
    }

    gbhp = (dvoid *)ctx->gbh_tnsgblctx;
    npd = ctx->npd_tnsgblctx;

    {
    NLTRDEFINE(“tnsrecv”, npd, NLDTTNSAPI, NLDTTDUMMY, NLDTTDUMMY);
    NLTRENTER();
    /*
    * if this is the first call to tnsrev(), no cxd has been allocated yet
    */
    if ( hdl->cxd_tnshdl == (nscxd *)NULL)
    {
    /*
    * Check if this is the client or the server,
    * Server: try to establish the connection.
    * Client: it is an error since client must first call tnssend()
    */
    if ( hdl->svr_tnshdl )
    {
    /* This is the server */
    if ((cxd = (nscxd *)snlmalc(1, sizeof(nscxd)))==(nscxd *)NULL)
    {
    retcode = MALFAIL_TNSAPIE;
    }
    else
    {
    nsinfo info;
    CLRSTRUCT(info);
    NSINFENABLENA(&info);

    /*
    * In the first release, we will require the user
    * to have listener up and and running in order to
    * user this API. In the future releases, we are
    * going to support the situation in which
    * listener is not present. However, for the sake
    * of testing, implementations for both cases have
    * been done.
    */
    if (address)
    {
    #ifdef NEVER
    /* removed to improve coverage, can’t be executed… */
    /* Since address is not NULL, this is the listening
    endpoint */
    nscnd cnda;
    nscxd lsncxd;

    CLRSTRUCT(cnda);
    NSSETCND(&cnda, address);

    if (nslisten(gbhp,
    &lsncxd,
    &cnda,
    &info,
    NULLP(nsres)) nscxdres
    */
    NLTRUSR((NLTRTRC,
    “Server failed to listen for connection request.\n”));
    /*
    * though this is actually the error for
    * failing to listen it is still put into
    * tres just in case we want to check it
    * later on
    */
    CPSTRUCT(tres->ns_tnsres, lsncxd.nscxdres);
    retcode = tres->res_tnsres = LSNFAIL_TNSAPIE;
    }
    /* nslisten succeed */
    else if (nsanswer(gbhp, cxd, NULLP(nscnd), &info,
    NULLP(nsres), &lsncxd) nscxdres
    */
    NLTRUSR((NLTRTRC,
    “Server failed to answer to connection request.\n”));
    CPSTRUCT(tres->ns_tnsres, cxd->nscxdres);
    DISCARD nsdisc(&lsncxd, 0);
    retcode = tres->res_tnsres = ANSFAIL_TNSAPIE;
    }
    #endif
    }
    /* inherit connection from listener */
    else
    {
    /*
    * Inherit the connection from the listener
    */
    if (nsinherit(gbhp,
    cxd,
    NULLP(nscnd),
    NULLP(nscnd),
    &info,
    NULLP(nsres)) nscxdres
    */
    NLTRUSR((NLTRTRC,
    “Server failed to inherit the connection from the listener.\n”));
    CPSTRUCT(tres->ns_tnsres, cxd->nscxdres);
    retcode = tres->res_tnsres = INHFAIL_TNSAPIE;
    }
    } /* if (address) */

    if (nsaccept(cxd, NULLP(nscnd)) != 0)
    {
    /*
    * server failed in accepting connection.
    * Set tres from cxd->nscxdres
    */
    NLTRUSR((NLTRTRC,
    “Server failed to accept the connection request.\n”));
    CPSTRUCT(tres->ns_tnsres, cxd->nscxdres);
    retcode = tres->res_tnsres = ACPTFAIL_TNSAPIE;
    DISCARD nsdisc(cxd, 0);
    }
    else
    {
    hdl->cxd_tnshdl = cxd;
    }
    } /* malloc cxd */
    } /* if (hdl->svr_tnshdl) */
    else
    {
    /*
    * This is the client. Client must NOT call tnsrecv()
    * after tnsopen() Signal error and write error info
    * into trace stream.
    */
    NLTRUSR((NLTRTRC,
    “Client should call tnssend() first to establish connection.\n”));
    retcode = tres->res_tnsres = INVCLIOP_TNSAPIE;
    }
    } /* if (cxd_tnshdl == NULL) */

    /* Set connection into nonblocking mode if it has been requested
    by a call before the connection was actually established –
    the default was blocking */
    if (!retcode && (hdl->io_tnshdl == IO_TNSHDL_NONBLOCKING))
    {
    retcode = tnsdcntl(TNSAPICNONBLOCKING, hdl);
    }

    /* if no error so far */
    if ( !retcode )
    {
    /*
    * Connections has been established. Just receive the data
    */
    if ((retcode = nsrecv(hdl->cxd_tnshdl, &what, data, length, 0))
    != 0)
    {
    if (hdl->cxd_tnshdl->nscxdres.nsresns == NSEWOULDBLOCK)
    {
    /* we’re in nonblocking mode and would block… */
    retcode = tres->res_tnsres = WOULDBLOCK_TNSAPIE;
    }
    else
    {
    /*
    * Receive failed, set up the tres from cxd->nscxdres;
    */
    NLTRUSR((NLTRTRC, “Underlying receive command failed.\n”));
    retcode = tres->res_tnsres = RECVFAIL_TNSAPIE;
    }
    CPSTRUCT(tres->ns_tnsres, hdl->cxd_tnshdl->nscxdres);
    }
    }
    NLTREXIT();
    }
    return(retcode);
    }

    /*
    * In the first release, only the control operation to return the error
    * status will be implemented. However, this could be easily extended.
    */
    STATICF sword tnsdcntl VAFD((opcode, hdl VAAELLIPSIS))
    sword opcode VAFDAD
    tnshdl *hdl VAFDAD
    VAFDELLIPSIS
    {
    tnsgblctx *ctx = (tnsgblctx *)hdl->gbl_tnshdl; /* TNS API global context */
    va_list varp;
    sword retcode = 0;
    dvoid *npd;
    dvoid *gbhp; /* NS per user global */
    tnsres *tres = hdl->res_tnshdl; /* error stack */
    ub2 opt;

    /* if the global handle has not been allocated, cannot call this
    function */
    if ( ctx == (tnsgblctx *)NULL)
    {
    /* Signal error, write error message into trace stream */
    return((sword)HDLUNINI_TNSAPIE);
    }

    gbhp = (dvoid *)ctx->gbh_tnsgblctx;
    npd = ctx->npd_tnsgblctx;
    {
    NLTRDEFINE(“tnscontrol”, npd, NLDTTNSAPI, NLDTTDUMMY, NLDTTDUMMY);
    NLTRENTER();

    /*
    * The handle must have been allocated already.
    */
    VASTART(varp, hdl);

    switch(opcode)
    {
    /* this is for future enhancement, take out in first release */
    /*
    case TNSAPIOLSN:
    hdl->svr_tnshdl = TRUE;
    break;
    */
    case TNSAPICNONBLOCKING:
    if (hdl->cxd_tnshdl)
    {
    /* if we’re connected, do this now. Else, just set the
    “nonblocking” flag and this will be implicitly done
    first time we get connected */
    opt = NSLDONTBLOCK;
    if (nscontrol(hdl->cxd_tnshdl, NSCSETL, (dvoid *)&opt) != 0)
    {
    NLTRUSR((NLTRTRC, “Failed to set nonblocking mode\n”));
    CPSTRUCT(tres->ns_tnsres, hdl->cxd_tnshdl->nscxdres);
    retcode = tres->res_tnsres = CTLFAIL_TNSAPIE;
    }
    }
    hdl->io_tnshdl = IO_TNSHDL_NONBLOCKING;
    break;

    case TNSAPICBLOCKING:
    if (hdl->cxd_tnshdl)
    {
    opt = NSLDONTBLOCK;
    if (nscontrol(hdl->cxd_tnshdl, NSCCLRL, (dvoid *)&opt) != 0)
    {
    NLTRUSR((NLTRTRC, “Failed to set blocking mode\n”));
    CPSTRUCT(tres->ns_tnsres, hdl->cxd_tnshdl->nscxdres);
    retcode = tres->res_tnsres = CTLFAIL_TNSAPIE;
    }
    }
    hdl->io_tnshdl = IO_TNSHDL_BLOCKING;
    break;

    default:
    /*
    * All the other control functions won’t be implemented in
    * the first release.
    */
    retcode = hdl->res_tnshdl->res_tnsres = INVCTL_TNSAPIE;
    break;
    }
    va_end(varp);
    NLTREXIT();
    }
    return(retcode);
    }

    /* ENABLE check_naming */

Leave a Reply

Your email address will not be published. Required fields are marked *