This module provides functions that send and receive commands and replies in this manner, being careful to never read-ahead in the stream (as stdio would), or to overflow any fixed-size buffers.
This module also provides a frame-work to multiplex many applications' state (data, code, and open resources) into a single process. Each such process holds a "session" for a single client that wishes to engage any more stateless service (viz. a web server) for a credentialed services. Applications that need session resources attach them to the session and recover then from the session as needed.
In addition to the communications layer these functions assumes that some of the required application interface "modules" must be dynamically loaded and/or configured at run-time. The application state modules are assumed to be compiled code (C, C++, or the like), as they are loaded with the dlopen(3) library interface.
After they are loaded some a common convention is applied to choose which entry points (from the module) to execute to build the required state. Any "wise compatible" program can load each module, although some combinations might be nonsensical.
The "stater" is a wise compatible program that process a stream of commands to manipulate, add, or refine session resources for a remote client (viz. CGI), the client then disconnects from the session to allow other clients access. Thus a CGI on a stater enabled web site can keep most of the session state data on the local network (rather than posting it in form data, or cookies).
machine.h
" which defines:
stater
as a default timeout for each session.
stater
, and some
other applications.
0
if the client
application is not a daemon. This switch turns on 2
calls to free
which are only needed if the
client application might call wise_load
in a tight loop (and never exit).
#include "machine.h" #include "wise.h"
typedef struct MTnode { ... } MOD_ENTRY
;
typedef
MOD_ENTRY
is used
by the wise_load
function to keep track of the
list of in-core and active modules (used by state).
extern int wise_load(char *pcModule, char *pcPath);
WISE_MOD_PATH
(used by state).
extern void *wise_module(char *pcName, void *pDLModule);
This (mostly internal) function returns the dlopen descriptor for the
named module. If the module is not in the active table, and the
Module parameter is not (void *)0, then that value is installed in the
table and returned (used by state).
This function is also useful to install a symbolic (or virtual) name for a module. For example the module used to authenticate credentials for a session (in the stater) is always called "auth".
extern void wise_setpad(long int);
extern unsigned int wise_settimeout(unsigned int);
extern char *wise_name(char *pcKey);
extern char *wise_host(char *pcKey, char *pcHost);
wise_name
did to the hostname. Put the "sso"
prefix back on (if the name starts with a /^[0-9]/). It is assumed
that the /etc/resolv.conf search order will find the suffix
we deleted.
extern wise_entry_t wise_entry(char *pcModule, char *pcEntry);
extern int wise_status(int iSlot, char *pcTxt);
wfmt
.
extern int wise_port(int *piPort);
extern int wise_put(int fd, int iNum, const char *pcText);
fd
.
The Num parameter is either -1 (for "no number" or a 3 digit base 10 number
for the command (or reply) code. For example the common ftp login
chat returns 3 line:
Which would look like:220 mirror.npcguild.org FTP server (Version 6.00LS) ready. ... 331 Password required for ksb. ... 230 User ksb logged in.
wise_put(fdClient, 220, "mirror.npcguild.org FTP server (Version 6.00LS) ready."); ... wise_put(fdClient, 331, "Password required for ksb."); ... wise_put(fdClient, 230, "User ksb logged in.");
This code is used in all three (session, remote, and module) contexts. Multiple lines (separated with \n, or \r\n) can (and should) be sent in a single call.
extern int wise_get(int fd, int *piNum, char **ppcText);
wise_put
sends. It breaks
the stream back into a number and the text. Multiple lines are
consolidated back into a single buffer.
The internal buffer wise_get
may be modified,
provided that no modifications are made beyond the sentinel '\000'.
Subsequent calls may reallocate, free or clobber any previous
data.
Returns 0 for success, -1 for failure.
extern int wise_cget(int fd, int *piNum, char **ppcText);
wise_get
, but while the number returned is
between 100 and 199 (inclusive) another call to wise_get
is made. This hides any "Positive Preliminary reply" codes from the caller.
Otherwise returns the same values as wise_get
would.
On order to read the FTP stream above:
Which should output: code=220, text="mirror.npcguild.org FTP server (Version 6.00LS) ready." code=331, text="Password required for ksb." code=230, text="User ksb logged in."auto int iCode; auto char *pcText; register int i; for (i = 0; i < 3 && 0 == wise_get(fdPeer, &iCode, &pcText); ++i) { printf("code=%d, text=\"%s\"\n", iCode, pcText) }
See the test drive for many more examples. Remember that -1 for a number means no integer code was read, and a text of (char *)0 means EOF (end of file) before any text was found. So given input like:
missing code
wise_cget
would set iCode to -1, and pcText to "missing code".
typedef int (*wise_entry_t)(int, int, char **);
typedef
defines a pointer to a function which
is appropriate to store any of the standard entry points defined
below.
extern int init(int argc, char **argv, void *pCS);
wise_load
when the defining module is loaded
(via dlopen(3)).
A module may be loaded in 3 ways:
wise_load
when it depends on
another module.
extern int info(int fd, int argc, char **argv);
extern int chat(int fd, int argc, char **argv);
extern int auth(int fd, int argc, char **argv);
Called when a remote client needs access to a new module, or resource and is not sure the customer should be allowed access.
extern int camp(int fd, int argc, char **argv);
extern int cleanup(int fd, int argc, char **argv);
extern int spinup(int fd, int argc, char **argv);
extern int spindown(int fd, int argc, char **argv);
There have been a few non-standard entry-points defined (mostly by other organizations:
extern char **attribute(char *pcWhich);
Attributes have no predefined meaning in the context of the wise framework, but are usually use as a UNIX group would be. For example the attribute "color" might have a value of either "blue", or "true" depending on the application. The author has had no use, himself, for this API (while others find it useful).
explode -s wise.h
explode wise.c
more wisetest.c
See the code for the "stater", "unity", "acld", or "rcld" for more examples.
$Id: wise.html,v 1.9 2012/03/21 16:15:05 ksb Exp $