WASP plugin entry points

Page content

By now you’ve probably taken a look inside of the WASP SDK header, WASPDLLEntryPoints.h and seen all of the various plugin entry points that you can export from your plugin. This tutorial will explain what each of them is for and how you use them and will present a simple plugin which uses all of the entry points and logs its actions to WASP’s debug log.

As you’ve seen from the previous tutorials, a WASP plugin can be either a message framing DLL or a message handling DLL or both depending on the entry points that it exports.

We’ve already covered all of the entry points that a WASP message framing DLL can export I’ll detail them again here anyway:

GetMinimumMessageSize

Optional.

Called once when the message framing DLL is loaded.

Returns the minimum number of bytes needed for a call to GetMessageSize() to potentially be able to return a valid message size.

_declspec(dllexport) WaspDataLength __cdecl GetMinimumMessageSize();

GetMessageSize

Required.

Called each time that new data is available, should return 0 if it is unable to determine the size of the message and the size as soon as it can determine the size. If 0 is returned then it will be called again for the same message when more data arrives, when called again the value of previousLength will be the dataLength of the previous call, you can use this to optimise scanning through a message. Each time it is called for a single message the value of pData will be the same and dataLength will increase as more data becomes available.

__declspec(dllexport) WaspDataLength __cdecl GetMessageSize(
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData,
   const BYTE * const pData,
   const WaspDataLength dataLength,
   const WaspDataLength previousLength);

WASP message handling DLLs need only export a single read completion handler to be a valid WASP plugin but there are lots of optional entry points to allow you to handle other networking events and to allow your plugin to pass state around during its lifetime and the lifetime of the connections that it manages.

Initialise

Optional.

Allows a plugin to support multiple instances, return a non zero value for WaspInstanceHandle and this will be passed to all subsequent calls into the plugin for this instance. Supplies the plugin with the WASP callback function table and with any configuration file data from the HandlerConfig value of the plugin’s <endpoint></endpoint> node.

__declspec(dllexport) WaspInstanceHandle __cdecl Initialise(
   WaspFunctions *pWaspFunctions,
   const char *pConfigValue);

OnConnectionEstablished

Optional.

Called when a new connection is established.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection and which will be passed to all subsequent calls into the plugin from this connection.
  • pAddress - the remote address of the client that has connected, cast it to the correct type by using the sa_family field.
  • addressLength - the size of the remote address structure that is pointer to by pAddress.

The plugin can return an opaque user data item (usually a dynamically allocated pointer) for this connection which will be passed to all subsequent calls into the plugin on this connection. This saves the plugin from needing to do a lookup based on the connectionHandle; the opaque connection user data is stored with the WASP connection data in such a way that no locking or lookups are required to access it.

__declspec(dllexport) WaspConnectionUserData __cdecl OnConnectionEstablished(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   const sockaddr *pAddress,
   const WaspAddressLength addressLength);

OnReadCompleted

Optional, although either this or OnReadCompletedEx() MUST be exported.

Called when new data is available on a connection.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
  • pDataIn - a pointer to the start of a buffer which contains the data that has arrived.
  • dataLength - the length of the data.

Note that if you have a message framing DLL installed on the end point then you will only get a read completion called once for each complete message that the message framing DLL has identified. If you do NOT have a message framing DLL installed then you will be called once for each read that completes and each call can pass you any number of bytes, from 1 to the buffer size that WASP is configured to use.

__declspec(dllexport) void __cdecl OnReadCompleted(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData,
   const BYTE * const pDataIn,
   const WaspDataLength dataLength);

OnReadCompletedEx

Optional, although either this or OnReadCompleted() MUST be exported.

Called when new data is available on a connection.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
  • pDataIn - a pointer to the start of a buffer which contains the data that has arrived.
  • dataLength - the length of the data.
  • pDataOut - a writable pointer to the same buffer as the input data, you can write your response back into this buffer, over the top of the input message.
  • outputBufferSize - the size of the output buffer. Do not write more data than this to pDataOut.

Return the number of bytes that you wrote to the output buffer.

Note that if you have a message framing DLL installed on the end point then you will only get a read completion called once for each complete message that the message framing DLL has identified. If you do NOT have a message framing DLL installed then you will be called once for each read that completes and each call can pass you any number of bytes, from 1 to the buffer size that WASP is configured to use.

This function is intended for a subset of servers where all of the following are true:

  • Your response will always fit in one buffer.
  • You can process your input message in such a way that you can generate your response without overwriting the input message until you’re done with it.

In these situations it’s slightly more efficient to use OnReadCompletedEx() than a combination of OnReadCompleted() and writeToConnection. Using OnReadCompletedEx() means that you re-use the input buffer which prevents a buffer allocation being required for the response data.

__declspec(dllexport) WaspDataLength __cdecl  OnReadCompletedEx(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData,
   const BYTE * const pDataIn,
   const WaspDataLength dataLength,
   const BYTE *pDataOut,
   const WaspDataLength outputBufferSize);

OnConnectionClientClosed

Optional.

Called when the client shuts down the send side of their socket connection, you wont get any more read completions but you can continue to send data to the client if you wish.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
__declspec(dllexport) void __cdecl OnConnectionClientClosed(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData);

OnConnectionReset

Optional.

Called if the connection has been reset (i.e. an RST has been received). The connection is now dead, you wont get any more read completions and you cannot send any more data.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
  • lastError - the reason for the connection reset. This is a standard Windows error code.
__declspec(dllexport) void __cdecl OnConnectionReset(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData,
   const WaspLastError lastError);

OnConnectionClosed

Optional.

Called when a connection is closed. Note that you’ll always get an OnConnectionClosed() callback for every connection that you got an OnConnectionEstablished() callback for.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
  • reason - the reason for the connection closure. Call getClosureReasonA() or getClosureReasonW() to get a textual representation of this code.
__declspec(dllexport) void __cdecl OnConnectionClosed(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData,
   const WaspConnectionClosureReason reason);

OnConnectionComplete

Optional.

This will always be the last callback that you ever recieve on a connection and it will only occur when all other callbacks have completed. Due to the multi-threaded nature of the WASP core you could have a read completion, a connection reset and a connection closure callback executing on the same connection at the same time. OnConnectionComplete() is the only place that you can safely clean up connetion user data as it is guaranteed to be called after all other callbacks have completed.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
  • connectionHandle - a handle that is used to represent this connection.
  • connectionUserData - the value that you returned from OnConnectionEstablished() if you exported it or zero otherwise.
__declspec(dllexport) void __cdecl OnConnectionComplete(
   const WaspInstanceHandle instanceHandle,
   const WaspConnectionHandle connectionHandle,
   WaspConnectionUserData connectionUserData);

OnShutdownInitialised

Optional.

Called when the end point that is hosting this plugin begins to shut down.

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
__declspec(dllexport) void __cdecl OnShutdownInitiated(
   const WaspInstanceHandle instanceHandle)

Shutdown

Optional.

Called after the end point that is hosting this plugin has been shut down and just before the plugin DLL is unloaded from memory.

You can use this to clean up any per instance data that you allocated in Initialise().

  • instanceHandle - the value returned from Initialise() or zero if Initialise() is not exported.
__declspec(dllexport) void __cdecl Shutdown(
   const WaspInstanceHandle instanceHandle)

You can find an example plugin which implements all of the plugin entry points here.