RD Controls Software Release Note 8.3<P> <b> Server Network Services</b><P> V3.8

RD Controls Software Release Note 8.3

Server Network Services

V3.8

David M. Kline

Server Network Services is a package of routines which simplify the nontransparent DECnet interface for server processes. The SNS routines manage the multiple inbound connections normally used by such servers to handle requests from clients. Although the SNS routines provide a simple interface for nontransparent DECnet operations, they may not be appropriate for all DECnet servers. The SNS package does not address the process quotas used by the server process; such quotas as ASTLM, BYTLM and BUFIO are likely to need to be larger for processes using the SNS routines (or, for that matter, for any process acting as a DECnet server for multiple simultaneous clients) than for normal processes.

The SNS routines began with a standard model of a request-reply server. In such a server, each message from a client is treated as a separate request (for services or information) operation for which the server will emit a single reply message. After the initial development of the SNS package, additional routines were added to extend this model to permit services which emit multiple reply messages for each request message or which emit no reply for some requests. In addition, users can declare and cancel exit handlers, insert requests onto the internal queue without queuing a read on the logical link, and declare multiple network objects. With these extensions, the SNS package is useful in a wider variety of DECnet servers.

The basic actions which need to be performed by a nontransparent DECnet server are:

The SNS package provides services to handle many of these actions internally to the package, usually via AST routines. The attempt is made to handle most of the complexity of dealing with DECnet within the SNS package to provide a simple interface to server programs which can concentrate on providing services and data to their clients.

The action is started by a call to the sns_init routine. This routine assigns a channel to the NET: pseudo-device and declares the process as a network object with a name specified in the argument list. As a network object, the process can now accept multiple inbound connections via a temporary mailbox and a set of AST routines setup by the sns_init routine. For each connection request, the mailbox AST routine allocates a Task Connection Block (TCB) from dynamic memory; provision is made, by an argument to the sns_init routine, to allocate additional space in the TCB for user-defined information. In addition, the sns_init routine can be called repetitively to declare multiple network objects.

The sns_init routine requires an address of a user-supplied routine which is called when an inbound connection request is received. Otherwise, the process will abort with the fatal signal BADPARAM (Bad Parameters Value) as an indicator that a programming error was made. The user's connect routine can select whether the connection request is to be accepted or rejected. For accepted connections, the connect routine has the opportunity to store information in an extended TCB (if such extension was specified in the call to sns_init) or to store the Task Connection Id (really the address of the TCB) for later use. The connect routine must return, for each connection, the addresses of a pair of request AST routines. These request AST routines are called when a new request message is received over the logical link (the request error AST routine is called only if the received message overflowed the input buffer). In addition, the connect routine must also supply a maximum message size for the connection; this is used to set the size of the data area of an input buffer.

The SNS package provides a pair of default request AST routines in a newly created TCB with the assumption that the user's connect routine will replace the routine addresses as needed. The default request AST routine is particularly useless; it will abort the process with the fatal signal IVSSRQ (Invalid System Service Request) as a sign that a programming error has been made. The default request error AST is more functional; it will signal the error (assumed to be a warning status) and reuse the buffer for a new read operation for the next incoming request message.

The sns_init can also be passed the address of a user-supplied routine which is to be called when a logical link is disconnected. This optional routine can be used to terminate outstanding operations or release resources being used to support the logical link. The actual TCB will not be released until any outstanding I/O operations are completed. The SNS routines were originally used to implement a request-reply model in which each request message received over a logical link connection results in one and only one reply message transmitted over the logical link. Thus, an input message increments a counter of expected outgoing messages in the TCB to prevent the TCB from being deleted with request messages waiting to be processed and replied to. The SNS package provides output routines which both conform to this model and allow provide escapes from it.

The mailbox AST routine setup by sns_init also intercepts messages reporting the failure of logical links for any of a variety of reasons. The SNS package treats logical link failures as disconnect operations and proceeds to run down all outstanding I/O operations associated with the logical link and to call any user-specified disconnect routine. The mailbox AST also provides special treatment for the NETSHUT message received when DECnet is being shutdown on the local node. In the case of the NETSHUT message, the mailbox AST routine calls the SYS$EXIT service with the status code SS$_SHUT as a success value. Therefore, exit handlers can be used to perform specific processing such as relinquishing resources. The sns_dclexh and sns_canexh routines are provided to manage exit handlers (see routine descriptions). The sns_dclexh routine is responsible for allocating resources to declare an exit handler. The user supplies the address to the routine that will be executed when the process terminates, and a handle. The handle is an identifier to the allocated resources; and is passed to the sns_canexh routine to cancel the exit handler and release resources. In addition, the sns_dclexh routine does not support parameters, however future releases will incorporate this functionality. The user should use the standard VMS system services ( SYS$DCLEXH) if this type of processing is required.

