WASP's config file

As you have discovered if you’ve been following the tutorials, WASP is configured using an XML file.

This file can either live in the same directory as the WASP executable or, for when you’re running WASP as a Windows Service, it can live in a place that is configured in the registry.

The file is pretty simple and we’ve covered most of the options in the various tutorials but there are some configuration options that we haven’t touched on yet and it seems sensible to have one place to look for details of all of the options that you can configure in the config file. This blog post is the place!

As I demonstrated here, a WASP config file consists of one node per WASP instance that is configured with the node name equal to the instance name; remember the default instance name is WASP. So a config file for a single default instance might look like this:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
  </WASP>
</Configuration>

And a config file for several named instances and a default instance might look like this:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
  </WASP>
  <Instance1>
  </Instance1>
  <PolicyFileServer>
  </PolicyFileServer>
  <WASP2>
  </WASP2>
</Configuration>

Neither of the files above is actually a valid WASP config file yet as to be valid at least one end point needs to be configured. Something like this:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
    <TCP>
      <Endpoints>
        <EndPoint
          Name="Echo Server"
          Port="5050"
          HandlerDLL="[CONFIG]\EchoServer.dll">
        </EndPoint>
      </Endpoints>
    </TCP>
  </WASP>
</Configuration>

You can configure multiple end points per instance as long as they listen on different ports. The file above configures a single end point in a single instance to listen on all IPv4 interfaces on the machine on port 5050. If you want to restrict the endpoint to a single interface you can specify the address of the interface that you want to listen on.

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
    <TCP>
      <Endpoints>
        <EndPoint
          Name="Echo Server"
          Address="192.168.0.3"
          Port="5050"
          HandlerDLL="[CONFIG]\EchoServer.dll">
        </EndPoint>
      </Endpoints>
    </TCP>
  </WASP>
</Configuration>

You could also use an IPv6 address if you wanted to:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
    <TCP>
      <Endpoints>
        <EndPoint
          Name="Echo Server"
          Address="fe80::50f:3b1d:6958:f921%10"
          Port="5050"
          HandlerDLL="[CONFIG]\EchoServer.dll">
        </EndPoint>
      </Endpoints>
    </TCP>
  </WASP>
</Configuration>

Or the IPv6 wildcard address “::”.

As we saw in this tutorial, you can configure a framing DLL for an endpoint and, here we discovered how to pass a configuration string, perhaps a file name, to the handler DLL.

There are some more configuration options that can be set on the <EndPoint> node.

  • NoDelay - takes a value of “true” or “false” and determines if Nagle is enabled on the endpoint. If this value is not present or “false” then Nagle is enabled.
  • ListenBacklog - specifies how large the listen backlog queue is for the endpoint. This affects how many simultaneous connection attempts the server can process, if the queue is too short and you get lots of simultaneous connection attempts then WASP may fail some connections. Note that this doesn’t in any way affect how many concurrent connections you can support just how many connections can begin at exactly the same moment. The default, if unspecified, is 150 which is most likely adequate for most systems.
  • EnableDebugLog - is a value that defaults to “true” and which controls whether the plugin can log to WASP’s debug log using the logMessage() callback functions that are detailed here.
  • DebugMask - is a value that describes a bit mask that is applied to a plugin’s log message level which determines if the message is displayed or not. See here for more details. The value defaults to 0xFFFFFFFF which enables all debug levels.

A file that included all of these settings might look something like this:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP>
    <TCP>
      <Endpoints>
        <EndPoint
          Name="Packet Echo Server"
          Address="fe80::50f:3b1d:6958:f921%10"
          Port="5050"
          NoDelay="true"
          ListenBacklog="200"
          FramingDLL="[CONFIG]\PacketEchoServer.dll"
          HandlerDLL="[CONFIG]\PacketEchoServer.dll"
          HandlerConfig="[CONFIG]\MyConfig.xml"
          EnableDebugLog = "true"
          DebugMask="0xFFFFFFFF">
        </EndPoint>
      </Endpoints>
    </TCP>
  </WASP>
</Configuration>

Endpoint debug logging can be turned off for all end points by adding a value to the instance node. There are several configuration options that can be set at this level:

  • EnableEndpointDebugLog - defaults to “false” and determines if plugins can log to the WASP debug log using the logMessage() callback.
  • EnablePerformanceCounters - defaults to “false” and determines if WASP publishes performance counters. See here for how to view them using perfmon.
  • BufferSize - defaults to 4096 and determines the size of the buffers that are used for I/O processing. Note that for message framing DLLs to work the buffer size needs to be larger than or equal to the maximum possible message size. If you use OnReadCompletedEx() then the largest response you can generate is also equal to the buffer size. If you use writeToConnection() to generate your responses then there’s no limit to the size of the response and it will automatically be split over multiple buffer if required.
  • BufferPoolSize - buffer allocation and release is optimised using a pool. This allows WASP to have buffers ready to use in most situations rather than needing to allocate new buffers on demand. The size of the pool should be tuned to give the best performance for the smallest memory foot print. By default the size of the pool is 10 buffers which is pretty low but it prevents WASP from appearing to have memory leaks or looking like a memory hog. If you anticipate, say, 100 concurrent users and each response can be generated in one buffer using OnReadCompleted() and writeToConnection() then you should set your pool size to 200 for the concurrent users and add the size of your listen backlog queue (as WASP uses a buffer for each queued AcceptEx() call that is pending and it has one pending for each entry in your listen backlog queue). You can see how the buffer pool is performing by looking at WASP’s performance counters which will clearly show when your pool size is adequate and when it isn’t.

For each active or pending connection WASP allocates a data structure to manage it, this socket structure is, like the I/O buffers, pooled for efficient reuse. The configuration for the socket pool size is called SocketPoolSize and is set in the <TCP> node. As with the buffer pool you can monitor the socket pool using WASP’s performance counters.

You can and should protect your server from denial of service attacks by limiting the number of concurrent connections that you support to a reasonable number given your hardware and the work that your server needs to do. You can restrict the number of concurrent connections that WASP will accept via TCP with the ConnectionLimit value which is also set on the <TCP> node.

We covered the various thread pool configuration options here, and that pretty much covers the configuration options for version 6.3.103 of WASP.

A file that included all of these settings might look something like this:

<?xml version="1.0" encoding="Windows-1252"?>
<Configuration>
  <WASP
    EnablePerformanceCounters = "true"
    EnableEndpointDebugLog = "true"
    BufferSize ="4096"
    BufferPoolSize ="100">
    <IOPool
      NumThreads="4">
    </IOPool>
    <ThreadPool
      InitialThreads="4"
      MinThread="4"
      MaxThreads="8"
      MaxDormantThreads="4"
      PoolMaintPeriod="5000"
      DispatchTimeout="100"
      COMThreadingModel="MTA">
    </ThreadPool>
    <TCP;
      SocketPoolSize="100"
      ConnectionLimit="100">
      <Endpoints>
        <EndPoint
          Name="Packet Echo Server"
          Address="fe80::50f:3b1d:6958:f921%10"
          Port="5050"
          NoDelay="true"
          ListenBacklog="200"
          FramingDLL="[CONFIG]\PacketEchoServer.dll"
          HandlerDLL="[CONFIG]\PacketEchoServer.dll"
          HandlerConfig="[CONFIG]\MyConfig.xml"
          EnableDebugLog = "true"
          DebugMask="0xFFFFFFFF">
        </EndPoint>
      </Endpoints>
    </TCP>
  </WASP>
</Configuration>