Multi User Server Client Linkage Environment v6.72

Open Source Software by Meyer Sound Laboratories Inc

Written by Jeremy Friesner, Last Updated 1/5/2018


Download the latest MUSCLE source and documentation (v6.72)

Subscribe to the MUSCLE developer's mailing list

Watch a short video of a MUSCLE server synchronizing multiple clients in real time

Read the Beginner's Guide to MUSCLE

Read the Guide to making a custom MUSCLE server

Demonstration of how to add multithreading to a custom MUSCLE server (v1.04)

Read the README file

Read the BeShare and MUSCLE BeNews article

MUSCLE is licensed under the BSD Open Source License

Study the MUSCLE API autodocs

Study the Java Client API Javadocs


What is MUSCLE?

MUSCLE is a robust, scalable, efficient, cross-platform client-server messaging system for dynamic distributed applications that runs under any POSIX-compliant operating system. MUSCLE has been developed, used, and refined as the networking component of BeShare, CueStation, D-Mitri, and various other audio control applications at Meyer Sound Laboratories for over twelve years. With MUSCLE, you can:


MUSCLE version history (recent releases only; for the full history see the History file in the muscle archive)

key:  - new feature
      * bug fixed
      o other

6.72 Released 1/5/2018
   - MUSCLE_AVOID_CPLUSPLUS11 will now be #defined automatically
     inside MuscleSupport.h if it wasn't explicitly specified AND
     the __cplusplus preprocessor token is defined to a value
     smaller than 201100.
   - Added a muscleClearArray() templated convenience functions to
     MuscleSupport.h
   o Fixed a deprecation warning for kSCNetworkInterfaceTypePPTP in
     NetworkUtilityFunctions.cpp (MacOS/X only)
   o AtomicCounter.h and Mutex.h will now use the corresponding
     C++11 APIs in their internal implementation unless 
     MUSCLE_AVOID_CPLUSPLUS11 is defined.
   o Added logic to detect XCode versions before 8.0 and auto-enable
     MUSCLE_AVOID_CPLUSPLUS11_THREAD_LOCAL_KEYWORD when they are
     detected, since XCode's clang++ didn't support the thread_local
     keyword before XCode 8.0.
   * Fixed compile error in AtomicCounter.h if C++11 was enabled
     and also MUSCLE_SINGLE_THREAD_ONLY was defined.

6.71 Release 11/3/2017
   - Added a GetFieldType() method to the MessageFieldNameIterator
     class, for convenience.
   - Added a 'writeToStdout' argument to StdinDataIO's constructor so
     that StdinDataIO can optionally Write() data to stdout as well.
     (The argument defaults to false, for backwards compatibility)
   - SanitySetupSystem now verifies that sizeof(void*)'s value
     corresponds correctly to the presence/absence of the
     MUSCLE_64_BIT_PLATFORM macro, and panics if it doesn't.
   - Added constructors to MultiQueryFilter (and its subclasses)
     that take a std::initializer_list of child ConstQueryFilterRef's,
     for convenience.  (requires C++11 or later to use)
   o CMakeLists.txt now includes the files in the dataio subdirectory
     as part of muscle.lib (except for SSLSocketDataIO.cpp, to avoid
     creating a hard-coded OpenSSL dependency)
   o Removed the 32-bit-specific implementation of CalculateHashCode64();
     now the 64-bit is used on both 32-bit and 64-bit CPUs so that
     the function will give the same results regardless of platform.

6.70 Released 10/17/2017
   - The ReflectServer class, if a DetectNetworkConfigChanges session
     is attached to it, will now automatically disconnect any non-local
     TCP connections just before the local computer goes to sleep, in
     order to avoid saddling any communicating peers with a moribund
     TCP connection.  It will reconnect them, if possible, after the
     computer re-awakes.
   - The DetectNetworkConfigChangesSession constructor now takes
     an optional argument indicating whether or not its presence
     should enable the behavior described in the previous bullet-point.
     Defaults to true, but can be explicitly set false if you don't want
     the new behavior for some reason.
   - Added a back-end for the Thread class that uses C++11's std::thread
   - Added a back-end for the Mutex class that uses C++11's std::recursive_mutex
   - Added a back-end for the ThreadLocalStorage class that uses
     C++11's thread_local keyword.
   - Added a CMakeLists.txt file to the root directory, for those who
     prefer to compile a basic MUSCLE library and muscled using cmake
     (e.g. "cd muscle; mkdir _build; cd _build; cmake ..; make")
   - Added a IsSelfAssigned() convenience method to the IPAddress class.
   - Added FindFirstSessionOfType() and FindSessionsOfType() convenience
     methods to the ReflectServer class.
   o Moved the INetworkConfigChangesTarget interface out of
     DetectNetworkConfigChanges.h and into its own separate header file.
   o MUSCLE now requires a C++11 compiler by default.  If you want to
     compile MUSCLE using an older (pre-C++11) compiler, you'll need to
     explicitly add -DMUSCLE_AVOID_CPLUSPLUS11 to your compile-flags.
   o MuscleSupport.h now automatically defines -DMUSCLE_USE_CPLUSPLUS11_THREADS
     if neither MUSCLE_AVOID_CPLUSPLUS11 nor MUSCLE_AVOID_CPLUSPLUS11_THREADS
     has been defined.
   o Checks for -DMUSCLE_USE_CPLUSPLUS11 have been removed, because
     C++11 is now the default compiler level.  C++11-specific code is
     now guarded by #ifndef MUSCLE_AVOID_CPLUSPLUS11 instead.
   o Removed the "borland" subdirectory since it's obsolete.
   o Removed the deprecated SetReflectToSelf() and GetReflectToSelf()
     methods from the DumbReflectSession class.

