#ifdef __cplusplus
extern "C" {
#endif /* #ifdef __cplusplus */
#ifdef _WIN32
#define __export __declspec(dllexport)
#else /* #ifdef _WIN32 */
#define __export
#endif /* #ifdef _WIN32 */
#ifdef _WIN32
#include <winsock.h> /* for in_addr */
#else /* #ifdef _WIN32 */
#include <netinet/in.h> /* for in_addr */
#endif /* #ifdef _WIN32 */
typedef struct ProtPlugStruct ProtPlug;
/*
|| ProtPlug only works for line-mode protocols!!!!
||
|| These five functions must be exported by each protocol
|| plugin module (PPModule) library:
|| PPModule_Init
|| PPModule_Exit
|| PPModule_NewProtPlug
|| ProtPlug_ProcessLine
|| ProtPlug_Delete
||
|| Since there is only one "new" function, only
one
|| PPModule may be exported per shared
library.
||
|| The server will load and initialize the configured
|| PPModules at startup time.
When a connection to
|| the server is established, a new
"ProtPlug" is
|| created using PPModule_NewProtPlug().
This
|| is the PPModule's notion of a session.
|| The PPModules are loaded in stack
in the order
|| of initialization (first on the top). Each
|| incoming command (line) is passed to the topmost
|| ProtPlug for processing, at which
time it can either
|| defer to its PPSession
|| (actually defer to the next ProtPlug down),
|| make a unilateral decision, or do
nothing.
|| The default server is at the bottom of
the stack.
||
|| Example:
|| SMTP Modules (in config):
|| libPPMrcptcheck.so,libPPMauthhack.so,libPPMgrammarstickler.so
||
|| The protocol line stack would then look like:
||
|| line in --+
+--> response out (if any)
||
| |
|| +- - - -|
|
|| |
v |<- - - +
|| on +-----------------+
|
|| skip | |
| if an RCPT line
||
|
| | comes in, this one
|| |
| rcptcheck |
checks recipient,
||
|
| | otherwise
|| |
|
| it returns PP_SKIP
||
+-----------------+ |
|| +- - - >|
^
||
| |- - - -+
|| +- - - -|
|
|| |
v |<- - - +
|| on +------------------+
|
|| skip | |
| handles hokey auth
||
|
| | framework, on
|| |
| authhack |
authhack, returns
||
|
| | response and
|| |
|
| PP_MORE until
||
|
| | last line, then
||
|
| PP_DONE
|| |
+------------------+ |
|| +- - - >|
^
||
| |- - - -+
|| +- - - -|
|
|| |
v |<- - - +
|| on +------------------+
|
|| skip | |
| gives error
||
|
| responses if the
|| |
| grammarstickler | | command has loose
||
|
| syntax, always
|| |
|
| | PP_SKIPs
|| |
+------------------+ |
|| +- - - >|
^
||
| |- - - -+
||
| |
||
v |
||
+-----------------+
||
|
| normal protocol
||
|
| (provided by Netscape)
||
| default |
||
|
|
||
+-----------------+
||
||
|| In this example rcptcheck (since it is at the top
of
|| the stack) is authoritative.
||
|| In general, a ProtPlug should return PP_SKIP, unless
|| the command is of particular interest.
||
|| If a ProtPlug calls its DEFERLINE function, it
|| should avoid changing DEFERLINE's return
value.
||
|| PPModule code must be thread-safe, either by using
|| the synch calls provided in PPModule_Init,
or by
|| avoiding static data altogether.
|| The memory allocation call provided must also be
|| used, which means no calls to strdup()
and the like.
||
*/
typedef struct PPMutexStruct PPMutex;
typedef struct ProtPlugSystemStruct
{
void *(*PPRealloc)(void *pOld, int nSize);
/* all memory comes from here */
PPMutex *(*PPMutex_New)(void);
void (*PPMutex_Lock)(PPMutex
*pm);
void (*PPMutex_Unlock)(PPMutex
*pm);
void (*PPMutex_Delete)(PPMutex
*pm);
char *(*PPGetIni)(char *pszKey,
char *pszDefault,
char *pszResult,
int nResultSize);
void (*PPLogPrintf)(char *pszFormat,
... );
struct in_addr (*PPGetHostByName)(char *pszName);
char
*(*PPGetHostByAddr)
(struct in_addr ina, char *pBuf,
int nBufSize);
} ProtPlugSystem;
/**
|| Function
|| --------
|| int PPModule_Init(ProtPlugSystem *pSys);
||
|| Description
|| -----------
|| initialization entry point for a protocol plugin
|| module library.
||
|| Parameters
|| ----------
|| ProtPlgSystem *pSys: structure with function pointers
|| for thread synch functions, memory object,
etc.
||
|| Returns
|| -------
|| 0 if successful, non-zero otherwise
||
|| Remarks
|| -------
|| if Init() fails, Exit() will not be called .
||
*/
__export int PPModule_Init(ProtPlugSystem *pSys);
/**
|| Function
|| --------
|| void PPModule_Exit(void);
||
|| Description
|| -----------
|| for resource cleanup in a PPModule, called after all
|| ProtPlugs have been deleted, before the server
exits.
||
|| Parameters
|| ----------
|| none
||
|| Returns
|| -------
|| nothing
||
|| Remarks
|| -------
||
*/
__export void PPModule_Exit(void);
/**
||
|| A PPSession is the ProtPlug's handle to the current
|| server session.
||
|| The below access macros should _always_ be used to
|| call the functions.
||
*/
typedef struct PPSessionStruct PPSession;
typedef struct PPSessionActionsStruct
{
int (*DeferLine)
(PPSession *ps, char
*pszLine, char **ppszResp);
const char *(*GetProperty)(PPSession *ps,
char *pszKey, char *pszDefault);
} PPSessionActions;
#define PPSESSION_DEFERLINE(p,l,r) \
((PPSessionActions *)(p))->DeferLine((p),(l),(r))
#define PPSESSION_GETPROPERTY(p,k,d) \
(((PPSessionActions *)(p))->GetProperty((p),(k),(d)))
/**
|| Function
|| --------
|| ProtPlug *PPModule_NewProtPlug(PPSession *ps)
||
|| Description
|| -----------
|| creates a new ProtPlug, the session analogue of a
|| PPModule.
||
|| Parameters
|| ----------
|| PPSession *ps: a pointer to session-specific
|| data/functions from the server itself.
||
|| Returns
|| -------
|| a new ProtPlug
||
|| Remarks
|| -------
||
*/
__export ProtPlug *PPModule_NewProtPlug(PPSession *ps);
/**
|| Function
|| --------
|| int ProtPlug_ProcessLine(ProtPlug *ppp,
||
char *pszLine,
||
char **ppszResp);
||
|| Description
|| -----------
|| function called on a ProtPlug when a line has been
|| received in the protocol.
||
|| Parameters
|| ----------
|| ProtPlug *ppp: the session pointer
|| char *pszLine: the line to be processed, null
||
terminated,includes "\r\n"
|| char **ppszResp: (input/output) a pointer to the
||
desired response, must be
||
null-terminated and include "\r\n"
||
|| Returns
|| -------
|| PP_DONE command was handled,
is over (no more
||
lines)
|| PP_MORE command was handled,
but has not
||
finished, need more lines
|| PP_SKIP command was ignored,
and subsequent
||
lines for the command
||
should not be sent to this ProtPlug
|| PP_CLOSE command was handled,
and the session
||
(connection) should be closed after
||
sending the response (if any)
||
|| Remarks
|| -------
|| The memory pointed to by pszLine is owned by the
|| server and may not be modified or freed by the
|| ProtPlug.
||
|| The memory pointed to by *ppszResp belongs to the
|| ProtPlug and need only be valid until
the next call
|| to ProcessLine or Delete. The server will
not
|| modify or free it.
||
|| NULL for pszLine is a request for a protocol banner
||
*/
__export int ProtPlug_ProcessLine(ProtPlug *ppp,
char *pszLine,
char **ppszResp);
#define PP_DONE 0
#define PP_MORE 1
#define PP_SKIP 2
#define PP_CLOSE -1
/**
|| Function
|| --------
|| void ProtPlug_Delete(ProtPlug *ppp);
||
|| Description
|| -----------
|| Deletes a ProtPlug
||
|| Parameters
|| ----------
|| ProtPlug *ppp: the session to be deleted
||
|| Returns
|| -------
|| nothing
||
|| Remarks
|| -------
|| This function must free all memory associated with
|| the ProtPlug.
||
*/
__export void ProtPlug_Delete(ProtPlug *ppp);
#ifdef __cplusplus
}
#endif /* #ifdef __cplusplus */
#endif /* #ifndef PROTPLUG_H */