Our lead article this month by Adam Jerome explores the use of the TLI
transport interface. By using this technology, you can greatly simplify the
development and debugging process of client/server software.
Novell is leading the industry in applying the client/server technology to solving big
company challenges. This enterprise- wide computing is a critical component of extending the
ability of all computing-power users to communicate and share with one another. As our
partnership with AT&T grows, and more and more corporations, schools and smaller
organizations, even individuals, begin to use the AT&T NetWare Connect Services, it is clear
that a solid, reliable and flexible naming system must be in place across this global network. We
are very excited about our Novell Directory Services technology and its ability to meet this need.
Though you may not see your applications operating in such a global network at present, rest
assured that your customers will attempt to do just that. Now is the time to develop a strategy and
implementation plan for NDS for your product.
As Novell prepares for the release of NetWare 4 version 4.1, our excitement builds about the
possibilities of the NDS technology. We know that many of our current NetWare 3 customers are
planning to migrate to this version of NetWare 4 very shortly after its release. You need to
consider the best way to design your products that will operate in this environment.
Take advantage of our latest education courses listed in the Developer Education section on
page 13 in this issue, which can guide you in the integration of NDS into your product. See you
in class!
On another note, you're undoubtedly aware of the upturn in our use of the
1-800-RED-WORD telephone number. We have improved the ways that you can reach us.
1-800-RED-WORD is becoming the contact point for all of your development needs. Through
this single telephone number you can learn about our latest SDK products, order them, register
for our Developer Programs, and receive support and other information about Novell developer
benefits. Please feel free to share your thoughts and ideas on how to make this even better via
E-mail at devprog@novell.com.
Our Extended Networking Division has relocated from Monterey, California to our Provo,
Utah headquarters. Our support team in Provo will now be handling the Embedded Systems
Technology issues in addition to providing support to those of you developing ALMs.
I'd like to thank you for participating with us in the world-changing activity of network
computing. With you, your products and technologies, and a solid partnership, we will
satisfactorily provide for the needs of the network computing user well into the future.
I wrote my first IPX communication program many years ago. It took me a
while to get the hang of ECBs, ESRs, AES, IPX headers, immediate addresses,
sockets and so on. Then as soon as I became somewhat fluent in IPX, I was
required to write a session type application using SPX. Later I had to learn a
bit about TCP/IP. Of course, when SPXII came out I was somehow expected to be
an expert in that too! Now they expect me to learn how to talk to a Mac using
the ADSP protocol? !!!STACK OVERFLOW!!!
Perhaps you need an NLM that can communicate to NetWare clients using IPX/SPX/SPXII,
TCP/IP to communicate to a UnixWare workstation, and ADSP to communicate with a
Macintosh all at the same time. That would be nice, but it would require an expert programmer in
each of these areas to make sure everything is in spec. Let's get real here! Unless you are a
professional protocol junkie, you probably don't have the resources to understand all network
protocols__or at least to a depth where you feel safe using them.
Well, there is another way. Transport Level Interface (TLI) is used to isolate an application
from specific network protocols. With TLI taking care of network communications, the
application can focus on its actual objective.
TLI Origins
TLI is not a NetWare native; it came from the AT&T/UNIX environment. UNIX gurus
designed TLI as the transport layer (layer four) of the OSI seven-layer cake, modeled after the
industry-standard ISO Transport Definition (ISO 8072). TLI aspires to make network access as
easy as file access. TLI functions use familiar STREAMS I/O mechanisms and implement
functions similar to fopen(), fread(), fwrite(), fclose() and so on.
Most network protocols offer two levels of communication: Datagram and Session (see
figure below). TLI provides a generic method to access both Datagram and Session network
protocols.
Datagrams
Datagrams are generally used for small amounts of one-time data. Datagram communication
assumes that the application has a method to make sure that data gets to the receiver. These
methods can be complex, simple or nonexistent, depending on the needs of the application.
Datagram communication protocols include IPX, DDP and UDP.
Sessions
Sessions are generally used to send larger amounts of data over an extent of
time. Session communication informs the application when data gets lost or cannot be delivered.
Session communication protocols include SPX/SPXII, ADSP and TCP.
Novell's implementation of TLI currently supports several protocols, depending on the OS
platform. On DOS, Windows and OS/2 platforms, developers can select from IPX, SPX/SPXII
and TCP. The NetWare NLM platform sports two additional AppleTalk protocols: DDP and
ADSP.
Most network protocols use some method to resolve addresses. In other words, if an
application wants to send some data to Brent, it must know Brent's network address. Novell's
IPX/SPX protocols use the Service Advertisement Protocol (SAP) to do name-to-address
resolution, since AppleTalk uses NBP. TLI does not offer address resolution. The application
must know enough about the protocol running under TLI to figure out the address of the guy on
the other side.
TLI Communications Model
If a tree falls in the forest and nobody is there to hear it, does it make a sound? Similarly, to have
network communication there must be a sender, a transport medium and a receiver. With TLI,
the sender and receiver are called endpoints. An application may have multiple endpoints open at
the same time. The transport medium is called the underlying protocol.
To successfully initiate communication there must be a listener and a caller. The listener is
sometimes referred to as a server application. Generally, the caller is referred to as the client
application. After the client and server have established a communication connection, the titles of
client and server are meaningless to TLI and the two are treated as equal peers.
The remainder of this article will walk through a sample TLI server application implemented
as a multithreaded NLM using SPX as the underlying transport protocol. The December issue of
Bullets will feature a walk-through of a sample TLI client application implemented as a DOS
executable. The source of both these sample applications is available on Compuserve in the
NDEVSUP forum, library 5, in a self-extracting file called XTLI1.EXE.
The TLI Server
The server application is called FILETX.C. In brief, it contains two parts: a core process and a
child process. The core process performs the following:
Opens a TLI endpoint to listen for new connections.
Advertises itself on the network as a service provider.
Goes into a loop listening for connection requests, establishing a connection with the
requesting client and handing off the connection to a new thread to service the connection.
Unloads smoothly and properly frees resources.
The child process does the following:
Receives a TLI handle to an active connection with a client.
Opens a file and sends its contents to the client via the TLI connection.
Sends a disconnect request to the client when the file has been sent, to indicate that it is
done sending data.
Waits for the client to send a disconnect message, then closes down the TLI connection
and terminates the child thread.
Let's examine the elements of FILETX's initialization process . First, we need to know the name
of the file that will be sent to the client. We will require that the user who loads FILETX.NLM
must supply a file name as the second parameter. For example, the user who loads this NLM
might specify SYS:SYSTEM\ AUTOEXEC.NCF as the file that will be sent to the client. A
quick check is made to make sure that the specified file exists (see Figure 1).
Figure 1: The elements of FILETX's initialization process
Next, open a TLI endpoint that will listen for connection requests. It is important to realize that
this endpoint will not be used to communicate data to a client; rather, its sole purpose is to listen
for new incoming connection requests. t_open() requires three parameters: path, oflag and info
(shown below).
The path parameter is the name of a TLI compliant protocol device driver; it is not
actually a path or file name at all. This application will use the SPX/SPXII protocol. Therefore it
will specify the driver "/dev/nspx". Since SPXS.NLM supplies the "/dev/nspx" device driver, the
error TBADNAME will be indicated if SPXS.NLM is not loaded prior to loading our
application.
Now, how can I claim to be using SPXII when I didn't specify the device driver
"/dev/nspx2"? Well, this is how it works: if SPXII is available on both endpoints (client and
server), then SPXII will be used even if "/dev/nspx" was specified by t_open(). Likewise, if one
or both endpoints do not support SPXII, the connection is downgraded to SPX even if
"/dev/nspx2" was specified. So it doesn't matter. Either specify "/dev/nspx" or "/dev/nspx2".
There is a method for your application to find out which protocol (SPX or SPXII) is actually
in use. t_getinfo() returns a tInfo structure which contains a field called servertype that will be set
to T_COTS if SPX is in use and set to T_COTS_ORD if SPXII is in use.
The second t_open() parameter is labeled oflag, used to specify settings for flags
O_NDELAY and O_RDRW. In the sample code, two flags have been OR-ed together. The
O_RDRW flag specifies the access mode. O_NDELAY is discussed in the t_listen section of this
article.
The third t_open() parameter is the address of a structure in which t_open() places
protocol-specific information about the endpoint.
t_alloc()
Next, the application needs to create and initialize some TLI structures, but TLI structures are
different for each protocol supported. We could figure out how big these structures are and then
malloc() them and fill in default values, but that would be the hard way. The easiest way is to use
t_alloc(), which performs all these functions. Using t_alloc also ensures that the program stays
compatible with future changes to TLI libraries and underlying protocols (i.e., SPXII and a
half?).
t_alloc() requires three parameters. The first parameter is the handle returned from t_open(),
used to access the characteristics of the transport provider. The second parameter is the type of
TLI structure to be allocated. The third parameter is used to indicate which substructures are
needed. When the entire substructure should be allocated, use the parameter T_ALL. Otherwise,
specific sub-substructure flags may be specified and OR-ed together. Like the malloc() function,
t_alloc() returns a pointer to the block of allocated memory (see figure below).
Our transport endpoint handle obtained from t_open() is of little use unless clients can get its
attention. We must assign (or bind) an (IPX/SPX style) address to this endpoint.
Non-TLI applications generally call IPXOpenSocket() to obtain a dynamic socket
assignment. Although an application may use the same method under TLI, it is generally easier
to have TLI call IPXOpenSocket() automatically.
IPX/SPX programmers also realize another issue: the process that is listening for new
connections had better be prepared to service more than one request at a time. Non-TLI
applications of the IPX/SPX persuasion usually do this by registering multiple receive ECBs
(also known as Packet Receive Buffers).
TLI offers a generic way to both assign dynamic IPX socket numbers and specify the
number of ECBs that will be associ-ated with this client's connection request socket. All this
takes place using the t_bind() function call, which takes three parameters: fd, req and rep.
(See figure above). The fd parameter is the TLI handle obtained from t_open().
The req parameter is a t_bind structure which contains an addr field. The addr field defines
the address (IPX/SPX address in this case) that the server application will use to listen for new
connection requests. The structure also contains a qlen field which specifies (in this case) the
number of ECBs or packet receive buffers to open on this address to listen for new connections.
Assigning qlen the value of one means that only one connection request may be serviced at a
time.
Note: setting qlen to zero means that the endpoint may be used for communication to a
known client but may not be used to listen for new connections. Setting the addr.len to zero tells
TLI that the address should be dynamically allocated by the underlying protocol (IPX/SPX). This
is similar to opening socket zero using IPXOpenSocket().
The rep parameter is also a t_bind structure which contains the actual address that was bound
to the endpoint, actual qlen (ECBs in IPX/SPX), and so on. This information is needed for the
next step when we will advertise the availability of our service on the network.
AdvertiseService()
Now we have to get our server application's network address advertised out on the network.
IPX/SPX uses a protocol called Service Advertising Protocol (SAP) to do this. Basically, our
server must broadcast a Service Advertising Packet (also SAP) once a minute which gives our
server's name, type and address. The AdvertiseService() function is used to perform this service
which requires the server's name, type and socket address as input (see Figure 2).
AdvertiseService() returns a SAP handle that will be used to discontinue advertising when our
server application is shut down.
Figure 2: Advertising the server application's network address
Our server's name will be defined by the user from the LOAD command line. .
The server's type in the sample code is defined as 0x0275. This value was issued by Novell
for use in Novell Developer Support's sample code. If you build such a client/server application
for production use, you must obtain your own Server SAP Type by calling Novell Developer
Support's Database Administrator at 1-801-429-3101.
The server's address in the IPX/SPX environment is made up of a four-byte Network
segment address, a six-byte Node address and a two-byte Socket address
[Network:Node:Socket]. AdvertiseService() only requires the Socket address. It obtains the
Network and Node addresses from internal sources. The Socket address for our application was
allocated dynamically and was stored as output from the t_bind() function in the t_bind structure.
t_listen()
Now let's examine the first half of FILETX's core process loop (see Figure 3).
Figure 3: FILETX's core process loop
This loop listens for and dispatches incoming client connection requests to a child process. To
check for these requests, the t_listen() function is used. t_listen() can be a blocking or
nonblocking function, depending on the O_NDELAY parameter passed into t_open(). This flag
causes t_listen() and other TLI functions to be nonblocking. Non-blocking means that t_listen()
will not wait for an incoming connection request before it returns. Instead it will return
immediately with an indicator of whether or not there is a pending connection request. If there is
no outstanding request, control is passed back to the top of the loop by the `C' continue
statement. Since t_listen() is in a nonblocking mode, the ThreadSwitch() function in the top of
the loop is very important. It allows other processes on the file server to get some CPU time. The
O_NDELAY flag also affects other TLI functions similarly.
t_accept()
The second half of the loop is only executed when a client connection request has been made.
The idea is to hand off the client to a child process so that our loop can get back to listening for
new requests. The loop will accept the new connection using a new TLI endpoint, then pass the
handle of this new endpoint to the child client service process.
The child process has a separate stack from our main() process so we can't use a TLI handle
that is allocated from the main() stack. The memory for the new TLI handle must be allocated so
that the handle can be passed to the child. Then the new endpoint can be opened. (See figure 4 on
page 5).
Figure 4: The second half of the core process loop
Notice that this time O_NDELAY is not specified as an option flag with t_open() (which will
cause the TLI functions to block when called with this new TLI handle). Then the new TLI
endpoint handle is bound to a dynamically assigned address (dynamic socket) and the client
connection request is accepted using the new handle. It is wise at this point to check for a
disconnect request from the client just in case it has changed its mind. BeginThread is called to
initiate a child thread, passing through the new TLI endpoint handle.
t_snd()
The child process will send the previously specified file to the client using the TLI endpoint
handle it was given. It opens the file, reads a buffer full and then calls t_snd(). The t_snd()
function needs the address and size of the buffer and also sports a flags parameter. (See Figure
5).
Figure 5: Sending the file to the client with the TLI endpoint handle
Each time t_snd() is called, the specified data is queued up to be sent, but may not be sent
immediately. TLI may buffer up data from several t_snd()s and send one large packet rather than
many small packets. The T_MORE flag tells TLI that there is more data to follow and suggests
that TLI should not send a half-filled packet. It is important to understand that the T_MORE flag
does not force TLI to do anything; rather, it is used by TLI to aid in its decisions in the packet
building process. The child process specifies the T_MORE flag on all t_snd()s, until the end of
the sendFile is encountered.
Application Termination
Although it would seem that we are finished here, t_close() cannot be called yet. As mentioned
before, data is queued up and TLI may still be sending packets to the client. If t_close() is called
in this state, TLI communication buffers would be freed, and all pending data lost.
Instead, the child process sends a connection disconnect request to the client indicating that
the server process will not be sending any more data. This information is sent as TLI control
information right behind the pending data. (See Figure 6).
Figure 6: Sending a disconnect request
When the client receives this information, it will know there is no more data and that the server is
waiting for it to finish receiving data. The client then sends a connection disconnect request back
to the server. The server listens for the client's disconnect request by calling t_rcvdis() repeatedly
until the request arrives. At that point the child process may close the connection by unbinding
the endpoint from the address (IPX/SPX dynamic socket close) and then by calling t_close().
The method used to terminate the TLI connection in FILETX is called an abortive release.
There is another method of connection termination called orderly release. Instead of using
t_snddis() and t_recdis(), the orderly release method uses the functions t_sndrel() and t_rcvrel().
An orderly release guarantees that no data will be lost in transit when the connection is
terminated. Not all protocols support orderly release; for example, SPXII supports orderly
release, but SPX does not. The t_getinfo() function returns a structure called t_info. The t_info
structure contains a field called servtype. If the underlying protocol supports orderly release,
servtype will contain the value T_COTS_ORD.
For more information about TLI, refer to the following:
Novell NetWare Using NetWare Services for NLMs; Chapters 41_55 and
Appendices A, B and C.
Novell NetWare Programmer's Guide for C; Chapter 25.
Programmer's Guide: Networking Interfaces; UNIX System V Release 4 .2
Documentation; UNIX Press. To order, call 1-515-284-6761.
Adam Jerome is an engineer in Novell's Developer Support Group. He has been with
Novell for four years. He describes himself as a "hick hacker" from Ferron, Utah. He likes to
drive his dump truck to work.
Static vs. Dynamic IPX Sockets
IPX Socket Definition
Network communication protocols use various addressing methods. The IPX/SPX protocols use
a three part address: (1) a four-byte Network segment address, (2) a six-byte Node address, and
(3) a two-byte Socket address.
The network segment address applies to physical as well as logical network segments. An
Ethernet segment is a physical segment. A NetWare 3.x or 4.x file server has a logical internal
network segment. No two segments on internetwork may have the same address.
The node address may be a hard-coded address burned into a LAN adapter, such as with
Ethernet; on the adapter, such as with ArcNet; or set with software, such as the IBM Token Ring
adapter's Locally Administered Address. The node address must be unique within the same
network segment. Two node addresses may be the same if they are located on separate network
segments.
The socket address may be a static address that is issued by Novell Developer Support, or a
dynamic address issued to the application at run-time by IPX. Several IPX applications may run
on the same node. IPX uses the socket address to determine which application on the destination
node will receive a packet. Only one application can open a specific socket address on a node at a
time. If a second application requests to open a socket address already opened by another
application on the same node, the open socket request will fail.
Static Sockets
When I lived in the Fiji Islands, I kept a post office box in various cities that I lived in to receive
mail. Each city's post office has an exterior wall of post office boxes. My assigned post office
box number in Lautoka was 275. When I moved to Tavua I was assigned box number 354. Post
office boxes are very similar to IPX socket addresses.
Static socket numbers are like owning a specific P.O. box number in every post office in the
world. Although this would be neat, it is not usually necessary. In fact, the only time a static
socket number is needed is for IPX LAN segment diagnostics applications where SAP and RIP
protocols may not exist.
Programmers are tempted to use static socket addresses for various reasons. Many times
programmers erroneously assume that if they have a static socket, they can hard-code it into their
application in order to make network communications easier. This is not true. In fact, static
socket addresses are bad news for applications that will be loaded more than once on a network
node.
Another consideration is that broadcast packets are limited to the local network segment.
This gives some programmers a real wake-up call when their application is ported from a simple
one segment development network to a multisegment production customer environment. "Hey!
Why doesn't your application work across an IPX router?" Developers then have to think fast and
implement a method to broadcast their packet to multiple IPX segments individually.
Because of the limitations of static sockets, Novell Developer Support is responsible for
assigning static sockets to developers when necessary. A more viable option than static sockets is
dynamic sockets. There is no additional overhead in using a dynamic socket as opposed to a
static socket for advertised services.
Dynamic Sockets
When someone wants to use a P.O. box in Fiji, the local postmaster allocates one for his or her
use. At that point it is up to P.O. box users to let people know their postal address. Dynamic
sockets are allocated in a similar way. When a process wants to use a dynamic socket it requests
one from IPX with a call to OpenSocket() with a value of 0x0000 in the socket number field. If
there is a dynamic socket address available on the node, OpenSocket() returns the assigned
address (a number between 0x4000 and 0x7FFF). Similar to a post office, the address returned
may be different in any given machine depending on what sockets are available on that node.
After a socket is allocated, it is up to the application service provider to let the network
community know where they are. This is done by telling them the network, node and socket that
they are listening on.
NetWare provides the Service Advertising Protocol (SAP) and NetWare Directory Services
(NDS) to advertise services. SAP provides an easy way to advertise a service and is similar to a
junk-mail method of advertisement. Novell also offers NDS as a method of advertisement, which
scales better than SAP and can provide more information about a service than just its location.
Conclusion
Novell Developer Support encourages developers to limit the use of static socket addresses. As
an alternative, use dynamic sockets for communication points in conjunction with SAP and/or
NDS.
Mark Oberg is an engineer in Novell's Developer Support Group. He was previously with
Novell National Accounts support group. He likes to ski and windsurf.
Server Statistical APIs in NetWare 4.x
Figure 7: Making a call to SSGetLANCustomCounters
/************************************************************/** Description :
This sample code shows how to make a call to
** the API SSGetLANCustomCounters and obtain the information
** about the custom statistics for a LAN Board.
** Syntax :
** LONG SSGetLANCustomCounters(
LONG boardNumber,
LONG startNumber,
BYTE *buffer,
LONG bufferLen);
** The structures GetCustomCountersInfoStructure and
** CustomCountersInfo that are returned in buffer are defined
** in NWSERVST.h
** The input and output parameters are explained in the
** Documentation "NLM Library Reference Volume II"
/***********************************************************/
/* INCLUDE HEADERS */
/* ANSI */
#include
/* OTHER */
#include
/* NetWare Specific */
#include
/* defines */
#define BOARD_NUMBER 1
/* FUNCTION PROTOTYPE */
int SSGetLANCustomCounters_T();
/*=========================================================*/
/* MAIN */
void main(void)
{
clrscr();
SSGetLANCustomCounters_T();
}
/*===========================================================
** FUNCTION: SSGetLANCustomCounters_T
** PURPOSE: Returns Custom Statistics for a LAN Board
*==========================================================*/
int SSGetLANCustomCounters_T()
{
LONG boardNumber;
LONG startNumber;
BYTE buffer[SS_DEFAULT_BUFFER_SIZE];
GetCustomCountersInfoStructure *customCounters;
CustomCountersInfo *CInfo;
BYTE *bPtr;
WORD bufferLen;
int x,z,offset;
LONG rtnVal;
/* BEGIN CODE */
boardNumber = BOARD_NUMBER;
startNumber = 0;
bufferLen = SS_DEFAULT_BUFFER_SIZE;
rtnVal = SSGetLANCustomCounters(
boardNumber,
startNumber,
buffer,
bufferLen);
if (!rtnVal)
{
customCounters = (GetCustomCountersInfoStructure *)
&buffer[0];
printf("Board Number = %d\n", boardNumber);
printf("Start Number = %d\n", startNumber);
printf("Buffer Length = %d\n", bufferLen);
printf("******* CUSTOM COUNTERS INFO *********\n");
printf("CurrentServerTime = %d\n", customCounters->
currentServerTime);
printf("VConsoleVersion = %X\n", customCounters->
vConsoleVersion);
printf("VconsoleRevision = %X\n", customCounters->
vConsoleRevision);
printf("More Flag = %d\n", customCounters->moreFlag);
printf("Number Of Custom Counters = %d\n",
customCounters->numberOfCustomCounters);
printf("Start Of Custom Counters = %d\n",
customCounters->startOfCustomCounters);
printf("***************************************\n");
z = z;
for (x = 0; offset = 0; x < customCounters->
numberOfCustomCounters; x++)
{
/* point to the offset of the customCountersInfo
struct */
bPtr = (BYTE *) &customCounters->
startOfCustomCounters;
/* add all strings in the struct so far,
(variable length */
bPtr += offset;
/* now offset the correct number of
customCountersInfo structs */
CInfo = (CustomCountersINfo *) bPtr;
CInfo += x;
bPtr = &CInfo->stringStart;
printf("\nValue = %d\n", CInfo->value);
printf("String Length = %d\n",
CInfo->stringLength); `
printf("StringStart = ");
for (z = 0; z < CInfo->stringLength; z++)
{
printf("%c", *bPtr++);
}
/* sub 1, since stringStart BYTE will be added at
`cPtr += x' */
offset += CInfo->stringLength - 1;
} /* for */
} /* if */
printf("\nSSGetLANCustomCounters returned = %d\n", rtnVal);
printf("===========================================\n");
return 0;
}
These Server Statistical APIs can be used in a wide range of applications that provide the
following:
Performance Analysis
Configuration of the File System
Detection of Hardware Failure
Detection of CPU Overload
and many more features.
The following list is a quick reference to "SSGet" APIs, documented in NLM Library Reference
Volume II, pages 1264 to 1346.
Latha Rao is an engineer in Novell's Developer Support Group. She has worked for Novell
for three-plus years. She came over from Novell Engineering. She likes to play tennis and run.
Novell Engineering will soon launch the NT Client Beta program. We would like interested
developers to contact us if they want to be considered for this program. Following is a list of
developer and Novell expectations for the NT SDK Beta program:
We expect you to do the following:
Join the PDP by calling 1-800-RED-WORD or returning the questionnaire printed
in the September issue of Bullets which serves as your PDP registration.
Install all the NT Client Beta files and begin testing within 48 hours of receiving the kit.
Thoroughly read all README files before testing.
Dedicate at least 10 hours per week working directly with the product.
Submit biweekly electronic status reports, including any bugs you find.
Submit suggestions for product improvement through NetWire, E-mail or Internet.
Provide a short summary report at the end of the beta cycle. (The report should include
overall impression of the product, outstanding issues and plans for future implementation).
Novell will provide the following:
Beta product and at least one update.
Free NetWire support.
Biweekly electronic reports to fill out.
Private NetWire forum to discuss the product with Novell and other beta sites.
NetWire status updates on the problems you report and the suggestions you make.
A free copy of the released product if you meet the above expectations.
If you can fulfill all of these activities, please download the form in NDEVSUP Library 1
entitled NTBETA and return it to the address specified in that form. Each approved beta site that
provides us with feedback on each of the defined activities will receive the final released kit at no
charge.
Obviously, we are looking for beta sites that will work with us and provide us the feedback
to make this Beta program a success. If you cannot fulfill all of the defined activities, then please
do not respond. The Beta program size is limited. Not everyone who submits their information
for consideration into the Beta program will be selected to participate.
QueryServices() Timeout Value Under NetWare Client SDK 1.0e
How long will QueryServices() wait before it times out and returns an error status?
The QueryServices() function returns with a status 01. This status indicates that no server of
the type passed into the function responded within the hard-coded timeout interval.
The QueryServices() function uses the following means to determine how long it will wait
for a response from the nearest server query:
QueryServices() sends out a GetLocalTarget request (RIP broadcast) to the local network
and uses the transport time value from the response to this broadcast as a variable for
determining the QueryServices() timeout value. A problem with this approach occurs when the
broadcast is destined for the local network.
IPX satisfies the request internally and passes back a transport time of one tick (1/18 sec).
The QueryServices() function multiplies this value by five for a total transport time of 5/18 of a
second. If a router does not respond within this interval of time the QueryServices() function will
time out and return a status 1 (v1.0d of the Client SDK) or a status 0 (v1.0e of the Client SDK).
At the present time, there is no way to increase this timeout interval.
Currently, the only way to circumvent this problem is to use IPX functions to build and
transmit a custom SAP query packet. This will allow the use of a variable timeout value. The
structure of the Service Query Packet is as follows:
Offset Content Type Order
0 IPX Header BYTE[30]
30 Query Type WORD hi-lo
32 Server Type WORD hi-lo
The Query type is set to one for General Service Query or three for Nearest Service
Query. The custom Service Query packet is an IPX packet built according to this outline and sent
in to the local network with the node address of 0xFFFFFFFFFFFF on socket 0x452. Post at
least one IPX packet (IPXListenForPacket) to retrieve the first response that comes back.
API Structures and Byte Alignment Under NetWare Client SDK 1.0e
For proper results to be returned in the elements of a structure, single byte alignment may be
required depending on the variable sizes in a structure. The first byte of a character array contains
corrupted or unexpected data.
The Microsoft compilers by default align structures on two-byte boundaries. This can result
in the last byte of one element of a structure being moved to the first byte of a following
structure. Borland compilers align structures on one-byte boundaries by default so this issue is
not a problem with these compilers.
Include the following Microsoft compiler directives above and below the structure in
question to force single-byte alignment. An example is shown in Figure 8.
This will align the bytes on one-byte boundaries and allow the proper data to appear in each
element of the structure. Borland compilers pack structures on one-byte boundaries by default.
The Borland IDE provides a way to change between WORD and BYTE alignment under the
compiler options menu.
NWServiceQueueJob2() Returns 89D5 Under NetWare Client SDK 1.0e
NWServiceQueueJob2() returns 89D5 (ERR_NO_Q_JOB) with the Client SDK 1.0e libraries
when there are jobs to be serviced.
This is a problem with the Client SDK version 1.0e libraries. The current solution is to use
the previous Client SDK libraries, version 1.0d. This problem will be corrected in future releases
of the Client SDK.
NWGetPreferredConnName() Parameters Under NetWare Client SDK 1.0e
The parameters for the NWGetPreferredConnName() function are incorrectly documented.
The NWGetPreferredConnName() function should not have a NWCONN_HANDLE as an
input parameter. There are just two output parameters for NWGetPreferredConnName(),
preferredName and preferredType.
GetMachineStaticInfo() Returns 0xFE Under NetWare Client SDK 1.0e
The diagnostic GNMA (Generic Network Management Responder) function
GetMachineStaticInfo() returns error code 0xFE. The GNMA responder does not exist on the
node to which the GetMachineStaticInfo() function is sent.
Two checks must be made to ensure that the GNMA responder is present on the node to
which the request is being made. First, the GNMA component must exist in the component list
returned from the node that will be the partner for the diagnostic session. This is component nine.
Second, if the GNMA component exists a call to GetGNMAInfo() must be made to determine
the number of GNMA responders available on the node. A structure of type GNMAInfoStruct is
passed as a parameter to GetGNMAInfo. If any responders exist then
GNMAInfoStruct.GNMANumberOfResponders will be greater than zero. The responder for the
call GetMachineStaticInfo() is the NMR.VLM (Network Management Responder) virtual
loadable module provided with the Client DOS Requester software. If this module is loaded then
GNMAInfoStruct.Type[0].ResponderType will equal one. The NMR.VLM is not loaded by
default. Add the following line under the "NetWare DOS Requester" header: VLM=NMR.VLM.
The function GetMachine-DynamicInfo() also relies on the NMR.VLM being loaded.
How to Calculate the Available Bytes on a Volume from your NLM
Call GetVolumeStatistics (File System Service)
GetVolumeStatistics(
fileServerID, /* the file Server ID */
volumeNumber, /* the volume number you want info for */
structSize, /* size of VOLUME_INFO */
&returned VolumeStatistics);
Refer to NLM Library Reference Volume I on page 565 for more information on
this API.
Reading Fields from LOGIN_CONTROL Property Under NetWare Client SDK 1.0e
Following is a description of how to read information from the LOGIN_CONTROL property of
a user object.
The LOGIN_CONTROL structure is an 86 byte structure that contains account and password
information. Figure 9 on page 11 is the structure of the LOGIN_CONTROL property and a
sample program that demonstrates how to read information from this structure.
Figure 9: The structure of the LOGIN_CONTROL property
typedef struct
{
BYTE accountExpiresYear;
BYTE accountExpiresMonth;
BYTE accountExpiresDay;
BYTE accountExpired;
BYTE passwordExpiresYear;
BYTE passwordExpiresMonth;
BYTE passwordExpiresDay;
BYTE passwordGraceLogins;
WORD expirationInterval;
BYTE graceReset;
BYTE minimumPasswordLength;
WORD maxConcurrentConnections;
BYTE timeBitMap[42];
BYTE lastLoginDate[6];
BYTE restrictionFlags;
BYTE filler;
LONG maxDiskBlocks;
WORD badLoginCount;
LONG nextResetTime;
BYTE badStationAddress[12];
} LOGIN_CONTROL;
/*****************************************************
**File: SCANLC.C
**
**Desc: Program designed to read any value from the LOGIN_CONTROL
** Structure.
**
** Usage: SCANLC
The latest NetWare drivers, example code for NetWare API development tools and OS/2
requester patches are available on Novell's NetWire forum on CompuServe. New information is
first stored in NOVLIB library 1 and moved to library 7 after a period of 30 days.
If you do not have access to CompuServe, request these files from Novell's Developer
Support Group at 1-801-429-5588. When you call, be ready to provide a shipping address, disk
preference (5.25", 3.5", HD or DD) and, if you prefer overnight delivery, your company's Federal
Express account number. If you do not provide a Federal Express account number, the patch disk
will be sent to you via regular mail.
Novell Professional Developer's Program members can obtain updated NetWare API SDK
components from Novell's NDEVSUP forum on CompuServe. For more information on Novell
developer programs contact Novell at 1-801-429-5588.
Novell Developer Relations' Automated Fax System
A document describing available patches and other files and their location on CompuServe is
available through Novell Developer Relations' Automated Fax System. This system can provide
you other useful information as well.
To use the Automated Fax System, call 1-800-RED-WORD (1-800-733-9673) from a
touch-tone phone. Then choose the option for the Automated Fax System, select the documents
you wish to receive and supply your fax number (the fax number to which you want your
document(s) sent). Document #1 lists all other documents available through the Automated Fax
System. Up to five documents can be requested per call.
Note: previous issues made reference to document #7805 in this article. That document is in
the process of being rewritten, but was unavailable previously.
Well, we're in a whole new world now with our telephones. With NetWare Telephony
Services, there are two points of view to the "world" as we "bit-heads" know it.
First, there are the added services that are now available to our computers. To a computer
user, we have another add-on. Yep, another peripheral and cable on the desk. I mean, why brag
about adding control of an analog telephone? Isn't it a lot more fun to say "I have a P90 with 32
meg of RAM, 1.2 gig disk, digital sound card with midi interface, 2 meg PCI video graphics
accelerator, .28 dpi non-interlaced monitor, 14.4 modem, 1 meg local bus caching scsi controller
. . ."? You at least get a good, blank "stare of respect" from people when you tell them that.
When you tell them you just added a telephone, they say "gee, that's nice."
The other point of view is that of the telephone or switch box. From this perspective, we
have just given control of the telephone or PBX to an entire network of users, each sitting at their
own workstations, running their own software. They may not even have to touch the phone
unless they want to use the handset!
From this second point of view, a programmer can build an application specifically designed
to take advantage of both the telephone network as well as the data network. This allows an
application to leverage the strengths of both__communication and sharing information.
When someone was on a call before and didn't know how to transfer the call to your
extension, did you ever want to do it for them? Were you ever hung up on as someone tried to
put you on hold and switch to another phone? Why can't you just do it from your phone?
The Telephony Server keeps track of calls that are going on by way of a CallID. This CallID
is allocated by the Telephony Server each time someone makes a call, or when a monitored
device receives a call. As long as that call is active on some device, the CallID will be valid.
An application can track calls being made from a device by checking the event structures
that are returned to it. In the structures will appear the CallIDs that have been allocated by the
Telephony Server during such events as making or conferencing calls. When another user (or
even the same user) wants to control that call from another station, the application could use a
communications protocol (such as TLI, IPX or SPX) to talk between the workstations and pass
the CallID between them. As long as a valid CallID is being used, and the workstation
controlling the call makes the valid CallID known, any application could use that CallID to
control the call.
This sharing of information between applications allows for more flexible phone
control__control that was not easily available before. Taking advantage of the strengths of both
the data and phone networks, application capabilities can reach a new high!
Tip CallID's are considered to be global on the TServer. That is, they are not specific
to any application, DLL or client machine. As long as a CallID is valid on one machine, it is
valid from all workstations.
TeleTip #8 Can't We All Just Get Along?
Wouldn't it be nice? Would I be considered living in a dream world to expect to have everyone
just get along__to have no disagreements? It's beyond my control, right? Out of my hands? Well,
while I may not be able to solve major world conflict, I can at least solve a disagreement between
two header files associated with the Telephony Services SDK.
The CSTADEFS.H file has the following three lines in it:
Well, there is a subtle disagreement here. When a PBX driver requests one type of
security, it may come across to the client Telephony Workstation as a different value. This
discrepancy will be fixed in future versions of the TSAPI SDK (the PBX driver interface will
remain as it is), but for now, you will need to make the changes yourself.
The CSTADEFS.H file will need to be modified so that the current SDBLevel_t typedef
(shown above) is changed to the following:
If you prefer not to modify the CSTADEFS.H file yourself, you may download the
updated file from the Novell Developer Support BBS. This file is in the Telephony section of the
BBS. The BBS number is 1-801-429-5836.
What POWER!!! Look at the conflict you just resolved! Well, we may not live in a dream
world, but we take what we can get, right?
Tip There is a change that needs to be made to the CSTADEFS.H file in the TSAPI
SDK. You can download an updated file from the Novell Developer Support BBS, or you can
make the changes yourself. Both of these methods are described above.
The following Novell Authorized Education Centers (NAECs) offer developer training:
Alternative Computer
with sites in Mt. Laurel, NJ; Albany, NY; Pittsburgh,
Allentown and Bluebell, PA offers courses 930, 940 and 945. Contact Jamie Anewalt at
1-800-321-1154.
C-Trec
in Houston, TX offers courses 930, 940, 941 and 945, and plans to teach 950
and 954. Contact Conni Templin at 1-713-871-8411.
Clarity
located in San Jose, CA offers courses 930, 940 and 945, and plans to teach
941, 950 and 954. Contact Kirstin Hills or Cyd Simerville at 1-800-729-9995.
Professional Computer Development Corp.
with sites in Norcross, GA; Shaumburg
and Mt. Prospect, IL; Livonia, MI; Edina, MN; Cincinnati and Maumee, OH; and Pittsburgh, PA
offers course 930. Contact Larry Guyette at 1-800-322-7232.
To obtain information on pricing, location, scheduling and course content for classes held in the
U.S. call 1-800-233-3382 or 1-801-429-5508. For information on classes in all other locations,
contact your local Novell office.
Developing computing systems is a complex, time-consuming and expensive task. Novell
understands this and is committed to its developer partners. The Novell Professional Developer's
Program allows you, our developer, to access our broad base of 40 million NetWare users to
develop and market your products.
This program is designed for a wide range of developers who design and create
commercially available solutions. This includes commercial developers, called Independent
Software Vendors (ISVs), and vertical application developers who create applications for
specialized markets such as manufacturing, medicine and law.
Key Features
Members of the Novell Professional Developer's Program receive the following benefits:
Co-Marketing Support
Members can participate in the Yes Program, which offers a variety of co-marketing
opportunities as well as ongoing information about Novell's direction. The ultimate goal of the
Yes Program is to make it easy for customers to identify and purchase products that are
optimized for Novell platforms.
Technical Support
To obtain product information and technical support, phone 1-800-RED-WORD
(1-800-733-9673) or 1-801-429-5281.
Skills Transfer
Members may participate in the Skills Transfer Workshops conducted by a Novell
specialist. The workshops offer cutting-edge training on solution design, development and
implementation. Members may also attend Novell Compass Special Interest Groups, where they
have the chance to review products and provide feedback directly to Novell development teams.
Project/Opportunity Services
Members have access to Novell expertise through the developer forums on CompuServe.
These forums address developer issues including technical information and support for Novell
products and development tools.
Information Services
As a developer, you receive Novell Developer Notes, a publication targeted at network
software developers. Other publications are also available: Bullets, a monthly technical journal;
AppNotes (subscription only), a technical journal for network design; and the annual Developer
Guide to Programs, Products, and Services. Members also get access to Novell's NDEVSUP
CompuServe forum_an electronic meeting place where developers can exchange information
with each other and with Novell staff members.
No Program Fees
Membership in this program is free of charge and open to all developers.
If you would like more information about the PDP or would like to apply for membership,
please phone 1-800-RED-WORD (1-800-733-9673) or 1-801-429-5281. If you would like to
order Novell development tools, please call 1-800-RED-WORD. You may also contact the
program administrator for general questions by E-mail at the following address:
devprog@novell.com. You may also submit SDK enhancement requests by E-mail at the
following address: devsdk@novell.com.
Developers in the U.S. and Canada may contact Novell Developer Support via telephone, fax,
BBS or electronic mail via CompuServe, MHS or the Internet.
Voice
For both presales and postsales support, call Novell Developer Support between 8:00 a.m. and
5:00 p.m. Mountain Time at 1-801-429-5588. Many calls to Novell Developer Support are
passed to a software support engineer immediately. Calls to Novell Developer Support generally
will be acknowledged or answered within four hours.
Fax
If you prefer, you may contact Novell Developer Support via fax at 1-801-429-2990. Faxed
questions are acknowledged or answered within 24 hours.
Developer BBS
If you do not have access to either CompuServe or the Internet, send test cases to our BBS. Set
your communication software to N-8-1 and call 1-801-429-5836.
E-mail: CompuServe
Post your messages in the appropriate section addressed to Novell at 76701,171. These messages
will receive a response within 24 hours.
E-mail: MHS
You may direct your questions and comments to Novell Developer Support via Novell's Message
Handling Service E-mail facility. Address your messages to devsup@novell. These messages
will receive a response within 24 hours.
E-mail: Internet (SMTP)
An alternative method of contacting Novell Developer Support is through the Internet E-mail
system. Send your messages to devsup@novell.com. These messages will receive a response
within 24 hours.
NetWire on CompuServe
Novell's NetWire forum is open to all registered CompuServe subscribers. Through the
NDEVSUP forum, professional developers writing applications with Novell development tools
can gain access to information specific to Novell development. Support, patches, periodicals and
product information, as well as information on all of the programs and services provided for
Novell developers are accessible through this forum. Post your messages in the appropriate
section addressed to Novell at 76701,171. Technical questions will be acknowledged or
answered by Novell Developer Support within 24 hours.
Novell Products and SDKs
Novell products on the "Currently Shipping Developer Products" list (see page 15 of this
issue), including the Red Box Products, are available to Novell Professional Developer's
Program members. Call 1-800-RED-WORD (1-800-733-9673) or 1-303-894-4135 to order these
products or to receive additional information. To order other Red Box Products not listed,
contact your local Novell office or Novell Authorized Reseller.
DeveloperNet Labs
For information on DeveloperNet Labs development tools, education classes and product certification,
in the U.S. and Canada call 1-800-453-1267 ext. 5544 or 1-801-429-5544, or call your local
Novell office (see back cover of this issue).
Novell Developer Relations
Novell Professional Developers or those wishing to become members may contact Novell
Developer Relations via telephone, fax, or electronic mail via Compuserve, MHS or the Internet.
Voice
For general information or questions on Novell Developer Relations programs, in the U.S.
or Canada call 1-800-RED-WORD (1-800-733-9673). All others call 1-801-429-5281.
Fax
If you prefer, you may contact Novell Developer Relations via fax at 1-801-429-7207.
NetWire on CompuServe
Novell's NetWire forum is open to all registered Compuserve subscribers. Through the
NDEVREL forum, Novell Professional Developer's Program-related issues or general questions
may be posted. Through the NDEVINFO forum, customers who do not have products may post
pre-sales product information questions on all Novell SDKs.
E-mail: MHS or Internet (SMTP)
You may direct your questions and comments to Novell Developer Relations via Novell's
Message Handling Service E-mail facility. Address your messages to devprog@novell.com. Use
the same address when going through the Internet E-mail system.