protplug_h
/*
 * CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF NETSCAPE
 * COMMUNICATIONS CORPORATION
 *
 * Copyright (c) 1998 Netscape Communications Corporation.
 * All Rights Reserved.
 *
 * Use of this Source Code is subject to the terms of the
 * applicable license agreement from Netscape
 * Communications Corporation.
 *
 * The copyright notice(s) in this Source Code does not
 * indicate actual or intended publication of this
 * Source Code.
 *
 *  Filename
 *  --------
 *  protplug.h
 *
 *  Description
 *  -----------
 *  protocol plug-in definitions
 *
 *  Author(s)
 *  ---------
 *  Rob Walker
 *
 *  History
 *  -------
 *  Tue Jul 28 15:44:14 1998 - Created
 *
 */
#ifndef PROTPLUG_H
#define PROTPLUG_H
 

#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 */