/***************************************************************************
 *                                                                         *
 *   SAPUTL.H                                                              *
 *                                                                         *
 *   Copyright (c) 1991-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   Header for Service Advertising Protocol utilities for Novell          *
 *   Netware based on GSBL/LAN.                                            *
 *                                                                         *
 *                                             - R. Stein 12/04/90         *
 *                                                                         *
 ***************************************************************************/

#ifndef __SAPUTL_H
#define __SAPUTL_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#define MAXSAP 16          /* Maximum number of servers maintained in table */
#define MAXSBC 7                 /* Max number of servers broadcast at once */
#define SNMLEN 47         /* Max characters in a server name (not incl NUL) */
#define SAPSOC 0x0452              /* Socket for S.A.P.                    */
#define GALSVR 0x030A     /* Object or Server type reserved for Galacticomm */

struct sqp {                       /* Service Query Packet                 */
     struct ipxhdr ipx;            /* IPX header                           */
     SHORT qrytyp;                 /* 1=general 3=nearest (hi-lo)          */
     SHORT svrtyp;                 /* FFFF=wild (hi-lo)                    */
};

struct svrinf {                    /* Server Information (used in struct sip)*/
     SHORT typ;                    /* server/object type (hi-lo)           */
                                   /* 0-7FFF=Novell 8000-FFFE=avail FFFF=wild*/
     CHAR nam[SNMLEN+1];           /* server name (NUL-terminated)         */
     CHAR net[4];                  /* network                              */
     CHAR nod[6];                  /* node                                 */
     SHORT soc;                    /* socket (hi-lo)                       */
     SHORT imnets;                 /* intermediate networks (hi-lo)        */
};

struct sip {                       /* Server Identification Packet         */
     struct ipxhdr ipx;            /* IPX header                           */
     SHORT rsptyp;                 /* 2=general 4=nearest (hi-lo)          */
     struct svrinf svr[MAXSBC];  /* array of up to 7 (or 8?) svr info blks */
};

struct sapinf {                    /* S.A.P. information table             */
     struct svrinf inf;            /* information on the server            */
     CHAR state;                   /* state code, see SISXXX's below       */
     SHORT minseen;         /* minute when remote server was last heard of */
};

/* S.A.P. Table Entry States:  (interracts with mask parm of saprep()) */

#define SISNON 0                   /* entry not in use                     */
#define SISRMT 1                   /* entry supported by remote system     */
#define SISLCL 2                   /* entry supported by this system       */

extern struct sapinf sitabl[];

#if 0

Server Advertising Protocol Utilities
-------------------------------------

These utilities can be used both to advertise local server information, and
to receive information about remote servers.

Use of the S.A.P. utility routines requires the GSBL/LAN (Galacticomm
Software Breakthrough Library, Advanced LAN version).  In this discussion,
"caller" refers to application-specific code that utilizes the S.A.P.
utilities, such as Wordlgroup by Galacticomm.

Caller must call btuitz()/btuend() to initialize/shutdown the GSBL.  Input and
output buffers must be big enough for sapitz() to reapportion them to 1024
bytes each.  Caller source code should include both IPX.H and SAPUTL.H


The S.A.P. utility routines:

     sapitz(chan,svtype)  Initialize S.A.P. utilities.  Must call after
                          btuitz().  Caller identifies chan=GSBL channel for
                          use by S.A.P. utilities (socket 0x452).  Channel
                          must not already be defined by caller (using
                          btusdf()/btudef()).  svtype=server type sought by
                          S.A.P. utilities from remote systems, or 0xFFFF =
                          listen for all remote servers, or 0x0000 = accept no
                          remote servers.  sapitz returns 1=ok 0=error (e.g.
                          IPX drivers not loaded, IPX Virtual circuits not
                          supported by GSBL/LAN, insufficient memory,
                          insufficient user count license, less than 2048
                          bytes of btusiz() buffer space).

     sapfin()             End of S.A.P. (shut down all local servers).

     done=sapfdn()        Transmit all the sapfin() shut-down notices, and
                          report when done (nonzero=done).

     sapprc()             S.A.P. utility processing. Caller should call
                          repeatedly in main loop.  Polls for incoming query's
                          and server broadcasts.

     sapmin()             S.A.P. minute processing.  Caller should call
                          once a minute after calling sapitz().

     sapsts(status)       S.A.P. channel status handler.

     sapadv(nam,typ,soc)  Advertise a local server.  nam=name of server, up to
                          48 ASCII characters long, including a NUL terminator.
                          typ=server type or Netware "object type". soc=local
                          socket where server will take requests.  Returns
                          nonzero=ok, 0=can't fit in server information table.

     sapdwn(nam)          Shut down a local server.  nam is NUL-terminated
                          ASCII string, up to 48 bytes including NUL. Returns
                          1=removed 0=not there anyway.

     sapprp()             Prepare for S.A.P. report

     saptr=saprep(1)      S.A.P. report on servers in server information table.
                          After calling sapprp(), call saprep() until it
                          returns NULL.  1 means look for remote server
                          information only.  (For other options, see comments
                          in SAPUTL.C near saprep().)  saptr is a pointer to an
                          entry in the server information table.  See the
                          sapinf structure above.  CAUTION:  don't call any of
                          the S.A.P. routines listed here from the inside of a
                          sapprp()/saprep() loop unless you're sure the
                          routines don't THEMSELVES call sapprp()/saprep().

                          Note:  when using sapprp()/saprep() to list a menu
                          of servers available, be sure to record just the
                          NAME of the server (saptr->inf.nam) for each
                          menu entry.  When the menu selection is made, then
                          look up that name again using sapfnd().  This avoids
                          the unusual cases when a server disappears between
                          menu listing and selection.

     saptr=sapfnd(name,2) Find information on a remote server in the server
                          information table.  Returns NULL if no remote
                          server by that name.  2 means remote servers only.
                          See sapfnd() code for other options.

     INT sapchg;          Set to 1 by sapprc() whenever server information
                          table changes.  May be set to 0 by caller to detect
                          such changes.