The SNS routines assume a common format for input and output buffers as shown:

center This buffer block format has a header of SNS-used information followed by a data area for the message itself (the SNS routines totally ignore the contents of the message). The first quadword of the buffer block is used for queue links (see below) or the I/O status block when the buffer is involved in an I/O operation. The next longword holds the allocated length of the buffer block used when releasing the buffer to the free memory list. Normally, the SNS routines automatically allocate buffers from dynamic memory and similarly release ``empty'' buffers back to the free memory lists. The Task Connection Id is stored in the buffer to match a buffer (particularly an output buffer) to a logical link connection. The final longword of the header (just before the message data area) contains the actually length of the message as received on an input operation or specifies the message length for an output operation.

The SNS package provides for two separate output routines. The sns_reply procedure implements the output side of the basic SNS request-reply model. The buffer passed to the sns_reply routine contains a reply message to an earlier request and causes the outstanding request count in the TCB to be decremented. The sns_write routine is identical to the sns_reply routine except that the message is not considered to be a reply to an earlier request and so the TCB request count is not decremented. The sns_noreply routine does not output a message but instead accounts for a request (result of a read operation) which will not have a corresponding reply message but just decrements the TCB's outstanding request count. All three of these routines will release the buffer to the free memory list ( sns_noreply immediately, the others do so after the write operation completes) unless overridden by a optional call argument.

SNS provides routines for supporting a queue of request messages. The sns_queue routine is specified as the request AST routine by the user's connect routine (no special request error AST routine is provided as yet). The filled read buffer passed to the sns_queue AST routine is placed on the tail of an internal queue. Queued requests are removed from the head of the queue by either calling the sns_dequeue routine in a main polling loop or by calling sns_dequeue_wait to hibernate until a request is available on the queue. The sns_queue AST will automatically issue a SYS$WAKE if the queue was empty when a new buffer is added. The simplest processing loop then consists of calling sns_dequeue_wait followed by processing the message returned by the routine. After sns_queue queues the filled buffer, it will call sns_read to allocate a new read buffer and issue a read $QIO to fill it. In addition, the sns_queue_noread routine is implemented to insert the message into the queue, but not call the sns_read routine. This allows processes to queue messages to themselves. Experience with the SNS routines suggests that sns_write calls should not be done in ASTs due to the possibility of the process entering a resource wait mode and blocking future ASTs (such as those I/O completion ASTs which would clear the resource block).

The SNS routines are available in the general Epicure library EPICURELIB.OLB found under the RDCS$LIB logical name on the WARNER Local Area VAXCluster. Sources of the routines can be found in the file:

WARNER::EPICURE_ROOT:[WORK.LIBRARY.SNS]SERVER.C
In addition, the document sources and current can also be found in the files:
WARNER::EPICURE_ROOT:[WORK.LIBRARY.SNS]SRN8.Q

WARNER::EPICURE_ROOT:[WORK.LIBRARY.SNS]SRN8.TEX WARNER::EPICURE_ROOT:[WORK.LIBRARY.SNS]SNSAPI.TEX

The SNS routines are maintained from the EPICURE project LIBRARY CMS library as the element SERVER.C.

The following simplistic program serves to illustrate a few of the finer points in dealing with the SNS services:

#module  EchoNet  "V1.0"
/*
 An over-simplified DECnet server using the SNS routines.
*/

#include vaxtypes /* VAX C Type extensions */

void sns_init(); /* Initializer Server services */ void sns_reply(); /* Server output service */ void sns_queue(); /* Server queuing AST */ void sns_dequeue_wait(); /* Server dequeuing service */ int connect(); /* Called at network connect request */

main( ) { static int bufp; /* To hold pointer to request buffer */

sns_init( "ECHOSERVER", connect);

/* Loop forever, dequeue request message and echo to sender. Note: buffer pointer kept in a longword as contents of buffer are ignored. Normally, a structure would have been defined... */

for(;;) { sns_dequeue_wait( &bufp);

sns_reply( bufp); } }

/* Connection routine. */

static int connect( tcid, tcbext, reqast, errast, bufsiz ) int tcid; /* Task Connection id */ int tcbext; /* Unused pointer to TCB extension */ void (**reqast)(); /* Returns pointer to function */ void (**errast)(); /* Returns pointer to function */ int *bufsiz; /* To return buffer size */ { *reqast = &sns_queue; /* Use queuing services */

*bufsiz = 512; /* A nominal buffer length */

return TRUE; /* Accept all connections */ }

