Written by Jeremy Friesner, Last Updated 2/24/2023
Go to the MUSCLE page on GitHub
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
Take the self-guided learn-by-example API tour
Read the Guide to making a custom MUSCLE server
Demonstration of how to add multithreading to a custom MUSCLE server (v1.05)
Read the BeShare and MUSCLE BeNews article
MUSCLE is licensed under the BSD Open Source License
Study the Java Client API Javadocs
key: - new feature
* bug fixed
o other
9.23 - Release 2/24/2023
- Added a -DWITH_THREAD_SANITIZER=ON option to the CMakeLists.txt.
- Added a -DMUSCLE_NUM_RESERVED_HIGH_BITS_IN_POINTERS flag to specify
how many of the most-significant-bits of a pointer are reserved for
system use. This value defaults to 16 for 64-bit Android systems
(to account for Android's MTE feature) and to 0 on everything else.
- Added a _registeredSubscribersMutex to the ICallbackMechanism class
so that it can handle unusual dispatching cases more gracefully.
- Added a runtests.sh script to tests folder. This script can be
run to quickly execute all tests and report any detected regressions.
- Added add_test() directives to test/CMakeLists.txt to enable CTest.
o Renamed -DMUSCLE_AVOID_BITSTUFFING to -DMUSCLE_AVOID_TAGGED_POINTERS
since the latter is a more commonly-used term.
o Changed the default setting of the WITH_TESTS option to OFF
in CMakeLists.txt
* GetNetworkInterfaceinfos() is now implemented for Android
(API level 24 or later).
* SharedMemory.cpp now compiles under Android (pre API level 26)
although its methods will return B_UNIMPLEMENTED if called.
* GetNetworkInterfaceInfos() now returns B_UNIMPLEMENTED when
called from an OS that it doesn't have an implementation for.
* Applied some Android build fixes as suggested by Ruurd Adema.
* SetFileLogLevel() was broken. Fixed.
* Avoid including sem.h when MUSCLE_FAKE_SHARED_MEMORY is defined.
9.22 - Released 2/2/2023
- Modified Queue::InternalizeIndex() to use subtraction
instead of modulo, for a 3x efficiency gain.
- Added a MUSCLE_NOEXCEPT keyword that expands to noexcept
under C++11 or later, or to nothing under C++03
- Added MUSCLE_NOEXCEPT tags to the SwapContents() methods
and move-constructors/operators that can make that guarantee.
- Added a MatchesNodeNameQueryFilter class, to support query
filtering against DataNode-names.
- Added DataNode::SetNodeName()
- Added a WITH_IPV6=OFF option to the CMakeLists.txt for
easier building of MUSCLE in IPv4-only mode.
- Added a "shareport" argument to hexterm to enable UDP port-sharing.
- Added an IsBroadcast() method to the IPAddress class.
- Added GetStatus() and SetStatus() methods to the
Ref/ConstRef/DummyRef/DummyConstRef classes, so that when they
are returned in a NULL state they can tell you why they aren't set.
- Added BooleansToBitChord() convenience-functions to PointerAndBits.h
- Updated PointerAndBits to be able to use the high bit in a
pointer as well as the low bit(s).
- Updated the captive zlib library to v1.2.13.
o Replaced the PointerAndBool.h header (and class) with a new
PointerAndBits.h header (and class) that does the same thing,
but in a simpler, more generalized fashion.
* Fixed broken UDP support in hexterm when -DMUSCLE_AVOID_IPV6
was set as a compiler-flag.
* Renamed SOCKET_FAMILY_IPV6 to SOCKET_FAMILY_IPV6_IS_DISABLED
when -DMUSCLE_AVOID_IPV6 is set, to avoid potential runtime bugs.
9.21 - Released 1/13/2023
- Added @tparam Doxygen tags for any template-arguments that
the calling code might need to specify explicitly.
- Enabled tagfile generation in muscle.dox.
- Added a DataIO::ReadFullyUpTo() convenience-method to handle
reading (up to n) bytes or (until EOF), whichever comes first.
- Added error code B_END_OF_STREAM to allow Read()-type methods
to unambiguously specify that the reason they are returning an
error is because they have reached EOF/EOS.
o Changed DataIO::ReadFully() and DataIO::WriteFully() to
return status_t instead of uint32.
o Removed the C APIs from the Doxygen output.
o Auto-updated the muscle.dox file to the latest Doxygen version.
* Fixed several issues to make Doxygen's output more useful.
* Fixed some compiler warnings in the captive regex library.
* Fixed the namespacing of the DoxyTemplates header so that
Doxygen generation works with the newest Doxygen version.
* Updated a number of out-of-date Doxygen comments.
9.20 - Released 12/30/2022
- Updated NetworkUtilityFunctions.cpp to better support "real"
IPv4 sockets (previously it assumed that IPv4 traffic would
be handled using IPv6 sockets and IPv4-mapped IPv6 addresses,
but that approach doesn't give 100% compatibility in all cases)
- Added a GetSocketFamily() method to the Socket class.
- Added an optional (socketFamily) argument to CreateUDPSocket().
- Added IsOK(io_status_t &) and IsError(io_status_t &) method
overrides to the io_status_t class.
- hexterm now instantiates a genuine IPv4 socket for use with
IPv4 multicast traffic.
- Tweaked gz*.c includes to compile without a configuration step.
- Added input-data-timestamping (including a PR_NAME_DATA_TIMESTAMP
field and SetReceiveTimestampingEnabled() and
GetReceiveTimestampingEnabled() methods) to the
RawDataMessageIOGateway class.
- Added SetLogLevelThreshold() and GetLogLevelThreshold() arguments
to the LogCallback class so that any LogCallback can now specify
what log-levels it is (or is not) interested in.
- Added templated overloads of Message::FindFlat(), Message::FindTag()
Message::GetFlat(), and Message::GetTag() that take any type of Ref
as an argument, so calling code no longer has to pass in a generic
RefCountableRef or FlatCountableRef and then do the necessary
downcasting separately afterward.
- Message::FindTag() now takes a ConstRefCountableRef as an
argument rather than a RefCountableRef, for better flexibility.
- Added templated overloads of Message::AddFlat(), PrependFlat(),
ReplaceFlat(), AddTag(), PrependTag(), and ReplaceTag() so that
the calling code no longer has to do manual upcasting of typed
FlatCountableRef or RefCountableRef objects before calling them.
- Added ConstMessageRef overloads of InflateMessage() and DeflateMessage().
- Added a ConstMessageRef-returning overload of Message::FindMessage().
o Removed the ByteBufferRef-specific *Flat() methods from
the Message class, since we now have more general templatized
methods that offer the same semantics for any type.
o SocketMultiplexer::WaitForEvents() now returns an io_status_t
rather than an int, for better error-reporting.
o Merged the IPv6 and IPv4 versions of AddSocketToMulticastGroup()
and RemoveSocketFromMulticastGroup() so that a single implementation
can work on either type of socket.
o Renamed SetSocketMulticastSendInterfaceAddress() and
GetSocketMulticastSendInterfaceAddress() to
SetIPv4SocketMulticastSendInterfaceAddress() and
GetIPv4SocketMulticastSendInterfaceAddress(), respectively,
and made them available even when -DMUSCLE_AVOID_IPV6 isn't set.
o Renamed Log() to LogPlain().
o Made LogTime() and LogPlain() into macros so that their arguments
will not be evaluated unless the logging-threshold-test passes.
o Improved error reporting in the ReflectServer event-loop.
o Removed the functions from TimeUnitConversions.h that take
(struct timeval &) as their argument, since they weren't being used.
o Removed SetConsoleLogLevel() and GetConsoleLogLevel() from the
DefaultConsoleLogger class, in favor of the new equivalent methods
in the LogCallback base class.
o Removed SetFileLogLevel() and GetFileLogLevel() from the
DefaultFileLogger class, in favor of the new equivalent methods
in the LogCallback base class.
o Renamed muscle's private namespaces to muscle_private.
o Replaced long with int32 in some I/O support functions.
o The default ByteBufferPool now clears the IMemoryAllocationStrategy
field of any ByteBuffer it recycles (after freeing its memory),
to avoid polluting the pool with user-installed strategies.
o Ref::SetFromRefCountableRef() now returns B_TYPE_MISMATCH on failure
rather than B_BAD_ARGUMENT.
o Removed the two-argument ConstRef and Ref "pseudo-constuctors"
and added instead a DowncastTo() method, to
make Ref-downcasting operations self-documenting.
o Changed ITraversalPruner::MatchPath() and CreateObjectFromArchiveMessage()
to take ConstMessageRef as an argument rather than MessageRef.
o Changed StorageReflectSession::SetDataNode(), InsertOrderedData(),
InsertOrderedChildNode(), and GetNewDataNode() to take
ConstMessageRef as an argument rather than MessageRef.
o Changed DataNode to hold a ConstMessageRef rather than a MessageRef.
o Changed StorageReflectSession::NotifySubscribersThatNodeChanged()
and StorageReflectSession::NodeChanged() to pass a ConstMessageRef
rather than a MessageRef.
o ByteBuffer::ReleaseBuffer() now returns (uint8 *) instead of
(const uint8 *).
* Fixed MLOG_ON_ERROR and friends to be usable with io_status_t.
* ExpandLocalhostAddress() no longer expands IPv6 loopback addresses.
* UDPSocketDataIO::ReadFrom() would call SetSourceOfLastReadPacket()
even when no packet had been read, clearing that field. Fixed.
* Some functions in MuscleSupport.h were unintentionally being
declared outside the muscle namespace. Fixed.
9.10 - Released 12/10/2022
- Rewrote the non-Windows implementation of muscleSprintf()
to call vsnprintf() instead of sprintf(), to avoid compiler
warnings about sprintf() being insecure.
- Instrumented the non-Windows implementation of muscleSprintf()
with MUSCLE_PRINTF_ARGS_ANNOTATION_PREFIX so that the compiler
will warn about calls to muscleSprintf() with the wrong format
specifiers.
- Added an io_status_t class to represent the result of an I/O
operation. An io_status_t contains both a status_t and an
int32 byte-count.
- Added a MUSCLE-by-example page for the status_t class.
- Added MTALLY_BYTES_OR_RETURN_ON_IO_ERROR() and
MTALLY_BYTES_OR_RETURN_ON_IO_ERROR_OR_BREAK() macros to
MuscleSupport.h.
o Changed the return-types of the NetworkUtilityFunctions that
previously returned (int32/byte-count-or-negative-1), aka
SendData(), ReceiveData(), SendDataUDP(), ReceiveDataUDP(),
ReadData(), and WriteData() to return a more informative
io_status_t instead.
o Changed the DataIO::Read() and DataIO::Write() methods to
return io_status_t instead of int32.
o Changed the PacketDataIO::ReadFrom() and PacketDataIO::WriteTo()
methods to return io_status_t instead of int32.
o Simplified the implementation of GetDefaultObjectForType() back
to one that compile under any version of C++. We'll rely on
the optimizer to do the right thing, rather than SFINAE.
o Modified Directory::SetDir() to return a static status_t value
rather than B_ERRNO, to avoid potential static-initialization
ordering problems on pre-C++11 compilers.
o tagged status_t as a MUSCLE_FINAL_CLASS.
o Replaced the MAKETYPE(x) macro with a MakeWhatCode() function.
* Updated message_transceiver_thread.py to catch and ignore any
EAGAIN exceptions generated by send() on a notification-socket.
* Fixed a spurious assertion failure in SimulatedMulticastDataIO.
* Changed some code to return B_IO_ERROR instead of B_ERRNO if
fread() or fwrite() fails, since those functions are not
guaranteed to set errno when they fail.
* Fixed a bug that would cause GetEnvironmentVariableValue() to
sometimes return garbage strings under Windows if the environment
variable did not exist.
* Added missing DOxygen parameter documentation for various
macros declared in MuscleSupport.h.
* Fixed a number of broken hyperlinks in the MUSCLE-by-example docs.
9.01 - Released 11/18/2022
- Added a WritePaddingBytesToAlignTo(uint32 alignSize)
convenience-method to the CheckedDataFlattenerHelper
and DataFlattenerHelper classes.
- Added a SeekPastPaddingBytesToAlignTo(uint32 alignSize)
convenience-method to the DataUnflattenerHelper class.
- Added DataUnflattener ctor and SetBuffer() calls that
take a ByteBufferRef, for convenience.
- Added a GetEnvironmentVariableValue() convenience function,
to avoid calling getenv() directly from user code.
- Added %p (aka process ID) to the set of tokens expanded by
HumanReadableTimeValues::ExpandTokens().
- DefaultFileLogger::EnsureLogFileCreated() now tries a little
harder: if it can't create a log file with the given file name,
it will try up to 10 variants of the file name in the hopes
of coming up with a file name that is unique and can be created.
- Added a IsBitIndexValid() convenience-method to the BitChord class.
- Added MUSCLE_CONSTEXPR_OR_CONST macro to expand to "constexpr"
if possible, or "const" otherwise.
- GetDefaultObjectForType() now uses constexpr to avoid on-demand
initialization, when -DMUSCLE_USE_CPLUSPLUS17 is defined.
- CMakeLists.txt now automatically specifies -DMUSCLE_USE_PTHREADS
if building on POSIX for C++03, and WITH_THREADS is ON.
- LogTime() calls now emit printf-style format-usage warnings
when compiled with g++ or clang++.
- Added INT16_FORMAT_SPEC_* macros, for completeness.
o PODSwapper now calls std::swap() rather than reimplementing it.
* Moved the definitions of the B_* error-codes out of SetupSystem.cpp
and into MuscleSupport.h, so that Clang's Static Analyzer can see
what values they contain and generate better output.
* Generation of the random number that %r expands to is now
actually random (not just calling rand()) (in C++11 or newer).
* Renamed several of the longer mkdocs examples folder names
to avoid hitting Windows' 260-character path limit.
* Fixed a potential uninitialized-memory-read in the String
class's GetLevenshteinDistance() method.
* Fixed the CMakeList.txt files in the sub-folders to use
the inherited CMAKE_CXX_STANDARD setting rather than
forcing C++11.
* GetCurrentThreadID() is no longer compiled if
-DMUSCLE_SINGLE_THREAD_ONLY is specified.
9.00 - Released 10/27/2022
- Added a MUSCLE_MAXIMUM_NODE_DEPTH constant that limits
how deep the MUSCLE node-tree may become, to prevent
stack-overflow attacks. Defaults to 100.
- Added DataFlattener and DataUnflattener classes to
allow for safer flattening/unflattening of data
to/from byte-buffers.
- Added an UncheckedDataUnflattener class, for better
efficiency when the calling code has already done its
own bounds-checking.
- Added a CheckedDataUnflattener class, for better
calling code that wants to use a dynamically-growing
output buffer.
- Added support/EndianConverter.h to allow templating
over big/little/native endian-encoding strategies.
- Added pages for DataFlattener and DataUnflattener
APIs to the muscle-by-example documentation.
- Adding -DMUSCLE_USE_BIG_ENDIAN_DATA_FOR_EVERYTHING
to your compile line will tell MUSCLE to use big-endian
data format for all of its data. Note that doing so will
break interoperability with all existing MUSCLE builds!
- Adding -DMUSCLE_USE_NATIVE_ENDIAN_DATA_FOR_EVERYTHING
to your compile line will tell MUSCLE to use native-endian
data format for all of its data. Note that doing so will
break compatibility with different-endian CPUs!
o Changed the PseudoFlattenable::Flatten() and
Flattenable::Flatten() methods to take a second
argument (flatSize) for better runtime error-checking.
o Changed the PseudoFlattenable::Unflatten() and
Flattenable::Unflatten() methods to take a
(DataUnflattener &) as an argument rather than
a raw pointer, for better caller/callee cooperation.
o Changed Message::TemplatedFlatten() to use
a DataFlattener as an argument.
o Changed Message::TemplatedUnflatten() to use
a DataUnflattener as an argument.
o Removed the SetEndianFlag(), Append*(), Write*(),
Read*() methods from the ByteBuffer class. Use
the new DataFlattener/DataUnflattener classes instead.
o Refactored the StringTokenizer class's constructors to
take a single (optSepChars) argument instead of separate
arguments for hard and soft separator characters.
o Made the calculation of DataNode depths more efficient.
o Removed Flattenable::WriteData() and Flattenable::ReadData()
methods (since DataFlattener/DataUnflattener do it better).
o Replaced most calls to B_LENDIAN_*_TO_HOST() and
B_HOST_TO_LENDIAN_*() with calls to DefaultEndianConverter's
Import() and Export() methods, to allow MUSCLE to be built
in big-endian mode.
o Changed the PseudoFlattenable class to be templatized, and
added methods to it so all the helper methods declared in
the Flattenable interface are also available in the
PseudoFlattenable interface.
o Refactored the ZLib-support classes in muscle/zlib so that they
no longer include any zlib-headers from their header files.
* Modified Snooze64() to call clock_nanosleep() under Linux,
and to call nanosleep() when -DMUSCLE_USE_LIBRT is defined.
* Changed all the #include "zlib/zlib/zlib.h" directives to
#include "zlib.h" to avoid using the captive zlib headers
together with any system-supplied zlib implementation (which
might be different)
* Fixed a bug that could cause ZLibDataIO::WriteAux() to
to into an infinite recursion if zlib's deflate() errored out.
* Fixed a bug in MessageIOGateway that could cause it fail
to report how many bytes it had sent or received, if an
I/O error occurred later on in the same call to DoInput()
or DoOutput().