6.62 Released 9/14/2017
   o Moved constructor-arguments in the .cpp files to separate lines,
     for better diff-ability when they are modified.
   o Removed the overrides of String::StartsWith() that took an
     offset parameter, since it doesn't really make sense to check
     for a prefix with an offset.
   o Fixed some warnings flagged by clang++'s -Weverything option
   o Lots of miscellaneous Doxygen header-comment fixes and cleanup
   o Added a DoxyTemplates.h header file to serve as a repository
     of common class-member definitions, to avoid repetitive boilerplate.
   o Modified String::operator==() to call memcmp() rather than strcmp()
   * Improved portablereflectclient's string parsing a little.
   * Added "const" tag to several operators in the IPAddress class
     that were supposed to have it, but didn't.

6.61 Released 7/21/2017
   - Added a WithInterfaceIndex() convenience method to the IPAddress
     class (for consistency with the IPAddressAndPort class's API)
   * Fixed a sign-casting error in ParseHumanReadableSignedTimeIntervalString()
     under Windows.  Thanks to Mika Lindqvist for reporting this error.
   * Fixed potential crash in GetSystemPath() under MacOS/X.
   * Fixed the MCRASH macro to explicitly specify muscle::Crash() 
     rather than just Crash(), so that it will work when called from
     other namespaces.

6.60 Released 6/22/2017
   - Added SetPriority() and GetPriority() methods to the Thread
     class, to allow specification of the CPU-priority a Thread
     should run at.
   - SimulatedMulticastDataIO's unicast-ping-packets now contain
     location information about other members of the group, so that
     even if some packets get dropped, there is a good chance that
     all members will end up knowing about of all other members anyway.
   - Added define MUSCLE_CONSTEXPR that expands to constexpr iff
     MUSCLE_ENABLE_CPLUSPLUS11 is defined, or expands to nothing otherwise.
   - Some static methods in IPAddress and IPAddressAndPort are now
     tagged with MUSCLE_CONSTEXPR so that they can be evaluated
     at compile-time, if necessary.
   - Added an optional (roundUp) argument to the
     GetHumanReadableTimeIntervalString() functions.
   - Added SetPacketSendDestination() and GetPacketSendDestination()
     virtual methods to the DataIO class.
   - Added a ProxyDataIO class that passes through all calls
     verbatim to its held child DataIO object
   o Renamed XorDataIO to XorProxyDataIO, and made it a subclass
     of ProxyDataIO.
   o Renamed PacketizedDataIO to PacketizedProxyDataIO, and made it
     a subclass of ProxyDataIO.
   o Modified the UDPSocketDataIO class to contain the above two
     virtual methods instead of SetSendDestination() and
     GetSendDestination()
   o Renamed the GetSendDestinations() and SetSendDestinations()
     methods in UDPSocketDataIO to SetPacketSentDestinations() and
     GetPacketSendDestinations(), respectively.
   o Added a GetPacketSendDestination() method implementation to the
     SimulatedMulticastDataIO class.
   o Removed the GetInternalQThread() virtual method from the
     Thread class, since there is now a more general (non-Qt-specific)
     mechanism in the Thread class that can be used instead.
   o Rewrote SimulatedMulticastDataIO to be simpler and more robust;
     in particular it now only creates two UDP sockets instead of four.
   o Removed the FailoverDataIO class, since it didn't seem useful.
   o Renamed DataIO::GetPacketMaximumSize() to GetMaximuPacketSize()
   o Split the DataIO class into separate classes:  DataIO for
     basic Read()/Write()-only I/O, SeekableDataIO for file-style
     I/O where the current-seek-position can be Seek()'d, and
     PacketDataIO for UDP-style packet-based I/O with explicit
     source and destination IP addresses.
   o Modified the various DataIO subclasses as necessary so that
     they now subclass from the appropriate interface.

6.50 Released 6/6/2017
   - Added SimulatedMulticastDataIO, which simulates multicast
     communication via directed unicast.  Useful for communicating
     multicast-style across a WiFi network, where real multicast
     communication doesn't work very well.
   - hexterm now supports a "wifi" keyword, which if specified along
     with the "udp=address:port" argument will replace the basic
   - Added some additional Inflate() and Deflate() methods
     to the ZLibCodec class so that it can now write its
     output into an existing ByteBuffer object rather than
     allocating a new one from the byte-buffer-pool, if desired.
   - hexterm now accepts a "verifyspam" argument; if specified,
     hexterm will check incoming packets to see if they match
     the dummy-data format sent out by hexterm's "spamspersecond"
     feature, and if they do not, it will log an error message.
   - Added a GetHardwareType() method to the
     NetworkInterfaceInfo class.  This method returns a
     NETWORK_INTERFACE_HARDWARE_TYPE_* value indicating what
     kind of network interface it is (e.g. Ethernet, WiFi, etc)
   - Added a GetNetworkHardwareTypeString() static method to
     the NetworkInterfaceInfo class.  This returns a human-readable
     string describing the given NETWORK_INTERFACE_HARDWARE_TYPE_*
   - Added some MacOS/X-specific utility methods to the String class:
     SetFromCFStringRef(), ToCFStringRef(), and a String constructor
     method that takes a (const CFStringRef &)
   - The ip_address and IPAddressAndPort classes now implement
     the PseudoFlattenable interface to allow for easier handling.
     UDPSocketDataIO functionality with SimulatedMulticastDataIO,
     for testing purposes.
   o Renamed the ip_address type to IPAddress, and made it a real
     class (and not a typedef'd alias for uint32) even when
     MUSCLE_AVOID_IPV6 is defined.  ip_address is now a typedef'd
     alias to IPAddress, for backwards compatibility with old code.
   o The various convenience methods that could be called on an
     ip_address object (e.g. IsAddressIPv4(), IsAddressValid(),
     IsAddressMulticast(), etc) are now methods in IPAddress instead.
   o AtomicCounter now uses std::atomic internally,
     if MUSCLE_USE_CPLUSPLUS11 is defined.
   o PODSwapper and SwapContentsSwapper now check for the
     corner-case where the two objects passed in are actually
     the same object (and if so, they don't attempt a swap)
   o Added a GetSourceOfLastReadPacket() method to the DataIO interface.
   o UDPSocketDataIO::GetSourceOfLastReadPacket() is now virtual.
   o Moved the ip_address/IPAddress and IPAddressAndPort classes'
     declarations out of NetworkUtilityFunctions.h and into IPAddress.h
   o Moved the NetworkInterfaceInfo class (and its associated
     functions) out of NetworkUtilityFunctions.h and into
     NetworkInterfaceInfo.h
   * Fixed several places in the codebase that were inappropriately
     relying on CFStringGetCStringPtr() to return a non-NULL value,
     when in fact it is documented to return NULL sometimes.
   * hexterm now exits gracefully when stdin is closed.

6.42 Released 5/12/2017
   - Added SetPerProcessRunTime64Offset() and
     GetPerProcessRunTime64Offset() calls, to support
     adding an artificial constant to the values returned
     by GetRunTime64(), for testing purposes
   - Added ParseHumanReadableSignedTimeIntervalString()
     and GetHumanReadableSignedTimeIntervalString() functions
     to TimeUtilityFunctions.h for better parsing of
     time-intervals that might be negative.
   - Added some new convenience methods to the Hashtable
     class:  GetKeyAtWithDefault(), GetValueAt(), and
     GetValueAtWithDefault()
   o Modified the signatures of a few API calls (including
     MessageIOGateway::UnflattenHeaderAndMessage(),
     DeflateByteBuffer(), InflateByteBuffer, and the
     RawDataQueryFilter class) to take a
     (const ConstByteBufferRef &) rather than a
     (const ByteBufferRef &), as they don't ever need to
     modify the referenced ByteBuffer object anyway.

6.41 Released 3/23/2017
   - Added ReadAndDeflateAndWrite() and ReadAndInflateAndWrite()
     functions to the ZLibUtilityFunctions.{cpp,h} API, and
     to the ZLibCodec class, to more easily support inflation/
     deflation of large files without having to load all their
     data into RAM at once.
   - Added Visual Studio 2017 RTM project files, as provided by
     Mika Lindqvist.
   - FileDataIO::GetReadSelectSocket() and GetWriteSelectSocket()
     now return valid ConstSocketRef objects on OS's that do
     support select-ing on a file's file descriptor (read:
     under POSIX-y OS's, but not under Windows)
   - hexterm now supports a file=filename argument, in case
     you want hexterm to read its input bytes from a file.
   * Fixed a number of DOxygen-commenting oversights detected by
     Alvaro Lopez Ortega's "doxy-coverage" comment-checking tool.
   * Tweaked some of the serialization/deserialization code to be
     more careful about avoiding non-aligned word accesses.
   o Changed the "OUT OF MEMORY" error message produced by
     WARN_OUT_OF_MEMORY macro to read "MEMORY ALLOCATION FAILURE"
     instead (since these errors can be caused by a corrupted
     heap as well as by actual memory exhaustion)

6.40 Released 2/10/2017
   - Added templated constructors to the Ref and ConstRef
     classes so that it is now possible to do implicit
     upcasting when creating or assigning a Ref or ConstRef
     object (e.g. DataIORef x = TCPSocketDataIORef(y))
   - Added DECLARE_REFTYPES macros to the declarations of all
     classes that are subclasses of RefCountable, for convenience.
   - Integrated Mika Lindqvist's patch to qt_muscled.pro so
     that qt_muscled now includes the necessary zlib files
     under Windows.
   o Removed explicit Ref-type-casting code from a number of
     locations where it is no longer necessary.

6.38 Released 1/11/2017
   - Added an Atoxll() function; it is the same as Atoull()
     except that it parses hexadecimal strings into uint64s
     rather than decimal strings.
   - hexterm now allows you to optionally specify a local port
     number to bind an otherwise transmit-only udp session to
     (e.g.  "./hexterm udp=127.0.0.1:5555_6666" would send to
     port 5555 but listen for incoming packets on port 6666)
   * Fixed a bug in MessageField::IsEqualTo() that could cause
     two Message objects to be considered equivalent to each
     other when in fact they are different.

6.37 Released 10/12/2016
   o Added an AUTOCHOOSE_LEGACY_PRIMITIVE_KEY_TYPE_HACK for
     (DataNode *) so that the code will again compile on old
     (3.x) versions of g++ that don't support SFINAE properly.
   - HandleStandardDaemonArgs() now prints out a list of network
     interface information if the command line argument
     "printnetworkinterfaces" is supplied by the user.
   - ParseHexBytes() (and therefore any programs that depend on it,
     such as hexterm) now understands C-style escaped-control-char
     conventions, e.g. \r means carriage-return, \n means newline.
   * Added a work-around for Windows' GetAdaptersAddresses() info
     returning 255.255.255.255 as the broadcast address for an
     IPv4 interface.  GetNetworkInterfaceInfos() will now detect
     when this happens and replace that address with the direct
     broadcast address for the subnet (e.g. 192.168.0.255) instead.

6.36 Released 6/24/2016
   - The NetworkInterfaceInfo class now has a GetMACAddress()
     method that will return the 48-bit MAC address associated
     with the interface.
   - udpproxy will now join a UDP socket to its multicast group
     if the provided IP address is a multicast IP address.
   - Added a new function Crash() which does just what it says.
     The MCRASH macro now calls Crash() after it prints a
     stack trace.

6.35 Released 5/25/2016 
   o Revised MessageIOGateway::DoInputImplementation() so that if
     a subclass's override of UnflattenHeaderAndMessage() has retained
     a reference to its scratch-input-buffer, DoInputImplementation()
     will recognize that and refrain from trying to reuse that buffer
     as a place to store subsequent incoming Message data.
   - Added Visual Studio 15 project files (Intel and ARM versions),
     as provided by Mika Lindqvist.
   * Fixed the MuscleQThreadSocketNotifier constructor so that it
     will compile in conjunction with Qt 4.x.
   * Merged in some ARM compatibility tweaks from Mika Lindqvist.
   * Suppressed some MSVC type-conversion warnings in SetupSystem.cpp

6.34 Released 3/14/2016
   - Added GetQThread() accessor methods to the Thread class.  These
     methods are only available when MUSCLE_USE_QT_THREADS is defined.
   - Added support for a new preprocessor flag,
     MUSCLE_ENABLE_QTHREAD_EVENT_LOOP_INTEGRATION.  When this flag
     is defined, the Thread::InternalThreadEntry() will use
     QThread::exec() as its event loop rather than a simple
     while(WaitForNextMessageFromOwner()) loop.  This allows for
     better integration with QObjects living inside the thread.
   - Modified the ThreadedInternalSession class in the
     qt_advanced_example to use a QTimer for its periodic messages
     when MUSCLE_ENABLE_QTHREAD_EVENT_LOOP_INTEGRATION is defined,
     rather than calling WaitForNextMessageFromOwner(), just as an
     example of what can be done with better Qt integration.
   o Replaced the Thread class's writable GetInternalSocketSet()
     method with a more user-friendly API, including new methods
     RegisterInternalThreadSocket(), UnregisterInternalThreadSocket(),
     UnregisterAllInternalThreadSockets(), and IsInternalThreadSocketReady().
   o Replaced the Thread class's writable GetOwnerSocketSet()
     method with a more user-friendly API, including new methods
     RegisterOwnerThreadSocket(), UnregisterOwnerThreadSocket(),
     UnregisterAllOwnerThreadSockets(), and IsOwnerThreadSocketReady().
   * Fixed a potential stack overflow in PlainTextMessageIOGateway::
     DoOutputImplementation().
   * Removed some unnecessary "#include " directives from
     the qt_advanced_example cpp files that were causing the example
     program not to build under Windows.
   * Added an #ifdef around IPAddressAndPort::WithInterfaceIndex()
     so that code will again compile if MUSCLE_AVOID_IPV6 is defined.

6.33 Released 2/25/2016
   - When MUSCLE_USE_CPLUSPLUS11 is defined, the Queue class
     no longer bothers resetting values in its internal array
     to their default state, if ItemType is a trivial type.
   - When MUSCLE_USE_CPLUSPLUS11 is defined, the Hashtable class
     no longer bothers resetting values in its internal array
     to their default state, if their type (KeyType or ValueType)
     is a trivial type.
   - When MUSCLE_USE_CPLUSPLUS11 is defined, the SanitySetupSystem
     class constructor now does some basic sanity checks on the
     std::is_trivial() method to make sure it is working as expected.
   - hexterm now prints time-since-previous-received-data whenever
     it prints incoming data, for easier performance checking.
   - Added GetBuildFlags(), PrintBuildFlags() and LogBuildFlags()
     functions to SystemInfo.h so that it's easy for a MUSCLE-based
     executable to report the preprocessor flags it was built with.
     This can be handy for debugging purposes.
   - muscled now reports its build-flags at startup, if is launched
     with log level "debug" or higher (e.g. "displaylevel=debug").
   - Added a WithInterfaceIndex() convenience method to the
     IPAddressAndPort class.
   - Usage of the DetectNetworkConfigChangesSession class has
     been simplified.  In particular, it is no longer necessary
     to subclass this class in order to use it; instead you can
     now just have any of your existing session or factory subclasses
     implement the new INetworkConfigChangesTarget interface, and
     the DetectNetworkConfigChangesSession will call their
     INetworkConfigChangesTarget methods when appropriate.
   - The Windows-only "console" command line argument now can take
     an optional value; e.g. console=foo.txt will cause the program's
     stdout and stderr output to be redirected to file foo.txt.
   - The Win32AllocateStdioConsole() function now takes an optional
     argument, as described above.
   - hexterm now looks for a "nojoin" command line argument when a
     multicast group is specified; if found, it will deliberately
     not join the multicast group (and become a send-only UDP session)
   o DetectNetworkConfigChangesSession::SetEnabled(false) now also
     suppresses calls to ComputerIsAboutSleep() and ComputerJustWokeUp().
   o The DECLARE_REFTYPES macro now specifies the muscle namespace
     explicitly, to make it easier to use from other namespaces.
   * Fixed an underflow bug in LogHexBytes() and friends that would
     cause 4 billion dashes to be printed if the title text was
     too long.
   * hexterm.vcproj now includes the necessary shlwapi.lib dependency

6.32 Released 12/3/2015
   - Added support for a new compiler flag,
     -DMUSCLE_RECORD_REFCOUNTABLE_ALLOCATION_LOCATIONS,
     that makes it easier to track down the cause of
     RefCountable objects not getting freed properly on
     process exit.  See BUILDOPTIONS.TXT for details.
   * Tweaked SetupSystem.cpp so that using it no longer
     requires MiscUtilityFunctions.cpp to be compiled also.
   * The _childProcessCrashed flag is now reset by
     WaitForChildProcessToExit() only when there is a child
     process handle available to wait on.  That way multiple
     calls to WaitForChildProcessToExit() won't obliterate
     the child-process-crashed information.
   * Under Windows, the default handled-signals set now
     also includes CTRL_C_EVENT and CTRL_BREAK_EVENT, so
     that when running "muscled.exe catchsignals", these
     keystrokes can also be used to cleanly shut down the
     muscled process.

6.31 Released 8/27/2015
   - The ChildProcessDataIO class now has a DidChildProcessCrash()
     method that will return true iff WaitForChildProcessToExit()
     detected that the child process exited due to an unhandled
     signal rather than via a normal process termination.
   * In v6.30, the windows implementation of ChildProcessDataIO
     would always hide the child process's windows, even in cases
     where it was desirable for the child process's windows to be
     visible.  To avoid that misbehavior, the child process's windows
     are now hidden only if the CHILD_PROCESS_LAUNCH_BIT_WIN32_HIDE_GUI
     bit is set in the (launchBits) argument.
   * Some of the the DOxygen comments for enumerations in the
     header files were not formed correctly, so the DOxygen
     HTML pages would leave them undocumented.  Fixed.
   * Fixed a compiler warning in MessageField::IsEqualTo().

6.30 Released 8/11/2015
   - The Message class now uses special-case variant logic for fields
     that contain only a single value, so that in the common case
     the allocation of an AbstractDataArray object is avoided.
   - Added a convenience overload of GetMessageFromPool() that
     takes a ByteBufferRef as its argument.
   * Merged in Mika's patch to fix the _sntprintf_s() calls in
     the Windows implementation of SysLog.cpp.
   * DetectNetworkConfigChanges.cpp would fail to compile under Windows
     under some circumstances, due to unicode-string handling issues.
     Fixed.
   * Added spaces to *_FORMAT_SPEC tokens in dataio/RS232DataIO.cpp
   * Added missing namespace qualifiers to MCRASH() macro, so that it
     can be called from another namespace.
   * Fixed a bug in the Hashtable class that could cause crashes
     after a call to EnsureSize(0, true).
   * Message::Unflatten() now resizes the Message's entries-Hashtable
     to be the exact size of the number of entries it will contain.
   * Added some #includes to the gz*.c zlib files so "implicit
     function declaration" warnings are no longer emitted when
     compiling under MacOS/X.
   * Fixed a static-initialization-ordering bug in the ObjectCounterBase
     class that could cause it to try and lock an invalid Mutex during
     process startup or shutdown.
   * Under Windows, use of the ChildProcessDataIO class could cause
     an empty Console window to appear.  That no longer happens.

6.23 Release 7/7/2015
   - The StringMatcher class now has a IsPatternListOfUniqueValues()
     method that returns true iff the that pattern is a comma-separated
     list of non-wildcarded values.
   o NodePathMatcher::DoTraversalAux() was using a Queue as a cache,
     which could be inefficient due to O(N^2) lookups in certain cases.
     Replaced it with a Hashtable for better performance.
   o Optimized the NodePathMatcher algorithm to be more efficient
     when node-paths that include clauses that are long lists of
     comma-separated node names.
   * SharedFilterSessionFactory.cpp wouldn't compile if -DMUSCLE_AVOID_IPV6
     was specified on the compile line.  Fixed.

6.22 Released 6/11/2015
   - Added an IsWaitingForEvents() method to ReflectServer class,
     so that a (user-supplied) watchdog thread can observe when the
     ReflectServer is blocked waiting for I/O vs when it is doing
     something.
   - Added Mika's vc++14 subdirectory, which contains Visual C++
     project files for Visual Studio 2015.
   - DataNode::GetAncestorNode() now takes an optional second argument
     that tells it what to return if the ancestor node isn't found.
   o Added some more Cygwin/MinGW compatibility changes contributed
     by Mika Lindqvist.
   o Rewrote some of the node-traversal callback methods so that they
     no longer pass an integer argument by casting it to (void *).
   * Tweaked various files to fix warnings reported by cppcheck 1.69.
   * The stdout-display in qt_muscled wasn't read-only.  Fixed.

6.21 Released 5/14/2015
   o Merged in Mika Lindqvist's patch to make the StackWalker code
     use less stack space.
   o Merged in Mika Linkdqvist's patches for better Cygwin compatibility.
   * Made the StackWalker code a bit more robust.
   * Merged in Mika Lindqvist's patch to the VC++12 projects
     to link debug builds against the MultiThreadedDebug
     run time library rather than the MultiThreaded library.
   * Fixed a couple of const-correctness issues in the StackWalker code.
   o Modified the Windows implementation of GetNetworkInterfaceInfos()
     to not specify an interface index for IPv6 network device address
     ::1, as doing so causes UDP-packet-routing problems under Windows 7.

6.20 Released 4/20/2015
   - Added a new sub-folder besupport/admin_gui.  It contains
     Fredrik Modeen's GUI shell for more easily running muscled
     under BeOS or Haiku.
   - Added new MUSCLE-specific versions of some potentially-insecure
     (per Microsoft) C functions to MuscleSupport.h:  muscleFopen(),
     muscleStrcpy(), muscleStrncpy(), muscleSprintf(), and
     muscleSnprintf().  These get expanded out to the appropriate
     system-specific equivalent, so that e.g. under Windows we can
     use the CRT-secure Windows-only equivalents, while not having
     to put #ifdefs all over the code to keep it compiling elsewhere.
   - Added Visual C++ 2013 project files, courtesy of Mika Lindqvist
     (in the new "vc++12" subfolder)
   o Renamed the vc++ subfolder to vc++8 to make it more obvious
     that the project files it contains are for Visual Studio 2008.
   o MUSCLE classes that should not be subclasses are now tagged
     with the MUSCLE_FINAL_CLASS keyword so that when compiled
     with -DMUSCLE_USE_CPLUSPLUS11 the compiler will produce a
     compile-time error if they are subclassed.
   o Modified the QueueGatewayMessageReceiver and StringMatcherQueue
     classes to no longer subclass from the Queue class, since
     subclassing from Queue is no longer allowed.  Instead, they
     now include a Queue object as a member variable and provide
     accessors to that object.
   o Modified the ObjectPool class to no longer subclass the
     ObjectNode internal class from the templated-type, since
     the templated-type might now be marked as "final".
   o Replaced various of the aforementioned calls with their
     muscle*() equivalents in the codebase.
   o Merged in some patches contributed by Mika Linqvist to avoid
     CRT security warnings when compiling under MSVC 2013.
   o Removed all calls to strcat() and strncat(), as their string
     truncation semantics are too difficult for me to reason about
     reliably.  The rewritten code is also generally more efficient.
   o Modified DefaultFileLogger::CloseLogFile() to reduce its
     stack usage.
   o Modified GetNetworkInterfaceInfos() to not specify an interface
     index for IPv6 network device address ::1, as doing so causes
     UDP-packet-routing problems under MacOS/X.
   * Fixed a const-correctness problem in ConvertMessages.cpp.
   * Removed a compiler warning (from SysLog.cpp) about
     GetVersionA() not working usefully under Windows 8 and higher.
   * Applied Mika Lindqvist's patch to fix some potential
     memory leaks in regcomp.c
   * Applied Mika Lindqvist's patch to make the Windows
     "StackWalker" stack-trace-generation routine Unicode-compliant.

6.12 Released 4/6/2015
   - The Python message_transceiver_thread class will now
     fall back to connecting via IPv4 if the supplied hostname
     cannot be expanded to an IPv6 address (and vice versa).
   o Added a NotCopyable base class to various classes
     (Socket, DataNode, AbstractReflectSession, etc) so that
     the compiler will verify that they are not being copied.
   o The StringMatcher class now interprets any simple wildcard
     string starting with a backtick character (`) as indicating
     a non-simple regex string.  That way it is possible to use
     the standard regex functionality, if desired, in contexts
     that otherwise provide no way to indicate that a string
     is meant to be a full regex string and not a simple wildcard
     string (e.g. in MUSCLE subscription strings)
   o Tweaked the codebase to get rid of a number of style
     problems and minor errors that were reported by cppcheck.
   * Added a patch to the captive regex library to fix a
     potential int32-overrun in regcomp().  Thanks to Mika
     Lindqvist for supplying me with the patch.
   * Merged in some patches from Mika Lindqvist to avoid
     some warnings when compiling in a 64-bit environment.

6.11 Released 2/2/2015
   - When compiled under Windows, SetupSystem.cpp now contains
     #pragma commands so that necessary Windows-libraries will
     be automatically linked in.  This means the user no longer
     has to spend time chasing down so many linker errors when
     setting up a new project file.
   o MutexGuard's argument is now a const reference, since
     Mutex::Lock() and Mutex::Unlock() are const methods.
   o Removed AbstractReflectSession::GetDefaultHostName()
     and replaced it with a new method named
     AbstractReflectSession::GenerateHostName().  The new
     method lets the session subclass choose a custom
     hostname for the session even if the IP address
     determination didn't fail.
   o Added some private/unimplemented method overloads for
     MessageTransceiverThread::AddNewConnectSession() and
     QMessageTransceiverHandler::SetupAsNewConnectSession()
     so that if the caller tries to call these methods
     with timeout-values but forgets to include the
     (expandLocalhost) argument, the error will be caught
     at compile-time rather than causing unexpected run-time
     behavior.

6.10 Released 12/12/2014
   - The DetectNetworkConfigChangesSession class now has
     ComputerIsAboutToSleep() and ComputerJustWokeUp()
     callback methods that are called at the times indicated
     by their names.  Currently this functionality is
     implemented only under MacOS/X and Windows.
   o Added work-arounds for gcc-3.x SFINAE incompatibilities
     to MuscleSupport.h
   o Updated the muscle.dox file using doxygen -u so that
     it is now up-to-date (as of DOxygen 1.8.8)
   * If a string like "for 10 seconds" was passed to
     ParseHumanReadableTimeIntervalString(), the "for"
     prefix would cause the returned value to be twice
     what it was expected to be.  Fixed.

6.09 Released 11/3/2014
   - Added a (preferIPv6) argument to GetHostByName().  If
     left as true (the default value), GetHostByName() will
     prefer to return an IPv6 address over an IPv4 address.
   - Added support for a DEBUG_LARGE_MEMORY_ALLOCATIONS_THRESHOLD
     compiler-flag into GlobalMemoryAllocator.cpp.  When this
     flag is set to a value (in bytes), any memory allocations
     greater than the value will result in a message and a stack
     trace being printed to stdout.
   - When MUSCLE_USE_CPLUSPLUS11 is defined, the PODHashFunctor
     class will provoke a compile-time error if the program tries to
     use a struct or class as a KeyType in a Hashtable and the
     struct/class does not have a "uint32 HashCode const" method
     defined.  (Previously the code would compile without error, and
     then hashing errors would occur at runtime due to the object's
     padding bytes being uninitialized)
   * The MCRASH() macro now calls abort() rather than assert(false),
     so that a crash will actually occur, even if the code was
     compiled with -DNDEBUG.
   o The Windows implementation of MCRASH() now calls RaiseException(),
     so that the crash will behave more like an actual caused-by-a-bug
     crash (in particular, a Windows Structured Exception will be raised)
   o Updated SendDataUDP() to work around a "feature" in OS/X 10.10 (aka
     Yosemite) that causes setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF)
     to fail when setting the socket's interface-index value back to 0.

6.08 Released 10/10/2014
   - Added a ShrinkToFit() convenience method to the Queue,
     Hashtable, and String classes.  This method shrinks the
     object so that the amount of memory it has allocated internally
     matches the size of the data it is actually holding.
   - Hashtable::EnsureSize() and Queue::EnsureSize() now take an optional
     (allowShrink) argument, that (if set to true) allows the object's
     internally-allocated array to be reallocated smaller if it is larger
     than necessary.
   o Tweaked the buffer-expansion behavior of the String class to
     be a bit more efficient.
   * Added a guard against a potential infinite recursion that
     could occur while logging an "OUT OF MEMORY" error after
     a memory allocation failure, if a LogCallback tried to
     allocate memory.

6.07 Released 9/18/2014
   - Added a GlobalPrintRecyclersToStream() method to the
     AbstractObjectRecycler class, for better debugging and
     analysis of the ObjectPool's memory usage.
   - Added an abstract PrintToStream() method to the
     AbstactObjectRecycler class, and a concrete implementation
     of that method to the ObjectPool and ThreadPool classes.
   - Added a testobjectpool.cpp test program to the tests
     folder, as a quick sanity check for the ObjectPool class.
   - Java performance improvement from Bryan Varner: Switched to a
     direct byte buffer, which is allocated by the OS outside of
     the GC's managed space.
   - Java performance improvement from Bryan Varner: Scoped the
     receiving byte buffer to the receiver, which cut down on a
     lot of time spent allocating short-lived buffers.
   - Java performance improvement from Bryan Varner: Added a
     constructor for the MessageReceiver to allocate it's buffer
     to the same size as the sockets underlying buffer and made
     use of the call where possible.
   - Added a GetObjectClassName() method to the ObjectPool class.
   - The GetNetworkInterfaceInfos() function now supports a new
     bit named GNII_INCLUDE_UNADDRESSED_INTERFACES, which tells
     it to return even network interfaces with no IP address.
   - The default value of the (includeBits) argument to
     GetNetworkInterfaceInfos() is now GNII_INCLUDE_ALL_ADDRESSED_INTERFACES
     rather than GNII_INCLUDE_ALL_INTERFACES, to reflect the nuance
     that was added above; the default behavior is unchanged, though.
   - When -DMUSCLE_USE_CPLUSPLUS11 is defined, muscleMin() and
     muscleMax() now use variadic templates so that they can
     accept any number of arguments (rather than just up to five).
   o Java fix from Bryan Varner:  Updated the handling code for
     NotEnoughDataExceptions to no longer rely on the position of
     the buffer (but rather look at the buffer limit, or the amount
     previously read into the buffer) -- which basically makes the
     above change unnecessary, but I'm paranoid.
   o Changed the Message, Queue, Hashtable, and String classes so
     that when they are set equal to an empty/default object, they
     now free any large dynamically-allocated buffer they may be holding.
     This avoids excessive memory usage by objects that have been
     returned to an ObjectPool after being used to hold large amounts
     of data.
   o Modified muscleMin(), muscleMax(), muscleSgn(), muscleClamp(),
     and musclAbs() to take arguments and return by value rather
     than by const-reference.
   * Java fix from Bryan Varner:  Fixed a bug causing communication
     failures in the NIO message unflattening.
   * Java fix from Bryan Varner:  Prior to throwing a
     NotEnoughDataException the position of the buffer wasn't
     being updated in MessageIOGateway and JZLibMessageIOGateway.

6.06 Released 8/15/2014
   - ParseHumanReadableTimeIntervalString() can now parse strings
     where only the time-unit is specified.  (e.g. "second" now
     returns 1000000)
   - Added GetInternalThreadPulseTime(), InternalThreadPulse(),
     WriteToMainThread(), and ShutdownInternalThread() methods
     to the AsyncDataIO class, so that it can be subclassed for
     use in impersonating a "live" socket, using test data
     internally generated inside its I/O thread.
   o Added code to testbytebuffer.cpp, so that if a filename is
     passed as an argument, the contents of the specified file 
     will be printed to stdout in annotated-hex format.
   o Added support for a -DMUSCLE_AVOID_XENOMAI flag, to be used
     when compiling with -DTARGET_PLATFORM_XENOMAI but we don't
     want MUSCLE to use Xenomai anyway.
   * Merged in Augustin Cavalier's patch to get MUSCLE to
     compile again under Haiku.
   * Modified the Queue code to avoid a static-analyizer warning.
   * Fixed a valgrind hit in AbstractReflectSession::Reconnect().
   * Fixed a bug in AsyncDataIO that would cause it to hang
     when being shut down.
   * Fixed a bug that could cause a QueryFilter's replacement
     ConstMessageRef object to be ignored in certain circumstances.

6.05 Released 6/27/2014
   - Upgraded the captive zlib implementation to v1.2.8.
   o Moved public repository from FreeCode to GitHub, because
     FreeCode no longer accepts release announcements.
   o Renamed LICENSE.txt to LICENSE, since that's how GitHub
     likes the license file to be named.
   * Merged in Mika Lindqvist's patch to avoid some truncation
     warnings for strlen() calls under 64-bit Visual C++.

6.04 Released 6/11/2014 
   - Added a public GetParametersConst() method to the
     StorageReflectSession, for easier debugging.
   * Fixed a bug that prevented the PR_COMMAND_REMOVEPARAMETERS
     handler from removing parameters that had escaped wildcard
     characters in their names.

6.03 Released 6/2/2014
   - Added a convenience method muscleArrayIndexIsValid() that
     returns true iff the specified numeric index is a valid index
     into the specified array.
   - Added a CloseCurrentLogFile() function that can be used to
     force the file-logger to close any log file that it currently
     has open.
   - Added a SetSendDestinations() method to the UDPSocketDataIO
     class, for convenience.
   - The Launch*() and System*() methods in the ChildProcessDataIO
     class now take an optional directory-path argument so that you
     can specify the current working directory of the child process.
   - Added move-constructors and move-assignment operators to the
     Ref and ConstRef classes (available only when
     MUSCLE_USE_CPLUSPLUS11 is defined, of course).
   - Added a Reset() method to the PointerAndBool class.
   - Added a SwapContents() method to the PointerAndBool class.
   - Added RemoveHeadMulti() and RemoveTailMulti() convenience
     methods to the Queue class.
   o Queue::GetArrayPointer() now makes sure to set (retLength)
     to 0 when it returns NULL.
   * Under Windows, GetConstSocketRefFromPool() now automatically
     sets the don't-inherit flag on any sockets passed to it.  This
     avoids problems caused by child processes unintionally holding
     sockets connections open in the parent process.
   * Fixed a bug in Queue::EnsureSizeAux() that would cause a
     bogus extra item to be added to the end of the Queue if the
     (setNumItems) argument was set to true.
   * The MacOS/X implementation of DetectNetworkConfigChangesSession
     would fail to notify its calling code about a changed network
     configuration if the network change did not include any
     IP address changes.  Now it does provide a notification
     for that scenario as well.

6.02 Released 4/2/2014
   - Added optional (addHeaderBytes) and (addFooterBytes) arguments
     to the DeflateByteBuffer() utility functions.
   - Added an implementation of GetByteBufferFromPool() that takes
     a DataIO as an argument, for easy reading in of files, etc.
   - Added a NybbleizeData() implementation that takes a pointer
     and length argument rather than a ByteBuffer object.
   - Added an AreKeySetsEqual() convenience method to the Hashtable
     class.  This method checks for equal key-sets while ignoring
     the values in the two Hashtables.
   - Added WithoutPrefixIgnoreCase() and WithoutSuffixIgnoreCase()
     convenience methods to the String class.
   - Added some missing convenience overloads for HexBytesToString().
   - CanWildcardStringMatchMultipleValues() now ignores dashes in the
     string, since they only have meaning when enclosed in brackets --
     and if there are brackets in the string, those will be sufficient
     to cause CanWildcardStringMatchMultipleValues() to return true.
   o Renamed CanRegexStringMatchMultipleValues() to
     CanWildcardStringMatchMultipleValues(), as it is really examining
     the simplified wild-card syntax and not the official regex
     syntax.
   o Several locations that were calling HasRegexTokens() to decide
     if it was worth doing pattern-matching with a key-string now
     call CanWildcardStringMatchMultipleValues() instead.
   o DataNode::Reset() now deletes any metadata structures the
     DataNode may have accumulated, rather than simply clearing them.
     This saves RAM, and also ensures that recycled DataNodes will
     act exactly the same as newly created ones.
   * The MemMem() function did not return correct results in all
     cases.  Rewrote it to work correctly.

6.01 Released 1/7/2014
   - Added a PrependWord() convenience method to the String class.
   - Added WithReplacements() convenience methods to the String class.
   - Added a SetExplicitDelayMicros() method to the
     DetectNetworkConfigChangesSession class.
   - Added a IsCopperDetected() method to the NetworkInterfaceInfo
     class, so that code can tell whether or not a Ethernet jack
     has a cable plugged in to it.
   - Added a "quietsend" argument to hexterm.
   o The NetworkInterfacesChanged() virtual method
     in the DetectNetworkConfigChangesSession class
     has been changed to take an argument that calls out
     which network interfaces in particular have changed.
     This functionality is currently only implemented under
     Linux, MacOS/X and Windows.  For other OS's the
     argument will always be an empty list.
   * Fixed a bug in the Linux implementation of
     DetectNetworkConfigChangesSession that could cause
     a segmentation fault if recvmsg() returned an error
     (e.g. due to a signal being received).

6.00 Released 10/14/2013
   - Rewrote the SSLSocketDataIO class to work better
     with non-blocking I/O (in conjunction with the
     new SSLSocketAdapterGateway class).
   - Added implementations of SSLSocketDataIO::SetPrivateKey()
     and SSLSocketDataIO::SetCertificate() that take a
     ByteBuffer as an argument.
   - Added an SSLSocketAdapterGateway class that is used
     to manage OpenSSL's internal state machine when using
     an SSLSocketDataIO class with your gateway.
   - Added SetSSLPrivateKey() and GetSSLPrivateKey() methods
     to the ReflectServer class, for easier enabling of SSL
     authentication on all incoming TCP connections.  These
     methods are available iff MUSCLE_ENABLE_SSL is defined.
   - Added SetSSLPublicKeyCertificate() and GetSSLPublicKeyCertificate()
     methods to the ReflectServer class, for easier enabling
     of SSL authentication on outgoing TCP connections.  These
     methods are available iff MUSCLE_ENABLE_SSL is defined.
   - Added SetSSLPrivateKey() and SetSSLPublicKeyCertificate()
     methods to the MessageTransceiverThread class, for easier
     enabling of SSL functionality when using threaded I/O.
   - Added an ssl_data folder with some info on generating
     OpenSSL public/private keypairs, and an example keypair
     for use in testing OpenSSL.
   - When MUSCLE_ENABLE_SSL is defined, muscled now accepts
     an optional 'privatekey=filename' argument.  When specified,
     SSL mode will be enabled and muscled will only accept incoming
     TCP connections that present public keys that match this
     private key/certificate.
   - When MUSCLE_ENABLE_SSL is defined, portablereflectclient
     and qt_example will now accept an optional
     'publickey=filename' argument.  When specified, SSL mode
     will be enabled and these clients will connect to muscled
     using OpenSSL and present this file as their credentials.
   - Added an "Animate" checkbox to the qt_example demo.
     Checking it causes the window to move its indicator around
     automatically.  This is fun and also useful if you want to
     test a scenario where multiple clients are generating traffic
     simultaneously.
   - Made the qt_example demo prettier.
   - Renamed the C++11-helper macros in Hashtable.h and Queue.h
     to make them less likely to collide with other packages' macros.
   * Fixed some minor errors in the SSLSocketDataIO class.
   o Renamed SSLSocketDataIO::SetKey() to SetPrivateKey().
   o Renamed SSLSocketDataIO::SetCertificate() to
     SetPublicKeyCertificate().
   o AbstractMessageIOGateway::SetDataIO() is now a virtual
     method.
[For history information about older releases, see the HISTORY.txt file in the muscle archive]