aboutsummaryrefslogtreecommitdiff
path: root/nxcomp/ClientChannel.h
diff options
context:
space:
mode:
Diffstat (limited to 'nxcomp/ClientChannel.h')
-rw-r--r--nxcomp/ClientChannel.h466
1 files changed, 466 insertions, 0 deletions
diff --git a/nxcomp/ClientChannel.h b/nxcomp/ClientChannel.h
new file mode 100644
index 000000000..9924bb263
--- /dev/null
+++ b/nxcomp/ClientChannel.h
@@ -0,0 +1,466 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXCOMP, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef ClientChannel_H
+#define ClientChannel_H
+
+#include "List.h"
+#include "Channel.h"
+
+#include "SequenceQueue.h"
+
+#include "ClientReadBuffer.h"
+
+//
+// Set the verbosity level.
+//
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+//
+// If defined, the client channel will
+// have the chance of suppressing more
+// opcodes for test purposes.
+//
+
+#undef LAME
+
+//
+// Define this to log a line when a
+// channel is created or destroyed.
+//
+
+#undef REFERENCES
+
+//
+// This class implements the X client
+// side compression of the protocol.
+//
+
+class ClientChannel : public Channel
+{
+ public:
+
+ ClientChannel(Transport *transport, StaticCompressor *compressor);
+
+ virtual ~ClientChannel();
+
+ virtual int handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
+ unsigned int length);
+
+ virtual int handleWrite(const unsigned char *message, unsigned int length);
+
+ virtual int handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store,
+ T_store_action action, int position, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ virtual int handleSplit(DecodeBuffer &decodeBuffer, MessageStore *store,
+ T_store_action action, int position, unsigned char &opcode,
+ unsigned char *&buffer, unsigned int &size)
+ {
+ return 0;
+ }
+
+ virtual int handleSplit(EncodeBuffer &encodeBuffer);
+
+ virtual int handleSplit(DecodeBuffer &decodeBuffer)
+ {
+ return 0;
+ }
+
+ virtual int handleSplitEvent(EncodeBuffer &encodeBuffer, Split *split);
+
+ virtual int handleSplitEvent(DecodeBuffer &decodeBuffer);
+
+ virtual int handleMotion(EncodeBuffer &encodeBuffer)
+ {
+ return 0;
+ }
+
+ virtual int handleCompletion(EncodeBuffer &encodeBuffer)
+ {
+ return 0;
+ }
+
+ virtual int handleConfiguration();
+
+ virtual int handleFinish();
+
+ virtual int handleAsyncEvents()
+ {
+ return 0;
+ }
+
+ virtual int needSplit() const
+ {
+ #if defined(TEST) || defined(SPLIT)
+ *logofs << "needSplit: SPLIT! Returning pending split "
+ << "flag " << splitState_.pending << " with "
+ << clientStore_ -> getSplitTotalSize()
+ << " splits in the split stores.\n"
+ << logofs_flush;
+ #endif
+
+ return splitState_.pending;
+ }
+
+ virtual int needMotion() const
+ {
+ return 0;
+ }
+
+ virtual T_channel_type getType() const
+ {
+ return channel_x11;
+ }
+
+ int setBigEndian(int flag);
+
+ //
+ // Initialize the static members.
+ //
+
+ static int setReferences();
+
+ private:
+
+ int handleFastReadRequest(EncodeBuffer &encodeBuffer, const unsigned char &opcode,
+ const unsigned char *&buffer, const unsigned int &size);
+
+ int handleFastWriteReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
+ unsigned char *&buffer, unsigned int &size);
+
+ int handleFastWriteEvent(DecodeBuffer &decodeBuffer, unsigned char &opcode,
+ unsigned char *&buffer, unsigned int &size);
+
+ //
+ // Intercept the request before the opcode
+ // is encoded.
+ //
+
+ int handleTaintRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size)
+ {
+ if (control -> isProtoStep7() == 0)
+ {
+ if (opcode == X_NXFreeSplit || opcode == X_NXAbortSplit ||
+ opcode == X_NXFinishSplit)
+ {
+ return handleTaintSplitRequest(opcode, buffer, size);
+ }
+ else if (opcode == X_NXSetCacheParameters)
+ {
+ return handleTaintCacheRequest(opcode, buffer, size);
+ }
+ else if (opcode == X_NXGetFontParameters)
+ {
+ return handleTaintFontRequest(opcode, buffer, size);
+ }
+ }
+
+ if (control -> TaintReplies > 0 &&
+ opcode == X_GetInputFocus)
+ {
+ return handleTaintSyncRequest(opcode, buffer, size);
+ }
+
+ #ifdef LAME
+
+ return handleTaintLameRequest(opcode, buffer, size);
+
+ #endif
+
+ return 0;
+ }
+
+ int handleTaintCacheRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size);
+
+ int handleTaintFontRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size);
+
+ int handleTaintSplitRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size);
+
+ int handleTaintLameRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size);
+
+ int handleTaintSyncRequest(unsigned char &opcode, const unsigned char *&buffer,
+ unsigned int &size);
+
+ int handleTaintSyncError(unsigned char opcode);
+
+ //
+ // How to handle sequence counter
+ // in notification event.
+ //
+
+ enum T_sequence_mode
+ {
+ sequence_immediate,
+ sequence_deferred
+ };
+
+ //
+ // Send split notifications to the
+ // agent.
+ //
+
+ int handleRestart(T_sequence_mode mode, int resource);
+
+ int handleNotify(T_notification_type type, T_sequence_mode mode,
+ int resource, int request, int position);
+
+ //
+ // Other utility functions used in
+ // handling of the image streaming.
+ //
+
+ int mustSplitMessage(int resource)
+ {
+ return (clientStore_ -> getSplitStore(resource) ->
+ getSize() != 0);
+ }
+
+ int canSplitMessage(T_split_mode mode, unsigned int size)
+ {
+ return ((int) size >= control -> SplitDataThreshold &&
+ (clientStore_ -> getSplitTotalStorageSize() < control ->
+ SplitTotalStorageSize && clientStore_ ->
+ getSplitTotalSize() < control -> SplitTotalSize));
+ }
+
+ int canSendSplit(Split *split)
+ {
+ return (split -> getMode() != split_sync ||
+ split -> getState() == split_missed ||
+ split -> getState() == split_loaded);
+ }
+
+ int handleSplitSend(EncodeBuffer &encodeBuffer, int resource,
+ int &total, int &bytes);
+
+ Split *handleSplitFind(T_checksum checksum, int resource);
+
+ int handleSplitChecksum(EncodeBuffer &encodeBuffer, T_checksum checksum);
+
+ void handleSplitEnable()
+ {
+ if (control -> isProtoStep7() == 0)
+ {
+ #if defined(TEST) || defined(SPLIT)
+ *logofs << "handleSplitEnable: WARNING! Disabling split "
+ << "with an old proxy version.\n"
+ << logofs_flush;
+ #endif
+
+ enableSplit_ = 0;
+ }
+ }
+
+ void handleSplitPending(int resource)
+ {
+ if (splitState_.pending == 0)
+ {
+ if (clientStore_ -> getSplitStore(resource) != NULL &&
+ clientStore_ -> getSplitStore(resource) ->
+ getFirstSplit() != NULL)
+ {
+ splitState_.pending = canSendSplit(clientStore_ ->
+ getSplitStore(resource) -> getFirstSplit());
+
+ #if defined(TEST) || defined(SPLIT)
+ *logofs << "handleSplitPending: SPLIT! Set the pending "
+ << "split flag to " << splitState_.pending
+ << " with " << clientStore_ -> getSplitTotalSize()
+ << " splits in the split stores.\n"
+ << logofs_flush;
+ #endif
+ }
+ }
+ }
+
+ //
+ // Scan all the split stores to find
+ // if there is any split to send.
+ //
+
+ void handleSplitPending();
+
+ //
+ // Handle the MIT-SHM initialization
+ // messages exchanged with the remote
+ // proxy.
+ //
+
+ int handleShmemRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ int handleShmemReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
+ unsigned char *&buffer, unsigned int &size);
+
+ //
+ // Query the port used to tunnel
+ // the font server connections.
+ //
+
+ int handleFontRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ int handleFontReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
+ unsigned char *&buffer, unsigned int &size);
+
+ //
+ // Let the agent set the cache
+ // policy for image requests.
+ //
+
+ int handleCacheRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ //
+ // Encode the start and end split
+ // requests.
+ //
+
+ int handleStartSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ int handleEndSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ //
+ // Empty a split store and send the
+ // restart event.
+ //
+
+ int handleAbortSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ //
+ // Force the proxy to finalize all
+ // the pending split operations and
+ // restart a resource.
+ //
+
+ int handleFinishSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ //
+ // Tell the remote peer to send the
+ // split requests to the X server.
+ //
+
+ int handleCommitSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
+ const unsigned char *buffer, const unsigned int size);
+
+ //
+ // Other utilities.
+ //
+
+ void handleDecodeCharInfo(DecodeBuffer &, unsigned char *);
+
+ //
+ // Own read buffer. It is able to identify
+ // full messages read from the X descriptor.
+ //
+
+ ClientReadBuffer readBuffer_;
+
+ //
+ // Sequence number of last request coming
+ // from the X client or the X server.
+ //
+
+ unsigned int clientSequence_;
+ unsigned int serverSequence_;
+
+ //
+ // Last sequence number known by client. It can
+ // be the real sequence generated by server or
+ // the one of the last auto-generated event.
+ //
+
+ unsigned int lastSequence_;
+
+ //
+ // Used to identify replies based on sequence
+ // number of original request.
+ //
+
+ SequenceQueue sequenceQueue_;
+
+ //
+ // This is used to test the synchronous flush
+ // in the proxy.
+ //
+
+ int lastRequest_;
+
+ //
+ // Current resource id selected as target and
+ // other information related to the image split.
+ // The pending and abort flags are set when we
+ // want the proxy to give us a chance to send
+ // more split data. We also save the position
+ // of the last commit operation performed by
+ // channel so we can differentially encode the
+ // position of next message to commit.
+ //
+
+ typedef struct
+ {
+ int resource;
+ int pending;
+ int commit;
+ T_split_mode mode;
+
+ } T_split_state;
+
+ T_split_state splitState_;
+
+ //
+ // List of agent resources.
+ //
+
+ List splitResources_;
+
+ //
+ // How many sync requests we
+ // have tainted so far.
+ //
+
+ int taintCounter_;
+
+ private:
+
+ //
+ // Keep track of object
+ // creation and deletion.
+ //
+
+ #ifdef REFERENCES
+
+ static int references_;
+
+ #endif
+};
+
+#endif /* ClientChannel_H */