Notes
-----

     1.  All socket numbers and server type codes are passed to these
         routines in the natural Intel lo-hi byte order.

     2.  To use S.A.P. utilities for local servers only, call sapitz()
         with svtype == 0.  For remote servers only, just don't call
         sapadv().

     3.  Novell's S.A.P. documentation is contradictory about how many
         servers can be represented by a single broadcast packet.  One
         place it says 7 another 8.  Tech support says 8.  S.A.P.
         utilities broadcast up to 7 at a time, but can receive 8 at a
         time.

     4.  When a server is advertised, the information is stored in the
         server information table and an immediate broadcast packet is
         sent.  All local server information in the table is also
         broadcast every minute.  When a server is shut down, an
         immediate broadcast packet is sent (with imnets == 16, saying
         server is shut down).  The next minutely broadcast also sends
         this notification, so the shutdown notice goes out twice.

     5.  Incoming broadcasts are stored in the server information table
         (avoiding duplicate entries).  Incoming reports of server
         shutdown remove the entry for that server from the server
         information table.

     6.  If case of name conflicts, local servers take precedence:
         received broadcasts from remote servers do not overwrite local
         servers with the same name; but local server advertisements will
         overwrite a remote server of the same name, if one is in the
         table.  Local servers can also bump a remote server out of the
         server information table if there's no room.

     7.  The S.A.P. utilities ignore queries and broadcasts from itself.

#endif                             /* if 0                                 */

GBOOL
sapitz(                            /* Initialize S.A.P.                    */
INT chan,                          /* GSBL channel to use for S.A.P.       */
INT type);           /* Server types sought (lo-hi order) (0xFFFF is wild) */
                             /* Returns 1=success 0=GSBL/LAN not available */

VOID
sapfin(VOID);               /* End of S.A.P. (shut down all local servers) */

INT
sapadv(                            /* Advertise a local Server             */
CHAR *name,  /* Name, NUL-terminated ASCII string, up to 48 bytes incl NUL */
INT type,        /* Object type (don't use 0x0000 or 0xFFFF) (lo-hi order) */
INT socket);       /* Local socket where service will reside (lo-hi order) */
   /* returns 1=logged, 2=overwrite dup name, 3=bumped remote, 0=can't fit */

INT
sapdwn(                            /* Announce shutdown of a server        */
CHAR *name);                       /* Name of server                       */
                                   /* returns 1=removed 0=not here anyway  */

VOID
sapprp(VOID);                      /* Prepare to report on S.A.P. servers  */

struct sapinf *
saprep(                           /* Report on one S.A.P. server at a time */
INT mask);        /* 1=report local servers 2=remote 3=both 0=report empty */

struct sapinf *
sapfnd(                      /* Find server information, given server name */
CHAR *name,        /* NUL-terminated ASCII string, up to 48 bytes incl NUL */
INT mask);                       /* 1=report local servers 2=remote 3=both */
                /* Returns pointer to entry in sitabl() or NULL=can't find */

VOID
sapprc(VOID);                      /* routine S.A.P processing             */

VOID
sapmin(VOID);                      /* Every minute handling of S.A.P.      */

VOID
sapsts(INT status);                /* S.A.P. channel status handler        */

INT
sapfdn(VOID);                      /* shut down the S.A.P.                 */

extern INT sapchg;         /* set to 1 whenever sitabl[] changed by remote */

/*--- sapitz() implicit inputs ---*/
extern INT sapecb;            /* Number of listen ECB's to post for S.A.P. */
extern INT sapisiz;                /* Size of S.A.P. input buffer          */
extern INT saposiz;                /* Size of S.A.P. output buffer         */

#ifdef __cplusplus
}; // extern "C"
#endif // __cplusplus

#endif                             /* __SAPUTL_H                           */
