This document serves to provide information regarding writing wonton modules.

1) Overview
   a) What is a module?
2) Minimum requirements
3) Examples
   a) A module that hooks the DCC chat function '.zoom'.
   b) A module that handles a special ioctl.
   c) A module that unloads itself inside wonLoad.

-------------------------------------------------------------------------------

1) Overview

   a) What is a module?

   	A module with respect to wonton is simply something that extends the 
	core functionality of the bot itself.  The wonton loader itself does
	absolutely nothing.  It simply waits for IRC and DCC connections to
	process as well as scheduled events to meet their time criteria.  Other 
	than that, it idles.  In order to make wonton actually do stuff, one
	needs to create modules.  A module can do anything from gathering
	statistics about how often upper case letters are used in messages
	to running an HTTP server internal to wonton that allows people to 
	manage channels and users from the outside world.

2) Minimum requirements

   	In order for something to be considered a wonton module it's required to 
   	implement a few functions.  Now require is actually a bit of a harsh word.
	In actuality one could create a wonton module that implemented none of the 
	3 "required" functions.  The module, however, would do absolutely nothing.
	The reason it would do nothing is because the core would have not interface
	by which to communicate with that module.  Aside from this point, the 
	module functions which should be implemented are:

	WON_STATUS wonLoad(WON_MODULE_CTX *modctx);

		This function is the entry point for the module.  When this module
		is loaded this function will be called.  Any handlers which need
		to be registered should be done here.  This function is optional 
		and should not be implemented in a "headless" design (where 
		only the wonIoctl function is implemented).

	WON_STATUS wonIoctl(WON_MODULE_CTX *modctx, uint32 ioctl, WON_IC *wic);

		This function serves as a medium for other modules to communicate
		with this module.  Other modules can send messages, called IOCTL's
		which will be passed down to this implemented function.  This 
		function is not required to be implemented.  Aside from this module
		being the medium for modules to communicate, it also serves as a
		method for the core to communicate with the module.  For instance,
		when an irc connection link comes up, the IOCTL WON_IOCTL_IRC_LINK_UP
		is broadcasted.  When a module calls wonConfigurationSave() an
		ioctl is broadcasted that passes a file descriptor for the in buffer
		(WON_IOCTL_CONFIG_SAVE).
		
	WON_STATUS wonUnload(WON_MODULE_CTX *modctx);

		This function is the exit point of the module.  When the module
		is to be unloaded from the core this function is called first.
		If this function returns WON_STATUS_FAILURE then the unload is
		aborted, otherwise all references to handlers which exist
		internal to this module are deleted.  A well formed module
		should clean up all of their handlers inside this function.  
		However, in order to make the core robust it has routines
		which will go through and verify that all references to a 
		module are destroyed before continuing.

3) Examples
  
   a) A module that hooks the DCC chat function '.zoom'.

	#include "won.h"

	/* This is the callback function for .zoom */

	uint32 dccZoom(WON_DCC_PACKET *wdp);

	WON_STATUS wonLoad(WON_MODULE_CTX *modctx)
	{
		/* We want to register our handler for .zoom in position 0 */

		wonDccRegisterLayeredHandler(modctx->wonctx,
						modctx,
						WON_LAYER_FIRST,
						".zoom",
						0,
						dccZoom);

		/* Log that we've been loaded! */

		wonLog(modctx->wonctx,modctx,"zoom module loaded!");

		return WON_STATUS_SUCCESS;
	}

	WON_STATUS wonUnload(WON_MODULE_CTX *modctx)
	{
		/* Deregister our handler for .zoom */

		wonDccDeregisterLayeredHandler(modctx->wonctx,
						modctx,
						".zoom",
						0,
						dccZoom);

		/* Log that we're unloading */

		wonLog(modctx->wonctx,modctx,"zoom module unloaded!");

		return WON_STATUS_SUCCESS;
	}

	/* Whenever someone types .zoom we want to send a message back
	   saying 'Zoom!'
	   */

	uint32 dccZoom(WON_DCC_PACKET *wdp)
	{
		wonDccSend(wdp->ctx,wdp->dcc,"Zoom!\n");

		return WON_STATUS_SUCCESS;
	}

   b) A module that handles a special ioctl.

   	#include "won.h"

	/* Whenever someone sends the MY_PERSONAL_IOCTL to our module
	   we want to set the outBuffer to 1234567.
	   */

	#define MY_PERSONAL_IOCTL	24

	WON_STATUS wonIoctl(WON_MODULE_CTX *modctx,uint32 ioctl,WON_IC *wic)
	{
		switch (ioctl)
		{
			case MY_PERSONAL_IOCTL:
				/* Make sure we have enough storage space */

				if ((!wic->outBuffer) || (wic->outLen < 4))
					return WON_STATUS_FAILURE;

				(*((unsigned long *)wic->outBuffer)) = 1234567;
				break;
		}

		return WON_STATUS_SUCCESS;
	}
   
   c) A module that unloads itself inside wonLoad.

   	#include "won.h"

	WON_STATUS wonLoad(WON_MODULE_CTX *modctx)
	{
		wonLog("We're inside wonLoad...let's unload ourselves..");

		/* It is not correct to call wonModuleUnload from inside 
		   our own module, instead, we must defer the unloading
		   until we're out of our modules context. 
		   */

		wonModuleDeferredUnload(modctx->wonctx,modctx);

		return WON_STATUS_SUCCESS;
	}
