aboutsummaryrefslogtreecommitdiff
path: root/nxcomp/Message.h
diff options
context:
space:
mode:
Diffstat (limited to 'nxcomp/Message.h')
-rw-r--r--nxcomp/Message.h1089
1 files changed, 0 insertions, 1089 deletions
diff --git a/nxcomp/Message.h b/nxcomp/Message.h
deleted file mode 100644
index 30883f101..000000000
--- a/nxcomp/Message.h
+++ /dev/null
@@ -1,1089 +0,0 @@
-/**************************************************************************/
-/* */
-/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
-/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
-/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
-/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
-/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
-/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
-/* */
-/* NXCOMP, NX protocol compression and NX extensions to this software */
-/* are copyright of the aforementioned persons and companies. */
-/* */
-/* Redistribution and use of the present software is allowed according */
-/* to terms specified in the file LICENSE.nxcomp which comes in the */
-/* source distribution. */
-/* */
-/* All rights reserved. */
-/* */
-/* NOTE: This software has received contributions from various other */
-/* contributors, only the core maintainers and supporters are listed as */
-/* copyright holders. Please contact us, if you feel you should be listed */
-/* as copyright holder, as well. */
-/* */
-/**************************************************************************/
-
-#ifndef Message_H
-#define Message_H
-
-#include <X11/Xproto.h>
-
-#include "NXproto.h"
-
-#include "Misc.h"
-#include "Control.h"
-
-#include "Types.h"
-#include "Timestamp.h"
-
-#include "ActionCache.h"
-
-#include "StaticCompressor.h"
-
-//
-// Forward class declarations.
-//
-
-class ChannelCache;
-
-class EncodeBuffer;
-class DecodeBuffer;
-
-class WriteBuffer;
-
-//
-// Set the verbosity level.
-//
-
-#define PANIC
-#define WARNING
-#undef TEST
-#undef DEBUG
-
-//
-// Define this to know how many messages
-// are allocated and deallocated.
-//
-
-#undef REFERENCES
-
-//
-// Set default values. We limit the maximum
-// size of a request to 262144 but we need to
-// consider the replies, whose size may be up
-// to 4MB.
-//
-
-#define MESSAGE_ENABLE_CACHE 0
-#define MESSAGE_ENABLE_DATA 0
-#define MESSAGE_ENABLE_SPLIT 0
-#define MESSAGE_ENABLE_COMPRESS 0
-
-#define MESSAGE_DATA_LIMIT 4194304 - 4
-#define MESSAGE_DATA_OFFSET 4
-
-#define MESSAGE_CACHE_SLOTS 6000
-#define MESSAGE_CACHE_THRESHOLD 50
-#define MESSAGE_CACHE_LOWER_THRESHOLD 5
-
-//
-// Base message class.
-//
-
-class Message
-{
- friend class MessageStore;
- friend class RenderExtensionStore;
-
- public:
-
- Message()
- {
- hits_ = 0;
- last_ = 0;
- locks_ = 0;
-
- size_ = 0;
- c_size_ = 0;
-
- md5_digest_ = NULL;
-
- #ifdef REFERENCES
-
- references_++;
-
- *logofs << "Message: Created new message at "
- << this << " out of " << references_
- << " allocated messages.\n"
- << logofs_flush;
-
- #endif
- }
-
- Message(const Message &message)
- {
- size_ = message.size_;
- c_size_ = message.c_size_;
- i_size_ = message.i_size_;
-
- hits_ = message.hits_;
- last_ = message.last_;
- locks_ = message.locks_;
-
- data_ = message.data_;
-
- #ifdef REFERENCES
-
- references_++;
-
- *logofs << "Message: Creating new copied message at "
- << this << " out of " << references_
- << " allocated messages.\n"
- << logofs_flush;
- #endif
-
- if (message.md5_digest_ != NULL)
- {
- md5_digest_ = new md5_byte_t[MD5_LENGTH];
-
- memcpy(md5_digest_, message.md5_digest_, MD5_LENGTH);
-
- #ifdef DEBUG
- *logofs << "Message: Created MD5 digest for object at "
- << this << ".\n" << logofs_flush;
- #endif
- }
- else
- {
- md5_digest_ = NULL;
- }
- }
-
- ~Message()
- {
- #ifdef DEBUG
- if (md5_digest_ != NULL)
- {
- *logofs << "Message: Deleted MD5 digest for object at "
- << this << ".\n" << logofs_flush;
- }
- #endif
-
- delete [] md5_digest_;
-
- #ifdef REFERENCES
-
- references_--;
-
- *logofs << "Message: Deleted message at "
- << this << " out of " << references_
- << " allocated messages.\n"
- << logofs_flush;
- #endif
- }
-
- //
- // This is the original message size
- // including the data part regardless
- // data is still stored in the object.
- //
-
- int size_;
-
- //
- // This is the size of the identity.
- //
-
- int i_size_;
-
- //
- // This is the size, including identity,
- // after message has been 'updated' to
- // reflect storage of data in compressed
- // format.
- //
-
- int c_size_;
-
- protected:
-
- //
- // This is the data part.
- //
-
- T_data data_;
-
- //
- // Time of last hit.
- //
-
- time_t last_;
-
- //
- // This is the number of cache hits
- // registered for the object.
- //
-
- short int hits_;
-
- //
- // This is used to mark messages
- // that have been split.
- //
-
- short int locks_;
-
- //
- // This is the MD5 checksum.
- //
-
- md5_byte_t *md5_digest_;
-
- //
- // Keep a reference counter
- // of allocated objects.
- //
-
- #ifdef REFERENCES
-
- static int references_;
-
- #endif
-};
-
-//
-// Repository of messages.
-//
-
-class MessageStore
-{
- public:
-
- //
- // Enable or disable cache of messages in store.
- //
-
- int enableCache;
-
- //
- // Does message have a distinct data part.
- //
-
- int enableData;
-
- //
- // Enable or disable split of data part.
- //
-
- int enableSplit;
-
- //
- // Enable or disable compression of data part.
- //
-
- int enableCompress;
-
- //
- // Set starting point of data part in the message.
- //
-
- int dataOffset;
-
- //
- // Set maximum size for the data part of each message.
- //
-
- int dataLimit;
-
- //
- // Set maximum elements in cache.
- //
-
- int cacheSlots;
-
- //
- // Set the percentage of total cache memory which
- // a given type of message is allowed to occupy.
- // When threshold is exceeded store is cleaned to
- // make room for a new message of the same type.
- //
-
- int cacheThreshold;
-
- //
- // Don't clean the store if percentage of cache
- // memory occupied by messages of this type is
- // below the threshold.
- //
-
- int cacheLowerThreshold;
-
- //
- // Last operation performed on cache.
- //
-
- T_store_action lastAction;
-
- //
- // Position of last element stored in cache.
- //
-
- short int lastAdded;
-
- //
- // Positions of last element found in cache.
- //
-
- short int lastHit;
-
- //
- // Position of last element erased.
- //
-
- short int lastRemoved;
-
- //
- // Used to encode the the action to
- // perform on the store and the slot
- // involved.
- //
-
- ActionCache lastActionCache;
-
- //
- // Position in cache where next insertion
- // is going to take place.
- //
-
- short int lastRated;
-
- //
- // Constructors and destructors.
- //
-
- public:
-
- MessageStore(StaticCompressor *compressor = NULL);
-
- virtual ~MessageStore();
-
- virtual const char *name() const = 0;
-
- virtual unsigned char opcode() const = 0;
-
- virtual unsigned int storage() const = 0;
-
- //
- // These are members that must be specialized.
- //
-
- public:
-
- virtual Message *create() const = 0;
-
- virtual Message *create(const Message &message) const = 0;
-
- virtual void destroy(Message *message) const = 0;
-
- void validateSize(int size)
- {
- if (size < control -> MinimumMessageSize ||
- size > control -> MaximumMessageSize)
- {
- *logofs << name() << ": PANIC! Invalid size " << size
- << " for message.\n" << logofs_flush;
-
- cerr << "Error" << ": Invalid size " << size
- << " for message opcode " << opcode() << ".\n";
-
- HandleAbort();
- }
- }
-
- void validateSize(int dataSize, int compressedDataSize)
- {
- if (dataSize < 0 || dataSize > control ->
- MaximumMessageSize - 4 || compressedDataSize < 0 ||
- compressedDataSize >= dataSize)
- {
- *logofs << name() << ": PANIC! Invalid data size "
- << dataSize << " and compressed data size "
- << compressedDataSize << " for message.\n"
- << logofs_flush;
-
- cerr << "Error" << ": Invalid data size "
- << dataSize << " and compressed data size "
- << compressedDataSize << " for message "
- << "opcode " << (unsigned) opcode() << ".\n";
-
- HandleAbort();
- }
- }
-
- //
- // Determine if the message can be stored
- // in the cache.
- //
-
- virtual int validateMessage(const unsigned char *buffer, int size)
- {
- return (size >= control -> MinimumMessageSize &&
- size <= control -> MaximumMessageSize);
- }
-
- //
- // Get data offset based on major and minor
- // opcode of the message.
- //
-
- virtual int identitySize(const unsigned char *buffer, unsigned int size)
- {
- return dataOffset;
- }
-
- //
- // Encode identity and data using the
- // specific message encoding.
- //
- // Some messages do not implement these
- // methods because the encoding is done
- // directly in the channel loop. Should
- // move the encoding methods in in the
- // message classes.
- //
-
- virtual int encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
- unsigned int size, int bigEndian,
- ChannelCache *channelCache) const
- {
- return 1;
- }
-
- virtual int decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
- unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
- ChannelCache *channelCache) const
- {
- return 1;
- }
-
- //
- // Encode differences between message
- // in cache and the one to be encoded.
- //
-
- virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
- const Message *cachedMessage, ChannelCache *channelCache) const
- {
- }
-
- //
- // Decode differences and update the
- // cached version of the same message.
- //
-
- virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
- ChannelCache *channelCache) const
- {
- }
-
- //
- // Post process the message information
- // contained in the store by either up-
- // dating the size record or the actual
- // data part once the message has been
- // completely sent to our peer.
- //
-
- void updateData(const int position, unsigned int dataSize,
- unsigned int compressedDataSize);
-
- void updateData(const T_checksum checksum, unsigned int compressedDataSize);
-
- void updateData(const int position, const unsigned char *newData,
- unsigned int dataSize, unsigned int compressedDataSize);
-
- //
- // These members, used internally
- // in the message store class, are
- // mandatory.
- //
-
- protected:
-
- virtual int parseIdentity(Message *message, const unsigned char *buffer,
- unsigned int size, int bigEndian) const = 0;
-
- virtual int unparseIdentity(const Message *message, unsigned char *buffer,
- unsigned int size, int bigEndian) const = 0;
-
- virtual void identityChecksum(const Message *message, const unsigned char *buffer,
- unsigned int size, int bigEndian) const = 0;
-
- virtual void dumpIdentity(const Message *message) const = 0;
-
- //
- // Design should preserve these from being
- // virtual.
- //
-
- int parseData(Message *message, int split, const unsigned char *buffer,
- unsigned int size, T_checksum_action checksumAction,
- T_data_action dataAction, int bigEndian);
-
- int parseData(Message *message, const unsigned char *buffer,
- unsigned int size, const unsigned char *compressedData,
- const unsigned int compressedDataSize, T_checksum_action checksumAction,
- T_data_action dataAction, int bigEndian);
-
- int unparseData(const Message *message, unsigned char *buffer,
- unsigned int size, int bigEndian);
-
- //
- // Manage efficient allocation of messages
- // in the heap.
- //
-
- void recycle(Message *message)
- {
- #ifdef TEST
-
- if (message == NULL)
- {
- *logofs << name() << ": PANIC! Cannot recycle a null message.\n"
- << logofs_flush;
-
- cerr << "Error" << ": Cannot recycle a null message.\n";
-
- HandleAbort();
- }
-
- #endif
-
- if (temporary_ == NULL)
- {
- //
- // Be careful when reusing the message as
- // it can contain valid data that must be
- // explicitly deallocated if not needed.
- // Note also that you cannot count on the
- // initialization made in costructor.
- //
-
- temporary_ = message;
- }
- else
- {
- destroy(message);
- }
- }
-
- void beginChecksum(Message *message)
- {
- if (message -> md5_digest_ == NULL)
- {
- message -> md5_digest_ = new md5_byte_t[MD5_LENGTH];
-
- #ifdef DEBUG
- *logofs << name() << ": Created MD5 digest structure "
- << "for object at " << message << ".\n"
- << logofs_flush;
- #endif
- }
- #ifdef DEBUG
- else
- {
- *logofs << name() << ": Using existing MD5 digest structure "
- << "for object at " << message << ".\n"
- << logofs_flush;
- }
- #endif
-
- #ifdef DEBUG
- *logofs << name() << ": Prepared MD5 digest for object at "
- << message << ".\n" << logofs_flush;
- #endif
-
- md5_init(md5_state_);
- }
-
- void endChecksum(Message *message)
- {
- md5_finish(md5_state_, message -> md5_digest_);
-
- #ifdef DEBUG
- *logofs << name() << ": Calculated checksum for object at "
- << message << ".\n" << logofs_flush;
- #endif
- }
-
- void dataChecksum(Message *message, const unsigned char *buffer,
- unsigned int size, int bigEndian)
- {
- //
- // Messages that have a data part starting
- // at an offset possibly beyond the end of
- // the message, must include the size in
- // the identity checksum.
- //
-
- if ((int) size > message -> i_size_)
- {
- md5_append(md5_state_, buffer + message -> i_size_,
- size - message -> i_size_);
- }
- }
-
- //
- // Repository handling methods.
- //
-
- public:
-
- //
- // Extract identity and data from buffer.
- // The size field will be updated at the
- // time of data parsing.
- //
-
- int parse(Message *message, int split, const unsigned char *buffer, unsigned int size,
- T_checksum_action checksumAction, T_data_action dataAction, int bigEndian);
-
- int parse(Message *message, const unsigned char *buffer, unsigned int size,
- const unsigned char *compressedData, const unsigned int compressedDataSize,
- T_checksum_action checksumAction, T_data_action dataAction, int bigEndian);
-
- //
- // From identity and data write the
- // final message to the raw buffer.
- //
-
- int unparse(const Message *message, unsigned char *buffer,
- unsigned int size, int bigEndian)
- {
- return (unparseData(message, buffer, size, bigEndian) &&
- unparseIdentity(message, buffer, size, bigEndian));
- }
-
- void dump(const Message *message) const
- {
- dumpIdentity(message);
-
- dumpData(message);
- }
-
- void dumpData(const Message *message) const;
-
- //
- // This returns the original message size as it
- // was received on the link. It takes in account
- // the data part, regardless data is still stored
- // in the message object. This information will
- // be used at the time message is unparsed.
- //
-
- int plainSize(const int position) const
- {
- return (*messages_)[position] -> size_;
- }
-
- //
- // This returns either the size of identity plus
- // the compressed data part or 0 if message is
- // stored in uncompressed format.
- //
-
- int compressedSize(const int position) const
- {
- return (*messages_)[position] -> c_size_;
- }
-
- //
- // Returns a pointer to message
- // given its position in cache.
- //
-
- Message *get(const int position) const
- {
- if (position < 0 || position >= cacheSlots)
- {
- #ifdef PANIC
- *logofs << name() << ": PANIC! Requested position "
- << position << " is not inside the "
- << "container.\n" << logofs_flush;
- #endif
-
- cerr << "Error" << ": Requested position "
- << position << " is not inside the"
- << "container.\n";
-
- HandleAbort();
- }
- else if ((*messages_)[position] == NULL)
- {
- #ifdef PANIC
- *logofs << name() << ": PANIC! Message at position "
- << position << " is NULL.\n"
- << logofs_flush;
- #endif
-
- cerr << "Error" << ": Message at position "
- << position << " is NULL.\n";
-
- HandleAbort();
- }
-
- return (*messages_)[position];
- }
-
- //
- // This is the method called at encoding
- // side to add a message to cache.
- //
-
- int findOrAdd(Message *message, T_checksum_action checksumAction,
- T_data_action dataAction, int &added, int &locked);
-
- //
- // Utility interfaces to message insertion
- // and deletion.
- //
-
- int add(Message *message, const int position,
- T_checksum_action checksumAction, T_data_action dataAction);
-
- int remove(const int position, T_checksum_action checksumAction,
- T_data_action dataAction);
-
- //
- // Make space in the repository by remove
- // the first suitable message object.
- //
-
- int clean(T_checksum_action checksumAction);
-
- //
- // Increase or decrease the "rating" of
- // the message object.
- //
-
- int touch(Message *message) const;
- int untouch(Message *message) const;
-
- int getTouches(const int position) const
- {
- Message *message = (*messages_)[position];
-
- if (message == NULL)
- {
- return 0;
- }
-
- return message -> hits_;
- }
-
- //
- // Gives a 'weight' to the cached message. A zero
- // value means object can be safely removed. A value
- // greater than zero means it is advisable to retain
- // the object. A negative result means it is mandato-
- // ry to keep object in cache.
- //
-
- int getRating(Message *message, T_rating type) const;
-
- //
- // Increase or decrease locks of message at given
- // position. A locked message will not be removed
- // from the message store until the lock counter
- // is zero.
- //
-
- int lock(const int position) const;
- int unlock(const int position) const;
-
- int getLocks(const int position) const
- {
- Message *message = (*messages_)[position];
-
- if (message == NULL)
- {
- return 0;
- }
-
- return message -> locks_;
- }
-
- T_checksum const getChecksum(const int position) const
- {
- return getChecksum(get(position));
- }
-
- T_checksum const getChecksum(const Message *message) const
- {
- if (message -> md5_digest_ == NULL)
- {
- #ifdef PANIC
- *logofs << name() << ": PANIC! Checksum not initialized "
- << "for object at " << message << ".\n"
- << logofs_flush;
- #endif
-
- cerr << "Error" << ": Checksum not initialized "
- << "for object at " << message << ".\n";
-
- HandleAbort();
- }
-
- #ifdef DEBUG
- *logofs << name() << ": Got checksum for object at "
- << message << ".\n" << logofs_flush;
- #endif
-
- return message -> md5_digest_;
- }
-
- //
- // Calculate the checksum on the fly based the
- // opcode in the buffer. Useful in the case a
- // message was not processed or was not stored
- // in the cache. The returned checksum must be
- // explicitly deallocated by the caller, after
- // use.
- //
-
- T_checksum getChecksum(const unsigned char *buffer,
- unsigned int size, int bigEndian);
-
- const unsigned char *getData(const Message *message) const
- {
- return message -> data_.begin();
- }
-
- int plainSize(const Message *message) const
- {
- return message -> size_;
- }
-
- int identitySize(Message *message)
- {
- return message -> i_size_;
- }
-
- int compressedSize(const Message *message) const
- {
- return message -> c_size_;
- }
-
- Message *getTemporary()
- {
- if (temporary_ == NULL)
- {
- temporary_ = create();
- }
-
- return temporary_;
- }
-
- void resetTemporary()
- {
- temporary_ = NULL;
- }
-
- //
- // On side where we don't have checksums, we
- // count how many messages are in the array.
- // This is obviously expensive and should be
- // only performed when reporting statistics.
- //
-
- int getSize() const
- {
- int size = checksums_ -> size();
-
- if (size == 0)
- {
- for (int i = 0; i < cacheSlots; i++)
- {
- if ((*messages_)[i] != NULL)
- {
- size++;
- }
- }
- }
-
- return size;
- }
-
- int getLocalStorageSize() const
- {
- return localStorageSize_;
- }
-
- int getRemoteStorageSize() const
- {
- return remoteStorageSize_;
- }
-
- int getLocalTotalStorageSize() const
- {
- return totalLocalStorageSize_;
- }
-
- int getRemoteTotalStorageSize() const
- {
- return totalRemoteStorageSize_;
- }
-
- static int getCumulativeTotalStorageSize()
- {
- return (totalLocalStorageSize_ > totalRemoteStorageSize_ ?
- totalLocalStorageSize_ : totalRemoteStorageSize_);
- }
-
- int saveStore(ostream *cachefs, md5_state_t *md5_state_stream,
- md5_state_t *md5_state_client, T_checksum_action checksumAction,
- T_data_action dataAction, int bigEndian);
-
- int loadStore(istream *cachefs, md5_state_t *md5_state_stream,
- T_checksum_action checksumAction, T_data_action dataAction,
- int bigEndian);
-
- protected:
-
- //
- // Estimate the memory requirements of given
- // instance of message. Size includes memory
- // allocated from heap to store checksum and
- // data.
- //
-
- void storageSize(const Message *message, unsigned int &local,
- unsigned int &remote) const;
-
- //
- // Just used for debug.
- //
-
- void printStorageSize();
-
- //
- // Repositories where to save cached messages.
- // First is a vector of pointers, the second
- // is a hash table used for fast lookups.
- //
-
- T_messages *messages_;
- T_checksums *checksums_;
-
- //
- // A message object to be used as a temporary.
- // Reuse the temporary object if possible, if
- // not, create a new instance.
- //
-
- Message *temporary_;
-
- //
- // Used to calculate message's checksum.
- //
-
- md5_state_t *md5_state_;
-
- private:
-
- //
- // Used to compress data payload.
- //
-
- StaticCompressor *compressor_;
-
- //
- // Keep track of how many bytes
- // are taken by cache.
- //
-
- int localStorageSize_;
- int remoteStorageSize_;
-
- static int totalLocalStorageSize_;
- static int totalRemoteStorageSize_;
-
- //
- // Used to track object allocation and deallocation.
- //
-
- #ifdef REFERENCES
-
- static int references_;
-
- #endif
-};
-
-//
-// This is an ancillary class of the message
-// store, used to encode extensions based on
-// the minor opcode.
-//
-
-class MinorMessageStore
-{
- public:
-
- virtual ~MinorMessageStore()
- {
- }
-
- virtual const char *name() const = 0;
-
- virtual int identitySize(const unsigned char *buffer, unsigned int size) = 0;
-
- virtual int encodeMessage(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
- const unsigned int size, int bigEndian,
- ChannelCache *channelCache) const
- {
- return 1;
- }
-
- virtual int decodeMessage(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
- unsigned int &size, unsigned char type, int bigEndian,
- WriteBuffer *writeBuffer, ChannelCache *channelCache) const
- {
- return 1;
- }
-
- virtual void encodeData(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
- unsigned int size, int bigEndian,
- ChannelCache *channelCache) const
- {
- }
-
- virtual void decodeData(DecodeBuffer &decodeBuffer, unsigned char *buffer,
- unsigned int size, int bigEndian,
- ChannelCache *channelCache) const
- {
- }
-
- virtual int parseIdentity(Message *message, const unsigned char *buffer,
- unsigned int size, int bigEndian) const = 0;
-
- virtual int unparseIdentity(const Message *message, unsigned char *buffer,
- unsigned int size, int bigEndian) const = 0;
-
- virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
- const Message *cachedMessage,
- ChannelCache *channelCache) const
- {
- }
-
- virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
- ChannelCache *channelCache) const
- {
- }
-
- virtual void identityChecksum(const Message *message, const unsigned char *buffer,
- unsigned int size, md5_state_t *md5_state,
- int bigEndian) const = 0;
-};
-
-#endif /* Message_H */
-