Multi User Server Client Linkage Environment v6.23

Open Source Software by Meyer Sound Laboratories Inc

Written by Jeremy Friesner, Last Updated 7/7/2015


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

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, somewhat scalable, 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 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.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]