The remainder of this document describes the individual SNS routines and their calling sequences.

sns_canexh isok = sns_canexh( ehid ) Cancels the exit handler specified with the ehid parameter and releases the dynamic memory used for the exit handler control block. If a zero is specified in the ehid parameter, all exit handlers are canceled for the current access mode. ehid identifier of the exit handler control block. Passed by value. isok returns TRUE (1) if exit handler was canceled, and dynamic memory was released successfully; otherwise failure status codes are signalled.

sns_dclexh isok = sns_dclexh( ehid, fnc ) Declares a user-mode exit handler that's executed part of image rundown. The routine returns an id associated with the exit block describing the exit handler; and can be used to cancel the exit handler using the sns_canexh() routine. ehid identifier of the exit handler control block. Used as the parameter in sns_canexh() to cancel th exit handler. Passed by reference. fnc the address of the function that will be executed when the image exits. No user supplied parameters are passed to the function. Passed by reference. isok returns TRUE (1) if exit handler was declared, and dynamic memory was allocated successfully; otherwise failure status codes are signalled.

sns_dequeue gotbuf = sns_dequeue( bufptr ) This routine is called to return a buffer containing a request message for processing. The buffer is removed from the head of a queue of buffers constructed by a network read completion AST (usually the sns_queue routine). If the queue is empty, this routine will return a NULL buffer pointer. bufptr Address of a longword to return a pointer to the dequeued buffer or zero if no buffers were queued. Passed by reference. gotbuf Returns an integer value of TRUE (1) if a buffer was available and FALSE (0) if the queue was empty.

sns_dequeue_wait sns_dequeue_wait( bufptr ) This routine is called to return a buffer containing a request message for processing. The buffer is removed from the head of a queue of buffers constructed by a network read completion AST (usually the sns_queue routine). If the queue is empty, then this routine will hibernate until a buffer arrives with a request. See the description of sns_write routine for a description of the format of a buffer. bufptr Address of a longword to return a pointer to the dequeued buffer. Passed by reference.

sns_init sns_init( netname, connector [,disconer] [,tcbextsiz] ) This routine performs the necessary initializations for the Server Network Services module. These routines provide support for non-transparent task-to-task communications over DECnet for server processes which handle multiple inbound connections. The sns_init routine assigns a channel to the NET: pseudo-device and associates a temporary mailbox with the channel. The name specified in the call to sns_init is declared as the network task (or network object) name to permit multiple inbound connections. The sns_init routine then initiates an asynchronous read of the mailbox to prepare for the first connection request. There is a limit to the number of network objects which can be declared for a given server. The sns_init routine will indicate when the limit has been exceeded by signaling an access violation (SS$_ACCVIO) status code. At this time, the limit is ten (10). However, if more are required the limit can be easily modified. netname Network task name, terminated by a NUL character. Passed by reference. connector User-provided routine called when an inbound connection request is received. This parameter is required and the status code SS$_BADPARAM will be signaled if not provided. Passed by reference (address of the routine's entry mask). See sns_user_connect for a description of the calling sequence of this routine. disconer Optional user routine called when a logical link is disconnected. Passed by reference (address of the routine's entry mask). See sns_user_disconnect for a description of the calling sequence of this routine. tcbextsiz Size, in bytes, of user's extension to the Task Connection Block used to describe each accepted network connection. Passed by value. The default is to provide no space for user data in the TCB.

sns_noreply sns_noreply( buffer [,retain] ) This routine is called to complete a request (gotten from a network read) without sending a reply message (network write) but to otherwise maintain the internal bookkeeping for the Task Connection. This routine will also release the read buffer to the free dynamic memory list (unless overridden by the retain argument). See the description of sns_reply routine for a description of the format of a request buffer. buffer buffer with completed request message (from read operation). Passed by reference. retain optional integer argument set to TRUE (1) to retain the read buffer (overrides releasing the read buffer to the free memory list). Passed by value. The default of FALSE (0) causes the read buffer to be returned to free memory.

sns_queue sns_queue( tcb, buffer ) This routine is specified as a read completion AST routine by the network connection routine specified in the call to sns_init. The read buffers with the network requests are queued by this routine onto the tail of an internal for processing in non-AST code; either the sns_dequeue or the sns_dequeue_wait routine is used to remove the buffers from the queue. After queuing the filled buffer, sns_queue allocates a new read buffer and starts a new read operation. See the description of sns_write routine for a description of the format of a request buffer. tcb Task Connection Block. Passed by reference. buffer Filled read buffer. Passed by reference.

