aboutsummaryrefslogtreecommitdiff
path: root/nxcomp/ClientChannel.cpp
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2017-06-30 20:13:51 +0200
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2017-07-26 10:12:43 +0200
commitf76c82403888bb498973ec974dbfd20e4edb02fe (patch)
treebe0cb6c112d9d9fb46387fbd114727510197ddec /nxcomp/ClientChannel.cpp
parent9193d11eeeea933e293acd5e0f03fa4e9887186b (diff)
downloadnx-libs-f76c82403888bb498973ec974dbfd20e4edb02fe.tar.gz
nx-libs-f76c82403888bb498973ec974dbfd20e4edb02fe.tar.bz2
nx-libs-f76c82403888bb498973ec974dbfd20e4edb02fe.zip
nxcomp: Switch to autoreconf.
Diffstat (limited to 'nxcomp/ClientChannel.cpp')
-rw-r--r--nxcomp/ClientChannel.cpp7877
1 files changed, 0 insertions, 7877 deletions
diff --git a/nxcomp/ClientChannel.cpp b/nxcomp/ClientChannel.cpp
deleted file mode 100644
index dbf5f6986..000000000
--- a/nxcomp/ClientChannel.cpp
+++ /dev/null
@@ -1,7877 +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. */
-/* */
-/**************************************************************************/
-
-#include <string.h>
-
-#include <X11/X.h>
-#include <X11/Xatom.h>
-
-#include "NXproto.h"
-#include "NXrender.h"
-
-#include "ClientChannel.h"
-
-#include "EncodeBuffer.h"
-#include "DecodeBuffer.h"
-
-#include "StaticCompressor.h"
-
-#include "Statistics.h"
-#include "Proxy.h"
-
-#include "PutImage.h"
-#include "PutPackedImage.h"
-
-extern Proxy *proxy;
-
-//
-// Set the verbosity level. You also
-// need to define OPCODES in Misc.cpp
-// if you want literals instead of
-// opcodes' numbers.
-//
-
-#define PANIC
-#define WARNING
-#undef OPCODES
-#undef TEST
-#undef DEBUG
-#undef DUMP
-
-//
-// Log the important tracepoints related
-// to writing packets to the peer proxy.
-//
-
-#undef FLUSH
-
-//
-// Log the operations related to splits.
-//
-
-#undef SPLIT
-
-//
-// Define this to trace the invocations
-// of the agent's callbacks.
-//
-
-#undef CALLBACK
-
-//
-// By defining this, a simple procedure is activated at
-// startup which just allocates and deallocates plenty
-// of cache objects. This is used to help determine the
-// current memory requirements.
-//
-
-#undef MEMORY
-
-//
-// Inspects target of common X operations.
-//
-
-#undef TARGETS
-
-#ifdef TARGETS
-
-#include <set>
-#include <map>
-
-typedef set < unsigned int, less<unsigned int> > T_windows;
-typedef set < unsigned int, less<unsigned int> > T_pixmaps;
-typedef map < unsigned int, unsigned int, less<unsigned int> > T_gcontexts;
-
-T_windows windows;
-T_pixmaps pixmaps;
-T_gcontexts gcontexts;
-
-#endif
-
-//
-// Define this to log when a channel
-// is created or destroyed.
-//
-
-#undef REFERENCES
-
-//
-// Here are the static members.
-//
-
-#ifdef REFERENCES
-
-int ClientChannel::references_ = 0;
-
-#endif
-
-ClientChannel::ClientChannel(Transport *transport, StaticCompressor *compressor)
-
- : Channel(transport, compressor), readBuffer_(transport_, this)
-{
- //
- // Sequence number of the next message
- // being encoded or decoded.
- //
-
- clientSequence_ = 0;
- serverSequence_ = 0;
-
- //
- // Current sequence known by NX agent.
- //
-
- lastSequence_ = 0;
-
- //
- // This is used to test the synchronous
- // flush in the proxy.
- //
-
- lastRequest_ = 0;
-
- //
- // Store information about the images
- // being streamed.
- //
-
- splitState_.resource = nothing;
- splitState_.pending = 0;
- splitState_.commit = 0;
- splitState_.mode = split_none;
-
- //
- // Number of outstanding tainted replies.
- //
-
- taintCounter_ = 0;
-
- #ifdef MEMORY
-
- *logofs << "ClientChannel: Created 1 ClientCache and 1 ServerCache. "
- << "You have 30 seconds to check the allocated size.\n"
- << logofs_flush;
-
- sleep(30);
-
- ClientCache *clientCacheTestArray[100];
- ServerCache *serverCacheTestArray[100];
-
- for (int i = 0; i < 100; i++)
- {
- clientCacheTestArray[i] = new ClientCache();
- }
-
- *logofs << "ClientChannel: Created further 100 ClientCache. "
- << "You have 30 seconds to check the allocated size.\n"
- << logofs_flush;
-
- sleep(30);
-
- for (int i = 0; i < 100; i++)
- {
- serverCacheTestArray[i] = new ServerCache();
- }
-
- *logofs << "ClientChannel: Created further 100 ServerCache. "
- << "You have 30 seconds to check the allocated size.\n"
- << logofs_flush;
-
- sleep(30);
-
- for (int i = 0; i < 100; i++)
- {
- delete clientCacheTestArray[i];
- delete serverCacheTestArray[i];
- }
-
- *logofs << "ClientChannel: Deleted 100 ClientCache and 100 ServerCache. "
- << "You have 30 seconds to check the allocated size.\n"
- << logofs_flush;
-
- sleep(30);
-
- #endif
-
- #ifdef REFERENCES
- *logofs << "ClientChannel: Created new object at "
- << this << " for FD#" << fd_ << " out of "
- << ++references_ << " allocated channels.\n"
- << logofs_flush;
- #endif
-}
-
-ClientChannel::~ClientChannel()
-{
- #ifdef REFERENCES
- *logofs << "ClientChannel: Deleted object at "
- << this << " for FD#" << fd_ << " out of "
- << --references_ << " allocated channels.\n"
- << logofs_flush;
- #endif
-}
-
-//
-// Beginning of handleRead().
-//
-
-int ClientChannel::handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
- unsigned int length)
-{
- #ifdef TEST
- *logofs << "handleRead: Called for FD#" << fd_
- << " with " << encodeBuffer.getLength()
- << " bytes already encoded.\n"
- << logofs_flush;
- #endif
-
- //
- // Pointer to located message and
- // its size in bytes.
- //
-
- const unsigned char *inputMessage;
- unsigned int inputLength;
-
- //
- // Set when message is found in
- // cache.
- //
-
- int hit;
-
- //
- // Check if we can borrow the buffer
- // from the caller.
- //
-
- if (message != NULL && length != 0)
- {
- readBuffer_.readMessage(message, length);
- }
- else
- {
- //
- // Get the data from the transport.
- //
-
- #if defined(TEST) || defined(INFO)
- *logofs << "handleRead: Trying to read from FD#"
- << fd_ << " at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- int result = readBuffer_.readMessage();
-
- #ifdef DEBUG
- *logofs << "handleRead: Read result on FD#" << fd_
- << " is " << result << ".\n"
- << logofs_flush;
- #endif
-
- if (result < 0)
- {
- //
- // Let the proxy close the channel.
- //
-
- return -1;
- }
- else if (result == 0)
- {
- #if defined(TEST) || defined(INFO)
-
- *logofs << "handleRead: PANIC! No data read from FD#"
- << fd_ << " while encoding messages.\n"
- << logofs_flush;
-
- HandleCleanup();
-
- #endif
-
- return 0;
- }
- }
-
- #if defined(TEST) || defined(INFO) || defined(FLUSH)
- *logofs << "handleRead: Encoding messages for FD#" << fd_
- << " with " << readBuffer_.getLength() << " bytes "
- << "in the buffer.\n" << logofs_flush;
- #endif
-
- //
- // Extract any complete message which
- // is available in the buffer.
- //
-
- if (proxy -> handleAsyncSwitch(fd_) < 0)
- {
- return -1;
- }
-
- while ((inputMessage = readBuffer_.getMessage(inputLength)) != NULL)
- {
- hit = 0;
-
- if (firstRequest_)
- {
- //
- // Need to add the length of the first
- // request as it was not present in
- // previous versions.
- //
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeValue(inputLength, 8);
-
- for (unsigned int i = 0; i < inputLength; i++)
- {
- encodeBuffer.encodeValue((unsigned int) inputMessage[i], 8);
- }
-
- firstRequest_ = 0;
-
- #if defined(TEST) || defined(OPCODES)
-
- int bits = encodeBuffer.diffBits();
-
- *logofs << "handleRead: Handled first request. " << inputLength
- << " bytes in, " << bits << " bits (" << ((float) bits) / 8
- << " bytes) out.\n" << logofs_flush;
- #endif
-
- priority_++;
- }
- else
- {
- //
- // First of all we get the opcode.
- //
-
- unsigned char inputOpcode = *inputMessage;
-
- #if defined(TEST) || defined(INFO)
-
- //
- // This is used to test the synchronous
- // flush in the parent proxy.
- //
-
- lastRequest_ = inputOpcode;
-
- #endif
-
- //
- // Check if the request is supported by the
- // remote. If not, only handle it locally and
- // taint the opcode as a X_NoOperation. Also
- // try to short-circuit some replies at this
- // side. XSync requests, for example, weight
- // for half of the total round-trips.
- //
-
- if (handleTaintRequest(inputOpcode, inputMessage,
- inputLength) < 0)
- {
- return -1;
- }
-
- encodeBuffer.encodeOpcodeValue(inputOpcode, clientCache_ -> opcodeCache);
-
- //
- // Update the current sequence.
- //
-
- clientSequence_++;
- clientSequence_ &= 0xffff;
-
- #ifdef DEBUG
- *logofs << "handleRead: Last client sequence number for FD#"
- << fd_ << " is " << clientSequence_ << ".\n"
- << logofs_flush;
- #endif
-
- //
- // If differential compression is disabled
- // then use the most simple encoding.
- //
-
- if (control -> LocalDeltaCompression == 0)
- {
- int result = handleFastReadRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength);
- if (result < 0)
- {
- return -1;
- }
- else if (result > 0)
- {
- continue;
- }
- }
-
- //
- // Go to the message's specific encoding.
- //
-
- switch (inputOpcode)
- {
- case X_AllocColor:
- {
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> colormapCache);
- const unsigned char *nextSrc = inputMessage + 8;
- unsigned int colorData[3];
- for (unsigned int i = 0; i < 3; i++)
- {
- unsigned int value = GetUINT(nextSrc, bigEndian_);
- encodeBuffer.encodeCachedValue(value, 16,
- *(clientCache_ -> allocColorRGBCache[i]), 4);
- colorData[i] = value;
- nextSrc += 2;
- }
-
- sequenceQueue_.push(clientSequence_, inputOpcode,
- colorData[0], colorData[1], colorData[2]);
-
- priority_++;
- }
- break;
- case X_ReparentWindow:
- {
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeValue(GetUINT(inputMessage + 12, bigEndian_), 16, 11);
- encodeBuffer.encodeValue(GetUINT(inputMessage + 14, bigEndian_), 16, 11);
- }
- break;
- case X_ChangeProperty:
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ChangeProperty);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- unsigned char format = inputMessage[16];
- encodeBuffer.encodeCachedValue(format, 8,
- clientCache_ -> changePropertyFormatCache);
- unsigned int dataLength = GetULONG(inputMessage + 20, bigEndian_);
- encodeBuffer.encodeValue(dataLength, 32, 6);
- encodeBuffer.encodeValue(inputMessage[1], 2);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 8, bigEndian_), 29,
- clientCache_ -> changePropertyPropertyCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 12, bigEndian_), 29,
- clientCache_ -> changePropertyTypeCache, 9);
- const unsigned char *nextSrc = inputMessage + 24;
- if (format == 8)
- {
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, dataLength);
- }
- else if (format == 32)
- {
- for (unsigned int i = 0; i < dataLength; i++)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, bigEndian_), 32,
- clientCache_ -> changePropertyData32Cache);
- nextSrc += 4;
- }
- }
- else
- {
- for (unsigned int i = 0; i < dataLength; i++)
- {
- encodeBuffer.encodeValue(GetUINT(nextSrc, bigEndian_), 16);
- nextSrc += 2;
- }
- }
- }
- break;
- case X_SendEvent:
- {
- //
- // TODO: This can be improved. In the worst
- // cases, it appears to provide a poor 1.6:1
- // ratio.
- //
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_SendEvent);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- unsigned int window = GetULONG(inputMessage + 4, bigEndian_);
-
- if (window == 0 || window == 1)
- {
- encodeBuffer.encodeBoolValue(1);
- encodeBuffer.encodeBoolValue(window);
- }
- else
- {
- encodeBuffer.encodeBoolValue(0);
- encodeBuffer.encodeXidValue(window, clientCache_ -> windowCache);
- }
-
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 8, bigEndian_), 32,
- clientCache_ -> sendEventMaskCache, 9);
- encodeBuffer.encodeCachedValue(*(inputMessage + 12), 8,
- clientCache_ -> sendEventCodeCache);
- encodeBuffer.encodeCachedValue(*(inputMessage + 13), 8,
- clientCache_ -> sendEventByteDataCache);
-
- unsigned int newSeq = GetUINT(inputMessage + 14, bigEndian_);
- unsigned int diffSeq = newSeq - clientCache_ -> sendEventLastSequence;
- clientCache_ -> sendEventLastSequence = newSeq;
- encodeBuffer.encodeValue(diffSeq, 16, 4);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 16, bigEndian_), 32,
- clientCache_ -> sendEventIntDataCache);
-
- for (unsigned int i = 20; i < 44; i++)
- {
- encodeBuffer.encodeCachedValue((unsigned int) inputMessage[i], 8,
- clientCache_ -> sendEventEventCache);
- }
- }
- break;
- case X_ChangeWindowAttributes:
- {
- encodeBuffer.encodeValue((inputLength - 12) >> 2, 4);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- unsigned int bitmask = GetULONG(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeCachedValue(bitmask, 15,
- clientCache_ -> createWindowBitmaskCache);
- const unsigned char *nextSrc = inputMessage + 12;
- unsigned int mask = 0x1;
- for (unsigned int j = 0; j < 15; j++)
- {
- if (bitmask & mask)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, bigEndian_), 32,
- *clientCache_ -> createWindowAttrCache[j]);
- nextSrc += 4;
- }
- mask <<= 1;
- }
- }
- break;
- case X_ClearArea:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_ClearArea target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_ClearArea target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_ClearArea target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ClearArea);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- const unsigned char *nextSrc = inputMessage + 8;
- for (unsigned int i = 0; i < 4; i++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> clearAreaGeomCache[i], 8);
- nextSrc += 2;
- }
- }
- break;
- case X_CloseFont:
- {
- unsigned int font = GetULONG(inputMessage + 4, bigEndian_);
- encodeBuffer.encodeValue(font - clientCache_ -> lastFont, 29, 5);
- clientCache_ -> lastFont = font;
- }
- break;
- case X_ConfigureWindow:
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ConfigureWindow);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- unsigned int bitmask = GetUINT(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeCachedValue(bitmask, 7,
- clientCache_ -> configureWindowBitmaskCache);
- unsigned int mask = 0x1;
- const unsigned char *nextSrc = inputMessage + 12;
- for (unsigned int i = 0; i < 7; i++)
- {
- if (bitmask & mask)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, bigEndian_),
- CONFIGUREWINDOW_FIELD_WIDTH[i],
- *clientCache_ -> configureWindowAttrCache[i], 8);
- nextSrc += 4;
- }
- mask <<= 1;
- }
- }
- break;
- case X_ConvertSelection:
- {
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> convertSelectionRequestorCache, 9);
- const unsigned char* nextSrc = inputMessage + 8;
- for (unsigned int i = 0; i < 3; i++)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, bigEndian_), 29,
- *(clientCache_ -> convertSelectionAtomCache[i]), 9);
- nextSrc += 4;
- }
- unsigned int timestamp = GetULONG(nextSrc, bigEndian_);
- encodeBuffer.encodeValue(timestamp -
- clientCache_ -> convertSelectionLastTimestamp, 32, 4);
- clientCache_ -> convertSelectionLastTimestamp = timestamp;
- }
- break;
- case X_CopyArea:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_CopyArea source id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_CopyArea source id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_CopyArea source id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- t_id = GetULONG(inputMessage + 8, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_CopyArea target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_CopyArea target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_CopyArea target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_CopyArea);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 12,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *nextSrc = inputMessage + 16;
- for (unsigned int i = 0; i < 6; i++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> copyAreaGeomCache[i], 8);
- nextSrc += 2;
- }
- }
- break;
- case X_CopyGC:
- {
- #ifdef TARGETS
-
- unsigned int s_g_id = GetULONG(inputMessage + 4, bigEndian_);
- unsigned int d_g_id = GetULONG(inputMessage + 8, bigEndian_);
-
- *logofs << "handleRead: X_CopyGC source gcontext id is " << s_g_id
- << " destination gcontext id is " << d_g_id << ".\n"
- << logofs_flush;
-
- #endif
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> gcCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 12,
- bigEndian_), 23, clientCache_ -> createGCBitmaskCache);
- }
- break;
- case X_CopyPlane:
- {
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 12,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *nextSrc = inputMessage + 16;
- for (unsigned int i = 0; i < 6; i++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> copyPlaneGeomCache[i], 8);
- nextSrc += 2;
- }
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 28, bigEndian_), 32,
- clientCache_ -> copyPlaneBitPlaneCache, 10);
- }
- break;
- case X_CreateGC:
- {
- #ifdef TARGETS
-
- unsigned int g_id = GetULONG(inputMessage + 4, bigEndian_);
- unsigned int t_id = GetULONG(inputMessage + 8, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_CreateGC id " << g_id
- << " target id is pixmap " << t_id
- << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_CreateGC id " << g_id
- << " target id is window " << t_id
- << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_CreateGC id " << g_id
- << " target id is unrecognized.\n"
- << logofs_flush;
- }
-
- gcontexts.insert(T_gcontexts::value_type(g_id, t_id));
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_CreateGC);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeNewXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> lastId, clientCache_ -> lastIdCache,
- clientCache_ -> gcCache,
- clientCache_ -> freeGCCache);
-
- const unsigned char *nextSrc = inputMessage + 8;
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> drawableCache);
- nextSrc += 4;
- unsigned int bitmask = GetULONG(nextSrc, bigEndian_);
- nextSrc += 4;
- encodeBuffer.encodeCachedValue(bitmask, 23,
- clientCache_ -> createGCBitmaskCache);
- unsigned int mask = 0x1;
- for (unsigned int i = 0; i < 23; i++)
- {
- if (bitmask & mask)
- {
- unsigned int value = GetULONG(nextSrc, bigEndian_);
- nextSrc += 4;
- unsigned int fieldWidth = CREATEGC_FIELD_WIDTH[i];
- if (fieldWidth <= 4)
- {
- encodeBuffer.encodeValue(value, fieldWidth);
- }
- else
- {
- encodeBuffer.encodeCachedValue(value, fieldWidth,
- *clientCache_ -> createGCAttrCache[i]);
- }
- }
- mask <<= 1;
- }
- }
- break;
- case X_ChangeGC:
- {
- #ifdef TARGETS
-
- unsigned int g_id = GetULONG(inputMessage + 4, bigEndian_);
-
- T_gcontexts::iterator i = gcontexts.find(g_id);
-
- if (i != gcontexts.end())
- {
- unsigned int t_id = i -> second;
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_ChangeGC gcontext id is " << g_id
- << " target id is pixmap " << t_id << ".\n"
- << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_ChangeGC gcontext id is " << g_id
- << " target id is window " << t_id << ".\n"
- << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_ChangeGC gcontext is " << g_id
- << " target id is unrecognized.\n"
- << logofs_flush;
- }
- }
- else
- {
- *logofs << "handleRead: X_ChangeGC gcontext id " << g_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- gcontexts.erase(g_id);
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ChangeGC);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *nextSrc = inputMessage + 8;
- unsigned int bitmask = GetULONG(nextSrc, bigEndian_);
- nextSrc += 4;
- encodeBuffer.encodeCachedValue(bitmask, 23,
- clientCache_ -> createGCBitmaskCache);
- unsigned int mask = 0x1;
- for (unsigned int i = 0; i < 23; i++)
- {
- if (bitmask & mask)
- {
- unsigned int value = GetULONG(nextSrc, bigEndian_);
- nextSrc += 4;
- unsigned int fieldWidth = CREATEGC_FIELD_WIDTH[i];
- if (fieldWidth <= 4)
- {
- encodeBuffer.encodeValue(value, fieldWidth);
- }
- else
- {
- encodeBuffer.encodeCachedValue(value, fieldWidth,
- *clientCache_ -> createGCAttrCache[i]);
- }
- }
- mask <<= 1;
- }
- }
- break;
- case X_CreatePixmap:
- {
- #ifdef TARGETS
-
- *logofs << "handleRead: X_CreatePixmap depth " << (unsigned) inputMessage[1]
- << ", pixmap id " << GetULONG(inputMessage + 4, bigEndian_)
- << ", drawable " << GetULONG(inputMessage + 8, bigEndian_)
- << ", width " << GetUINT(inputMessage + 12, bigEndian_)
- << ", height " << GetUINT(inputMessage + 14, bigEndian_)
- << ", size " << GetUINT(inputMessage + 2, bigEndian_) << 2
- << ".\n" << logofs_flush;
-
- unsigned int p_id = GetULONG(inputMessage + 4, bigEndian_);
- unsigned short p_sx = GetUINT(inputMessage + 12, bigEndian_);
- unsigned short p_sy = GetUINT(inputMessage + 14, bigEndian_);
-
- *logofs << "handleRead: X_CreatePixmap id is " << p_id
- << " width is " << p_sx << " height is " << p_sy
- << ".\n" << logofs_flush;
-
- if (p_sx * p_sy <= 64 * 64)
- {
- *logofs << "handleRead: X_CreatePixmap id " << p_id << " of size "
- << p_sx << "x" << p_sy << "=" << p_sx * p_sy
- << " will be painted at client side.\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_CreatePixmap id " << p_id << " of size "
- << p_sx << "x" << p_sy << "=" << p_sx * p_sy
- << " will be painted at server side.\n" << logofs_flush;
- }
-
- pixmaps.insert(p_id);
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_CreatePixmap);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- break;
- case X_CreateWindow:
- {
- #ifdef TARGETS
-
- unsigned int w_id = GetULONG(inputMessage + 4, bigEndian_);
-
- *logofs << "handleRead: X_CreateWindow id is " << w_id
- << ".\n" << logofs_flush;
-
- windows.insert(w_id);
-
- #endif
-
- unsigned bitmask = GetULONG(inputMessage + 28, bigEndian_);
- encodeBuffer.encodeCachedValue((unsigned int) inputMessage[1], 8,
- clientCache_ -> depthCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8, bigEndian_),
- clientCache_ -> windowCache);
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeNewXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> lastId, clientCache_ -> lastIdCache,
- clientCache_ -> windowCache,
- clientCache_ -> freeWindowCache);
-
- const unsigned char *nextSrc = inputMessage + 12;
- for (unsigned int i = 0; i < 6; i++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> createWindowGeomCache[i], 8);
- nextSrc += 2;
- }
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 24,
- bigEndian_), 29, clientCache_ -> visualCache);
- encodeBuffer.encodeCachedValue(bitmask, 15,
- clientCache_ -> createWindowBitmaskCache);
- nextSrc = inputMessage + 32;
- unsigned int mask = 0x1;
- for (unsigned int j = 0; j < 15; j++)
- {
- if (bitmask & mask)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, bigEndian_), 32,
- *clientCache_ -> createWindowAttrCache[j]);
- nextSrc += 4;
- }
- mask <<= 1;
- }
- }
- break;
- case X_DeleteProperty:
- {
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeValue(GetULONG(inputMessage + 8, bigEndian_), 29, 9);
- }
- break;
- case X_FillPoly:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_FillPoly target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_FillPoly target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_FillPoly target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_FillPoly);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- unsigned int numPoints = ((inputLength - 16) >> 2);
-
- // Since ProtoStep10 (#issue 108)
- encodeBuffer.encodeCachedValue(numPoints, 16,
- clientCache_ -> fillPolyNumPointsCache, 4);
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8, bigEndian_),
- clientCache_ -> gcCache);
- encodeBuffer.encodeValue((unsigned int) inputMessage[12], 2);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[13]);
- int relativeCoordMode = (inputMessage[13] != 0);
- const unsigned char *nextSrc = inputMessage + 16;
- unsigned int pointIndex = 0;
-
- for (unsigned int i = 0; i < numPoints; i++)
- {
- if (relativeCoordMode)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> fillPolyXRelCache[pointIndex], 8);
- nextSrc += 2;
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> fillPolyYRelCache[pointIndex], 8);
- nextSrc += 2;
- }
- else
- {
- unsigned int x = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int y = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int j;
- for (j = 0; j < 8; j++)
- if ((x == clientCache_ -> fillPolyRecentX[j]) &&
- (y == clientCache_ -> fillPolyRecentY[j]))
- break;
- if (j < 8)
- {
- encodeBuffer.encodeBoolValue(1);
- encodeBuffer.encodeValue(j, 3);
- }
- else
- {
- encodeBuffer.encodeBoolValue(0);
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> fillPolyXAbsCache[pointIndex], 8);
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> fillPolyYAbsCache[pointIndex], 8);
- clientCache_ -> fillPolyRecentX[clientCache_ -> fillPolyIndex] = x;
- clientCache_ -> fillPolyRecentY[clientCache_ -> fillPolyIndex] = y;
- clientCache_ -> fillPolyIndex++;
- if (clientCache_ -> fillPolyIndex == 8)
- clientCache_ -> fillPolyIndex = 0;
- }
- }
-
- if (++pointIndex == 10) pointIndex = 0;
- }
- }
- break;
- case X_FreeColors:
- {
- unsigned int numPixels = GetUINT(inputMessage + 2, bigEndian_) - 3;
- encodeBuffer.encodeValue(numPixels, 16, 4);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> colormapCache);
- encodeBuffer.encodeValue(GetULONG(inputMessage + 8, bigEndian_), 32, 4);
- const unsigned char *nextSrc = inputMessage + 12;
- while (numPixels)
- {
- encodeBuffer.encodeValue(GetULONG(nextSrc, bigEndian_), 32, 8);
- nextSrc += 4;
- numPixels--;
- }
- }
- break;
- case X_FreeCursor:
- {
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_),
- 29, clientCache_ -> cursorCache, 9);
- }
- break;
- case X_FreeGC:
- {
- #ifdef TARGETS
-
- unsigned int g_id = GetULONG(inputMessage + 4, bigEndian_);
-
- T_gcontexts::iterator i = gcontexts.find(g_id);
-
- if (i != gcontexts.end())
- {
- unsigned int t_id = i -> second;
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_FreeGC gcontext id is " << g_id
- << " target id is pixmap " << t_id << ".\n"
- << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_FreeGC gcontext id is " << g_id
- << " target id is window " << t_id << ".\n"
- << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_FreeGC gcontext id is " << g_id
- << " target id is unrecognized.\n"
- << logofs_flush;
- }
- }
- else
- {
- *logofs << "handleRead: X_FreeGC gcontext id " << g_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- gcontexts.erase(g_id);
-
- #endif
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeFreeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> freeGCCache);
- }
- break;
- case X_FreePixmap:
- {
- #ifdef TARGETS
-
- unsigned int p_id = GetULONG(inputMessage + 4, bigEndian_);
-
- *logofs << "handleRead: X_FreePixmap id is " << p_id << ".\n" << logofs_flush;
-
- pixmaps.erase(p_id);
-
- #endif
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeFreeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> freeDrawableCache);
- }
- break;
- case X_GetAtomName:
- {
- encodeBuffer.encodeValue(GetULONG(inputMessage + 4, bigEndian_), 29, 9);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetGeometry:
- {
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> drawableCache);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetInputFocus:
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetModifierMapping:
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetKeyboardMapping:
- {
- encodeBuffer.encodeValue((unsigned int) inputMessage[4], 8);
- encodeBuffer.encodeValue((unsigned int) inputMessage[5], 8);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetProperty:
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_GetProperty);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- unsigned int property = GetULONG(inputMessage + 8, bigEndian_);
-
- sequenceQueue_.push(clientSequence_, inputOpcode, property);
-
- priority_++;
-
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- unsigned int property = GetULONG(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeValue(property, 29, 9);
- encodeBuffer.encodeValue(GetULONG(inputMessage + 12, bigEndian_), 29, 9);
- encodeBuffer.encodeValue(GetULONG(inputMessage + 16, bigEndian_), 32, 2);
- encodeBuffer.encodeValue(GetULONG(inputMessage + 20, bigEndian_), 32, 8);
-
- sequenceQueue_.push(clientSequence_, inputOpcode, property);
-
- priority_++;
- }
- break;
- case X_GetSelectionOwner:
- {
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> getSelectionOwnerSelectionCache, 9);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GrabButton:
- {
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 8, bigEndian_), 16,
- clientCache_ -> grabButtonEventMaskCache);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[10]);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[11]);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 12, bigEndian_), 29,
- clientCache_ -> grabButtonConfineCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 16, bigEndian_), 29,
- clientCache_ -> cursorCache, 9);
- encodeBuffer.encodeCachedValue(inputMessage[20], 8,
- clientCache_ -> grabButtonButtonCache);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 22, bigEndian_), 16,
- clientCache_ -> grabButtonModifierCache);
- }
- break;
- case X_GrabPointer:
- {
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 8, bigEndian_), 16,
- clientCache_ -> grabButtonEventMaskCache);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[10]);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[11]);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 12,
- bigEndian_), 29,
- clientCache_ -> grabButtonConfineCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 16,
- bigEndian_), 29, clientCache_ -> cursorCache, 9);
-
- unsigned int timestamp = GetULONG(inputMessage + 20, bigEndian_);
- encodeBuffer.encodeValue(timestamp -
- clientCache_ -> grabKeyboardLastTimestamp, 32, 4);
- clientCache_ -> grabKeyboardLastTimestamp = timestamp;
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GrabKeyboard:
- {
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- unsigned int timestamp = GetULONG(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeValue(timestamp -
- clientCache_ -> grabKeyboardLastTimestamp, 32, 4);
- clientCache_ -> grabKeyboardLastTimestamp = timestamp;
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[12]);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[13]);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GrabServer:
- case X_UngrabServer:
- case X_NoOperation:
- {
- }
- break;
- case X_PolyText8:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyText8 target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyText8 target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyText8 target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyText8);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- unsigned int x = GetUINT(inputMessage + 12, bigEndian_);
- int xDiff = x - clientCache_ -> polyTextLastX;
- clientCache_ -> polyTextLastX = x;
- encodeBuffer.encodeCachedValue(xDiff, 16,
- clientCache_ -> polyTextCacheX);
- unsigned int y = GetUINT(inputMessage + 14, bigEndian_);
- int yDiff = y - clientCache_ -> polyTextLastY;
- clientCache_ -> polyTextLastY = y;
- encodeBuffer.encodeCachedValue(yDiff, 16,
- clientCache_ -> polyTextCacheY);
- const unsigned char *end = inputMessage + inputLength - 1;
- const unsigned char *nextSrc = inputMessage + 16;
- while (nextSrc < end)
- {
- unsigned int textLength = (unsigned int) *nextSrc++;
- encodeBuffer.encodeBoolValue(1);
- encodeBuffer.encodeValue(textLength, 8);
- if (textLength == 255)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, 1), 29,
- clientCache_ -> polyTextFontCache);
- nextSrc += 4;
- }
- else
- {
- encodeBuffer.encodeCachedValue(*nextSrc++, 8,
- clientCache_ -> polyTextDeltaCache);
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength);
- nextSrc += textLength;
- }
- }
- encodeBuffer.encodeBoolValue(0);
- }
- break;
- case X_PolyText16:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyText16 target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyText16 target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyText16 target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyText16);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- unsigned int x = GetUINT(inputMessage + 12, bigEndian_);
- int xDiff = x - clientCache_ -> polyTextLastX;
- clientCache_ -> polyTextLastX = x;
- encodeBuffer.encodeCachedValue(xDiff, 16,
- clientCache_ -> polyTextCacheX);
- unsigned int y = GetUINT(inputMessage + 14, bigEndian_);
- int yDiff = y - clientCache_ -> polyTextLastY;
- clientCache_ -> polyTextLastY = y;
- encodeBuffer.encodeCachedValue(yDiff, 16,
- clientCache_ -> polyTextCacheY);
- const unsigned char *end = inputMessage + inputLength - 1;
- const unsigned char *nextSrc = inputMessage + 16;
- while (nextSrc < end)
- {
- unsigned int textLength = (unsigned int) *nextSrc++;
- encodeBuffer.encodeBoolValue(1);
- encodeBuffer.encodeValue(textLength, 8);
- if (textLength == 255)
- {
- encodeBuffer.encodeCachedValue(GetULONG(nextSrc, 1), 29,
- clientCache_ -> polyTextFontCache);
- nextSrc += 4;
- }
- else
- {
- encodeBuffer.encodeCachedValue(*nextSrc++, 8,
- clientCache_ -> polyTextDeltaCache);
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength * 2);
- nextSrc += textLength * 2;
- }
- }
- encodeBuffer.encodeBoolValue(0);
- }
- break;
- case X_ImageText8:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_ImageText8 target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_ImageText8 target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_ImageText8 target id "
- << t_id << " is unrecognized.\n"
- << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ImageText8);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- unsigned int textLength = (unsigned int) inputMessage[1];
- encodeBuffer.encodeCachedValue(textLength, 8,
- clientCache_ -> imageTextLengthCache, 4);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- unsigned int x = GetUINT(inputMessage + 12, bigEndian_);
- int xDiff = x - clientCache_ -> imageTextLastX;
- clientCache_ -> imageTextLastX = x;
- encodeBuffer.encodeCachedValue(xDiff, 16,
- clientCache_ -> imageTextCacheX);
- unsigned int y = GetUINT(inputMessage + 14, bigEndian_);
- int yDiff = y - clientCache_ -> imageTextLastY;
- clientCache_ -> imageTextLastY = y;
- encodeBuffer.encodeCachedValue(yDiff, 16,
- clientCache_ -> imageTextCacheY);
- const unsigned char *nextSrc = inputMessage + 16;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength);
- }
- break;
- case X_ImageText16:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_ImageText16 target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_ImageText16 target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_ImageText16 target id "
- << t_id << " is unrecognized.\n"
- << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_ImageText16);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- unsigned int textLength = (unsigned int) inputMessage[1];
- encodeBuffer.encodeCachedValue(textLength, 8,
- clientCache_ -> imageTextLengthCache, 4);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- unsigned int x = GetUINT(inputMessage + 12, bigEndian_);
- int xDiff = x - clientCache_ -> imageTextLastX;
- clientCache_ -> imageTextLastX = x;
- encodeBuffer.encodeCachedValue(xDiff, 16,
- clientCache_ -> imageTextCacheX);
- unsigned int y = GetUINT(inputMessage + 14, bigEndian_);
- int yDiff = y - clientCache_ -> imageTextLastY;
- clientCache_ -> imageTextLastY = y;
- encodeBuffer.encodeCachedValue(yDiff, 16,
- clientCache_ -> imageTextCacheY);
- const unsigned char *nextSrc = inputMessage + 16;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength * 2);
- }
- break;
- case X_InternAtom:
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_InternAtom);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- //
- // Set the priority, also if doing so will
- // penalize all the well written clients
- // using XInternAtoms() to pipeline multi-
- // ple replies.
- //
-
- priority_++;
-
- hit = 1;
-
- break;
- }
-
- unsigned int nameLength = GetUINT(inputMessage + 4, bigEndian_);
- encodeBuffer.encodeValue(nameLength, 16, 6);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- const unsigned char *nextSrc = inputMessage + 8;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, nameLength);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_ListExtensions:
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_ListFonts:
- {
- unsigned int textLength = GetUINT(inputMessage + 6, bigEndian_);
- encodeBuffer.encodeValue(textLength, 16, 6);
- encodeBuffer.encodeValue(GetUINT(inputMessage + 4, bigEndian_), 16, 6);
- const unsigned char* nextSrc = inputMessage + 8;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_LookupColor:
- case X_AllocNamedColor:
- {
- unsigned int textLength = GetUINT(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeValue(textLength, 16, 6);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_),
- 29, clientCache_ -> colormapCache);
- const unsigned char *nextSrc = inputMessage + 12;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, textLength);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_MapWindow:
- case X_UnmapWindow:
- case X_MapSubwindows:
- case X_GetWindowAttributes:
- case X_DestroyWindow:
- case X_DestroySubwindows:
- case X_QueryPointer:
- case X_QueryTree:
- {
- #ifdef TARGETS
-
- if (inputOpcode == X_DestroyWindow)
- {
- unsigned int w_id = GetULONG(inputMessage + 4, bigEndian_);
-
- *logofs << "handleRead: X_DestroyWindow id is "
- << w_id << ".\n" << logofs_flush;
-
- windows.erase(w_id);
- }
-
- #endif
-
- if (inputOpcode == X_DestroyWindow)
- {
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeFreeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> freeWindowCache);
- }
- else
- {
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> windowCache);
- }
-
- if ((inputOpcode == X_QueryPointer) ||
- (inputOpcode == X_GetWindowAttributes) ||
- (inputOpcode == X_QueryTree))
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- }
- break;
- case X_OpenFont:
- {
- unsigned int nameLength = GetUINT(inputMessage + 8, bigEndian_);
- encodeBuffer.encodeValue(nameLength, 16, 7);
- unsigned int font = GetULONG(inputMessage + 4, bigEndian_);
- encodeBuffer.encodeValue(font - clientCache_ -> lastFont, 29, 5);
- clientCache_ -> lastFont = font;
- const unsigned char *nextSrc = inputMessage + 12;
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeTextData(nextSrc, nameLength);
- }
- break;
- case X_PolyFillRectangle:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyFillRectangle target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyFillRectangle target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyFillRectangle target id "
- << t_id << " is unrecognized.\n"
- << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyFillRectangle);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
-
- unsigned int index = 0;
- unsigned int lastX = 0, lastY = 0;
- unsigned int lastWidth = 0, lastHeight = 0;
-
- //
- // TODO: Could send the size at the beginning
- // instead of a bool at each iteration.
- //
-
- for (unsigned int i = 12; i < inputLength;)
- {
- unsigned int x = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newX = x;
- x -= lastX;
- lastX = newX;
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> polyFillRectangleCacheX[index], 8);
- i += 2;
- unsigned int y = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newY = y;
- y -= lastY;
- lastY = newY;
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> polyFillRectangleCacheY[index], 8);
- i += 2;
- unsigned int width = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newWidth = width;
- width -= lastWidth;
- lastWidth = newWidth;
- encodeBuffer.encodeCachedValue(width, 16,
- *clientCache_ -> polyFillRectangleCacheWidth[index], 8);
- i += 2;
- unsigned int height = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newHeight = height;
- height -= lastHeight;
- lastHeight = newHeight;
- encodeBuffer.encodeCachedValue(height, 16,
- *clientCache_ -> polyFillRectangleCacheHeight[index], 8);
- i += 2;
-
- if (++index == 4) index = 0;
-
- encodeBuffer.encodeBoolValue((i < inputLength) ? 1 : 0);
- }
- }
- break;
- case X_PolyFillArc:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyFillArc target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyFillArc target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyFillArc target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyFillArc);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
-
- unsigned int index = 0;
- unsigned int lastX = 0, lastY = 0;
- unsigned int lastWidth = 0, lastHeight = 0;
- unsigned int lastAngle1 = 0, lastAngle2 = 0;
-
- //
- // TODO: Could send the size at the beginning
- // instead of a bool at each iteration.
- //
-
- for (unsigned int i = 12; i < inputLength;)
- {
- unsigned int x = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newX = x;
- x -= lastX;
- lastX = newX;
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> polyFillArcCacheX[index], 8);
- i += 2;
- unsigned int y = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newY = y;
- y -= lastY;
- lastY = newY;
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> polyFillArcCacheY[index], 8);
- i += 2;
- unsigned int width = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newWidth = width;
- width -= lastWidth;
- lastWidth = newWidth;
- encodeBuffer.encodeCachedValue(width, 16,
- *clientCache_ -> polyFillArcCacheWidth[index], 8);
- i += 2;
- unsigned int height = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newHeight = height;
- height -= lastHeight;
- lastHeight = newHeight;
- encodeBuffer.encodeCachedValue(height, 16,
- *clientCache_ -> polyFillArcCacheHeight[index], 8);
- i += 2;
- unsigned int angle1 = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newAngle1 = angle1;
- angle1 -= lastAngle1;
- lastAngle1 = newAngle1;
- encodeBuffer.encodeCachedValue(angle1, 16,
- *clientCache_ -> polyFillArcCacheAngle1[index], 8);
- i += 2;
- unsigned int angle2 = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newAngle2 = angle2;
- angle2 -= lastAngle2;
- lastAngle2 = newAngle2;
- encodeBuffer.encodeCachedValue(angle2, 16,
- *clientCache_ -> polyFillArcCacheAngle2[index], 8);
- i += 2;
-
- if (++index == 2) index = 0;
-
- encodeBuffer.encodeBoolValue((i < inputLength) ? 1 : 0);
- }
- }
- break;
- case X_PolyArc:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyArc target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyArc target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyArc target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyArc);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
-
- unsigned int index = 0;
- unsigned int lastX = 0, lastY = 0;
- unsigned int lastWidth = 0, lastHeight = 0;
- unsigned int lastAngle1 = 0, lastAngle2 = 0;
-
- //
- // TODO: Could send the size at the beginning
- // instead of a bool at each iteration.
- //
-
- for (unsigned int i = 12; i < inputLength;)
- {
- unsigned int x = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newX = x;
- x -= lastX;
- lastX = newX;
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> polyArcCacheX[index], 8);
- i += 2;
- unsigned int y = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newY = y;
- y -= lastY;
- lastY = newY;
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> polyArcCacheY[index], 8);
- i += 2;
- unsigned int width = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newWidth = width;
- width -= lastWidth;
- lastWidth = newWidth;
- encodeBuffer.encodeCachedValue(width, 16,
- *clientCache_ -> polyArcCacheWidth[index], 8);
- i += 2;
- unsigned int height = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newHeight = height;
- height -= lastHeight;
- lastHeight = newHeight;
- encodeBuffer.encodeCachedValue(height, 16,
- *clientCache_ -> polyArcCacheHeight[index], 8);
- i += 2;
- unsigned int angle1 = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newAngle1 = angle1;
- angle1 -= lastAngle1;
- lastAngle1 = newAngle1;
- encodeBuffer.encodeCachedValue(angle1, 16,
- *clientCache_ -> polyArcCacheAngle1[index], 8);
- i += 2;
- unsigned int angle2 = GetUINT(inputMessage + i, bigEndian_);
- unsigned int newAngle2 = angle2;
- angle2 -= lastAngle2;
- lastAngle2 = newAngle2;
- encodeBuffer.encodeCachedValue(angle2, 16,
- *clientCache_ -> polyArcCacheAngle2[index], 8);
- i += 2;
-
- if (++index == 2) index = 0;
-
- encodeBuffer.encodeBoolValue((i < inputLength) ? 1 : 0);
- }
- }
- break;
- case X_PolyPoint:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyPoint target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyPoint target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyPoint target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyPoint);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeValue(GetUINT(inputMessage + 2, bigEndian_) - 3, 16, 4);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8, bigEndian_),
- clientCache_ -> gcCache);
- const unsigned char *nextSrc = inputMessage + 12;
-
- unsigned int index = 0;
- unsigned int lastX = 0, lastY = 0;
-
- for (unsigned int i = 12; i < inputLength; i += 4)
- {
- unsigned int x = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int tmp = x;
- x -= lastX;
- lastX = tmp;
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> polyPointCacheX[index], 8);
- unsigned int y = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- tmp = y;
- y -= lastY;
- lastY = tmp;
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> polyPointCacheY[index], 8);
-
- if (++index == 2) index = 0;
- }
- }
- break;
- case X_PolyLine:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolyLine target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolyLine target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolyLine target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolyLine);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeValue(GetUINT(inputMessage + 2, bigEndian_) - 3, 16, 4);
- encodeBuffer.encodeBoolValue((unsigned int) inputMessage[1]);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *nextSrc = inputMessage + 12;
-
- unsigned int index = 0;
- unsigned int lastX = 0, lastY = 0;
-
- for (unsigned int i = 12; i < inputLength; i += 4)
- {
- unsigned int x = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int tmp = x;
- x -= lastX;
- lastX = tmp;
- encodeBuffer.encodeCachedValue(x, 16,
- *clientCache_ -> polyLineCacheX[index], 8);
- unsigned int y = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- tmp = y;
- y -= lastY;
- lastY = tmp;
- encodeBuffer.encodeCachedValue(y, 16,
- *clientCache_ -> polyLineCacheY[index], 8);
-
- if (++index == 2) index = 0;
- }
- }
- break;
- case X_PolyRectangle:
- {
- encodeBuffer.encodeValue((GetUINT(inputMessage + 2,
- bigEndian_) - 3) >> 1, 16, 3);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *end = inputMessage + inputLength;
- const unsigned char *nextSrc = inputMessage + 12;
- while (nextSrc < end)
- {
- for (unsigned int i = 0; i < 4; i++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> polyRectangleGeomCache[i], 8);
- nextSrc += 2;
- }
- }
- }
- break;
- case X_PolySegment:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PolySegment target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PolySegment target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PolySegment target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PolySegment);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeValue((GetUINT(inputMessage + 2,
- bigEndian_) - 3) >> 1, 16, 4);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 8,
- bigEndian_), clientCache_ -> gcCache);
- const unsigned char *end = inputMessage + inputLength;
- const unsigned char *nextSrc = inputMessage + 12;
- // unsigned int index = 0;
- // unsigned int lastX1, lastY1, lastX2, lastY2;
- while (nextSrc < end)
- {
- unsigned int x = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int xDiff0 =
- x - clientCache_ -> polySegmentLastX[0];
- unsigned int xDiff1 =
- x - clientCache_ -> polySegmentLastX[1];
- int xDiff0Abs = (int) xDiff0;
- if (xDiff0Abs < 0)
- xDiff0Abs = -xDiff0Abs;
- int xDiff1Abs = (int) xDiff1;
- if (xDiff1Abs < 0)
- xDiff1Abs = -xDiff1Abs;
-
- unsigned int y = GetUINT(nextSrc, bigEndian_);
- nextSrc += 2;
- unsigned int yDiff0 =
- y - clientCache_ -> polySegmentLastY[0];
- unsigned int yDiff1 =
- y - clientCache_ -> polySegmentLastY[1];
- int yDiff0Abs = (int) yDiff0;
- if (yDiff0Abs < 0)
- yDiff0Abs = -yDiff0Abs;
- int yDiff1Abs = (int) yDiff1;
- if (yDiff1Abs < 0)
- yDiff1Abs = -yDiff1Abs;
-
- int diff0 = xDiff0Abs + yDiff0Abs;
- int diff1 = xDiff1Abs + yDiff1Abs;
- if (diff0 < diff1)
- {
- encodeBuffer.encodeBoolValue(0);
- encodeBuffer.encodeCachedValue(xDiff0, 16,
- clientCache_ -> polySegmentCacheX, 6);
- encodeBuffer.encodeCachedValue(yDiff0, 16,
- clientCache_ -> polySegmentCacheY, 6);
- }
- else
- {
- encodeBuffer.encodeBoolValue(1);
- encodeBuffer.encodeCachedValue(xDiff1, 16,
- clientCache_ -> polySegmentCacheX, 6);
- encodeBuffer.encodeCachedValue(yDiff1, 16,
- clientCache_ -> polySegmentCacheY, 6);
- }
-
- clientCache_ -> polySegmentLastX[clientCache_ -> polySegmentCacheIndex] = x;
- clientCache_ -> polySegmentLastY[clientCache_ -> polySegmentCacheIndex] = y;
-
- clientCache_ -> polySegmentCacheIndex =
- clientCache_ -> polySegmentCacheIndex == 1 ? 0 : 1;
- }
- }
- break;
- case X_PutImage:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_PutImage target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_PutImage target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_PutImage target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_PutImage);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- break;
- case X_QueryBestSize:
- {
- encodeBuffer.encodeValue((unsigned int)inputMessage[1], 2);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- encodeBuffer.encodeValue(GetUINT(inputMessage + 8, bigEndian_), 16, 8);
- encodeBuffer.encodeValue(GetUINT(inputMessage + 10, bigEndian_), 16, 8);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_QueryColors:
- {
- // Differential encoding.
- encodeBuffer.encodeBoolValue(1);
-
- unsigned int numColors = ((inputLength - 8) >> 2);
- encodeBuffer.encodeValue(numColors, 16, 5);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> colormapCache);
- const unsigned char *nextSrc = inputMessage + 8;
- unsigned int predictedPixel = clientCache_ -> queryColorsLastPixel;
- for (unsigned int i = 0; i < numColors; i++)
- {
- unsigned int pixel = GetULONG(nextSrc, bigEndian_);
- nextSrc += 4;
- if (pixel == predictedPixel)
- encodeBuffer.encodeBoolValue(1);
- else
- {
- encodeBuffer.encodeBoolValue(0);
- encodeBuffer.encodeValue(pixel, 32, 9);
- }
- if (i == 0)
- clientCache_ -> queryColorsLastPixel = pixel;
- predictedPixel = pixel + 1;
- }
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_QueryExtension:
- {
- #ifdef TEST
-
- char data[256];
-
- int length = GetUINT(inputMessage + 4, bigEndian_);
-
- if (length > 256)
- {
- length = 256;
- }
-
- strncpy(data, (char *) inputMessage + 8, length);
-
- *(data + length) = '\0';
-
- *logofs << "handleRead: Going to query extension '"
- << data << "' for FD#" << fd_ << ".\n"
- << logofs_flush;
- #endif
-
- unsigned int nameLength = GetUINT(inputMessage + 4, bigEndian_);
- encodeBuffer.encodeValue(nameLength, 16, 6);
- const unsigned char *nextSrc = inputMessage + 8;
-
- for (; nameLength; nameLength--)
- {
- encodeBuffer.encodeValue((unsigned int) *nextSrc++, 8);
- }
-
- unsigned int extension = 0;
-
- if (strncmp((char *) inputMessage + 8, "SHAPE", 5) == 0)
- {
- extension = X_NXInternalShapeExtension;
- }
- else if (strncmp((char *) inputMessage + 8, "RENDER", 6) == 0)
- {
- extension = X_NXInternalRenderExtension;
- }
-
- sequenceQueue_.push(clientSequence_, inputOpcode, extension);
-
- priority_++;
- }
- break;
- case X_QueryFont:
- {
- unsigned int font = GetULONG(inputMessage + 4, bigEndian_);
- encodeBuffer.encodeValue(font - clientCache_ -> lastFont, 29, 5);
- clientCache_ -> lastFont = font;
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_SetClipRectangles:
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_SetClipRectangles);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- hit = 1;
-
- break;
- }
-
- unsigned int numRectangles = ((inputLength - 12) >> 3);
-
- // Since ProtoStep9 (#issue 108)
- encodeBuffer.encodeValue(numRectangles, 15, 4);
-
- encodeBuffer.encodeValue((unsigned int) inputMessage[1], 2);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> gcCache);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 8, bigEndian_), 16,
- clientCache_ -> setClipRectanglesXCache, 8);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 10, bigEndian_), 16,
- clientCache_ -> setClipRectanglesYCache, 8);
- const unsigned char *nextSrc = inputMessage + 12;
- for (unsigned int i = 0; i < numRectangles; i++)
- {
- for (unsigned int j = 0; j < 4; j++)
- {
- encodeBuffer.encodeCachedValue(GetUINT(nextSrc, bigEndian_), 16,
- *clientCache_ -> setClipRectanglesGeomCache[j], 8);
- nextSrc += 2;
- }
- }
- }
- break;
- case X_SetDashes:
- {
- unsigned int numDashes = GetUINT(inputMessage + 10, bigEndian_);
- encodeBuffer.encodeCachedValue(numDashes, 16,
- clientCache_ -> setDashesLengthCache, 5);
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4, bigEndian_),
- clientCache_ -> gcCache);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 8, bigEndian_), 16,
- clientCache_ -> setDashesOffsetCache, 5);
- const unsigned char *nextSrc = inputMessage + 12;
- for (unsigned int i = 0; i < numDashes; i++)
- encodeBuffer.encodeCachedValue(*nextSrc++, 8,
- clientCache_ -> setDashesDashCache_[i & 1], 5);
- }
- break;
- case X_SetSelectionOwner:
- {
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> setSelectionOwnerCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 8, bigEndian_), 29,
- clientCache_ -> getSelectionOwnerSelectionCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 12, bigEndian_), 32,
- clientCache_ -> setSelectionOwnerTimestampCache, 9);
- }
- break;
- case X_TranslateCoords:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_TranslateCoords source id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_TranslateCoords source id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_TranslateCoords source id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- t_id = GetULONG(inputMessage + 8, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_TranslateCoords target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_TranslateCoords target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_TranslateCoords target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_TranslateCoords);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
-
- hit = 1;
-
- break;
- }
-
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 4, bigEndian_), 29,
- clientCache_ -> translateCoordsSrcCache, 9);
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 8, bigEndian_), 29,
- clientCache_ -> translateCoordsDstCache, 9);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 12, bigEndian_), 16,
- clientCache_ -> translateCoordsXCache, 8);
- encodeBuffer.encodeCachedValue(GetUINT(inputMessage + 14, bigEndian_), 16,
- clientCache_ -> translateCoordsYCache, 8);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetImage:
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_GetImage source id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_GetImage source id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_GetImage source id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_GetImage);
-
- if (handleEncodeCached(encodeBuffer, clientCache_, messageStore,
- inputMessage, inputLength))
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
-
- hit = 1;
-
- break;
- }
-
- // Format.
- encodeBuffer.encodeValue((unsigned int) inputMessage[1], 2);
- // Drawable.
- encodeBuffer.encodeXidValue(GetULONG(inputMessage + 4,
- bigEndian_), clientCache_ -> drawableCache);
- // X.
- unsigned int x = GetUINT(inputMessage + 8, bigEndian_);
- int xDiff = x - clientCache_ -> putImageLastX;
- clientCache_ -> putImageLastX = x;
- encodeBuffer.encodeCachedValue(xDiff, 16,
- clientCache_ -> putImageXCache, 8);
- // Y.
- unsigned int y = GetUINT(inputMessage + 10, bigEndian_);
- int yDiff = y - clientCache_ -> putImageLastY;
- clientCache_ -> putImageLastY = y;
- encodeBuffer.encodeCachedValue(yDiff, 16,
- clientCache_ -> putImageYCache, 8);
- // Width.
- unsigned int width = GetUINT(inputMessage + 12, bigEndian_);
- encodeBuffer.encodeCachedValue(width, 16,
- clientCache_ -> putImageWidthCache, 8);
- // Height.
- unsigned int height = GetUINT(inputMessage + 14, bigEndian_);
- encodeBuffer.encodeCachedValue(height, 16,
- clientCache_ -> putImageHeightCache, 8);
- // Plane mask.
- encodeBuffer.encodeCachedValue(GetULONG(inputMessage + 16, bigEndian_), 32,
- clientCache_ -> getImagePlaneMaskCache, 5);
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetPointerMapping:
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- case X_GetKeyboardControl:
- {
- sequenceQueue_.push(clientSequence_, inputOpcode);
-
- priority_++;
- }
- break;
- default:
- {
- if (inputOpcode == opcodeStore_ -> renderExtension)
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXInternalRenderExtension);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> shapeExtension)
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXInternalShapeExtension);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> putPackedImage)
- {
- #ifdef TARGETS
-
- unsigned int t_id = GetULONG(inputMessage + 4, bigEndian_);
-
- if (pixmaps.find(t_id) != pixmaps.end())
- {
- *logofs << "handleRead: X_NXPutPackedImage target id is pixmap "
- << t_id << ".\n" << logofs_flush;
- }
- else if (windows.find(t_id) != windows.end())
- {
- *logofs << "handleRead: X_NXPutPackedImage target id is window "
- << t_id << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleRead: X_NXPutPackedImage target id " << t_id
- << " is unrecognized.\n" << logofs_flush;
- }
-
- #endif
-
- #ifdef DEBUG
- *logofs << "handleRead: Encoding packed image request for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- //
- // The field carries the destination data
- // length. We add the request's size of
- // the final X_PutImage.
- //
-
- unsigned int outputLength = GetULONG(inputMessage + 20, bigEndian_) + 24;
-
- statistics -> addPackedBytesIn(inputLength);
-
- statistics -> addPackedBytesOut(outputLength);
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXPutPackedImage);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> setUnpackColormap)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding set unpack colormap request "
- << "for FD#" << fd_ << " with size " << inputLength
- << ".\n" << logofs_flush;
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXSetUnpackColormap);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> setUnpackAlpha)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding set unpack alpha request "
- << "for FD#" << fd_ << " with size " << inputLength
- << ".\n" << logofs_flush;
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXSetUnpackAlpha);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> setUnpackGeometry)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding set unpack geometry request "
- << "for FD#" << fd_ << " with size " << inputLength
- << ".\n" << logofs_flush;
- #endif
-
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXSetUnpackGeometry);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
- }
- else if (inputOpcode == opcodeStore_ -> startSplit)
- {
- if (handleStartSplitRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> endSplit)
- {
- if (handleEndSplitRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> commitSplit)
- {
- if (handleCommitSplitRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> abortSplit)
- {
- if (handleAbortSplitRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> finishSplit)
- {
- if (handleFinishSplitRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> freeSplit)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding free split request "
- << "for FD#" << fd_ << " with size " << inputLength
- << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeCachedValue(*(inputMessage + 1), 8,
- clientCache_ -> resourceCache);
- }
- else if (inputOpcode == opcodeStore_ -> freeUnpack)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding free unpack request "
- << "for FD#" << fd_ << " with size " << inputLength
- << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeCachedValue(*(inputMessage + 1), 8,
- clientCache_ -> resourceCache);
- }
- else if (inputOpcode == opcodeStore_ -> getControlParameters)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding get control parameters "
- << "request for FD#" << fd_ << " with size "
- << inputLength << ".\n" << logofs_flush;
- #endif
-
- //
- // Add the reply to the write buffer. If found
- // to contain a message, it it will be flushed
- // to the X client before leaving the loop.
- //
-
- unsigned char *reply = writeBuffer_.addMessage(32);
-
- *(reply + 0) = X_Reply;
-
- PutUINT(clientSequence_, reply + 2, bigEndian_);
-
- PutULONG(0, reply + 4, bigEndian_);
-
- //
- // Save the sequence number we used
- // to auto-generate this reply.
- //
-
- lastSequence_ = clientSequence_;
-
- #ifdef TEST
- *logofs << "handleRead: Registered " << lastSequence_
- << " as last auto-generated sequence number.\n"
- << logofs_flush;
- #endif
-
- *(reply + 1) = control -> LinkMode;
-
- *(reply + 8) = control -> LocalVersionMajor;
- *(reply + 9) = control -> LocalVersionMinor;
- *(reply + 10) = control -> LocalVersionPatch;
-
- *(reply + 11) = control -> RemoteVersionMajor;
- *(reply + 12) = control -> RemoteVersionMinor;
- *(reply + 13) = control -> RemoteVersionPatch;
-
- PutUINT(control -> SplitTimeout, reply + 14, bigEndian_);
- PutUINT(control -> MotionTimeout, reply + 16, bigEndian_);
-
- *(reply + 18) = control -> SplitMode;
-
- PutULONG(control -> SplitDataThreshold, reply + 20, bigEndian_);
-
- *(reply + 24) = control -> PackMethod;
- *(reply + 25) = control -> PackQuality;
-
- *(reply + 26) = control -> LocalDataCompressionLevel;
- *(reply + 27) = control -> LocalStreamCompressionLevel;
- *(reply + 28) = control -> LocalDeltaCompression;
-
- *(reply + 29) = (control -> LocalDeltaCompression == 1 &&
- control -> PersistentCacheEnableLoad == 1);
- *(reply + 30) = (control -> LocalDeltaCompression == 1 &&
- control -> PersistentCacheEnableSave == 1);
- *(reply + 31) = (control -> LocalDeltaCompression == 1 &&
- control -> PersistentCacheEnableLoad == 1 &&
- control -> PersistentCacheName != NULL);
-
- if (handleFlush(flush_if_any) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> getCleanupParameters)
- {
- #ifdef WARNING
- *logofs << "handleRead: WARNING! Encoding fake get cleanup "
- << "parameters request for FD#" << fd_ << " with size "
- << inputLength << ".\n" << logofs_flush;
- #endif
- }
- else if (inputOpcode == opcodeStore_ -> getImageParameters)
- {
- #ifdef WARNING
- *logofs << "handleRead: WARNING! Encoding fake get cleanup "
- << "parameters request for FD#" << fd_ << " with size "
- << inputLength << ".\n" << logofs_flush;
- #endif
- }
- else if (inputOpcode == opcodeStore_ -> getUnpackParameters)
- {
- #ifdef DEBUG
- *logofs << "handleRead: Encoding get unpack parameters "
- << "request for FD#" << fd_ << " with size "
- << inputLength << ".\n" << logofs_flush;
- #endif
-
- sequenceQueue_.push(clientSequence_, inputOpcode);
- }
- else if (inputOpcode == opcodeStore_ -> getShmemParameters)
- {
- if (handleShmemRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> setExposeParameters)
- {
- //
- // Enable or disable expose events
- // coming from the real server.
- //
-
- encodeBuffer.encodeBoolValue(*(inputMessage + 4));
- encodeBuffer.encodeBoolValue(*(inputMessage + 5));
- encodeBuffer.encodeBoolValue(*(inputMessage + 6));
- }
- else if (inputOpcode == opcodeStore_ -> setCacheParameters)
- {
- if (handleCacheRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else if (inputOpcode == opcodeStore_ -> getFontParameters)
- {
- if (handleFontRequest(encodeBuffer, inputOpcode,
- inputMessage, inputLength) < 0)
- {
- return -1;
- }
- }
- else
- {
- MessageStore *messageStore = clientStore_ ->
- getRequestStore(X_NXInternalGenericRequest);
-
- hit = handleEncode(encodeBuffer, clientCache_, messageStore,
- inputOpcode, inputMessage, inputLength);
-
- //
- // Don't flush if the opcode is unrecognized.
- // We may optionally flush it is an extension
- // but would penalize the well written clients.
- //
- // if (inputOpcode > 127)
- // {
- // priority_++;
- // }
- //
- }
- }
- } // End of switch on opcode.
-
- int bits = encodeBuffer.diffBits();
-
- #if defined(TEST) || defined(OPCODES)
-
- const char *cacheString = (hit ? "cached " : "");
-
- *logofs << "handleRead: Handled " << cacheString << "request OPCODE#"
- << (unsigned int) inputOpcode << " (" << DumpOpcode(inputOpcode)
- << ")" << " for FD#" << fd_ << " sequence " << clientSequence_
- << ". " << inputLength << " bytes in, " << bits << " bits ("
- << ((float) bits) / 8 << " bytes) out.\n" << logofs_flush;
-
- #endif
-
- if (hit)
- {
- statistics -> addCachedRequest(inputOpcode);
- }
-
- statistics -> addRequestBits(inputOpcode, inputLength << 3, bits);
-
- if (inputOpcode == opcodeStore_ -> renderExtension)
- {
- if (hit)
- {
- statistics -> addRenderCachedRequest(*(inputMessage + 1));
- }
-
- statistics -> addRenderRequestBits(*(inputMessage + 1), inputLength << 3, bits);
- }
-
- } // End if (firstRequest_)... else ...
-
- } // End of while ((inputMessage = readBuffer_.getMessage(inputLength)) != 0) ...
-
- //
- // Check if we need to flush because of
- // prioritized data.
- //
-
- if (priority_ > 0)
- {
- #if defined(TEST) || defined(INFO)
- *logofs << "handleRead: WARNING! Requesting flush "
- << "because of " << priority_ << " prioritized "
- << "messages for FD#" << fd_ << ".\n"
- << logofs_flush;
- #endif
-
- if (proxy -> handleAsyncPriority() < 0)
- {
- return -1;
- }
-
- //
- // Reset the priority flag.
- //
-
- priority_ = 0;
- }
-
- //
- // Flush if we exceeded the token length.
- //
-
- if (proxy -> canAsyncFlush() == 1)
- {
- #if defined(TEST) || defined(INFO)
- *logofs << "handleRead: WARNING! Requesting flush "
- << "because of token length exceeded.\n"
- << logofs_flush;
- #endif
-
- if (proxy -> handleAsyncFlush() < 0)
- {
- return -1;
- }
- }
-
- #if defined(TEST) || defined(INFO)
-
- if (transport_ -> pending() != 0 ||
- readBuffer_.checkMessage() != 0)
- {
- *logofs << "handleRead: PANIC! Buffer for X descriptor FD#"
- << fd_ << " has " << transport_ -> pending()
- << " bytes to read.\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- #endif
-
- //
- // Reset the read buffer.
- //
-
- readBuffer_.fullReset();
-
- return 1;
-}
-
-//
-// End of handleRead().
-//
-
-//
-// Beginning of handleWrite().
-//
-
-int ClientChannel::handleWrite(const unsigned char *message, unsigned int length)
-{
- #ifdef TEST
- *logofs << "handleWrite: Called for FD#" << fd_
- << ".\n" << logofs_flush;
- #endif
-
- //
- // Create the buffer from which to
- // decode messages.
- //
-
- DecodeBuffer decodeBuffer(message, length);
-
- #if defined(TEST) || defined(INFO) || defined(FLUSH)
- *logofs << "handleWrite: Decoding messages for FD#" << fd_
- << " with " << length << " bytes in the buffer.\n"
- << logofs_flush;
- #endif
-
- if (firstReply_)
- {
- #ifdef TEST
- *logofs << "handleWrite: First reply detected.\n" << logofs_flush;
- #endif
-
- unsigned int outputOpcode;
-
- decodeBuffer.decodeValue(outputOpcode, 8);
- unsigned int secondByte;
- decodeBuffer.decodeValue(secondByte, 8);
- unsigned int major;
- decodeBuffer.decodeValue(major, 16);
- unsigned int minor;
- decodeBuffer.decodeValue(minor, 16);
- unsigned int extraLength;
- decodeBuffer.decodeValue(extraLength, 16);
- unsigned int outputLength = 8 + (extraLength << 2);
-
- unsigned char *outputMessage = writeBuffer_.addMessage(outputLength);
- *outputMessage = (unsigned char) outputOpcode;
- outputMessage[1] = (unsigned char) secondByte;
- PutUINT(major, outputMessage + 2, bigEndian_);
- PutUINT(minor, outputMessage + 4, bigEndian_);
- PutUINT(extraLength, outputMessage + 6, bigEndian_);
- unsigned char *nextDest = outputMessage + 8;
- unsigned int cached;
- decodeBuffer.decodeBoolValue(cached);
-
- if (cached)
- {
- memcpy(nextDest, ServerCache::lastInitReply.getData(), outputLength - 8);
- }
- else
- {
- for (unsigned i = 8; i < outputLength; i++)
- {
- unsigned int nextByte;
- decodeBuffer.decodeValue(nextByte, 8);
- *nextDest++ = (unsigned char) nextByte;
- }
-
- ServerCache::lastInitReply.set(outputLength - 8, outputMessage + 8);
- }
-
- imageByteOrder_ = outputMessage[30];
- bitmapBitOrder_ = outputMessage[31];
- scanlineUnit_ = outputMessage[32];
- scanlinePad_ = outputMessage[33];
-
- firstReply_ = 0;
-
- } // End of if (firstReply_)
-
- //
- // This was previously in a 'else' block.
- // Due to the way the first request was
- // handled, we could not decode multiple
- // messages in the first frame.
- //
-
- { // Start of the decoding block.
-
- #ifdef DEBUG
- *logofs << "handleWrite: Starting loop on opcodes.\n"
- << logofs_flush;
- #endif
-
- unsigned char outputOpcode;
-
- //
- // NX client needs this line to consider
- // the initialization phase successfully
- // completed.
- //
-
- if (firstClient_ == -1)
- {
- cerr << "Info" << ": Established X client connection.\n" ;
-
- firstClient_ = fd_;
- }
-
- while (decodeBuffer.decodeOpcodeValue(outputOpcode, serverCache_ -> opcodeCache, 1))
- {
- #ifdef DEBUG
- *logofs << "handleWrite: Decoded a new OPCODE#"
- << (unsigned int) outputOpcode << ".\n"
- << logofs_flush;
- #endif
-
- unsigned char *outputMessage = NULL;
- unsigned int outputLength = 0;
-
- //
- // General-purpose temp variables
- // for decoding ints and chars.
- //
-
- unsigned int value = 0;
- unsigned char cValue = 0;
-
- //
- // Check first if we need to abort any split,
- // then if this is a reply, finally if it is
- // en event or error.
- //
-
- if (outputOpcode == opcodeStore_ -> splitEvent)
- {
- //
- // It's an abort split, not a normal
- // burst of proxy data.
- //
-
- handleSplitEvent(decodeBuffer);
-
- continue;
- }
- else if (outputOpcode == X_Reply)
- {
- #ifdef DEBUG
- *logofs << "handleWrite: Decoding sequence number of reply.\n"
- << logofs_flush;
- #endif
-
- unsigned int sequenceNum;
- unsigned int sequenceDiff;
-
- decodeBuffer.decodeCachedValue(sequenceDiff, 16,
- serverCache_ -> replySequenceCache, 7);
-
- sequenceNum = (serverSequence_ + sequenceDiff) & 0xffff;
-
- serverSequence_ = sequenceNum;
-
- #ifdef DEBUG
- *logofs << "handleWrite: Last server sequence number for FD#"
- << fd_ << " is " << serverSequence_ << " with "
- << "difference " << sequenceDiff << ".\n"
- << logofs_flush;
- #endif
-
- //
- // In case of reply we can follow the X server and
- // override any event's sequence number generated
- // by this side.
- //
-
- #ifdef TEST
- *logofs << "handleWrite: Updating last event's sequence "
- << lastSequence_ << " to reply's sequence number "
- << serverSequence_ << " for FD#" << fd_ << ".\n"
- << logofs_flush;
- #endif
-
- lastSequence_ = serverSequence_;
-
- unsigned short int requestSequenceNum;
- unsigned char requestOpcode;
-
- #ifdef DEBUG
-
- requestSequenceNum = 0;
- requestOpcode = 0;
-
- *logofs << "handleWrite: Peek of sequence number returns ";
-
- *logofs << sequenceQueue_.peek(requestSequenceNum, requestOpcode);
-
- *logofs << " with sequence " << requestSequenceNum << " and opcode "
- << (unsigned int) requestOpcode << ".\n" << logofs_flush;
-
- #endif
-
- if (sequenceQueue_.peek(requestSequenceNum, requestOpcode) == 1 &&
- (requestSequenceNum == sequenceNum))
- {
- unsigned int requestData[3];
-
- sequenceQueue_.pop(requestSequenceNum, requestOpcode,
- requestData[0], requestData[1], requestData[2]);
-
- #ifdef DEBUG
- *logofs << "handleWrite: Identified reply to OPCODE#"
- << (unsigned int) requestOpcode << ".\n"
- << logofs_flush;
- #endif
-
- //
- // Is differential encoding disabled?
- //
-
- if (control -> RemoteDeltaCompression == 0)
- {
- int result = handleFastWriteReply(decodeBuffer, requestOpcode,
- outputMessage, outputLength);
- if (result < 0)
- {
- return -1;
- }
- else if (result > 0)
- {
- continue;
- }
- }
-
- switch (requestOpcode)
- {
- case X_AllocColor:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- unsigned char *nextDest = outputMessage + 8;
- for (unsigned int i = 0; i < 3; i++)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- PutUINT(requestData[i], nextDest, bigEndian_);
- }
- else
- {
- decodeBuffer.decodeValue(value, 16, 6);
- PutUINT(requestData[i] + value, nextDest, bigEndian_);
- }
- nextDest += 2;
- }
- decodeBuffer.decodeValue(value, 32, 9);
- PutULONG(value, outputMessage + 16, bigEndian_);
- }
- break;
- case X_GetAtomName:
- {
- unsigned int nameLength;
- decodeBuffer.decodeValue(nameLength, 16, 6);
- outputLength = RoundUp4(nameLength) + 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- PutUINT(nameLength, outputMessage + 8, bigEndian_);
- unsigned char* nextDest = outputMessage + 32;
-
- // Since ProtoStep7 (#issue 108)
- decodeBuffer.decodeTextData(nextDest, nameLength);
- }
- break;
- case X_GetGeometry:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> depthCache);
- outputMessage[1] = cValue;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> getGeometryRootCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- unsigned char *nextDest = outputMessage + 12;
- for (unsigned int i = 0; i < 5; i++)
- {
- decodeBuffer.decodeCachedValue(value, 16,
- *serverCache_ -> getGeometryGeomCache[i], 8);
- PutUINT(value, nextDest, bigEndian_);
- nextDest += 2;
- }
- }
- break;
- case X_GetInputFocus:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeValue(value, 2);
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> getInputFocusWindowCache);
- PutULONG(value, outputMessage + 8, bigEndian_);
- }
- break;
- case X_GetKeyboardMapping:
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- unsigned int dataLength =
- ServerCache::getKeyboardMappingLastMap.getLength();
- outputLength = 32 + dataLength;
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] =
- ServerCache::getKeyboardMappingLastKeysymsPerKeycode;
- memcpy(outputMessage + 32,
- ServerCache::getKeyboardMappingLastMap.getData(),
- dataLength);
- break;
- }
- unsigned int numKeycodes;
- decodeBuffer.decodeValue(numKeycodes, 8);
- unsigned int keysymsPerKeycode;
- decodeBuffer.decodeValue(keysymsPerKeycode, 8, 4);
- ServerCache::getKeyboardMappingLastKeysymsPerKeycode =
- keysymsPerKeycode;
- outputLength = 32 + numKeycodes * keysymsPerKeycode * 4;
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] = (unsigned char) keysymsPerKeycode;
- unsigned char *nextDest = outputMessage + 32;
- unsigned char previous = 0;
- for (unsigned int count = numKeycodes * keysymsPerKeycode;
- count; --count)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- PutULONG((unsigned int) NoSymbol, nextDest, bigEndian_);
- else
- {
- unsigned int keysym;
- decodeBuffer.decodeCachedValue(keysym, 24,
- serverCache_ -> getKeyboardMappingKeysymCache, 9);
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> getKeyboardMappingLastByteCache, 5);
- previous += cValue;
- PutULONG((keysym << 8) | previous, nextDest, bigEndian_);
- }
- nextDest += 4;
- }
- ServerCache::getKeyboardMappingLastMap.set(outputLength - 32,
- outputMessage + 32);
- }
- break;
- case X_GetModifierMapping:
- {
- unsigned int keycodesPerModifier;
- decodeBuffer.decodeValue(keycodesPerModifier, 8);
- outputLength = 32 + (keycodesPerModifier << 3);
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] = (unsigned char) keycodesPerModifier;
- unsigned char *nextDest = outputMessage + 32;
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- memcpy(outputMessage + 32,
- ServerCache::getModifierMappingLastMap.getData(),
- ServerCache::getModifierMappingLastMap.getLength());
- break;
- }
- for (unsigned int count = outputLength - 32; count; count--)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- *nextDest++ = 0;
- else
- {
- decodeBuffer.decodeValue(value, 8);
- *nextDest++ = value;
- }
- }
- ServerCache::getModifierMappingLastMap.set(outputLength - 32,
- outputMessage + 32);
- }
- break;
- case X_GetProperty:
- {
- MessageStore *messageStore = serverStore_ ->
- getReplyStore(X_GetProperty);
-
- handleDecode(decodeBuffer, serverCache_, messageStore,
- requestOpcode, outputMessage, outputLength);
- }
- break;
- case X_GetSelectionOwner:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> getSelectionOwnerCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- }
- break;
- case X_GetWindowAttributes:
- {
- outputLength = 44;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeValue(value, 2);
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> visualCache);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> getWindowAttributesClassCache, 3);
- PutUINT(value, outputMessage + 12, bigEndian_);
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> getWindowAttributesBitGravityCache);
- outputMessage[14] = cValue;
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> getWindowAttributesWinGravityCache);
- outputMessage[15] = cValue;
- decodeBuffer.decodeCachedValue(value, 32,
- serverCache_ -> getWindowAttributesPlanesCache, 9);
- PutULONG(value, outputMessage + 16, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 32,
- serverCache_ -> getWindowAttributesPixelCache, 9);
- PutULONG(value, outputMessage + 20, bigEndian_);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[24] = (unsigned char) value;
- decodeBuffer.decodeBoolValue(value);
- outputMessage[25] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 2);
- outputMessage[26] = (unsigned char) value;
- decodeBuffer.decodeBoolValue(value);
- outputMessage[27] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> colormapCache, 9);
- PutULONG(value, outputMessage + 28, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 32,
- serverCache_ -> getWindowAttributesAllEventsCache);
- PutULONG(value, outputMessage + 32, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 32,
- serverCache_ -> getWindowAttributesYourEventsCache);
- PutULONG(value, outputMessage + 36, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> getWindowAttributesDontPropagateCache);
- PutUINT(value, outputMessage + 40, bigEndian_);
- }
- break;
- case X_GrabKeyboard:
- case X_GrabPointer:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeValue(value, 3);
- outputMessage[1] = (unsigned char) value;
- }
- break;
- case X_InternAtom:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeValue(value, 29, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- }
- break;
- case X_ListExtensions:
- {
- decodeBuffer.decodeValue(value, 32, 8);
- outputLength = 32 + (value << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
- unsigned int numExtensions;
- decodeBuffer.decodeValue(numExtensions, 8);
- outputMessage[1] = (unsigned char) numExtensions;
- unsigned char *nextDest = outputMessage + 32;
- for (; numExtensions; numExtensions--)
- {
- unsigned int length;
- decodeBuffer.decodeValue(length, 8);
- *nextDest++ = (unsigned char) length;
- for (; length; length--)
- {
- decodeBuffer.decodeValue(value, 8);
- *nextDest++ = value;
- }
- }
- }
- break;
- case X_ListFonts:
- {
- //
- // Differential compression can achieve a 12:1 to 14:1
- // ratio, while the best ZLIB compression can achieve
- // a mere 4:1 to 5:1. In the first case, though, the
- // huge amount of data constituting the message would
- // be stored uncompressed at the remote side. We need
- // to find a compromise. The solution is to use diffe-
- // rential compression at startup and ZLIB compression
- // later on.
- //
-
- MessageStore *messageStore = serverStore_ ->
- getReplyStore(X_ListFonts);
-
- if (handleDecodeCached(decodeBuffer, serverCache_, messageStore,
- outputMessage, outputLength))
- {
- break;
- }
-
- decodeBuffer.decodeValue(value, 32, 8);
- outputLength = 32 + (value << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
- unsigned int numFonts;
- decodeBuffer.decodeValue(numFonts, 16, 6);
- PutUINT(numFonts, outputMessage + 8, bigEndian_);
-
- // Differential or plain data compression?
- decodeBuffer.decodeBoolValue(value);
-
- if (value)
- {
- unsigned char* nextDest = outputMessage + 32;
- for (; numFonts; numFonts--)
- {
- unsigned int length;
- decodeBuffer.decodeValue(length, 8);
- *nextDest++ = (unsigned char)length;
-
- // Since ProtoStep7 (#issue 108)
- decodeBuffer.decodeTextData(nextDest, length);
- nextDest += length;
- }
-
- handleSave(messageStore, outputMessage, outputLength);
- }
- else
- {
- const unsigned char *compressedData = NULL;
- unsigned int compressedDataSize = 0;
-
- int decompressed = handleDecompress(decodeBuffer, requestOpcode, messageStore -> dataOffset,
- outputMessage, outputLength, compressedData,
- compressedDataSize);
- if (decompressed < 0)
- {
- return -1;
- }
- else if (decompressed > 0)
- {
- handleSave(messageStore, outputMessage, outputLength,
- compressedData, compressedDataSize);
- }
- else
- {
- handleSave(messageStore, outputMessage, outputLength);
- }
- }
- }
- break;
- case X_LookupColor:
- case X_AllocNamedColor:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- unsigned char *nextDest = outputMessage + 8;
- if (requestOpcode == X_AllocNamedColor)
- {
- decodeBuffer.decodeValue(value, 32, 9);
- PutULONG(value, nextDest, bigEndian_);
- nextDest += 4;
- }
- unsigned int count = 3;
- do
- {
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, nextDest, bigEndian_);
- unsigned int visualColor;
- decodeBuffer.decodeValue(visualColor, 16, 5);
- visualColor += value;
- visualColor &= 0xffff;
- PutUINT(visualColor, nextDest + 6, bigEndian_);
- nextDest += 2;
- }
- while (--count);
- }
- break;
- case X_QueryBestSize:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeValue(value, 16, 8);
- PutUINT(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeValue(value, 16, 8);
- PutUINT(value, outputMessage + 10, bigEndian_);
- }
- break;
- case X_QueryColors:
- {
- // Differential or plain data compression?
- decodeBuffer.decodeBoolValue(value);
-
- if (value)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- unsigned int numColors =
- serverCache_ -> queryColorsLastReply.getLength() / 6;
- outputLength = 32 + (numColors << 3);
- outputMessage = writeBuffer_.addMessage(outputLength);
- PutUINT(numColors, outputMessage + 8, bigEndian_);
- const unsigned char *nextSrc =
- serverCache_ -> queryColorsLastReply.getData();
- unsigned char *nextDest = outputMessage + 32;
- for (; numColors; numColors--)
- {
- for (unsigned int i = 0; i < 6; i++)
- *nextDest++ = *nextSrc++;
- nextDest += 2;
- }
- }
- else
- {
- unsigned int numColors;
- decodeBuffer.decodeValue(numColors, 16, 5);
- outputLength = 32 + (numColors << 3);
- outputMessage = writeBuffer_.addMessage(outputLength);
- PutUINT(numColors, outputMessage + 8, bigEndian_);
- unsigned char *nextDest = outputMessage + 32;
- for (unsigned int c = 0; c < numColors; c++)
- {
- for (unsigned int i = 0; i < 3; i++)
- {
- decodeBuffer.decodeValue(value, 16);
- PutUINT(value, nextDest, bigEndian_);
- nextDest += 2;
- }
- }
- serverCache_ -> queryColorsLastReply.set(numColors * 6,
- outputMessage + 32);
- const unsigned char *nextSrc = nextDest - 1;
- nextDest = outputMessage + 32 + ((numColors - 1) << 3) + 5;
- for (; numColors > 1; numColors--)
- {
- for (unsigned int i = 0; i < 6; i++)
- *nextDest-- = *nextSrc--;
- nextDest -= 2;
- }
- }
- }
- else
- {
- // Reply length.
- unsigned int numColors;
- decodeBuffer.decodeValue(numColors, 16, 5);
- outputLength = 32 + (numColors << 3);
- outputMessage = writeBuffer_.addMessage(outputLength);
- PutUINT(numColors, outputMessage + 8, bigEndian_);
-
- const unsigned char *compressedData = NULL;
- unsigned int compressedDataSize = 0;
-
- int decompressed = handleDecompress(decodeBuffer, requestOpcode, 32,
- outputMessage, outputLength, compressedData,
- compressedDataSize);
- if (decompressed < 0)
- {
- return -1;
- }
- }
- }
- break;
- case X_QueryExtension:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[8] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 8);
- outputMessage[9] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 8);
- outputMessage[10] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 8);
- outputMessage[11] = (unsigned char) value;
-
- //
- // We use a predefined opcode to address
- // extensions' message stores, while real
- // opcodes are used for communication with
- // X server and clients.
- //
-
- if (requestData[0] == X_NXInternalShapeExtension)
- {
- opcodeStore_ -> shapeExtension = outputMessage[9];
-
- #ifdef TEST
- *logofs << "handleWrite: Shape extension opcode for FD#" << fd_
- << " is " << (unsigned int) opcodeStore_ -> shapeExtension
- << ".\n" << logofs_flush;
- #endif
- }
- else if (requestData[0] == X_NXInternalRenderExtension)
- {
- opcodeStore_ -> renderExtension = outputMessage[9];
-
- #ifdef TEST
- *logofs << "handleWrite: Render extension opcode for FD#" << fd_
- << " is " << (unsigned int) opcodeStore_ -> renderExtension
- << ".\n" << logofs_flush;
- #endif
- }
- }
- break;
- case X_QueryFont:
- {
- //
- // Use differential compression at startup and plain
- // data compression later. Check X_ListFonts message
- // for an explaination.
- //
-
- MessageStore *messageStore = serverStore_ ->
- getReplyStore(X_QueryFont);
-
- if (handleDecodeCached(decodeBuffer, serverCache_, messageStore,
- outputMessage, outputLength))
- {
- break;
- }
-
- // Differential or plain data compression?
- decodeBuffer.decodeBoolValue(value);
-
- if (value)
- {
- unsigned int numProperties;
- unsigned int numCharInfos;
- decodeBuffer.decodeValue(numProperties, 16, 8);
- decodeBuffer.decodeValue(numCharInfos, 32, 10);
- outputLength = 60 + numProperties * 8 + numCharInfos * 12;
- outputMessage = writeBuffer_.addMessage(outputLength);
- PutUINT(numProperties, outputMessage + 46, bigEndian_);
- PutULONG(numCharInfos, outputMessage + 56, bigEndian_);
- handleDecodeCharInfo(decodeBuffer, outputMessage + 8);
- handleDecodeCharInfo(decodeBuffer, outputMessage + 24);
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, outputMessage + 40, bigEndian_);
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, outputMessage + 42, bigEndian_);
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, outputMessage + 44, bigEndian_);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[48] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 8);
- outputMessage[49] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 8);
- outputMessage[50] = (unsigned char) value;
- decodeBuffer.decodeBoolValue(value);
- outputMessage[51] = (unsigned char) value;
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, outputMessage + 52, bigEndian_);
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, outputMessage + 54, bigEndian_);
- unsigned char *nextDest = outputMessage + 60;
- decodeBuffer.decodeBoolValue(value);
-
- int end = 0;
-
- if (value == 1)
- {
- unsigned int index;
- decodeBuffer.decodeValue(index, 4);
- unsigned int length;
- const unsigned char *data;
- ServerCache::queryFontFontCache.get(index, length, data);
- memcpy(nextDest, data, length);
-
- end = 1;
- }
-
- if (end == 0)
- {
- unsigned char *saveDest = nextDest;
- unsigned int length = numProperties * 8 + numCharInfos * 12;
- for (; numProperties; numProperties--)
- {
- decodeBuffer.decodeValue(value, 32, 9);
- PutULONG(value, nextDest, bigEndian_);
- decodeBuffer.decodeValue(value, 32, 9);
- PutULONG(value, nextDest + 4, bigEndian_);
- nextDest += 8;
- }
- for (; numCharInfos; numCharInfos--)
- {
- handleDecodeCharInfo(decodeBuffer, nextDest);
-
- nextDest += 12;
- }
- ServerCache::queryFontFontCache.set(length, saveDest);
- }
-
- handleSave(messageStore, outputMessage, outputLength);
- }
- else
- {
- // Reply length.
- unsigned int replyLength;
- decodeBuffer.decodeValue(replyLength, 32, 16);
- outputLength = 32 + (replyLength << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
-
- const unsigned char *compressedData = NULL;
- unsigned int compressedDataSize = 0;
-
- int decompressed = handleDecompress(decodeBuffer, requestOpcode, messageStore -> dataOffset,
- outputMessage, outputLength, compressedData,
- compressedDataSize);
- if (decompressed < 0)
- {
- return -1;
- }
- else if (decompressed > 0)
- {
- handleSave(messageStore, outputMessage, outputLength,
- compressedData, compressedDataSize);
- }
- else
- {
- handleSave(messageStore, outputMessage, outputLength);
- }
- }
- }
- break;
- case X_QueryPointer:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> queryPointerRootCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> queryPointerChildCache, 9);
- PutULONG(value, outputMessage + 12, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyRootXCache, 8);
- serverCache_ -> motionNotifyLastRootX += value;
- PutUINT(serverCache_ -> motionNotifyLastRootX, outputMessage + 16,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyRootYCache, 8);
- serverCache_ -> motionNotifyLastRootY += value;
- PutUINT(serverCache_ -> motionNotifyLastRootY, outputMessage + 18,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyEventXCache, 8);
- PutUINT(serverCache_ -> motionNotifyLastRootX + value,
- outputMessage + 20, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyEventYCache, 8);
- PutUINT(serverCache_ -> motionNotifyLastRootY + value,
- outputMessage + 22, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyStateCache);
- PutUINT(value, outputMessage + 24, bigEndian_);
- }
- break;
- case X_QueryTree:
- {
- unsigned int children;
- decodeBuffer.decodeValue(children, 16, 8);
-
- outputLength = 32 + (children << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
-
- PutULONG(outputLength, outputMessage + 4, bigEndian_);
-
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> queryTreeWindowCache);
-
- PutULONG(value, outputMessage + 8, bigEndian_);
-
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> queryTreeWindowCache);
-
- PutULONG(value, outputMessage + 12, bigEndian_);
-
- unsigned char *next = outputMessage + 32;
-
- PutUINT(children, outputMessage + 16, bigEndian_);
-
- for (unsigned int i = 0; i < children; i++)
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> queryTreeWindowCache);
-
- PutULONG(value, next + (i * 4), bigEndian_);
- }
- }
- break;
- case X_TranslateCoords:
- {
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> translateCoordsChildCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> translateCoordsXCache, 8);
- PutUINT(value, outputMessage + 12, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> translateCoordsYCache, 8);
- PutUINT(value, outputMessage + 14, bigEndian_);
- }
- break;
- case X_GetImage:
- {
- MessageStore *messageStore = serverStore_ ->
- getReplyStore(X_GetImage);
-
- if (handleDecodeCached(decodeBuffer, serverCache_, messageStore,
- outputMessage, outputLength))
- {
- break;
- }
-
- // Depth.
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> depthCache);
- // Reply length.
- unsigned int replyLength;
- decodeBuffer.decodeValue(replyLength, 32, 9);
- outputLength = 32 + (replyLength << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] = (unsigned char) cValue;
- // Visual.
- unsigned int visual;
- decodeBuffer.decodeCachedValue(visual, 29,
- serverCache_ -> visualCache);
- PutULONG(visual, outputMessage + 8, bigEndian_);
-
- // Since ProtoStep8 (#issue 108)
- handleCopy(decodeBuffer, requestOpcode, messageStore ->
- dataOffset, outputMessage, outputLength);
-
- handleSave(messageStore, outputMessage, outputLength);
- }
- break;
- case X_GetPointerMapping:
- {
- unsigned int nextByte;
- decodeBuffer.decodeValue(nextByte, 8, 4);
- unsigned int replyLength;
- decodeBuffer.decodeValue(replyLength, 32, 4);
- outputLength = 32 + (replyLength << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] = (unsigned char) nextByte;
- unsigned char *nextDest = outputMessage + 32;
- for (unsigned int i = 32; i < outputLength; i++)
- {
- decodeBuffer.decodeValue(nextByte, 8, 4);
- *nextDest++ = (unsigned char) nextByte;
- }
- }
- break;
- case X_GetKeyboardControl:
- {
- unsigned int nextByte;
- decodeBuffer.decodeValue(nextByte, 8, 2);
- unsigned int replyLength;
- decodeBuffer.decodeValue(replyLength, 32, 8);
- outputLength = 32 + (replyLength << 2);
- outputMessage = writeBuffer_.addMessage(outputLength);
- outputMessage[1] = (unsigned char) nextByte;
- unsigned char *nextDest = outputMessage + 8;
- for (unsigned int i = 8; i < outputLength; i++)
- {
- decodeBuffer.decodeValue(nextByte, 8, 4);
- *nextDest++ = (unsigned char) nextByte;
- }
- }
- break;
- default:
- {
- if (requestOpcode == opcodeStore_ -> getUnpackParameters)
- {
- #ifdef TEST
- *logofs << "handleWrite: Received get unpack parameters reply "
- << "OPCODE#" << (unsigned int) opcodeStore_ -> getUnpackParameters
- << ".\n" << logofs_flush;
- #endif
-
- outputLength = 32 + PACK_METHOD_LIMIT;
-
- outputMessage = writeBuffer_.addMessage(outputLength);
-
- unsigned int method;
-
- //
- // Let agent use only the unpack methods
- // implemented at both sides.
- //
-
- for (int i = 0; i < PACK_METHOD_LIMIT; i++)
- {
- decodeBuffer.decodeBoolValue(method);
-
- control -> RemoteUnpackMethods[i] = method;
-
- *(outputMessage + 32 + i) =
- (control -> LocalUnpackMethods[i] == 1 &&
- method == 1);
- }
- }
- else if (requestOpcode == opcodeStore_ -> getShmemParameters)
- {
- if (handleShmemReply(decodeBuffer, requestOpcode,
- outputMessage, outputLength) < 0)
- {
- return -1;
- }
- }
- else if (requestOpcode == opcodeStore_ -> getFontParameters)
- {
- if (handleFontReply(decodeBuffer, requestOpcode,
- outputMessage, outputLength) < 0)
- {
- return -1;
- }
- }
- else
- {
- #ifdef PANIC
- *logofs << "handleWrite: PANIC! No matching request for "
- << "reply with sequence number " << sequenceNum
- << ".\n" << logofs_flush;
- #endif
-
- cerr << "Error" << ": No matching request for "
- << "reply with sequence number " << sequenceNum
- << ".\n";
-
- return -1;
- }
- }
- }
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleWrite: Handled reply to OPCODE#"
- << (unsigned) requestOpcode << " (" << DumpOpcode(requestOpcode)
- << ")" << " for FD#" << fd_ << " with sequence " << serverSequence_
- << ". Output size is " << outputLength << ".\n" << logofs_flush;
- #endif
-
- statistics -> addRepliedRequest(requestOpcode);
- }
- else // End of if (sequenceQueue_.peek() && ...)
- {
- //
- // Reply didn't match any request opcode.
- // Check again if differential encoding
- // is disabled.
- //
-
- #ifdef DEBUG
- *logofs << "handleWrite: Identified generic reply.\n"
- << logofs_flush;
- #endif
-
- requestOpcode = X_Reply;
-
- if (control -> RemoteDeltaCompression == 0)
- {
- int result = handleFastWriteReply(decodeBuffer, requestOpcode,
- outputMessage, outputLength);
- if (result < 0)
- {
- return -1;
- }
- else if (result > 0)
- {
- continue;
- }
- }
-
- //
- // All replies whose opcode is not pushed in
- // sequence number queue are cached together.
- // Among such replies are those to extension
- // requests.
- //
-
- MessageStore *messageStore = serverStore_ ->
- getReplyStore(X_NXInternalGenericReply);
-
- handleDecode(decodeBuffer, serverCache_, messageStore,
- requestOpcode, outputMessage, outputLength);
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleWrite: Handled generic reply for FD#" << fd_
- << " with sequence " << serverSequence_ << ". Output size is "
- << outputLength << ".\n" << logofs_flush;
- #endif
-
- statistics -> addRepliedRequest(requestOpcode);
-
- } // End of if (sequenceQueue_.peek() && ...) else ...
-
- //
- // If any output was produced then write opcode,
- // sequence number and size to the buffer.
- //
-
- if (outputLength > 0)
- {
- *outputMessage = outputOpcode;
-
- PutUINT(serverSequence_, outputMessage + 2, bigEndian_);
-
- PutULONG((outputLength - 32) >> 2, outputMessage + 4, bigEndian_);
- }
-
- } // End of if (outputOpcode == 1)...
- else
- {
- //
- // It's an event or error.
- //
-
- unsigned int sequenceNum;
- unsigned int sequenceDiff;
-
- decodeBuffer.decodeCachedValue(sequenceDiff, 16,
- serverCache_ -> eventSequenceCache, 7);
-
- sequenceNum = (serverSequence_ + sequenceDiff) & 0xffff;
-
- serverSequence_ = sequenceNum;
-
- #ifdef DEBUG
- *logofs << "handleWrite: Last server sequence number for FD#"
- << fd_ << " is " << serverSequence_ << " with "
- << "difference " << sequenceDiff << ".\n"
- << logofs_flush;
- #endif
-
- //
- // Check if this is an error that matches
- // a sequence number for which we were
- // expecting a reply.
- //
-
- if (outputOpcode == X_Error)
- {
- unsigned short int errorSequenceNum;
- unsigned char errorOpcode;
-
- if (sequenceQueue_.peek(errorSequenceNum, errorOpcode) &&
- ((unsigned) errorSequenceNum == serverSequence_))
- {
- //
- // Remove the queued sequence of the reply.
- //
-
- #ifdef TEST
- *logofs << "handleWrite: WARNING! Removing reply to OPCODE#"
- << (unsigned) errorOpcode << " sequence "
- << errorSequenceNum << " for FD#" << fd_
- << " due to error.\n" << logofs_flush;
- #endif
-
- sequenceQueue_.pop(errorSequenceNum, errorOpcode);
-
- //
- // Send to the client the current sequence
- // number, not the number that matched the
- // reply. Because we are generating replies
- // at our side, Xlib can incur in a sequence
- // lost if the error comes after the auto-
- // generated reply.
- //
-
- if (control -> SessionMode == session_proxy)
- {
- #ifdef TEST
- *logofs << "handleWrite: Updating last event's sequence "
- << lastSequence_ << " to X server's error sequence "
- << "number " << serverSequence_ << " for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- lastSequence_ = serverSequence_;
- }
- }
-
- //
- // In case of errors always send to client the
- // original X server's sequence associated to
- // the failing request.
- //
-
- if (control -> SessionMode != session_proxy)
- {
- #ifdef TEST
- *logofs << "handleWrite: Updating last event's sequence "
- << lastSequence_ << " to X server's error sequence "
- << "number " << serverSequence_ << " for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- lastSequence_ = serverSequence_;
- }
- }
-
- //
- // Check if by producing events at client side we
- // have modified the events' sequence numbering.
- // In this case taint the original sequence to
- // comply with the last one known by client.
- //
-
-/*
-FIXME: Recover the sequence number if the proxy
- is not connected to an agent.
-*/
- if (serverSequence_ > lastSequence_ ||
- control -> SessionMode != session_proxy)
- {
- #ifdef DEBUG
- *logofs << "handleWrite: Updating last event's sequence "
- << lastSequence_ << " to X server's sequence number "
- << serverSequence_ << " for FD#" << fd_
- << ".\n" << logofs_flush;
- #endif
-
- lastSequence_ = serverSequence_;
- }
- #ifdef DEBUG
- else if (serverSequence_ < lastSequence_)
- {
- //
- // Use our last auto-generated sequence.
- //
-
- *logofs << "handleWrite: Tainting sequence number "
- << serverSequence_ << " to last event's sequence "
- << lastSequence_ << " for FD#" << fd_ << ".\n"
- << logofs_flush;
- }
- #endif
-
- //
- // Check if remote side used fast encoding.
- //
-
- if (control -> RemoteDeltaCompression == 0)
- {
- int result = handleFastWriteEvent(decodeBuffer, outputOpcode,
- outputMessage, outputLength);
- if (result < 0)
- {
- return -1;
- }
- else if (result > 0)
- {
- continue;
- }
- }
-
- //
- // Make space for message in the outgoing buffer
- // and write opcode and sequence number.
- //
-
- outputLength = 32;
- outputMessage = writeBuffer_.addMessage(outputLength);
-
- *outputMessage = outputOpcode;
-
- PutUINT(lastSequence_, outputMessage + 2, bigEndian_);
-
- #ifdef DEBUG
- *logofs << "handleWrite: Going to handle event or error OPCODE#"
- << (unsigned int) outputOpcode << " for FD#" << fd_
- << " sequence " << lastSequence_ << " (real was "
- << serverSequence_ << ").\n" << logofs_flush;
- #endif
-
- switch (outputOpcode)
- {
- case X_Error:
- {
- unsigned char code;
- decodeBuffer.decodeCachedValue(code, 8,
- serverCache_ -> errorCodeCache);
- outputMessage[1] = code;
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleWrite: Handled error ERR_CODE#"
- << (unsigned int) code << " for FD#" << fd_;
- #endif
-
- if ((code != 11) && (code != 8) &&
- (code != 15) && (code != 1))
- {
- decodeBuffer.decodeValue(value, 32, 16);
- PutULONG(value, outputMessage + 4, bigEndian_);
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << " RES_ID#" << value;
- #endif
- }
-
- if (code >= 18)
- {
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> errorMinorCache);
- PutUINT(value, outputMessage + 8, bigEndian_);
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << " MIN_OP#" << value;
- #endif
- }
-
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> errorMajorCache);
- outputMessage[10] = cValue;
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << " MAJ_OP#" << (unsigned int) cValue;
- #endif
-
- if (code >= 18)
- {
- unsigned char *nextDest = outputMessage + 11;
- for (unsigned int i = 11; i < 32; i++)
- {
- decodeBuffer.decodeValue(value, 8);
- *nextDest++ = (unsigned char) cValue;
- }
- }
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << " sequence " << lastSequence_ << " (real was "
- << serverSequence_ << ") . Size is "
- << (unsigned int) outputLength << ".\n"
- << logofs_flush;
- #endif
- }
- break;
- case ButtonPress:
- case ButtonRelease:
- case KeyPress:
- case KeyRelease:
- case MotionNotify:
- case EnterNotify:
- case LeaveNotify:
- {
- if (outputOpcode == MotionNotify)
- {
- decodeBuffer.decodeBoolValue(value);
- }
- else if (outputOpcode == EnterNotify || outputOpcode == LeaveNotify)
- {
- decodeBuffer.decodeValue(value, 3);
- }
- else if (outputOpcode == KeyRelease)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- value = serverCache_ -> keyPressLastKey;
- }
- else
- {
- decodeBuffer.decodeValue(value, 8);
- }
- }
- else if (outputOpcode == ButtonPress || outputOpcode == ButtonRelease)
- {
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> buttonCache);
- value = (unsigned int) cValue;
- }
- else
- {
- decodeBuffer.decodeValue(value, 8);
- }
-
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 32,
- serverCache_ -> motionNotifyTimestampCache, 9);
- serverCache_ -> lastTimestamp += value;
- PutULONG(serverCache_ -> lastTimestamp, outputMessage + 4,
- bigEndian_);
- unsigned char *nextDest = outputMessage + 8;
- int skipRest = 0;
- if (outputOpcode == KeyRelease)
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- {
- for (unsigned int i = 0; i < 23; i++)
- {
- *nextDest++ = serverCache_ -> keyPressCache[i];
- }
- skipRest = 1;
- }
- }
-
- if (!skipRest)
- {
- for (unsigned int i = 0; i < 3; i++)
- {
- decodeBuffer.decodeCachedValue(value, 29,
- *serverCache_ -> motionNotifyWindowCache[i], 6);
- PutULONG(value, nextDest, bigEndian_);
- nextDest += 4;
- }
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyRootXCache, 6);
- serverCache_ -> motionNotifyLastRootX += value;
- PutUINT(serverCache_ -> motionNotifyLastRootX, outputMessage + 20,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyRootYCache, 6);
- serverCache_ -> motionNotifyLastRootY += value;
- PutUINT(serverCache_ -> motionNotifyLastRootY, outputMessage + 22,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyEventXCache, 6);
- PutUINT(serverCache_ -> motionNotifyLastRootX + value,
- outputMessage + 24, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyEventYCache, 6);
- PutUINT(serverCache_ -> motionNotifyLastRootY + value,
- outputMessage + 26, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> motionNotifyStateCache);
- PutUINT(value, outputMessage + 28, bigEndian_);
- if (outputOpcode == EnterNotify || outputOpcode == LeaveNotify)
- {
- decodeBuffer.decodeValue(value, 2);
- }
- else
- {
- decodeBuffer.decodeBoolValue(value);
- }
- outputMessage[30] = (unsigned char) value;
- if (outputOpcode == EnterNotify || outputOpcode == LeaveNotify)
- {
- decodeBuffer.decodeValue(value, 2);
- outputMessage[31] = (unsigned char) value;
- }
- else if (outputOpcode == KeyPress)
- {
- serverCache_ -> keyPressLastKey = outputMessage[1];
- for (unsigned int i = 8; i < 31; i++)
- {
- serverCache_ -> keyPressCache[i - 8] = outputMessage[i];
- }
- }
- }
- }
- break;
- case ColormapNotify:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> colormapNotifyWindowCache, 8);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> colormapNotifyColormapCache, 8);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[12] = (unsigned char) value;
- decodeBuffer.decodeBoolValue(value);
- outputMessage[13] = (unsigned char) value;
- }
- break;
- case ConfigureNotify:
- {
- unsigned char *nextDest = outputMessage + 4;
- for (unsigned int i = 0; i < 3; i++)
- {
- decodeBuffer.decodeCachedValue(value, 29,
- *serverCache_ -> configureNotifyWindowCache[i], 9);
- PutULONG(value, nextDest, bigEndian_);
- nextDest += 4;
- }
- for (unsigned int j = 0; j < 5; j++)
- {
- decodeBuffer.decodeCachedValue(value, 16,
- *serverCache_ -> configureNotifyGeomCache[j], 8);
- PutUINT(value, nextDest, bigEndian_);
- nextDest += 2;
- }
- decodeBuffer.decodeBoolValue(value);
- *nextDest = value;
- }
- break;
- case CreateNotify:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> createNotifyWindowCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeValue(value, 29, 5);
- serverCache_ -> createNotifyLastWindow += value;
- serverCache_ -> createNotifyLastWindow &= 0x1fffffff;
- PutULONG(serverCache_ -> createNotifyLastWindow, outputMessage + 8,
- bigEndian_);
- unsigned char* nextDest = outputMessage + 12;
- for (unsigned int i = 0; i < 5; i++)
- {
- decodeBuffer.decodeValue(value, 16, 9);
- PutUINT(value, nextDest, bigEndian_);
- nextDest += 2;
- }
- decodeBuffer.decodeBoolValue(value);
- *nextDest = (unsigned char) value;
- }
- break;
- case Expose:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> exposeWindowCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- unsigned char *nextDest = outputMessage + 8;
- for (unsigned int i = 0; i < 5; i++)
- {
- decodeBuffer.decodeCachedValue(value, 16,
- *serverCache_ -> exposeGeomCache[i], 6);
- PutUINT(value, nextDest, bigEndian_);
- nextDest += 2;
- }
- }
- break;
- case FocusIn:
- case FocusOut:
- {
- decodeBuffer.decodeValue(value, 3);
- outputMessage[1] = (unsigned char) value;
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> focusInWindowCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeValue(value, 2);
- outputMessage[8] = (unsigned char) value;
- }
- break;
- case KeymapNotify:
- {
- decodeBuffer.decodeBoolValue(value);
- if (value)
- memcpy(outputMessage + 1, ServerCache::lastKeymap.getData(), 31);
- else
- {
- unsigned char *nextDest = outputMessage + 1;
- for (unsigned int i = 1; i < 32; i++)
- {
- decodeBuffer.decodeValue(value, 8);
- *nextDest++ = (unsigned char) value;
- }
- ServerCache::lastKeymap.set(31, outputMessage + 1);
- }
- }
- break;
- case MapNotify:
- case UnmapNotify:
- case DestroyNotify:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> mapNotifyEventCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> mapNotifyWindowCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- if (outputOpcode == MapNotify || outputOpcode == UnmapNotify)
- {
- decodeBuffer.decodeBoolValue(value);
- outputMessage[12] = (unsigned char) value;
- }
- }
- break;
- case NoExpose:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> noExposeDrawableCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 16,
- serverCache_ -> noExposeMinorCache);
- PutUINT(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(cValue, 8,
- serverCache_ -> noExposeMajorCache);
- outputMessage[10] = cValue;
- }
- break;
- case PropertyNotify:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> propertyNotifyWindowCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> propertyNotifyAtomCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeValue(value, 32, 9);
- serverCache_ -> lastTimestamp += value;
- PutULONG(serverCache_ -> lastTimestamp, outputMessage + 12,
- bigEndian_);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[16] = (unsigned char) value;
- }
- break;
- case ReparentNotify:
- {
- unsigned char* nextDest = outputMessage + 4;
- for (unsigned int i = 0; i < 3; i++)
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> reparentNotifyWindowCache, 9);
- PutULONG(value, nextDest, bigEndian_);
- nextDest += 4;
- }
- decodeBuffer.decodeValue(value, 16, 6);
- PutUINT(value, nextDest, bigEndian_);
- decodeBuffer.decodeValue(value, 16, 6);
- PutUINT(value, nextDest + 2, bigEndian_);
- decodeBuffer.decodeBoolValue(value);
- outputMessage[20] = (unsigned char)value;
- }
- break;
- case SelectionClear:
- {
- decodeBuffer.decodeValue(value, 32, 9);
- serverCache_ -> lastTimestamp += value;
- PutULONG(serverCache_ -> lastTimestamp, outputMessage + 4,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearWindowCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearAtomCache, 9);
- PutULONG(value, outputMessage + 12, bigEndian_);
- }
- break;
- case SelectionRequest:
- {
- decodeBuffer.decodeValue(value, 32, 9);
- serverCache_ -> lastTimestamp += value;
- PutULONG(serverCache_ -> lastTimestamp, outputMessage + 4,
- bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearWindowCache, 9);
- PutULONG(value, outputMessage + 8, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearWindowCache, 9);
- PutULONG(value, outputMessage + 12, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearAtomCache, 9);
- PutULONG(value, outputMessage + 16, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearAtomCache, 9);
- PutULONG(value, outputMessage + 20, bigEndian_);
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> selectionClearAtomCache, 9);
- PutULONG(value, outputMessage + 24, bigEndian_);
- }
- break;
- case VisibilityNotify:
- {
- decodeBuffer.decodeCachedValue(value, 29,
- serverCache_ -> visibilityNotifyWindowCache, 9);
- PutULONG(value, outputMessage + 4, bigEndian_);
- decodeBuffer.decodeValue(value, 2);
- outputMessage[8] = (unsigned char) value;
- }
- break;
- default:
- {
- #ifdef TEST
- *logofs << "handleWrite: Using generic event compression "
- << "for OPCODE#" << (unsigned int) outputOpcode
- << ".\n" << logofs_flush;
- #endif
-
- decodeBuffer.decodeCachedValue(*(outputMessage + 1), 8,
- serverCache_ -> genericEventCharCache);
-
- for (unsigned int i = 0; i < 14; i++)
- {
- decodeBuffer.decodeCachedValue(value, 16,
- *serverCache_ -> genericEventIntCache[i]);
-
- PutUINT(value, outputMessage + i * 2 + 4, bigEndian_);
- }
- }
- } // End of switch (outputOpcode)...
-
- #if defined(TEST) || defined(OPCODES)
- if (outputOpcode != X_Error)
- {
- *logofs << "handleWrite: Handled event OPCODE#"
- << (unsigned int) outputOpcode << " for FD#"
- << fd_ << " sequence " << lastSequence_ << " (real was "
- << serverSequence_ << "). Size is " << outputLength
- << ".\n" << logofs_flush;
- }
- #endif
-
- //
- // Check if we need to suppress the error.
- //
-
- if (outputOpcode == X_Error &&
- handleTaintSyncError(*(outputMessage + 10)) > 0)
- {
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleWrite: WARNING! Suppressed error OPCODE#"
- << (unsigned int) outputOpcode << " for FD#"
- << fd_ << " sequence " << lastSequence_ << ".\n"
- << logofs_flush;
- #endif
-
- writeBuffer_.removeMessage(32);
- }
-
- } // End of if (outputOpcode == 1)... else ...
-
- //
- // Check if we produced enough data. We need to
- // decode all provided messages. Just update the
- // finish flag in case of failure.
- //
-
- handleFlush(flush_if_needed);
-
- } // End of while (decodeBuffer.decodeOpcodeValue(outputOpcode, 8, ...
-
- } // End of the decoding block.
-
- //
- // Write any remaining data to the X connection.
- //
-
- if (handleFlush(flush_if_any) < 0)
- {
- return -1;
- }
-
- return 1;
-}
-
-//
-// End of handleWrite().
-//
-
-//
-// Other members.
-//
-
-int ClientChannel::handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store,
- T_store_action action, int position, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- #if defined(TEST) || defined(SPLIT)
-
- // Since ProtoStep8 (#issue 108)
- *logofs << "handleSplit: PANIC! SPLIT! Split should "
- << "not be enabled for message " << "OPCODE#"
- << (unsigned int) store -> opcode() << ".\n"
- << logofs_flush;
-
- HandleCleanup();
-
- #endif
-
- //
- // Refuse the split if it is not introduced
- // by a start split.
- //
-
- // Since ProtoStep7 (#issue 108)
- if (splitState_.resource == nothing || enableSplit_ == 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Nothing to do for message "
- << "OPCODE#" << (unsigned int) store -> opcode()
- << " of size " << size << " position " << position
- << " with action [" << DumpAction(action) << "] at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeBoolValue(0);
-
- return 0;
- }
-
- //
- // It's not advisable to allocate the store at
- // the time we receive the start-split because
- // we may process all the splits received and
- // deallocate the store even before we receive
- // the end split. Another message for the same
- // split sequence may then come and we would
- // have a null split store.
- //
-
- handleSplitStoreAlloc(&splitResources_, splitState_.resource);
-
- //
- // Check if the split was actually requested by
- // the agent and if the request was saved in the
- // message store. The split can also be refused
- // if the message is smaller than the threshold
- // or if the split store is already full.
- //
-
- if (mustSplitMessage(splitState_.resource) == 0)
- {
- if (action == IS_HIT || canSplitMessage(splitState_.mode, size) == 0)
- {
- #if defined(TEST) || defined(SPLIT)
-
- if (splitState_.mode == split_none)
- {
- #ifdef PANIC
- *logofs << "handleSplit: PANIC! SPLIT! Split state has "
- << "mode 'none'.\n" << logofs_flush;
- #endif
-
- HandleCleanup();
- }
-
- if (action != IS_HIT && (int) size >=
- control -> SplitDataThreshold)
- {
- #ifdef WARNING
- *logofs << "handleSplit: WARNING! SPLIT! Split stores have "
- << clientStore_ -> getSplitTotalSize() << " messages "
- << "and " << clientStore_ -> getSplitTotalStorageSize()
- << " allocated bytes.\n" << logofs_flush;
- #endif
- }
-
- #endif
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Message OPCODE#"
- << (unsigned int) store -> opcode() << " of size " << size
- << " [not split] with resource " << splitState_.resource
- << " mode " << splitState_.mode << " position " << position
- << " and action [" << DumpAction(action) << "] at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeBoolValue(0);
-
- return 0;
- }
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Message OPCODE#"
- << (unsigned int) store -> opcode() << " of size " << size
- << " [split] with resource " << splitState_.resource
- << " mode " << splitState_.mode << " position " << position
- << " and action [" << DumpAction(action) << "] at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeBoolValue(1);
-
- T_checksum checksum = NULL;
-
- if (action == IS_ADDED)
- {
- checksum = store -> getChecksum(position);
- }
- else if (action == is_discarded)
- {
- //
- // Generate the checksum on the fly.
- //
-
- checksum = store -> getChecksum(buffer, size, bigEndian_);
- }
-
- //
- // The method must abort the connection
- // if it can't allocate the split.
- //
-
- Split *splitMessage = clientStore_ -> getSplitStore(splitState_.resource) ->
- add(store, splitState_.resource, splitState_.mode,
- position, action, checksum, buffer, size);
-
- //
- // Send the checksum. By using the checksum,
- // the remote end will try to locate the
- // message and load it from disk.
- //
-
- if (action == IS_HIT)
- {
- splitMessage -> setState(split_loaded);
- }
- else if (handleSplitChecksum(encodeBuffer, checksum) == 0)
- {
- //
- // If the checksum is not sent, for example
- // because loading of messages from disk is
- // disabled, then mark the split as missed.
- //
-
- #ifdef WARNING
- *logofs << "handleSplit: WARNING! Checksum not sent. "
- << "Marking the split as [missed].\n"
- << logofs_flush;
- #endif
-
- splitMessage -> setState(split_missed);
- }
-
- if (action == is_discarded)
- {
- delete [] checksum;
- }
-
- //
- // Check if we are ready to send a new split
- // for this store.
- //
-
- handleSplitPending(splitState_.resource);
-
- #if defined(TEST) || defined(SPLIT)
-
- *logofs << "handleSplit: SPLIT! There are " << clientStore_ ->
- getSplitTotalSize() << " messages and " << clientStore_ ->
- getSplitTotalStorageSize() << " bytes to send in "
- << "the split stores.\n" << logofs_flush;
-
- clientStore_ -> dumpSplitStore(splitState_.resource);
-
- #endif
-
- return 1;
-}
-
-int ClientChannel::handleSplit(EncodeBuffer &encodeBuffer)
-{
- //
- // Determine the maximum amount of bytes
- // we can write in this iteration.
- //
-
- int total = control -> SplitDataPacketLimit;
-
- int bytes = total;
- int splits = 0;
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Handling splits "
- << "for FD#" << fd_ << " with " << clientStore_ ->
- getSplitTotalSize() << " elements and " << total
- << " bytes to write at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- if (proxy -> handleAsyncSwitch(fd_) < 0)
- {
- return -1;
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Looping to find "
- << "if there is any split to send.\n"
- << logofs_flush;
- #endif
-
- SplitStore *splitStore;
-
- Split *splitMessage;
-
- //
- // Divide the available bandwidth among all the active
- // split stores by implementing a simple round-robin
- // mechanism. This can be extended by using an external
- // function returning the number of bytes to be written
- // based on the state of the split (splits which didn't
- // receive yet a confirmation event could be delayed),
- // the current bitrate, and by letting the agent asso-
- // ciate a priority to the resource in the start split
- // operation.
- //
-
- splitState_.pending = 0;
-
- splitResources_.rotate();
-
- //
- // Copy the list since elements can be removed
- // in the middle of the loop.
- //
-
- T_list splitList = splitResources_.copyList();
-
- for (T_list::iterator j = splitList.begin();
- j != splitList.end(); j++)
- {
- int resource = *j;
-
- #ifdef DEBUG
- *logofs << "handleSplit: SPLIT! Looping with current "
- << "resource " << resource << ".\n"
- << logofs_flush;
- #endif
-
- splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore != NULL)
- {
- //
- // Don't send more than the the packet size
- // bytes but ensure that we abort any split
- // found in the disk cache.
- //
-
- for (;;)
- {
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpSplitStore(resource);
-
- #endif
-
- splitMessage = splitStore -> getFirstSplit();
-
- if (splitMessage == NULL)
- {
- //
- // We have created the store after a start
- // split but no message was added yet.
- //
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: WARNING! SPLIT! The split store "
- << "is still empty.\n" << logofs_flush;
- #endif
-
- break;
- }
-
- //
- // Splits already aborted can't be in the
- // split store.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitMessage -> getState() == split_aborted)
- {
- *logofs << "handleSplit: PANIC! SPLIT! Found an "
- << "aborted split in store [" << resource
- << "].\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- #endif
-
- //
- // Check if there are more messages in the
- // store that can be aborted or if we have
- // exceeded the number of bytes we can send
- // for this iteration.
- //
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Checking closure "
- << "of the inner loop with " << bytes
- << " bytes to write and split state ["
- << DumpState(splitMessage -> getState())
- << "].\n" << logofs_flush;
- #endif
-
- if ((splitMessage -> getMode() == split_sync &&
- splitMessage -> getState() == split_added) ||
- (bytes <= 0 && splitMessage ->
- getState() != split_loaded))
- {
- break;
- }
-
- //
- // If the split was loaded at the remote
- // side abort it immediately.
- //
-
- if (splitMessage -> getState() == split_loaded)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Sending more data "
- << "for store [" << resource << "] with "
- << "a split to be aborted.\n"
- << logofs_flush;
- #endif
-
- if (handleSplitSend(encodeBuffer, resource, splits, bytes) < 0)
- {
- return -1;
- }
- }
- else if (bytes > 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Sending more data "
- << "for store [" << resource << "] with "
- << bytes << " bytes to send.\n"
- << logofs_flush;
- #endif
-
- if (handleSplitSend(encodeBuffer, resource, splits, bytes) < 0)
- {
- return -1;
- }
- }
-
- //
- // Check if the split store was deleted.
- //
-
- splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore == NULL)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Exiting from the "
- << "inner loop with split store [" << resource
- << "] destroyed.\n" << logofs_flush;
- #endif
-
- break;
- }
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplit: SPLIT! Completed handling splits "
- << "for store [" << resource << "] with " << bytes
- << " bytes still to send.\n" << logofs_flush;
- #endif
-
- //
- // Check if there is still a split to
- // send for the store just processed.
- //
-
- handleSplitPending(resource);
- }
- }
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splits == 0)
- {
- #ifdef PANIC
- *logofs << "handleSplit: PANIC! Function called but "
- << "no split message was sent.\n"
- << logofs_flush;
- #endif
-
- HandleCleanup();
- }
-
- *logofs << "handleSplit: SPLIT! Sent " << splits
- << " splits and " << total - bytes << " bytes for FD#" << fd_
- << " with " << clientStore_ -> getSplitTotalStorageSize()
- << " bytes and [" << clientStore_ -> getSplitTotalSize()
- << "] splits remaining.\n" << logofs_flush;
-
- *logofs << "handleSplit: SPLIT! The pending split flag is "
- << splitState_.pending << " with " << clientStore_ ->
- getSplitTotalSize() << " splits in the split stores.\n"
- << logofs_flush;
-
- clientStore_ -> dumpSplitStores();
-
- #endif
-
- return 1;
-}
-
-int ClientChannel::handleSplitSend(EncodeBuffer &encodeBuffer, int resource,
- int &splits, int &bytes)
-{
- #if defined(TEST) || defined(SPLIT)
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- Split *splitMessage = splitStore -> getFirstSplit();
-
- if (splitStore -> getResource() != resource ||
- splitMessage -> getResource() != resource)
- {
- #ifdef PANIC
- *logofs << "handleSplitSend: PANIC! The resource doesn't "
- << "match the split store.\n" << logofs_flush;
- #endif
-
- HandleCleanup();
- }
-
- *logofs << "handleSplitSend: SPLIT! Sending message "
- << "OPCODE#" << (unsigned) opcodeStore_ -> splitData
- << " for resource " << splitMessage -> getResource()
- << " with request " << splitMessage -> getRequest()
- << " position " << splitMessage -> getPosition()
- << " and " << bytes << " bytes to write.\n"
- << logofs_flush;
- #endif
-
- //
- // Use a special opcode to signal the other
- // side this is part of a split and not a
- // new message.
- //
-
- encodeBuffer.encodeOpcodeValue(opcodeStore_ -> splitData,
- clientCache_ -> opcodeCache);
-
- encodeBuffer.encodeCachedValue(resource, 8,
- clientCache_ -> resourceCache);
-
- int result = clientStore_ -> getSplitStore(resource) ->
- send(encodeBuffer, bytes);
-
- if (result < 0)
- {
- #ifdef PANIC
- *logofs << "handleSplit: PANIC! Error sending splits for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- cerr << "Error" << ": Error sending splits for FD#"
- << fd_ << ".\n";
-
- return -1;
- }
-
- //
- // Get the bits written and update the
- // statistics for this special opcode.
- //
-
- int bits = encodeBuffer.diffBits();
-
- #if defined(TEST) || defined(SPLIT)|| defined(OPCODES)
- *logofs << "handleSplitSend: SPLIT! Handled request OPCODE#"
- << (unsigned int) opcodeStore_ -> splitData << " ("
- << DumpOpcode(opcodeStore_ -> splitData) << ")" << " for FD#"
- << fd_ << " sequence none. 0 bytes in, " << bits << " bits ("
- << ((float) bits) / 8 << " bytes) out.\n" << logofs_flush;
- #endif
-
- statistics -> addRequestBits(opcodeStore_ -> splitData, 0, bits);
-
- bytes -= bits >> 3;
-
- splits++;
-
- if (result == 1)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitSend: SPLIT! Split at the head "
- << "of the list was completely transferred.\n"
- << logofs_flush;
- #endif
-
- //
- // The split at the head of the list was
- // completely transferred.
- //
-
- handleRestart(sequence_deferred, resource);
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleSplitSend: SPLIT! More data to send "
- << "for the split at the head of the list.\n"
- << logofs_flush;
- }
- #endif
-
- return result;
-}
-
-int ClientChannel::handleSplitChecksum(EncodeBuffer &encodeBuffer, T_checksum checksum)
-{
- //
- // Send the checksum only if the loading
- // or the saving of the message to the
- // persistent image cache is enabled.
- //
-
- if ((control -> ImageCacheEnableLoad == 1 ||
- control -> ImageCacheEnableSave == 1) &&
- (enableLoad_ == 1 || enableSave_ == 1))
- {
- encodeBuffer.encodeBoolValue(1);
-
- for (unsigned int i = 0; i < MD5_LENGTH; i++)
- {
- encodeBuffer.encodeValue((unsigned int) checksum[i], 8);
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitChecksum: SPLIT! Sent checksum "
- << "[" << DumpChecksum(checksum) << "].\n"
- << logofs_flush;
- #endif
-
- return 1;
- }
- else
- {
- encodeBuffer.encodeBoolValue(0);
-
- return 0;
- }
-}
-
-void ClientChannel::handleSplitPending()
-{
- #if defined(TEST) || defined(SPLIT)
-
- int previous = splitState_.pending;
-
- #endif
-
- if (clientStore_ -> getSplitTotalSize() == 0)
- {
- splitState_.pending = 0;
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitPending: SPLIT! Set the pending "
- << "split flag to " << splitState_.pending
- << " with split stores empty.\n"
- << logofs_flush;
- #endif
- }
- else
- {
- //
- // Loop through the stores to find if
- // there is any split that has become
- // ready.
- //
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitPending: WARNING! SPLIT! Looping to "
- << "find if there is any split pending.\n"
- << logofs_flush;
- #endif
-
- splitState_.pending = 0;
-
- T_list &splitList = splitResources_.getList();
-
- for (T_list::iterator j = splitList.begin();
- j != splitList.end(); j++)
- {
- int resource = *j;
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore != NULL)
- {
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpSplitStore(resource);
-
- #endif
-
- Split *splitMessage = splitStore -> getFirstSplit();
-
- if (splitMessage != NULL && canSendSplit(splitMessage) == 1)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitPending: SPLIT! Found a pending "
- << "split in store [" << resource << "].\n"
- << logofs_flush;
- #endif
-
- splitState_.pending = 1;
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitMessage -> getState() == split_loaded)
- {
- *logofs << "handleSplitPending: PANIC! SPLIT! Found a "
- << "loaded split in store [" << resource
- << "].\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- #endif
-
- break;
- }
- }
- }
-
- #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
- }
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitState_.pending != previous)
- {
- *logofs << "handleSplitPending: SPLIT! Pending state "
- << "changed from " << previous << " to "
- << splitState_.pending << ".\n"
- << logofs_flush;
- }
-
- #endif
-}
-
-int ClientChannel::handleSplitEvent(EncodeBuffer &encodeBuffer, Split *splitMessage)
-{
- SplitStore *splitStore;
-
- int resource = splitMessage -> getResource();
-
- #if defined(TEST) || defined(INFO)
-
- splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore == NULL)
- {
- #ifdef PANIC
- *logofs << "handleSplitEvent: PANIC! The split store can't "
- << "be NULL handling abort splits.\n"
- << logofs_flush;
- #endif
-
- HandleCleanup();
- }
- else if (splitMessage -> getState() != split_loaded)
- {
- *logofs << "handleSplitEvent: PANIC! Can't find the split "
- << "to be aborted.\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- #endif
-
- //
- // Send any split that it is possible to
- // abort until the store is either empty
- // or the next split can't be aborted.
- //
-
- if (proxy -> handleAsyncSwitch(fd_) < 0)
- {
- return -1;
- }
-
- while ((splitStore = clientStore_ ->
- getSplitStore(resource)) != NULL &&
- (splitMessage = splitStore -> getFirstSplit()) != NULL &&
- splitMessage -> getState() == split_loaded)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Aborting split with "
- << "checksum [" << DumpChecksum(splitMessage ->
- getChecksum()) << "] for resource " << resource
- << " at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- int any = 0;
-
- if (handleSplitSend(encodeBuffer, resource, any, any) < 0)
- {
- return -1;
- }
- }
-
- #if defined(TEST) || defined(SPLIT)
-
- if ((splitStore = clientStore_ ->
- getSplitStore(resource)) == NULL)
- {
- *logofs << "handleSplitEvent: SPLIT! The split store ["
- << resource << "] has been destroyed.\n"
- << logofs_flush;
- }
- else if ((splitMessage = splitStore ->
- getFirstSplit()) == NULL)
- {
- *logofs << "handleSplitEvent: SPLIT! The split store ["
- << resource << "] is empty.\n"
- << logofs_flush;
- }
- else if (splitMessage -> getState() != split_loaded)
- {
- *logofs << "handleSplitEvent: SPLIT! The split at the "
- << "head of store [" << resource << "] doesn't "
- << "need to be aborted.\n" << logofs_flush;
- }
-
- #endif
-
- return 1;
-}
-
-int ClientChannel::handleSplitEvent(DecodeBuffer &decodeBuffer)
-{
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Handling abort "
- << "split messages for FD#" << fd_ << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- // Since ProtoStep7 (#issue 108)
-
- //
- // Decode the information about the
- // message to be updated.
- //
-
- unsigned char resource;
-
- decodeBuffer.decodeCachedValue(resource, 8,
- serverCache_ -> resourceCache);
-
- unsigned int loaded;
-
- decodeBuffer.decodeBoolValue(loaded);
-
- unsigned char request;
- unsigned int size;
-
- if (loaded == 1)
- {
- decodeBuffer.decodeOpcodeValue(request, serverCache_ -> abortOpcodeCache);
-
- decodeBuffer.decodeValue(size, 32, 14);
- }
- else
- {
- request = 0;
- size = 0;
- }
-
- unsigned int value;
-
- md5_byte_t checksum[MD5_LENGTH];
-
- for (unsigned int i = 0; i < MD5_LENGTH; i++)
- {
- decodeBuffer.decodeValue(value, 8);
-
- checksum[i] = (unsigned char) value;
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Checking split "
- << "with checksum [" << DumpChecksum(checksum)
- << "] loaded " << loaded << " request " << (unsigned int)
- request << " compressed size " << size << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- Split *splitMessage = handleSplitFind(checksum, resource);
-
- if (splitMessage != NULL)
- {
- if (loaded == 1)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Marked split with "
- << "checksum [" << DumpChecksum(checksum) << "] "
- << "as [loaded] at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- splitMessage -> setState(split_loaded);
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitMessage -> compressedSize() != (int) size)
- {
- *logofs << "handleSplitEvent: WARNING! SPLIT! Updating "
- << "compressed data size from " << splitMessage ->
- compressedSize() << " to " << size << ".\n"
- << logofs_flush;
- }
-
- #endif
-
- splitMessage -> compressedSize(size);
-
- //
- // The splits to be aborted are checked by the split
- // store at the time we are going to send a new chunk
- // of split data. The splits must be strictly handled
- // in the same order as they were added to the split
- // store and the split we want to abort here may be
- // not at the head of the list.
- //
-
- if (splitMessage == clientStore_ ->
- getSplitStore(resource) -> getFirstSplit())
- {
- //
- // We don't need to flush this packet immediately.
- // The abort can be sent at any time to the remote
- // proxy. What's important is that we restart the
- // agent resource as soon as possible.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- T_timestamp startTs = getTimestamp();
-
- *logofs << "handleSplitEvent: SPLIT! Encoding abort "
- << "split events for FD#" << fd_ << " with "
- << "resource " << (unsigned) resource << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- if (proxy -> handleAsyncSplit(fd_, splitMessage) < 0)
- {
- return -1;
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Spent "
- << diffTimestamp(startTs, getTimestamp()) << " Ms "
- << "handling abort split events for FD#" << fd_
- << ".\n" << logofs_flush;
- #endif
-
- //
- // Check if we can clear the pending flag.
- //
-
- handleSplitPending();
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleSplitEvent: WARNING! SPLIT! Abort split "
- << "event not sent because not at the head "
- << "of the list.\n" << logofs_flush;
- }
- #endif
- }
- else
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: SPLIT! Marked split with "
- << "checksum [" << DumpChecksum(checksum) << "] "
- << "as [missed] at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- splitMessage -> setState(split_missed);
-
- //
- // Check if we can set the pending flag.
- //
-
- handleSplitPending(resource);
- }
- }
- else
- {
- //
- // The split report came after the split was already
- // sent or the split store deleted. If the message
- // had been loaded from disk by the remote side, we
- // need to update the compressed size in our message
- // store or the checksum will not match at the time
- // we will try to save the message store on disk.
- //
-
- if (loaded == 1 && size != 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitEvent: WARNING! SPLIT! Can't find "
- << "the split. Updating in the message store.\n"
- << logofs_flush;
- #endif
-
- MessageStore *store = clientStore_ -> getRequestStore(request);
-
- if (store != NULL)
- {
- store -> updateData(checksum, size);
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- #ifdef PANIC
- *logofs << "handleSplitEvent: PANIC! The message store "
- << "can't be null.\n" << logofs_flush;
- #endif
-
- HandleCleanup();
- }
- #endif
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleSplitEvent: WARNING! SPLIT! No need to "
- << "update the store with loaded " << loaded
- << " and compressed size " << size << ".\n"
- << logofs_flush;
- }
- #endif
- }
-
- return 1;
-}
-
-Split *ClientChannel::handleSplitFind(T_checksum checksum, int resource)
-{
- //
- // It can be that we handled all the splits,
- // restarted the resource and deleted the
- // store before the event could even reach
- // our side.
- //
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore != NULL)
- {
- Split *splitMessage;
-
- T_splits *splitList = splitStore -> getSplits();
-
- for (T_splits::iterator i = splitList -> begin();
- i != splitList -> end(); i++)
- {
- splitMessage = (*i);
-
- if (splitMessage -> getChecksum() != NULL)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitFind: SPLIT! Comparing with message ["
- << DumpChecksum(splitMessage -> getChecksum())
- << "].\n" << logofs_flush;
- #endif
-
- if (memcmp(checksum, splitMessage -> getChecksum(), MD5_LENGTH) == 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitFind: SPLIT! Located split for "
- << "checksum [" << DumpChecksum(checksum) << "] "
- << "in store [" << splitStore -> getResource()
- << "].\n" << logofs_flush;
- #endif
-
- return splitMessage;
- }
- }
- }
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleSplitFind: WARNING! SPLIT! The split store "
- << "was already deleted.\n" << logofs_flush;
- }
- #endif
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleSplitFind: WARNING! SPLIT! Can't find the "
- << "split for checksum [" << DumpChecksum(checksum)
- << "].\n" << logofs_flush;
- #endif
-
- return NULL;
-}
-
-int ClientChannel::handleRestart(T_sequence_mode mode, int resource)
-{
- //
- // The agent must send a start-split message, followed by the
- // X messages that may be optionally split by the proxy. Usu-
- // ally, in the middle of a start-split/end-split sequence is
- // a single PutImage() or PutPackedImage(), that, in turn,
- // can generate multiple partial requests, like a SetUnpack-
- // Colormap() and SetUnpackAlpha() followed by the image that
- // must be transferred. Multiple requests may be also genera-
- // ted because the maximum size of a X request has been exce-
- // eded, so that Xlib has divided the single image in multi-
- // ple sub-image requests. The agent doesn't need to take care
- // of that, except tracking the result of the split operation.
- //
- // By monitoring the notify events sent by the proxy, the
- // agent will have to implement its own strategy to deal with
- // its resources (for example its clients). For example:
- //
- // - It will issue a new image request and suspend a client
- // if the image was not entirely sent in the main X oputput
- // stream.
- //
- // - It will choose to commit or discard the messages after
- // they are recomposed at the remote side. The set of mes-
- // sages that will have to be committed will include all
- // messages that were part of the split (the colormap, the
- // alpha channel).
- //
- // - It will restart its own client, in the case it had been
- // suspended.
- //
- // A more useful strategy would be to replace the original im-
- // age with a tiny 'placeholder' if a split took place, and
- // synchronize the content of the drawable at later time. This
- // is generally referred as 'lazy encoding'.
- //
- // The agent will be able to identify the original split ope-
- // ration (the one marked with the start-spit) by the small
- // integer number (0-255) referred to as the 'resource' field.
- //
- // Before the proxy will be able to report the status of the
- // split, the agent will have to close the sequence by issueing
- // an end-split. The proxy will then report the result of the
- // operation, so that the agent will have the option of suspend-
- // ing the client or marking the drawable as dirty and take
- // care of synchronizing it at later time.
- //
- // One of the following cases may be encountered:
- //
- // notify_no_split: All messages were sent in the main out-
- // put stream, so that no split actually
- // took place.
- //
- // notify_start_split: One or more messages were split, so,
- // at discrection of the agent, the client
- // may be suspended until the transferral
- // is completed.
- //
- // notify_commit_split: One of the requests that made up the
- // split was recomposed. The agent should
- // either commit the given request or tell
- // the proxy to discard it.
- //
- // notify_end_split: The split was duly completed. The agent
- // can restart the client.
- //
- // notify_empty_split: No more split operation are pending.
- // The agent can use this information to
- // implement specific strategies requiring
- // that all messages have been recomposed
- // at the remote end, like updating the
- // drawables that were not synchronized
- // because of the lazy encoding.
- //
- // By checking the split and commit store we can determine if we
- // need to send a new notification event to the agent. There can
- // be four different cases:
- //
- // - If the split store is not null and not empty, we are still
- // in the middle of a split.
- //
- // - If the commit store is not empty, we completely recomposed
- // a full message and can send a new commit notify.
- //
- // - If the split store has become empty, we recomposed all the
- // messages added for the given resource, and so will be able
- // to restart the resource.
- //
- // - If no more messages are in the split stores, we can notify
- // an empty split event to the agent.
- //
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Handling ["
- << (mode == sequence_immediate ? "immediate" : "deferred")
- << "] restart events for resource " << resource << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- if (mode == sequence_immediate)
- {
- //
- // We have received an end-split request. If the store
- // was not deleted already, we mark the last split added
- // as the one ending the row for this resource. If the
- // commit() function returns 0 it means that the split
- // store is either empty or that we did not add any split
- // for this resource. This is because when connected to
- // an old proxy version we only have a single store for
- // all the resources.
- //
- // It can happen that all the split messages that were
- // originally appended to the list were completely sent
- // before our client had the chance of ending the split
- // sequence. In this case the split store will be empty
- // or already deleted and so we will be able to restart
- // the resource.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitStore == NULL)
- {
- *logofs << "handleRestart: WARNING! SPLIT! Split store ["
- << resource << "] was already deleted.\n"
- << logofs_flush;
- }
- else
- {
- clientStore_ -> dumpSplitStore(resource);
- }
-
- #endif
-
- if (splitStore == NULL || splitStore -> getSize() == 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Immediate agent split event "
- << "TYPE#" << (unsigned) opcodeStore_ -> noSplitNotify
- << " [no split] with resource " << resource
- << " at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- if (handleNotify(notify_no_split, sequence_immediate,
- resource, nothing, nothing) < 0)
- {
- return -1;
- }
- }
- else
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Immediate agent split event "
- << "TYPE#" << (unsigned) opcodeStore_ -> startSplitNotify
- << " [start split] with resource " << resource
- << " at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- #endif
-
- if (handleNotify(notify_start_split, sequence_immediate,
- resource, nothing, nothing) < 0)
- {
- return -1;
- }
- }
- }
- else
- {
- //
- // We have completely transferred a message
- // that was put in the split store.
- //
- // The id of the resource can be different
- // than the index of the store if we are
- // connected to an old proxy.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitStore == NULL)
- {
- #ifdef PANIC
- *logofs << "handleRestart: PANIC! The split store can't "
- << "be NULL handling deferred restart events.\n"
- << logofs_flush;
- #endif
-
- HandleCleanup();
- }
- else
- {
- clientStore_ -> dumpSplitStore(resource);
- }
-
- #endif
-
- CommitStore *commitStore = clientStore_ -> getCommitStore();
-
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpCommitStore();
-
- #endif
-
- //
- // Check if there is any commit to notify.
- //
-
- Split *split;
-
- T_splits *commitList = commitStore -> getSplits();
-
- for (T_splits::iterator i = commitList -> begin();
- i != commitList -> end(); i++)
- {
- split = *i;
-
- if (split -> getState() != split_notified)
- {
- #if defined(TEST) || defined(SPLIT)
-
- if (split -> getResource() != resource)
- {
- #ifdef PANIC
- *logofs << "handleSplitSend: PANIC! The resource doesn't "
- << "match the split store.\n" << logofs_flush;
- #endif
-
- HandleCleanup();
- }
-
- #endif
-
- int request = split -> getRequest();
- int position = split -> getPosition();
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Deferred agent split event "
- << "TYPE#" << (unsigned) opcodeStore_ -> commitSplitNotify
- << " [commit split] with resource " << resource << " request "
- << request << " position " << position << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- if (handleNotify(notify_commit_split, sequence_deferred,
- resource, request, position) < 0)
- {
- return -1;
- }
-
- //
- // Don't send the notification again.
- //
-
- split -> setState(split_notified);
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleRestart: SPLIT! Split for request "
- << split -> getRequest() << " and position "
- << split -> getPosition() << " was already "
- << "notified.\n" << logofs_flush;
- }
- #endif
- }
-
- //
- // Don't send the end split if we are still
- // in the middle of a start-split/end-split
- // sequence. We'll send a no-split at the
- // time the end-split is received.
- //
-
- if (splitStore -> getSize() == 0 &&
- splitStore -> getResource() != splitState_.resource)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Deferred agent split event "
- << "TYPE#" << (unsigned) opcodeStore_ -> endSplitNotify
- << " [end split] with resource " << resource << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- if (handleNotify(notify_end_split, sequence_deferred,
- resource, nothing, nothing) < 0)
- {
- return -1;
- }
- }
- #if defined(TEST) || defined(SPLIT)
- else if (splitStore -> getSize() == 0 &&
- splitStore -> getResource() == splitState_.resource)
- {
- *logofs << "handleRestart: SPLIT! WARNING! The split store "
- << "for resource " << resource << " was emptied in the "
- << "split sequence at " << strMsTimestamp() << ".\n"
- << logofs_flush;
- }
- #endif
- }
-
- //
- // Remove the split store if it's empty.
- //
-
- if (splitStore != NULL && splitStore -> getSize() == 0 &&
- splitStore -> getResource() != splitState_.resource)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Removing the split store ["
- << resource << "] at " << strMsTimestamp()
- << ".\n" << logofs_flush;
- #endif
-
- handleSplitStoreRemove(&splitResources_, resource);
-
- if (clientStore_ -> getSplitTotalSize() == 0)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! Deferred agent split event "
- << "TYPE#" << (unsigned) opcodeStore_ -> emptySplitNotify
- << " [empty split] for FD#" << fd_ << " at "
- << strMsTimestamp() << ".\n" << logofs_flush;
- #endif
-
- if (handleNotify(notify_empty_split, sequence_deferred,
- nothing, nothing, nothing) < 0)
- {
- return -1;
- }
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleRestart: SPLIT! There are " << clientStore_ ->
- getSplitTotalSize() << " messages and " << clientStore_ ->
- getSplitTotalStorageSize() << " bytes to send in "
- << "the split stores.\n" << logofs_flush;
-
- if ((clientStore_ -> getSplitTotalSize() != 0 &&
- clientStore_ -> getSplitTotalStorageSize() == 0) ||
- (clientStore_ -> getSplitTotalSize() == 0 &&
- clientStore_ -> getSplitTotalStorageSize() != 0))
- {
- #ifdef PANIC
- *logofs << "handleRestart: PANIC! Inconsistency detected "
- << "while handling the split stores.\n"
- << logofs_flush;
- #endif
-
- HandleCleanup();
- }
-
- #endif
- }
-
- return 1;
-}
-
-int ClientChannel::handleTaintLameRequest(unsigned char &opcode, const unsigned char *&buffer,
- unsigned int &size)
-{
- //
- // Test the efficiency of the encoding
- // without these RENDER requests.
- //
-
- if (opcode == opcodeStore_ -> renderExtension &&
- (*(buffer + 1) == X_RenderCompositeGlyphs8 ||
- *(buffer + 1) == X_RenderCompositeGlyphs16 ||
- *(buffer + 1) == X_RenderCompositeGlyphs32 ||
- *(buffer + 1) == X_RenderAddGlyphs ||
- *(buffer + 1) == X_RenderTrapezoids))
- {
- #ifdef TEST
- *logofs << "handleTaintLameRequest: Tainting request "
- << "OPCODE#" << (unsigned int) opcode << " MINOR#"
- << (unsigned int) *(buffer + 1) << " for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- opcode = X_NoOperation;
-
- return 1;
- }
-
- return 0;
-}
-
-int ClientChannel::handleTaintSyncRequest(unsigned char &opcode, const unsigned char *&buffer,
- unsigned int &size)
-{
- //
- // Should short-circuit other common replies
- // whose values could be queried only once.
- // Examples are X_InterAtom, X_ListExtension
- // and X_QueryExtension.
- //
-
- if (taintCounter_ >= control -> TaintThreshold)
- {
- #ifdef DEBUG
- *logofs << "handleTaintSyncRequest: Reset taint counter after "
- << taintCounter_ << " replies managed.\n"
- << logofs_flush;
- #endif
-
- taintCounter_ = 0;
-
- return 0;
- }
-
- //
- // Check if we are rolling the counter.
- // The client sequence number has not
- // been incremented yet in the loop.
- //
-
- unsigned int sequence = (clientSequence_ + 1) & 0xffff;
-
- #ifdef DEBUG
- *logofs << "handleTaintSyncRequest: Opcode is " << (unsigned) opcode
- << " expected client sequence is " << sequence
- << ".\n" << logofs_flush;
- #endif
-
- if (sequence == 0xffff)
- {
- return 0;
- }
-
- unsigned short t1;
- unsigned char t2;
-
- //
- // Check if there is a previous reply
- // pending.
- //
-
- if (sequenceQueue_.peek(t1, t2) != 0)
- {
- #ifdef DEBUG
- *logofs << "handleTaintSyncRequest: Skipping taint of reply due to "
- << "pending request OPCODE#" << t1 << " with sequence "
- << (unsigned int) t2 << ".\n" << logofs_flush;
- #endif
-
- return 0;
- }
-
- #ifdef DEBUG
- *logofs << "handleTaintSyncRequest: Suppressing get input focus "
- << "request for FD#" << fd_ << " with sequence "
- << sequence << ".\n" << logofs_flush;
- #endif
-
- unsigned char *reply = writeBuffer_.addMessage(32);
-
- *(reply + 0) = X_Reply;
-
- PutUINT(sequence, reply + 2, bigEndian_);
-
- PutULONG(0, reply + 4, bigEndian_);
-
- //
- // Set revert-to to none.
- //
-
- *(reply + 1) = 0;
-
- //
- // Set focus to none.
- //
-
- PutULONG(0, reply + 8, bigEndian_);
-
- //
- // Save the sequence number, not incremented
- // yet, we used to auto-generate this reply.
- //
-
- lastSequence_ = clientSequence_ + 1;
-
- #ifdef TEST
- *logofs << "handleTaintSyncRequest: Registered " << lastSequence_
- << " as last auto-generated sequence number.\n"
- << logofs_flush;
- #endif
-
- //
- // Taint the request to a X_NoOperation.
- //
-
- opcode = X_NoOperation;
-
- //
- // We may assume that the client has finished
- // drawing and flush immediately, even if this
- // seems to perceively affect the performance.
- //
- // priority_++;
- //
-
- if (handleFlush(flush_if_any) < 0)
- {
- return -1;
- }
-
- taintCounter_++;
-
- return 1;
-}
-
-int ClientChannel::handleTaintSyncError(unsigned char opcode)
-{
- if (control -> TaintReplies > 0)
- {
- //
- // By enabling short-circuiting of replies
- // some window managers can get confused
- // by some otherwise innocuous X errors.
- //
-
- if (opcode == X_GrabKey || opcode == X_ReparentWindow ||
- opcode == X_ConfigureWindow)
- {
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleTaintSyncError: WARNING! Suppressed error "
- << "on OPCODE#" << (unsigned int) opcode << " for FD#"
- << fd_ << " sequence " << lastSequence_ << " (real was "
- << serverSequence_ << ").\n" << logofs_flush;
- #endif
-
- return 1;
- }
- }
-
- return 0;
-}
-
-int ClientChannel::handleNotify(T_notification_type type, T_sequence_mode mode,
- int resource, int request, int position)
-{
- if (finish_ == 1)
- {
- #if defined(TEST) || defined(INFO)
- *logofs << "handleNotify: Discarding notification on "
- << "channel for FD#" << fd_ << ".\n"
- << logofs_flush;
- #endif
-
- return 0;
- }
-
- //
- // Add a new message to the write buffer.
- //
-
- unsigned char *event = writeBuffer_.addMessage(32);
-
- //
- // Event is ClientMessage, atom and
- // window are 0, format is 32.
- //
-
- *(event + 0) = ClientMessage;
-
- PutULONG(0, event + 4, bigEndian_);
- PutULONG(0, event + 8, bigEndian_);
-
- *(event + 1) = 32;
-
- //
- // If the event follows immediately the request (that is the
- // sequence mode is 'immediate') then the sequence number is
- // the one of the last request, else it should be the last
- // sequence number encoded by peer proxy but, as we are ins-
- // erting events in the stream, we must ensure that the se-
- // quence we send is not less than the last sequence we have
- // auto-generated.
- //
-
- if (mode == sequence_immediate)
- {
- //
- // Save the sequence number we used
- // to auto-generate this event.
- //
-
- lastSequence_ = clientSequence_;
-
- #if defined(TEST) || defined(INFO)
- *logofs << "handleNotify: Registered " << lastSequence_
- << " as last auto-generated sequence number.\n"
- << logofs_flush;
- #endif
- }
- else
- {
- if (serverSequence_ > lastSequence_)
- {
- #ifdef DEBUG
- *logofs << "handleNotify: Updating last event's sequence "
- << lastSequence_ << " to X server's sequence number "
- << serverSequence_ << " for FD#" << fd_ << ".\n"
- << logofs_flush;
- #endif
-
- lastSequence_ = serverSequence_;
- }
- #ifdef DEBUG
- else if (serverSequence_ < lastSequence_)
- {
- //
- // Use our last auto-generated sequence.
- //
-
- *logofs << "handleNotify: Tainting sequence number "
- << serverSequence_ << " to last event's sequence "
- << lastSequence_ << " for FD#" << fd_ << ".\n"
- << logofs_flush;
- }
- #endif
- }
-
- PutUINT(lastSequence_, event + 2, bigEndian_);
-
- //
- // Be sure we set to void the fields that
- // are not significant for the specific
- // notification message.
- //
-
- PutULONG(nothing, event + 16, bigEndian_);
- PutULONG(nothing, event + 20, bigEndian_);
- PutULONG(nothing, event + 24, bigEndian_);
-
- switch (type)
- {
- case notify_no_split:
- {
- PutULONG(opcodeStore_ -> noSplitNotify,
- event + 12, bigEndian_);
-
- PutULONG(resource, event + 16, bigEndian_);
-
- break;
- }
- case notify_start_split:
- {
- PutULONG(opcodeStore_ -> startSplitNotify,
- event + 12, bigEndian_);
-
- PutULONG(resource, event + 16, bigEndian_);
-
- break;
- }
- case notify_commit_split:
- {
- PutULONG(opcodeStore_ -> commitSplitNotify,
- event + 12, bigEndian_);
-
- PutULONG(resource, event + 16, bigEndian_);
-
- PutULONG(request, event + 20, bigEndian_);
-
- PutULONG(position, event + 24, bigEndian_);
-
- break;
- }
- case notify_end_split:
- {
- PutULONG(opcodeStore_ -> endSplitNotify,
- event + 12, bigEndian_);
-
- PutULONG(resource, event + 16, bigEndian_);
-
- break;
- }
- case notify_empty_split:
- {
- PutULONG(opcodeStore_ -> emptySplitNotify,
- event + 12, bigEndian_);
- break;
- }
- default:
- {
- #ifdef PANIC
- *logofs << "handleNotify: PANIC! Unrecognized notify "
- << "TYPE#" << type << ".\n"
- << logofs_flush;
- #endif
-
- return -1;
- }
- }
-
- #if defined(TEST) || defined(INFO) || defined (SPLIT)
-
- *logofs << "handleNotify: Sending "
- << (mode == sequence_immediate ? "immediate " : "deferred ")
- << "agent notify event TYPE#" << GetULONG(event + 12, bigEndian_)
- << logofs_flush;
-
- if (resource != nothing)
- {
- *logofs << " with resource " << GetULONG(event + 16, bigEndian_)
- << logofs_flush;
-
- if (request != nothing && position != nothing)
- {
- *logofs << " request " << GetULONG(event + 20, bigEndian_)
- << " position " << GetULONG(event + 24, bigEndian_)
- << logofs_flush;
- }
- }
-
- *logofs << ".\n" << logofs_flush;
-
- #endif
-
- //
- // Send the notification now.
- //
-
- if (handleFlush(flush_if_any) < 0)
- {
- return -1;
- }
-
- return 1;
-}
-
-int ClientChannel::handleCommitSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- //
- // Get the data of the request to be
- // committed.
- //
-
- unsigned char request = *(buffer + 5);
-
- MessageStore *store = clientStore_ -> getRequestStore(request);
-
- if (store == NULL)
- {
- #ifdef PANIC
- *logofs << "handleCommitSplitRequest: PANIC! Can't commit split for "
- << "request OPCODE#" << (unsigned int) request
- << ". No message store found.\n"
- << logofs_flush;
- #endif
-
- cerr << "Error" << ": Can't commit split for request "
- << "OPCODE#" << (unsigned int) request
- << ". No message store found.\n";
-
- return -1;
- }
-
- //
- // The position in cache of the message
- // to commit. Encode it as difference in
- // respect to the last encoded value.
- //
-
- unsigned int position = GetULONG(buffer + 8, bigEndian_);
-
- unsigned char resource = *(buffer + 1);
- unsigned int commit = *(buffer + 4);
-
- #if defined(TEST) || defined(SPLIT)
-
- if (commit == 1)
- {
- *logofs << "handleCommitSplitRequest: SPLIT! Committing request "
- << "OPCODE#" << (unsigned) request << " at position "
- << position << " for FD#" << fd_ << " with resource "
- << (unsigned) resource << ".\n" << logofs_flush;
- }
- else
- {
- *logofs << "handleCommitSplitRequest: SPLIT! Discarding request "
- << "OPCODE#" << (unsigned) request << " at position "
- << position << " for FD#" << fd_ << " with resource "
- << (unsigned) resource << ".\n" << logofs_flush;
- }
-
- #endif
-
- encodeBuffer.encodeOpcodeValue(request, clientCache_ -> opcodeCache);
-
- int diffCommit = position - splitState_.commit;
-
- splitState_.commit = position;
-
- encodeBuffer.encodeValue(diffCommit, 32, 5);
-
- //
- // Send the resource id and the commit
- // flag.
- //
-
- encodeBuffer.encodeCachedValue(resource, 8,
- clientCache_ -> resourceCache);
-
- encodeBuffer.encodeBoolValue(commit);
-
- //
- // Remove the split from the split queue.
- //
-
- Split *split = handleSplitCommitRemove(request, resource, splitState_.commit);
-
- if (split == NULL)
- {
- return -1;
- }
-
- clientStore_ -> getCommitStore() -> update(split);
-
- //
- // Free the split.
- //
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleCommitSplitRequest: SPLIT! Freeing up the "
- << "committed split.\n" << logofs_flush;
- #endif
-
- delete split;
-
- return 1;
-}
-
-int ClientChannel::handleAbortSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- unsigned char resource = *(buffer + 1);
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleAbortSplitRequest: SPLIT! Handling abort split "
- << "request for FD#"<< fd_ << " and resource "
- << (unsigned int) resource << ".\n"
- << logofs_flush;
- #endif
-
- encodeBuffer.encodeCachedValue(resource, 8,
- clientCache_ -> resourceCache);
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore == NULL)
- {
- #ifdef WARNING
- *logofs << "handleAbortSplitRequest: WARNING! SPLIT! The split "
- << "store [" << (unsigned int) resource << "] "
- << "is already empty.\n" << logofs_flush;
- #endif
-
- return 0;
- }
-
- //
- // Loop through the messages in the split
- // store and discard from the memory cache
- // the messages that are still incomplete.
- // Then remove the message from the split
- // store.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpSplitStore(resource);
-
- #endif
-
- int splits = 0;
-
- Split *splitMessage;
-
- for (;;)
- {
- splitMessage = splitStore -> getFirstSplit();
-
- if (splitMessage == NULL)
- {
- //
- // Check if we had created the store
- // but no message was added yet.
- //
-
- #ifdef WARNING
-
- if (splits == 0)
- {
- *logofs << "handleAbortSplitRequest: WARNING! SPLIT! The "
- << "split store [" << (unsigned int) resource
- << "] is unexpectedly empty.\n"
- << logofs_flush;
- }
-
- #endif
-
- break;
- }
-
- //
- // Splits already aborted can't be in the
- // split store.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitMessage -> getState() == split_aborted)
- {
- *logofs << "handleAbortSplitRequest: PANIC! SPLIT! Found an "
- << "aborted split in store [" << (unsigned int) resource
- << "].\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- #endif
-
- if (splitMessage -> getAction() == IS_HIT)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleAbortSplitRequest: SPLIT! Removing the "
- << "split from the memory cache.\n"
- << logofs_flush;
- #endif
-
- splitMessage -> getStore() -> remove(splitMessage -> getPosition(),
- use_checksum, discard_data);
- }
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleAbortSplitRequest: SPLIT! Removing the "
- << "split from the split store.\n"
- << logofs_flush;
- #endif
-
- splitMessage = splitStore -> pop();
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleAbortSplitRequest: SPLIT! Freeing up the "
- << "aborted split.\n" << logofs_flush;
- #endif
-
- delete splitMessage;
-
- splits++;
- }
-
- //
- // If the start-split/end-split sequence
- // was closed, send the notification now,
- // else wait for the end-split.
- //
-
- if (resource != splitState_.resource)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleAbortSplitRequest: SPLIT! Sending the "
- << "deferred [end split] event.\n"
- << logofs_flush;
- #endif
-
- handleRestart(sequence_deferred, resource);
- }
- #if defined(TEST) || defined(SPLIT)
- else
- {
- *logofs << "handleAbortSplitRequest: WARNING! SPLIT! Still "
- << "waiting for the closure of the split "
- << "sequence.\n" << logofs_flush;
- }
- #endif
-
- //
- // Check if there is any other store
- // having splits to send.
- //
-
- handleSplitPending();
-
- return (splits > 0);
-}
-
-int ClientChannel::handleFinishSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- unsigned char resource = *(buffer + 1);
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleFinishSplitRequest: SPLIT! Handling finish split "
- << "request for FD#"<< fd_ << " and resource "
- << (unsigned int) resource << ".\n"
- << logofs_flush;
- #endif
-
- encodeBuffer.encodeCachedValue(resource, 8,
- clientCache_ -> resourceCache);
-
- //
- // We need to get the protocol statistics
- // for the finish message we are handling
- // here because sending a new split will
- // reset the bits counter.
- //
-
- int bits = encodeBuffer.diffBits();
-
- statistics -> addRequestBits(opcode, size << 3, bits);
-
- SplitStore *splitStore = clientStore_ -> getSplitStore(resource);
-
- if (splitStore == NULL)
- {
- #ifdef WARNING
- *logofs << "handleFinishSplitRequest: WARNING! SPLIT! The split "
- << "store [" << (unsigned int) resource << "] "
- << "is already empty.\n" << logofs_flush;
- #endif
-
- return 0;
- }
-
- //
- // Send all the split queued for the given
- // resource until the split store becomes
- // empty.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpSplitStore(resource);
-
- #endif
-
- Split *splitMessage;
-
- int total = MESSAGE_DATA_LIMIT;
-
- int bytes = total;
- int splits = 0;
-
- for (;;)
- {
- splitMessage = splitStore -> getFirstSplit();
-
- if (splitMessage == NULL)
- {
- //
- // We have presumably created the store
- // after a start split but no message
- // was added yet.
- //
-
- #ifdef WARNING
- *logofs << "handleFinishSplitRequest: WARNING! SPLIT! The "
- << "split store [" << (unsigned int) resource
- << "] is unexpectedly empty.\n"
- << logofs_flush;
- #endif
-
- break;
- }
-
- //
- // Splits already aborted can't be in the
- // split store.
- //
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitMessage -> getState() == split_aborted)
- {
- *logofs << "handleFinishSplitRequest: PANIC! SPLIT! Found an "
- << "aborted split in store [" << (unsigned int) resource
- << "].\n" << logofs_flush;
-
- HandleCleanup();
- }
-
- *logofs << "handleFinishSplitRequest: SPLIT! Sending more "
- << "data for store [" << (unsigned int) resource
- << "].\n" << logofs_flush;
- #endif
-
- if (handleSplitSend(encodeBuffer, resource, splits, bytes) < 0)
- {
- return -1;
- }
-
- //
- // Check if the split store was deleted.
- //
-
- if (clientStore_ -> getSplitStore(resource) == NULL)
- {
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleFinishSplitRequest: SPLIT! Exiting "
- << "from the finish loop with split store ["
- << (unsigned int) resource << "] destroyed.\n"
- << logofs_flush;
- #endif
-
- break;
- }
- }
-
- //
- // Check if there is any other store
- // having splits to send.
- //
-
- handleSplitPending();
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleFinishSplitRequest: SPLIT! Sent " << splits
- << " splits and " << total - bytes << " bytes for FD#" << fd_
- << " with " << clientStore_ -> getSplitTotalStorageSize()
- << " bytes and [" << clientStore_ -> getSplitTotalSize()
- << "] splits remaining.\n" << logofs_flush;
- #endif
-
- return (splits > 0);
-}
-
-int ClientChannel::handleConfiguration()
-{
- #ifdef TEST
- *logofs << "ClientChannel: Setting new buffer parameters.\n"
- << logofs_flush;
- #endif
-
- readBuffer_.setSize(control -> ClientInitialReadSize,
- control -> ClientMaximumBufferSize);
-
- writeBuffer_.setSize(control -> TransportXBufferSize,
- control -> TransportXBufferThreshold,
- control -> TransportMaximumBufferSize);
-
- transport_ -> setSize(control -> TransportXBufferSize,
- control -> TransportXBufferThreshold,
- control -> TransportMaximumBufferSize);
-
- return 1;
-}
-
-int ClientChannel::handleFinish()
-{
- #ifdef TEST
- *logofs << "ClientChannel: Finishing channel for FD#"
- << fd_ << ".\n" << logofs_flush;
- #endif
-
- congestion_ = 0;
- priority_ = 0;
-
- finish_ = 1;
-
- taintCounter_ = 0;
-
- splitState_.resource = nothing;
- splitState_.pending = 0;
- splitState_.commit = 0;
- splitState_.mode = split_none;
-
- transport_ -> finish();
-
- return 1;
-}
-
-//
-// If differential compression is disabled then use the
-// most simple encoding but handle the image requests
-// and the X_ListExtensions and X_QueryExtension messa-
-// ges (needed to detect the opcode of the shape or the
-// other extensions) in the usual way.
-//
-
-int ClientChannel::handleFastReadRequest(EncodeBuffer &encodeBuffer, const unsigned char &opcode,
- const unsigned char *&buffer, const unsigned int &size)
-{
- //
- // All the NX requests are handled in the
- // main message loop. The X_PutImage can
- // be handled here only if the split was
- // not requested (since ProtoStep7 #issue 108).
- //
-
- if ((opcode >= X_NXFirstOpcode && opcode <= X_NXLastOpcode) ||
- (opcode == X_PutImage && splitState_.resource != nothing) ||
- opcode == X_ListExtensions ||
- opcode == X_QueryExtension)
- {
- return 0;
- }
-
- #ifdef DEBUG
- *logofs << "handleFastReadRequest: Encoding raw request OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_
- << " with size " << size << ".\n"
- << logofs_flush;
- #endif
-
- encodeBuffer.encodeMemory(buffer, size);
-
- //
- // Put request on the fast track
- // if it needs a reply.
- //
-
- switch (opcode)
- {
- case X_GetAtomName:
- case X_GetGeometry:
- case X_GetInputFocus:
- case X_GetModifierMapping:
- case X_GetKeyboardMapping:
- case X_GetProperty:
- case X_GetSelectionOwner:
- case X_GrabPointer:
- case X_GrabKeyboard:
- case X_ListExtensions:
- case X_ListFonts:
- case X_LookupColor:
- case X_AllocNamedColor:
- case X_QueryPointer:
- case X_GetWindowAttributes:
- case X_QueryTree:
- case X_QueryBestSize:
- case X_QueryColors:
- case X_QueryFont:
- case X_TranslateCoords:
- case X_GetImage:
- case X_GetPointerMapping:
- case X_GetKeyboardControl:
- case X_InternAtom:
- case X_AllocColor:
- {
- sequenceQueue_.push(clientSequence_, opcode);
-
- priority_++;
-
- break;
- }
- default:
- {
- break;
- }
- }
-
- int bits = encodeBuffer.diffBits();
-
- #if defined(TEST) || defined(OPCODES)
-
- *logofs << "handleFastReadRequest: Handled raw request OPCODE#"
- << (unsigned int) opcode << " (" << DumpOpcode(opcode) << ")"
- << " for FD#" << fd_ << " sequence " << clientSequence_
- << ". " << size << " bytes in, " << bits << " bits ("
- << ((float) bits) / 8 << " bytes) out.\n" << logofs_flush;
-
- #endif
-
- statistics -> addRequestBits(opcode, size << 3, bits);
-
- if (opcode == opcodeStore_ -> renderExtension)
- {
- statistics -> addRenderRequestBits(*(buffer + 1), size << 3, bits);
- }
-
- return 1;
-}
-
-int ClientChannel::handleFastWriteReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
- unsigned char *&buffer, unsigned int &size)
-{
- if ((opcode >= X_NXFirstOpcode &&
- opcode <= X_NXLastOpcode) ||
- opcode == X_ListExtensions ||
- opcode == X_QueryExtension)
- {
- return 0;
- }
-
- #ifdef DEBUG
- *logofs << "handleFastWriteReply: Decoding raw reply OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_
- << ".\n" << logofs_flush;
- #endif
-
- buffer = writeBuffer_.addMessage(8);
-
- #ifndef __sun
-
- unsigned int *next = (unsigned int *) decodeBuffer.decodeMemory(8);
-
- *((unsigned int *) buffer) = *next++;
- *((unsigned int *) (buffer + 4)) = *next;
-
- #else /* #ifndef __sun */
-
- memcpy(buffer, decodeBuffer.decodeMemory(8), 8);
-
- #endif /* #ifndef __sun */
-
- size = 32 + (GetULONG(buffer + 4, bigEndian_) << 2);
-
- writeBuffer_.registerPointer(&buffer);
-
- if (writeBuffer_.getAvailable() < size - 8 ||
- (int) size >= control -> TransportFlushBufferSize)
- {
- #ifdef DEBUG
- *logofs << "handleFastWriteReply: Using scratch buffer for OPCODE#"
- << (unsigned int) opcode << " with size " << size << " and "
- << writeBuffer_.getLength() << " bytes in buffer.\n"
- << logofs_flush;
- #endif
-
- writeBuffer_.removeMessage(8);
-
- buffer = writeBuffer_.addScratchMessage(((unsigned char *)
- decodeBuffer.decodeMemory(size - 8)) - 8, size);
- }
- else
- {
- writeBuffer_.addMessage(size - 8);
-
- #ifndef __sun
-
- if (size == 32)
- {
- next = (unsigned int *) decodeBuffer.decodeMemory(size - 8);
-
- for (int i = 8; i < 32; i += sizeof(unsigned int))
- {
- *((unsigned int *) (buffer + i)) = *next++;
- }
- }
- else
- {
- memcpy(buffer + 8, decodeBuffer.decodeMemory(size - 8), size - 8);
- }
-
- #else /* #ifndef __sun */
-
- memcpy(buffer + 8, decodeBuffer.decodeMemory(size - 8), size - 8);
-
- #endif /* #ifndef __sun */
- }
-
- writeBuffer_.unregisterPointer();
-
- //
- // We don't need to write our local sequence
- // number. Replies are always sent with the
- // original X server's sequence number.
- //
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleFastWriteReply: Handled raw reply OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_ << " with sequence "
- << serverSequence_ << ". Output size is " << size << ".\n"
- << logofs_flush;
- #endif
-
- #ifdef DEBUG
- *logofs << "handleFastWriteReply: Length of sequence queue is "
- << sequenceQueue_.length() << ".\n" << logofs_flush;
- #endif
-
- statistics -> addRepliedRequest(opcode);
-
- handleFlush(flush_if_needed);
-
- return 1;
-}
-
-int ClientChannel::handleFastWriteEvent(DecodeBuffer &decodeBuffer, unsigned char &opcode,
- unsigned char *&buffer, unsigned int &size)
-{
- #ifdef DEBUG
- *logofs << "handleFastWriteEvent: Decoding raw "
- << (opcode == X_Error ? "error" : "event") << " OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_
- << ".\n" << logofs_flush;
- #endif
-
- size = 32;
-
- buffer = writeBuffer_.addMessage(size);
-
- #ifndef __sun
-
- unsigned int *next = (unsigned int *) decodeBuffer.decodeMemory(size);
-
- for (int i = 0; i < 32; i += sizeof(unsigned int))
- {
- *((unsigned int *) (buffer + i)) = *next++;
- }
-
- #else /* #ifndef __sun */
-
- memcpy(buffer, decodeBuffer.decodeMemory(size), size);
-
- #endif /* #ifndef __sun */
-
- //
- // Use our local sequence number.
- //
-
- PutUINT(lastSequence_, buffer + 2, bigEndian_);
-
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleFastWriteEvent: Handled raw "
- << (opcode == X_Error ? "error" : "event") << " OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_ << " with sequence "
- << lastSequence_ << ". Output size is " << size << ".\n"
- << logofs_flush;
- #endif
-
- //
- // Check if we need to suppress the error.
- //
-
- if (opcode == X_Error && handleTaintSyncError(*(buffer + 10)) > 0)
- {
- #if defined(TEST) || defined(OPCODES)
- *logofs << "handleFastWriteEvent: WARNING! Suppressed error OPCODE#"
- << (unsigned int) opcode << " for FD#" << fd_
- << " with sequence " << lastSequence_ << ".\n"
- << logofs_flush;
- #endif
-
- writeBuffer_.removeMessage(32);
- }
-
- handleFlush(flush_if_needed);
-
- return 1;
-}
-
-int ClientChannel::handleShmemRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- //
- // Will push sequence and set
- // priority according to stage.
- //
-
- unsigned int stage = *(buffer + 1);
-
- #ifdef TEST
- *logofs << "handleShmemRequest: Encoding shmem request "
- << "OPCODE#" << (unsigned int) opcode << " for FD#"
- << fd_ << " with size " << size << " at stage "
- << stage << ".\n" << logofs_flush;
- #endif
-
- encodeBuffer.encodeValue(stage, 2);
-
- if (stage == 0)
- {
- unsigned int enableClient = 0;
- unsigned int enableServer = 0;
-
- if (control -> ShmemClient == 1)
- {
- enableClient = *(buffer + 4);
- }
-
- if (control -> ShmemServer == 1)
- {
- enableServer = *(buffer + 5);
- }
-
- encodeBuffer.encodeBoolValue(enableClient);
- encodeBuffer.encodeBoolValue(enableServer);
-
- unsigned int clientSegment = GetULONG(buffer + 8, bigEndian_);
- unsigned int serverSegment = GetULONG(buffer + 12, bigEndian_);
-
- encodeBuffer.encodeValue(clientSegment, 29, 9);
- encodeBuffer.encodeValue(serverSegment, 29, 9);
-
- #ifdef TEST
- *logofs << "handleShmemRequest: Enable client is "
- << enableClient << " enable server is " << enableServer
- << " client segment is " << (void *) clientSegment
- << " server segment is " << (void *) serverSegment
- << ".\n" << logofs_flush;
- #endif
-
- #ifdef TEST
- *logofs << "handleShmemRequest: Size of the shared memory "
- << "segment will be " << control -> ShmemServerSize
- << ".\n" << logofs_flush;
- #endif
- }
-
- if (stage != 1)
- {
- sequenceQueue_.push(clientSequence_, opcodeStore_ ->
- getShmemParameters);
-
- priority_++;
- }
-
- return 1;
-}
-
-int ClientChannel::handleShmemReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
- unsigned char *&buffer, unsigned int &size)
-{
- #ifdef TEST
- *logofs << "handleShmemReply: Received shmem parameters "
- << "reply OPCODE#" << (unsigned int) opcode
- << ".\n" << logofs_flush;
- #endif
-
- size = 32;
- buffer = writeBuffer_.addMessage(size);
-
- unsigned int stage;
-
- decodeBuffer.decodeValue(stage, 2);
-
- *(buffer + 1) = stage;
-
- if (stage == 2)
- {
- unsigned int clientEnabled;
- unsigned int serverEnabled;
-
- decodeBuffer.decodeBoolValue(clientEnabled);
- decodeBuffer.decodeBoolValue(serverEnabled);
-
- //
- // Client support is not implemented
- // and not useful. It is here only
- // for compatibility.
- //
-
- clientEnabled = 0;
-
- *(buffer + 8) = clientEnabled;
- *(buffer + 9) = serverEnabled;
-
- PutULONG(0, buffer + 12, bigEndian_);
-
- if (serverEnabled == 1)
- {
- #ifdef TEST
- *logofs << "handleShmemReply: Enabled shared memory "
- << "support in X server with segment size "
- << control -> ShmemServerSize << ".\n"
- << logofs_flush;
- #endif
-
- PutULONG(control -> ShmemServerSize, buffer + 16, bigEndian_);
- }
- else
- {
- PutULONG(0, buffer + 16, bigEndian_);
- }
- }
- else
- {
- *(buffer + 8) = 0;
- *(buffer + 9) = 0;
-
- PutULONG(0, buffer + 12, bigEndian_);
- PutULONG(0, buffer + 16, bigEndian_);
- }
-
- return 1;
-}
-
-int ClientChannel::handleFontRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- #ifdef TEST
- *logofs << "handleFontRequest: Encoding font request "
- << "OPCODE#" << (unsigned int) opcode << " for FD#"
- << fd_ << " with size " << size << ".\n"
- << logofs_flush;
- #endif
-
- sequenceQueue_.push(clientSequence_, opcodeStore_ ->
- getFontParameters);
-
- return 1;
-}
-
-int ClientChannel::handleFontReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
- unsigned char *&buffer, unsigned int &size)
-{
- #ifdef TEST
- *logofs << "handleFontReply: Received font operation "
- << "reply OPCODE#" << (unsigned int) opcode
- << ".\n" << logofs_flush;
- #endif
-
- unsigned int length;
-
- decodeBuffer.decodeValue(length, 8);
-
- size = 32 + RoundUp4(length + 1);
- buffer = writeBuffer_.addMessage(size);
-
- unsigned char *next = buffer + 32;
-
- *next++ = length;
-
- decodeBuffer.decodeTextData(next, length);
-
- #ifdef TEST
-
- *logofs << "handleFontReply: Received tunneled font server "
- << "path '";
-
- for (unsigned int i = 0; i < length; i++)
- {
- *logofs << *(buffer + 32 + 1 + i);
- }
-
- *logofs << "' for FD#" << fd_ << ".\n" << logofs_flush;
-
- #endif
-
- if (fontPort_ == -1)
- {
- //
- // The local side is not going to forward
- // the font server connections.
- //
-
- #ifdef TEST
- *logofs << "handleFontReply: WARNING! Returning an empty "
- << "font server path.\n" << logofs_flush;
- #endif
-
- writeBuffer_.removeMessage(size);
-
- size = 36;
- buffer = writeBuffer_.addMessage(size);
-
- //
- // Set the length of the returned
- // path to 0.
- //
-
- *(buffer + 32) = 0;
- }
- #ifdef TEST
- else
- {
- *logofs << "handleFontReply: Returning the received "
- << "font server path.\n" << logofs_flush;
- }
- #endif
-
- return 1;
-}
-
-int ClientChannel::handleCacheRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- #ifdef TEST
- *logofs << "handleCacheRequest: Handling cache request "
- << "for FD#" << fd_ << ".\n" << logofs_flush;
- #endif
-
- enableCache_ = *(buffer + 4);
- enableSplit_ = *(buffer + 5);
- enableSave_ = *(buffer + 6);
- enableLoad_ = *(buffer + 7);
-
- #ifdef TEST
- *logofs << "handleCacheRequest: Set cache parameters to "
- << " cache " << enableCache_ << " split " << enableSplit_
- << " save " << enableSave_ << " load " << enableLoad_
- << ".\n" << logofs_flush;
- #endif
-
- //
- // Encode all the parameters as a
- // single unsigned int so we can
- // use an int cache.
- //
-
- unsigned int mask = enableSave_ << 8 | enableLoad_;
-
- encodeBuffer.encodeCachedValue(mask, 32, clientCache_ ->
- setCacheParametersCache);
- return 0;
-}
-
-int ClientChannel::handleStartSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleStartSplitRequest: SPLIT! Handling start split "
- << "request for FD#"<< fd_ << ".\n" << logofs_flush;
- #endif
-
- if (splitState_.resource != nothing)
- {
- #ifdef PANIC
- *logofs << "handleStartSplitRequest: PANIC! SPLIT! Split requested "
- << "for resource id " << (unsigned int) *(buffer + 1)
- << " while handling resource " << splitState_.resource
- << ".\n" << logofs_flush;
- #endif
-
- cerr << "Error" << ": Split requested for "
- << "resource id " << (unsigned int) *(buffer + 1)
- << " while handling resource " << splitState_.resource
- << ".\n";
-
- return -1;
- }
- else if (fd_ != firstClient_)
- {
- //
- // It can be that an auxiliary channel is the
- // first to connect, then comes the agent that
- // is actually using the NX opcodes.
- //
-
- #ifdef WARNING
- *logofs << "handleStartSplitRequest: WARNING SPLIT! Split requested "
- << "on FD#" << fd_ << " while expecting FD#" << firstClient_
- << ".\n" << logofs_flush;
- #endif
-
- firstClient_ = fd_;
- }
-
- //
- // Set the agent's resource for which we are
- // going to split the request.
- //
-
- splitState_.resource = *(buffer + 1);
-
- #if defined(TEST) || defined(SPLIT)
-
- *logofs << "handleStartSplitRequest: SPLIT! Registered id "
- << splitState_.resource << " as resource "
- << "waiting for a split.\n" << logofs_flush;
-
- if (clientStore_ -> getSplitStore(splitState_.resource) != NULL)
- {
- *logofs << "handleStartSplitRequest: WARNING! SPLIT! A split "
- << "store for resource id " << splitState_.resource
- << " already exists.\n" << logofs_flush;
-
- clientStore_ -> dumpSplitStore(splitState_.resource);
- }
-
- #endif
-
- //
- // Send the selected resource to the remote.
- //
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeCachedValue(splitState_.resource, 8,
- clientCache_ -> resourceCache);
-
- splitState_.mode = (T_split_mode) *(buffer + 4);
-
- if (splitState_.mode != NXSplitModeAsync &&
- splitState_.mode != NXSplitModeSync)
- {
- splitState_.mode = (T_split_mode) control -> SplitMode;
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleStartSplitRequest: SPLIT! Set split "
- << "mode to '" << splitState_.mode << "' with "
- << "provided value '" << (unsigned) *(buffer + 4)
- << "'.\n" << logofs_flush;
- #endif
- }
-
- #if defined(TEST) || defined(SPLIT)
-
- if (splitState_.mode == NXSplitModeAsync)
- {
- *logofs << "handleStartSplitRequest: SPLIT! Selected split "
- << "mode is [split_async].\n" << logofs_flush;
- }
- else if (splitState_.mode == NXSplitModeSync)
- {
- *logofs << "handleStartSplitRequest: SPLIT! Selected split "
- << "mode is [split_sync].\n" << logofs_flush;
- }
-
- clientStore_ -> dumpSplitStores();
-
- #endif
-
- return 1;
-}
-
-int ClientChannel::handleEndSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
- const unsigned char *buffer, const unsigned int size)
-{
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleEndSplitRequest: SPLIT! Handling end split "
- << "request for FD#"<< fd_ << ".\n" << logofs_flush;
- #endif
-
- //
- // Verify that the agent resource matches.
- //
-
- if (splitState_.resource == nothing)
- {
- #ifdef PANIC
- *logofs << "handleEndSplitRequest: PANIC! SPLIT! Received an end of "
- << "split for resource id " << (unsigned int) *(buffer + 1)
- << " without a previous start.\n"
- << logofs_flush;
- #endif
-
- cerr << "Error" << ": Received an end of split "
- << "for resource id " << (unsigned int) *(buffer + 1)
- << " without a previous start.\n";
-
- return -1;
- }
- else if (splitState_.resource != *(buffer + 1))
- {
- #ifdef PANIC
- *logofs << "handleEndSplitRequest: PANIC! SPLIT! Invalid resource id "
- << (unsigned int) *(buffer + 1) << " received while "
- << "waiting for resource id " << splitState_.resource
- << ".\n" << logofs_flush;
- #endif
-
- cerr << "Error" << ": Invalid resource id "
- << (unsigned int) *(buffer + 1) << " received while "
- << "waiting for resource id " << splitState_.resource
- << ".\n";
-
- return -1;
- }
-
- //
- // Send the selected resource to the remote.
- //
-
- // Since ProtoStep7 (#issue 108)
- encodeBuffer.encodeCachedValue(splitState_.resource, 8,
- clientCache_ -> resourceCache);
-
- //
- // Send the split notification events
- // to the agent.
- //
-
- handleRestart(sequence_immediate, splitState_.resource);
-
- //
- // Check if we still have splits to send.
- //
-
- handleSplitPending();
-
- #if defined(TEST) || defined(SPLIT)
- *logofs << "handleEndSplitRequest: SPLIT! Reset id "
- << splitState_.resource << " as resource "
- << "selected for splits.\n" << logofs_flush;
- #endif
-
- splitState_.resource = nothing;
- splitState_.mode = split_none;
-
- #if defined(TEST) || defined(SPLIT)
-
- clientStore_ -> dumpSplitStores();
-
- #endif
-
- return 1;
-}
-
-void ClientChannel::handleDecodeCharInfo(DecodeBuffer &decodeBuffer, unsigned char *nextDest)
-{
- unsigned int value;
-
- decodeBuffer.decodeCachedValue(value, 32,
- *serverCache_ -> queryFontCharInfoCache[0], 6);
-
- PutUINT(value & 0xffff, nextDest, bigEndian_);
- PutUINT(value >> 16, nextDest + 10, bigEndian_);
-
- nextDest += 2;
-
- for (unsigned int i = 1; i < 5; i++)
- {
- unsigned int value;
-
- decodeBuffer.decodeCachedValue(value, 16,
- *serverCache_ -> queryFontCharInfoCache[i], 6);
-
- PutUINT(value, nextDest, bigEndian_);
-
- nextDest += 2;
- }
-}
-
-int ClientChannel::setBigEndian(int flag)
-{
- bigEndian_ = flag;
-
- return 1;
-}
-
-int ClientChannel::setReferences()
-{
- #ifdef TEST
- *logofs << "ClientChannel: Initializing the static "
- << "members for the client channels.\n"
- << logofs_flush;
- #endif
-
- #ifdef REFERENCES
-
- references_ = 0;
-
- #endif
-
- return 1;
-}