#ifndef MCP_H #define MCP_H /* the type used to specify the connection */ typedef void *connection_t; #define MCP_MESG_PREFIX "#$#" #define MCP_QUOTE_PREFIX "#$\"" #define EMCP_SUCCESS 0 /* successful result */ #define EMCP_NOMCP -1 /* MCP isn't supported on this connection. */ #define EMCP_NOPACKAGE -2 /* Package isn't supported for this connection. */ #define EMCP_ARGCOUNT -3 /* Too many arguments in mesg. */ #define EMCP_ARGNAMELEN -5 /* Arg name is too long. */ #define EMCP_MESGSIZE -6 /* Message is too large. */ #define MAX_MCP_ARGNAME_LEN 30 /* max length of argument name. */ #define MAX_MCP_MESG_ARGS 30 /* max number of args per mesg. */ #define MAX_MCP_MESG_SIZE 262144 /* max mesg size in bytes. */ /* This is a convenient struct for dealing with MCP versions. */ typedef struct McpVersion_T { unsigned short vermajor; /* major version number */ unsigned short verminor; /* minor version number */ } McpVer; /* This is one line of a multi-line argument value. */ typedef struct McpArgPart_T { struct McpArgPart_T *next; char *value; } McpArgPart; /* This is one argument of a message. */ typedef struct McpArg_T { struct McpArg_T *next; char *name; McpArgPart *value; McpArgPart *last; int was_shown; } McpArg; /* This is an MCP message. */ typedef struct McpMesg_T { struct McpMesg_T *next; char *package; char *mesgname; char *datatag; McpArg *args; int incomplete; int bytes; } McpMesg; struct McpFrame_T; typedef void (*McpPkg_CB) (struct McpFrame_T * mfr, McpMesg * mesg, McpVer version, void *context); typedef void (*ContextCleanup_CB) (void *context); /* This is used to keep track of registered packages. */ typedef struct McpPkg_T { char *pkgname; /* Name of the package */ McpVer minver; /* min supported version number */ McpVer maxver; /* max supported version number */ McpPkg_CB callback; /* function to call with mesgs */ void *context; /* user defined callback context */ ContextCleanup_CB cleanup; /* callback to use to free context */ struct McpPkg_T *next; } McpPkg; /* This keeps connection specific data for MCP. */ typedef struct McpFrame_T { void *descriptor; /* The descriptor to send output to */ unsigned int enabled; /* Flag denoting if MCP is enabled. */ char *authkey; /* Authorization key. */ McpVer version; /* Supported MCP version number. */ McpPkg *packages; /* Pkgs supported on this connection. */ McpMesg *messages; /* Partial messages, under construction. */ } McpFrame; /***************************************************************** * * void mcp_package_register( * const char* pkgname, * McpVer minver, * McpVer maxver, * McpPkg_CB callback, * void* context * ); * ***************************************************************** * * void mcp_package_deregister( * const char* pkgname, * ); * * ***************************************************************** * * void mcp_initialize(); * * Initializes MCP globally at startup time. * ***************************************************************** * * void mcp_negotiation_start(McpFrame* mfr); * * Starts MCP negotiations, if any are to be had. * ***************************************************************** * * void mcp_frame_init(McpFrame* mfr, connection_t con); * * Initializes an McpFrame for a new connection. * You MUST call this to initialize a new McpFrame. * The caller is responsible for the allocation of the McpFrame. * ***************************************************************** * * void mcp_frame_clear(McpFrame* mfr); * * Cleans up an McpFrame for a closing connection. * You MUST call this when you are done using an McpFrame. * ***************************************************************** * * void mcp_frame_package_add( * McpFrame* mfr, * char* package, * McpVer minver, * McpVer maxver * ); * * Attempt to register a package for this connection. * Returns EMCP_SUCCESS if the package was deemed supported. * Returns EMCP_NOMCP if MCP is not supported on this connection. * Returns EMCP_NOPACKAGE if the package versions didn't overlap. * ***************************************************************** * * void mcp_frame_package_remove( * McpFrame* mfr, * char* package, * McpVer minver, * McpVer maxver * ); * * Deregisters a package for a given frame. * ***************************************************************** * * void mcp_frame_package_supported( * McpFrame* mfr, * char* package * ); * * Returns the supported version of the given package. * Returns {0,0} if the package is not supported. * ***************************************************************** * * void mcp_frame_package_docallback( * McpFrame* mfr, * McpMesg* msg * ); * * Executes the callback function for the given message. * Returns EMCP_SUCCESS if the call completed successfully. * Returns EMCP_NOMCP if MCP is not supported for that connection. * Returns EMCP_NOPACKAGE if the package is not supported. * ***************************************************************** * * int mcp_frame_process_input( * McpFrame* mfr, * const char* linein, * char *outbuf, * int bufsize * ); * * Check a line of input for MCP commands. * Returns 0 if the line was an out-of-band MCP message. * Returns 1 if the line was in-band data. * outbuf will contain the in-band data on return, if any. * ***************************************************************** * * void mcp_frame_output_inband( * McpFrame* mfr, * const char* lineout * ); * * Sends a string to the given connection, using MCP escaping * if needed and supported. * ***************************************************************** * * int mcp_frame_output_mesg( * McpFrame* mfr, * McpMesg* msg * ); * * Sends an MCP message to the given connection. * Returns EMCP_SUCCESS if successful. * Returns EMCP_NOMCP if MCP isn't supported on this connection. * Returns EMCP_NOPACKAGE if this connection doesn't support the package. * ***************************************************************** * * void mcp_mesg_init( * McpMesg* msg, * const char* package, * const char* mesgname * ); * * Initializes an MCP message. * You MUST initialize a message before using it. * You MUST also mcp_mesg_clear() a mesg once you are done using it. * ***************************************************************** * * void mcp_mesg_clear( * McpMesg* msg * ); * * Clear the given MCP message. * You MUST clear every message after you are done using it, to * free the memory used by the message. * ***************************************************************** * * int mcp_mesg_arg_linecount( * McpMesg* msg, * const char* name * ); * * Returns the count of the number of lines in the given arg of * the given message. * ***************************************************************** * * char* mcp_mesg_arg_getline( * McpMesg* msg, * const char* argname * int linenum; * ); * * Gets the value of a named argument in the given message. * ***************************************************************** * * int mcp_mesg_arg_append( * McpMesg* msg, * const char* argname, * const char* argval * ); * * Appends to the list value of the named arg in the given mesg. * If that named argument doesn't exist yet, it will be created. * This is used to construct arguments that have lists as values. * Returns the success state of the call. EMCP_SUCCESS if the * call was successful. EMCP_ARGCOUNT if this would make too * many arguments in the message. EMCP_ARGLENGTH is this would * cause an argument to exceed the max allowed number of lines. * ***************************************************************** * * void mcp_mesg_arg_remove( * McpMesg* msg, * const char* argname * ); * * Removes the named argument from the given message. * ***************************************************************** * * int mcp_version_compare(McpVer v1, McpVer v2); * * Compares two McpVer structs. * Results are similar to strcmp(): * Returns negative if v1 < v2 * Returns 0 (zero) if v1 == v2 * Returns positive if v1 > v2 * ***************************************************************** * * McpVer mcp_version_select( * McpVer min1, * McpVer max1, * McpVer min2, * McpVer max2 * ); * * Given the min and max package versions supported by a client * and server, this will return the highest version that is * supported by both. * Returns a McpVer of {0, 0} if there is no version overlap. * *****************************************************************/ void mcp_initialize(void); void mcp_negotiation_start(McpFrame * mfr); void mcp_package_register(const char *pkgname, McpVer minver, McpVer maxver, McpPkg_CB callback, void *context, ContextCleanup_CB cleanup); void mcp_package_deregister(const char *pkgname); void mcp_frame_init(McpFrame * mfr, connection_t con); void mcp_frame_clear(McpFrame * mfr); int mcp_frame_package_add(McpFrame * mfr, const char *package, McpVer minver, McpVer maxver); void mcp_frame_package_remove(McpFrame * mfr, const char *package); void mcp_frame_package_renegotiate(const char *package); McpVer mcp_frame_package_supported(McpFrame * mfr, const char *package); int mcp_frame_package_docallback(McpFrame * mfr, McpMesg * msg); int mcp_frame_process_input(McpFrame * mfr, const char *linein, char *outbuf, int bufsize); void mcp_frame_output_inband(McpFrame * mfr, const char *lineout); int mcp_frame_output_mesg(McpFrame * mfr, McpMesg * msg); void mcp_mesg_init(McpMesg * msg, const char *package, const char *mesgname); void mcp_mesg_clear(McpMesg * msg); int mcp_mesg_arg_linecount(McpMesg * msg, const char *name); char *mcp_mesg_arg_getline(McpMesg * msg, const char *argname, int linenum); int mcp_mesg_arg_append(McpMesg * msg, const char *argname, const char *argval); void mcp_mesg_arg_remove(McpMesg * msg, const char *argname); int mcp_version_compare(McpVer v1, McpVer v2); McpVer mcp_version_select(McpVer min1, McpVer max1, McpVer min2, McpVer max2); #endif /* MCP_H */