diff options
Diffstat (limited to 'nxcomp/ClientChannel.h')
-rw-r--r-- | nxcomp/ClientChannel.h | 466 |
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 */ |