sns_queue_noread sns_queue_noread( buffer ) This routine is similar to the sns_queue routine however a read is not re-issued on the logical link. The read buffer is inserted onto the tail of the internal queue for non-AST level processing. The sns_dequeue or sns_dequeue_wait routines are used to remove the buffer from the queue. The intention of this routine is to provide a common queuing and buffer processing functionality to server processes. buffer Filled read buffer. Passed by reference.

sns_read sns_read( tcb [,buffer] ) This routine starts a new read operation on the logical link described by the Task Connection Block. Normally this routine is called from within the read completion AST with a new buffer (this is how sns_queue operates). See the description of sns_write routine for a description of the format of a read buffer (same format as used for write buffers). If a read is already queued or in progress for this logical link, the fatal condition SS$_DEVACTIVE will be signaled. tcb Task Connection Block. Passed by reference. (Note: the address of the TCB is used as the Task Connection Id). buffer New read buffer. Passed by reference. If a read buffer is not specified in by the caller, a new buffer will be allocated from dynamic memory and used as the read buffer.

sns_reply sns_reply( buffer [,retain] ) This routine is called to complete a request (gotten from a network read) by sending a reply message (network write) and maintaining the internal bookkeeping for the Task Connection. The format of the write buffer is: +--------------------------------+ | | +- Queue links or I/O status -+ | | +--------------------------------+ | Allocated length of buffer | +--------------------------------+ | task connection id | +--------------------------------+ | Length of data in buffer | +--------------------------------+ | | | Data area of buffer | | | +--------------------------------+ verbatim where the ``allocated length'' includes the header and any unused portion of the data area. The ``length of data'' specifies the number of bytes of data for the write operation. The Task Connection id is maintained from the from the original request (read) buffer (copied if a new buffer was allocated for the reply , rather than using the request buffer for the reply message). The normal action of the write completion AST is to release the write buffer to the free memory list after the completion status has been checked; the buffer release can be disabled by the optional retain argument. buffer buffer with reply message for write operation. Passed by reference. retain optional argument giving the address of user's write completion AST routine. Passed by reference. The default of FALSE (0) causes the write buffer to be returned to free memory by the default write completion AST.

sns_rsrcerrs sns_rsrcerrs( readerr, writerr ) Specifies the address of user-specified callback functions to be called when a read or write $QIO operation fails due to insufficient resources. This may be due to insufficient process quota (EXQUOTA) or system memory resources (INSFMEM), which will be returned only if Resource Wait Mode is disabled for the process (see SYS$SETRWM system service). By default, Resource Wait Mode is enabled. These callback routines are called by the sns routines after the $QIO returns the error status. Either or both callbacks can be disabled by passing a null pointer to this routine (initial setting is that both callbacks are disabled). See the sns_rsrc_callback topic for information on the calling sequence used for the callback routines. readerr the address of the user-provided read $QIO resource failure callback routines. Passed by reference. writerr the address of the user-provided write $QIO resource failure callback routines. Passed by reference.

sns_rsrc_callback user_callback( buffer, tcb, sts ) These user-provided callback routines (pointers to the functions are provided in the call to the sns_rsrcerrs routine) are called when a read or write $QIO operation fails due to insufficient resources. This may be due to insufficient process quota (EXQUOTA) or system memory resources (INSFMEM), which will be returned only if Resource Wait Mode is disabled for the process (see SYS$SETRWM system service). By default, Resource Wait Mode is enabled. These callback routines are called by the sns routines after the $QIO returns the error status. The parameters these user routines are called with are provided by the sns routines, from the original user input to the sns routine (such as the buffer pointer passed into the sns_write routine). See the description of the sns_write or the sns_reply routine for a description of the format of a buffer (same format as used for both read and write buffers). The limit of callback routines for each IO function is equal to the number of network objects allowed (see sns_init routine). This routine will indicate when the limit is reached by signaling the SS$_ACCVIO status condition code. buffer buffer pointer originally passed to the sns routine which is making this callback. See sns_reply or sns_write for format. Passed by reference. tcb Task Connection Block. Passed by reference. (Note: the address of the TCB is used as the Task Connection Id). sts status returned by $QIO call (either EXQUOTA or INSFMEM). Passed by value.

sns_tcbextptr extptr = sns_tcbextptr( tcid ) This routine is called to return a pointer to user's extension area in the Task Connection Block given the Task Connection Id. The returned pointer is a pointer to char and must be cast into a pointer to the appropriate type (such as a pointer to the struct defining the extension). tcid Task Connection Id. Passed by value. extptr Returns pointer to the user's extension to the TCB as a pointer to char.

