Written by Jeremy Friesner, Last Updated 3/6/2024
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.36 - Released 3/6/2024 - Added GetMostRecentInputTimeStamp() and GetMostRecentOutputTimeStamp() methods to the AbstractReflectSession class - Added a GetMostRecentAcceptTimeStamp() method to the ReflectSessionFactory class. - Added a GetAcceptCount() method to the ReflectSessionFactory class. - PrintSessionsInfo() now includes text describing how recently each session has sent or received data. - PrintFactoriesInfo() now includes text describing how recently each factory has accepted an incoming TCP connection, and how many connections the factory has received so far. - Added a GetClientDescriptionString() virtual method to the AbstractReflectSession class to support more-useful debug output. - Added a GetSocketBindAddress() function to NetworkUtilityFunctions.h for querying where a socket is bound to on the local machine. o Renamed GetPeerIPAddress() to GetPeerAddress(), and changed it to return an IPAddressAndPort instead of returning an IPAddress and also using a separate (optPort) argument. o Tweaked zlib/zlib/zconf.h so that the gzlib files can build successfully even if ./configure wasn't called in the zlib/zlib folder first. o SocketMultiplexer::RegisterSocket() now emits an error message to the log if a file descriptor is too large to pass to FD_SET(). * Updated build instructions to specify cmake instead of Visual Studio 9.35 - Released 2/14/2024 - Added an optional (optRunAsUser) argument to the various process launch methods in ChildProcessDataIO. - Added convenience constructors to the IPAddress class that take an in_addr or in6_addr as an argument. - Added convenience constructors to the IPAddressAndPort class that take a sockaddr_in or sockaddr_in6 as an argument. - Added WriteToInAddr() and WriteToIn6Addr() convenience methods to the IPAddress class. - Added WriteToSockAddrIn() and WriteToSockAddrIn6() convenience methods to the IPAddressAndPort class. - Added convenience overloads of the SendDataUDP() and ReceiveDataUDP() functions that take an IPAddressAndPort as their source/destination argument. - Added method IPAddress::IsIPv6LinkLocal(). o Changed ChildProcessDataIO::ChildProcessReadyToRun() to be protected instead of public. o Removed ip_address typedef; use IPAddress instead. o Tweaked Inet_NtoA() so that when called with the (preferIPv4) flag, it will return the invalid/all-zeroes IP address string as "" rather than "::". * Updated TarFileWriter to handle it a little more elegantly when a file's length changes while the tar data is being written out to a non-seekable DataIO. * Fixed a bug in the Ref class that would cause a NULL Ref's status-string to be returned as "OK" rather than "NULL Ref" * BitChord::SetByte()'s second argument was the wrong type. Fixed. 9.34 - Released 12/18/2023 - Added an optional localnicip=local.nic.ip.address argument to hexterm, to better support sending IPv4 multicast packets. - Added a B_SHUTTING_DOWN error code, useful for returning from Thread::MessageReceivedFromOwner() overrides if there isn't any real error but the internal thread is exiting on request. - Added a templated GetConstRefToDefaultObjectForType() convenience function to util/RefCount.h - Added a GetHardLinkCount() method to the FilePathInfo class. o Modified IsRegexToken() to return false for '-', since hyphens aren't meaningful except in the context of "character class" regex tokens (which will get escaped anyway). o Replaced the IsHosed() and SetHosed() methods of the AbstractMessageIOGateway class with more descriptive methods GetUnrecoverableErrorStatus() and SetUnrecoverableErrorStatus(). 9.33 - Released 10/30/2023 - Added FromHexString() and FromBinaryString() methods to the BitChord class, to complement the ToHexString() and ToBinaryString() methods. - Added a Queue::IsIndexValid(uint32) convenience-method. - Updated the Queue::Remove*() methods to use std::move() when possible. - Updated the Hashtable::Remove*() methods to use std::move() when possible. - Added IsAtStart() and IsAtEnd() convenience-methods to the HashtableIterator class. - The snoopsharedmem tool now support an optional (maxBytesToPrint) argument, in case you only want to see the header of the region. o Removed obsolete references to TARGET_PLATFORM_XENOMAI. o Updated the captive zlib library to the current GitHub version, to avoid "function declaration without a prototype is deprecated" compiler warnings. * Fixed the LogTime() and LogPlain() macros so that they compile when called from a different namespace. * Changed ImmutableHashtablePool::GetWithAux() to repurpose an existing table (if possible) while adding an item, as well as when removing one. 9.32 - Released 9/8/2023 - Added a -DWITH_HELGRIND option to CMakeLists.txt to enable causality annotations in the reference-counting of RefCount.h so that helgrind doesn't give false-positive warnings when analyzing an execution of this code for race conditions. - Added MUSCLE_CONSTEXPR tag to trivial constructors and methods of various POD-like utility classes. - Added MUSCLE_CONSTEXPR_17 macro, for places where a constexpr tag is useful but only allowed in C++17 or later. o Updated PythonUtilityFunctions.h to use a forward-declaration instead of #include-ing Python.h directly, to avoid potential namespace-collisions between Python and Qt. * Applied fixes for various minor issues flagged by pvs-studio-analyzer. * Changed SignalMultiplexer's received-signal-counters to be AtomicCounters rather than uint32 to avoid helgrind complaints when a signal is handled. * The ObjectPool constructor now calls GetDefaultObjectForType() on its object-type and the associated Ref-types, to ensure that the static singleton is initialized while the process is still in a single-threaded state. * IsMessageDeflated() now takes a ConstMessageRef rather than MessageRef. * Fixed a pointer-type-mismatch issue that could cause unnecessary compile-time errors in the templated version of Hashtable::Remove() 9.31 - Released 6/14/2023 - Added an IsFileOpen() method to the GZDataIO class. - Modified the Hashtable class so that HashtableIterators are only registered in the iterators-list if they are actually pointing at a valid HashtableEntry. - ParseConnectArg() and IPAddressAndPort::SetFromString() now support an alternate port-syntax that doesn't require brackets, to get around osascript's command-parsing limitations. E.g. you can now specify "::1_port_1234" instead of "[::1]:1234" - Added convenience PODHashFunctor specializations (for QSize, QPoint, and QRect) to QMuscleSupport.h o Increased the Snooze64() time in testatomicvalue's writer thread to 10mS as it appears that 1mS snoozes were being rounded down to zero. o Added MUSCLE_NODISCARD tag to the String and IPAddressAndPort classes. o Increased the default value of AtomicValue's ATOMIC_BUFFER_SIZE template argument to 8. * Fixed code that was passing NULL as an argument to %s in printf() or LogTime(). Thanks to Ruurd Adema for pointing out that doing that is undefined behavior. * Changed Hashtable::_iteratorThreadID to be a std::atomic<> to avoid potential undefined behavior in multithreaded scenarios. * Fixed AtomicValue class to use bitmasks instead of modulo and only support powers-of-two array sizes. * Fixed the handling of InterlockedCompareExchange()'s return value in the AtomicValue class. 9.30 - Released 4/28/2023 - Tagged the constructor of the MutexGuard class (and friends) as MUSCLE_NODISCARD so the compiler will warm about anonymous guards. - Tagged ObjectPool::ObtainObject() with MUSCLE_NODISCARD. - Added MUSCLE_NODISCARD to all the functions and methods that it wouldn't make sense to call without examining their return value. - Added MUSCLE_NODISCARD to various concrete classes (String, Queue, Hashtable, IPAddress, etc) that shouldn't be ignored when used as return values. o Renamed String::Append() to String::WithAppend(). o Renamed String::Prepend() to String::WithPrepend(). o Renamed String::AppendWord() to String::WithAppendedWord(). o Renamed String::PrependWord() to String::WithPrependedWord(). o Renamed String::Trim() to String::Trimmed(). o Renamed String::Pad() to String::PaddedBy(). o Renamed String::Indent() to String::IndentedBy(). o Removed DEFAULT_MUSCLE_ROUTING_FLAGS_BIT_CHORD, and rewrote the routing flags to use the BitChord class. o Rewrote testnagle.cpp to include a unit-test for automated testing. o Updated function declarations in regex captive library to avoid compiler warnings. o Updated the unit tests so none of them takes more than 5 seconds to complete when done as part of a CMake "make test" pass. * Fixed logic error in testgateway.cpp. * MUSCLE_NODISCARD is now defined as a no-op when compiling C code, to avoid breaking the build under C compilers that say they support C23 but nevertheless don't grok [[nodiscard]] yet. 9.25 - Release 4/7/2023 - Rewrote String::WithReplacements(const Hashtable<String,String> & to only scan the input string once, instead of once per key. - Added a String::Replace(const Hashtable<String,String> & method. - Added a ReplaceAllItems() convenience-method to the Queue class. - Added MUSCLE_NO_DISCARD keyword, and applied it to the Ref and ConstRef classes and to the status_t and io_status_t types, so that calls ignoring these return values will generate compile-time warnings. - Added a TruncateToLength() convenience method to the ByteBuffer class. - Added a PR_NAME_KEEPALIVE_INTERVAL_SECONDS parameter so clients can tell muscled to send a PR_RESULT_NOOP every (so many) seconds to verify TCP connectivity on an otherwise idle connection. o Removed DataIO::GetReadByteTimeStamp() as it wasn't being used. o CloseSocket() now prints an error message if its call to close() fails. * GetProcessMemoryUsage() now returns more accurate values. * Fixed a number of broken hyperlinks in the MUSCLE-by-example mkdocs. 9.24 - Release 3/20/2023 - Added a CMakePresets.json file for quick specification of minimal (i.e. library-only) or full (i.e. including unit-tests) builds. - Added a CMAKEOPTIONS.txt file to describe the options available for building MUSCLE via cmake. o Moved the non-unit-test executables out of the "test" folder and into their own new/separate "tools" folder. o Renamed BUILDOPTIONS.txt to COMPILEROPTIONS.txt * Modified AbstractReflectSession::Reconnect() to not fail if CreateDefaultSocket() return a NULL reference. * The Python3 implementation of message.py wasn't encoding non-ASCII utf8 strings correctly when flattening a Message. Fixed. * ZLibCodec::Inflate() would fail when inflating a compressed zero-byte buffer. Fixed. 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().