1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */ 4 /* */ 5 /* NXCOMP, NX protocol compression and NX extensions to this software */ 6 /* are copyright of NoMachine. Redistribution and use of the present */ 7 /* software is allowed according to terms specified in the file LICENSE */ 8 /* which comes in the source distribution. */ 9 /* */ 10 /* Check http://www.nomachine.com/licensing.html for applicability. */ 11 /* */ 12 /* NX and NoMachine are trademarks of Medialogic S.p.A. */ 13 /* */ 14 /* All rights reserved. */ 15 /* */ 16 /**************************************************************************/ 17 18 #ifndef ClientChannel_H 19 #define ClientChannel_H 20 21 #include "List.h" 22 #include "Channel.h" 23 24 #include "SequenceQueue.h" 25 26 #include "ClientReadBuffer.h" 27 28 // 29 // Set the verbosity level. 30 // 31 32 #define PANIC 33 #define WARNING 34 #undef TEST 35 #undef DEBUG 36 37 // 38 // If defined, the client channel will 39 // have the chance of suppressing more 40 // opcodes for test purposes. 41 // 42 43 #undef LAME 44 45 // 46 // Define this to log a line when a 47 // channel is created or destroyed. 48 // 49 50 #undef REFERENCES 51 52 // 53 // This class implements the X client 54 // side compression of the protocol. 55 // 56 57 class ClientChannel : public Channel 58 { 59 public: 60 61 ClientChannel(Transport *transport, StaticCompressor *compressor); 62 63 virtual ~ClientChannel(); 64 65 virtual int handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message, 66 unsigned int length); 67 68 virtual int handleWrite(const unsigned char *message, unsigned int length); 69 70 virtual int handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store, 71 T_store_action action, int position, const unsigned char opcode, 72 const unsigned char *buffer, const unsigned int size); 73 handleSplit(DecodeBuffer & decodeBuffer,MessageStore * store,T_store_action action,int position,unsigned char & opcode,unsigned char * & buffer,unsigned int & size)74 virtual int handleSplit(DecodeBuffer &decodeBuffer, MessageStore *store, 75 T_store_action action, int position, unsigned char &opcode, 76 unsigned char *&buffer, unsigned int &size) 77 { 78 return 0; 79 } 80 81 virtual int handleSplit(EncodeBuffer &encodeBuffer); 82 handleSplit(DecodeBuffer & decodeBuffer)83 virtual int handleSplit(DecodeBuffer &decodeBuffer) 84 { 85 return 0; 86 } 87 88 virtual int handleSplitEvent(EncodeBuffer &encodeBuffer, Split *split); 89 90 virtual int handleSplitEvent(DecodeBuffer &decodeBuffer); 91 handleMotion(EncodeBuffer & encodeBuffer)92 virtual int handleMotion(EncodeBuffer &encodeBuffer) 93 { 94 return 0; 95 } 96 handleCompletion(EncodeBuffer & encodeBuffer)97 virtual int handleCompletion(EncodeBuffer &encodeBuffer) 98 { 99 return 0; 100 } 101 102 virtual int handleConfiguration(); 103 104 virtual int handleFinish(); 105 handleAsyncEvents()106 virtual int handleAsyncEvents() 107 { 108 return 0; 109 } 110 needSplit()111 virtual int needSplit() const 112 { 113 #if defined(TEST) || defined(SPLIT) 114 *logofs << "needSplit: SPLIT! Returning pending split " 115 << "flag " << splitState_.pending << " with " 116 << clientStore_ -> getSplitTotalSize() 117 << " splits in the split stores.\n" 118 << logofs_flush; 119 #endif 120 121 return splitState_.pending; 122 } 123 needMotion()124 virtual int needMotion() const 125 { 126 return 0; 127 } 128 getType()129 virtual T_channel_type getType() const 130 { 131 return channel_x11; 132 } 133 134 int setBigEndian(int flag); 135 136 // 137 // Initialize the static members. 138 // 139 140 static int setReferences(); 141 142 private: 143 144 int handleFastReadRequest(EncodeBuffer &encodeBuffer, const unsigned char &opcode, 145 const unsigned char *&buffer, const unsigned int &size); 146 147 int handleFastWriteReply(DecodeBuffer &decodeBuffer, unsigned char &opcode, 148 unsigned char *&buffer, unsigned int &size); 149 150 int handleFastWriteEvent(DecodeBuffer &decodeBuffer, unsigned char &opcode, 151 unsigned char *&buffer, unsigned int &size); 152 153 // 154 // Intercept the request before the opcode 155 // is encoded. 156 // 157 handleTaintRequest(unsigned char & opcode,const unsigned char * & buffer,unsigned int & size)158 int handleTaintRequest(unsigned char &opcode, const unsigned char *&buffer, 159 unsigned int &size) 160 { 161 if (control -> isProtoStep7() == 0) 162 { 163 if (opcode == X_NXFreeSplit || opcode == X_NXAbortSplit || 164 opcode == X_NXFinishSplit) 165 { 166 return handleTaintSplitRequest(opcode, buffer, size); 167 } 168 else if (opcode == X_NXSetCacheParameters) 169 { 170 return handleTaintCacheRequest(opcode, buffer, size); 171 } 172 else if (opcode == X_NXGetFontParameters) 173 { 174 return handleTaintFontRequest(opcode, buffer, size); 175 } 176 } 177 178 if (control -> TaintReplies > 0 && 179 opcode == X_GetInputFocus) 180 { 181 return handleTaintSyncRequest(opcode, buffer, size); 182 } 183 184 #ifdef LAME 185 186 return handleTaintLameRequest(opcode, buffer, size); 187 188 #endif 189 190 return 0; 191 } 192 193 int handleTaintCacheRequest(unsigned char &opcode, const unsigned char *&buffer, 194 unsigned int &size); 195 196 int handleTaintFontRequest(unsigned char &opcode, const unsigned char *&buffer, 197 unsigned int &size); 198 199 int handleTaintSplitRequest(unsigned char &opcode, const unsigned char *&buffer, 200 unsigned int &size); 201 202 int handleTaintLameRequest(unsigned char &opcode, const unsigned char *&buffer, 203 unsigned int &size); 204 205 int handleTaintSyncRequest(unsigned char &opcode, const unsigned char *&buffer, 206 unsigned int &size); 207 208 int handleTaintSyncError(unsigned char opcode); 209 210 // 211 // How to handle sequence counter 212 // in notification event. 213 // 214 215 enum T_sequence_mode 216 { 217 sequence_immediate, 218 sequence_deferred 219 }; 220 221 // 222 // Send split notifications to the 223 // agent. 224 // 225 226 int handleRestart(T_sequence_mode mode, int resource); 227 228 int handleNotify(T_notification_type type, T_sequence_mode mode, 229 int resource, int request, int position); 230 231 // 232 // Other utility functions used in 233 // handling of the image streaming. 234 // 235 mustSplitMessage(int resource)236 int mustSplitMessage(int resource) 237 { 238 return (clientStore_ -> getSplitStore(resource) -> 239 getSize() != 0); 240 } 241 canSplitMessage(T_split_mode mode,unsigned int size)242 int canSplitMessage(T_split_mode mode, unsigned int size) 243 { 244 return ((int) size >= control -> SplitDataThreshold && 245 (clientStore_ -> getSplitTotalStorageSize() < control -> 246 SplitTotalStorageSize && clientStore_ -> 247 getSplitTotalSize() < control -> SplitTotalSize)); 248 } 249 canSendSplit(Split * split)250 int canSendSplit(Split *split) 251 { 252 return (split -> getMode() != split_sync || 253 split -> getState() == split_missed || 254 split -> getState() == split_loaded); 255 } 256 257 int handleSplitSend(EncodeBuffer &encodeBuffer, int resource, 258 int &total, int &bytes); 259 260 Split *handleSplitFind(T_checksum checksum, int resource); 261 262 int handleSplitChecksum(EncodeBuffer &encodeBuffer, T_checksum checksum); 263 handleSplitEnable()264 void handleSplitEnable() 265 { 266 if (control -> isProtoStep7() == 0) 267 { 268 #if defined(TEST) || defined(SPLIT) 269 *logofs << "handleSplitEnable: WARNING! Disabling split " 270 << "with an old proxy version.\n" 271 << logofs_flush; 272 #endif 273 274 enableSplit_ = 0; 275 } 276 } 277 handleSplitPending(int resource)278 void handleSplitPending(int resource) 279 { 280 if (splitState_.pending == 0) 281 { 282 if (clientStore_ -> getSplitStore(resource) != NULL && 283 clientStore_ -> getSplitStore(resource) -> 284 getFirstSplit() != NULL) 285 { 286 splitState_.pending = canSendSplit(clientStore_ -> 287 getSplitStore(resource) -> getFirstSplit()); 288 289 #if defined(TEST) || defined(SPLIT) 290 *logofs << "handleSplitPending: SPLIT! Set the pending " 291 << "split flag to " << splitState_.pending 292 << " with " << clientStore_ -> getSplitTotalSize() 293 << " splits in the split stores.\n" 294 << logofs_flush; 295 #endif 296 } 297 } 298 } 299 300 // 301 // Scan all the split stores to find 302 // if there is any split to send. 303 // 304 305 void handleSplitPending(); 306 307 // 308 // Handle the MIT-SHM initialization 309 // messages exchanged with the remote 310 // proxy. 311 // 312 313 int handleShmemRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 314 const unsigned char *buffer, const unsigned int size); 315 316 int handleShmemReply(DecodeBuffer &decodeBuffer, unsigned char &opcode, 317 unsigned char *&buffer, unsigned int &size); 318 319 // 320 // Query the port used to tunnel 321 // the font server connections. 322 // 323 324 int handleFontRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 325 const unsigned char *buffer, const unsigned int size); 326 327 int handleFontReply(DecodeBuffer &decodeBuffer, unsigned char &opcode, 328 unsigned char *&buffer, unsigned int &size); 329 330 // 331 // Let the agent set the cache 332 // policy for image requests. 333 // 334 335 int handleCacheRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 336 const unsigned char *buffer, const unsigned int size); 337 338 // 339 // Encode the start and end split 340 // requests. 341 // 342 343 int handleStartSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 344 const unsigned char *buffer, const unsigned int size); 345 346 int handleEndSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 347 const unsigned char *buffer, const unsigned int size); 348 349 // 350 // Empty a split store and send the 351 // restart event. 352 // 353 354 int handleAbortSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 355 const unsigned char *buffer, const unsigned int size); 356 357 // 358 // Force the proxy to finalize all 359 // the pending split operations and 360 // restart a resource. 361 // 362 363 int handleFinishSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 364 const unsigned char *buffer, const unsigned int size); 365 366 // 367 // Tell the remote peer to send the 368 // split requests to the X server. 369 // 370 371 int handleCommitSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode, 372 const unsigned char *buffer, const unsigned int size); 373 374 // 375 // Other utilities. 376 // 377 378 void handleDecodeCharInfo(DecodeBuffer &, unsigned char *); 379 380 // 381 // Own read buffer. It is able to identify 382 // full messages read from the X descriptor. 383 // 384 385 ClientReadBuffer readBuffer_; 386 387 // 388 // Sequence number of last request coming 389 // from the X client or the X server. 390 // 391 392 unsigned int clientSequence_; 393 unsigned int serverSequence_; 394 395 // 396 // Last sequence number known by client. It can 397 // be the real sequence generated by server or 398 // the one of the last auto-generated event. 399 // 400 401 unsigned int lastSequence_; 402 403 // 404 // Used to identify replies based on sequence 405 // number of original request. 406 // 407 408 SequenceQueue sequenceQueue_; 409 410 // 411 // This is used to test the synchronous flush 412 // in the proxy. 413 // 414 415 int lastRequest_; 416 417 // 418 // Current resource id selected as target and 419 // other information related to the image split. 420 // The pending and abort flags are set when we 421 // want the proxy to give us a chance to send 422 // more split data. We also save the position 423 // of the last commit operation performed by 424 // channel so we can differentially encode the 425 // position of next message to commit. 426 // 427 428 typedef struct 429 { 430 int resource; 431 int pending; 432 int commit; 433 T_split_mode mode; 434 435 } T_split_state; 436 437 T_split_state splitState_; 438 439 // 440 // List of agent resources. 441 // 442 443 List splitResources_; 444 445 // 446 // How many sync requests we 447 // have tainted so far. 448 // 449 450 int taintCounter_; 451 452 private: 453 454 // 455 // Keep track of object 456 // creation and deletion. 457 // 458 459 #ifdef REFERENCES 460 461 static int references_; 462 463 #endif 464 }; 465 466 #endif /* ClientChannel_H */ 467