sns_user_asts reqast( tcid, buffer ) reqerr( tcid, buffer ) These user-provided routines (specified by pointers-to-functions returned from the call to the user-provided connection routine) are called upon at the successful completion of a read operation (reqast) or upon failure of a read operation due to a buffer overflow (reqerr). The reqerr AST is only invoked for the DATAOVERUN status code; all other failures are either signalled or result in the termination of the task connection. See the description of the sns_write or the sns_reply routine for a description of the format of a read buffer (same format as used for write buffers). For these AST routines, the completion I/O status is found in the quadword at the head of the buffer block. The sns_queue routine can be used as the reqast function to place incoming request buffers on a processing queue and setup a new read buffer for the channel. The reqerr routine should call sns_noreply if no reply message is to be sent to the requestor (the DATAOVERUN buffer is still counted as an outstanding request message). tcid Task Connection id used to identify the logical link. Passed by value. buffer Just filled read buffer. Passed by reference.

sns_user_connect accept = connector( tcid, tcbext, preqast, preqerr, pbufsiz, [node], [user], [dncb] ) This user-provided routine (specified in the call to sns_init) is called on each inbound connection request. The routine can perform validation of the connect request and then specify if the request is to be accepted or rejected. Optionally, the routine can record information in an extension to the Task Connection Block or record the Task Connection Id for later use. The routine must specify a read completion AST routine to be called when a request message is received over the logical link represented by this connection request and this routine must also return a maximum size for the request read buffers to be used for input from this logical link. tcid Task Connection id used to identify the logical link. Passed by value. tcbext User's extension to the Task Connection Block (size of the extension is defined by the tcb_ext_size argument to the sns_init routine). If no TCB extension was specified in the sns_init call, this argument should be ignored. Passed by reference. preqast returns the address of the user-provided request (read completion) AST routine. Passed by reference. See sns_user_asts for more information. preqerr returns the address of the user-provided read completion AST routine call on a DATAOVERUN error. Passed by reference. See sns_user_asts for more information. pbufsiz returns the size of the request (read) buffer data area. Passed by reference. node Name of remote node requesting logical link connection. Passed by reference and NUL-terminated. user Name of remote user requesting logical link connection (remote task name from NCB). Passed by reference and NUL-terminated. dncb Network Connection Block for the connection request. Passed by descriptor. accept returns a non-zero integer (TRUE) if the logical link connection is to be accepted or zero (FALSE) if the link connection request is to be rejected.

sns_user_disconnect disconnector( tcid, tcbext) This optional user-provided routine is called whenever a logical link is disconnected (either by request or as a result of a failure in an I/O operation) in order to permit the cleanup of auxiliary information and structures that may have been associated with the task connection by the user. tcid Task Connection id used to identify the logical link. Passed by value. tcbext User's extension to the Task Connection Block (size of the extension is defined by the tcb_ext_size argument to the sns_init routine). This argument should be ignored if the sns_init call did not define any user extension to the TCB. Passed by reference.

sns_write sns_write( buffer [,retain] ) This routine is similar to sns_reply, except that the message being sent is not considered a reply to an earlier request and so there is no internal bookkeeping to be maintained in the Task Connection Block. The format of the write buffer is: +--------------------------------+ | | +- Queue links or I/O status -+ | | +--------------------------------+ | Allocated length of buffer | +--------------------------------+ | task connection id | +--------------------------------+ | Length of data in buffer | +--------------------------------+ | | | Data area of buffer | | | +--------------------------------+ verbatim where the ``allocated length'' includes the header and any unused portion of the data area. The ``length of data'' specifies the number of bytes of data for the write operation. The Task Connection id is maintained from or is to be copied from the original request (read) buffer. The normal action of the write completion AST is to release the write buffer to the free memory list after the completion status has been checked; the buffer release can be disabled by the optional retain argument. buffer buffer with reply message for write operation. Passed by reference. retain optional argument giving the address of user's write completion AST routine. Passed by reference. The default of FALSE (0) causes the write buffer to be returned to free memory by the default write completion AST.

sns_writecheck isok = sns_writecheck( buffer ) This routine is to called from a write completion AST routine. It checks the completion status of the write operation. Failure status codes other than ABORT, CANCEL or a status code indicating failure of the logical link are signalled. buffer write buffer. Passed by reference. isok Returns TRUE (1) if the write operation completed successfully and FALSE (0) otherwise. FALSE is returned for those failing status codes which are recognized and not signalled.

Keywords: DECnet, servers, services

Distribution: normal

Security, Privacy, Legal

rwest@fsus04.fnal.gov