source: trunk/src/gui/embedded/qwscommand_qws.cpp@ 855

Last change on this file since 855 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 17.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwscommand_qws_p.h"
43#include "qtransportauth_qws.h"
44#include "qtransportauth_qws_p.h"
45
46#include <unistd.h>
47
48// #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
49
50#ifdef QWSCOMMAND_DEBUG
51# include <qdebug.h>
52# include "qfile.h"
53# include <ctype.h>
54#endif
55
56QT_BEGIN_NAMESPACE
57
58#ifdef QWSCOMMAND_DEBUG
59// QWSHexDump -[ start ]---------------------------------------------
60# define QWSHEXDUMP_MAX 32
61class QWSHexDump
62{
63public:
64
65 QWSHexDump(const void *address, int len, int wrapAt = 16)
66 : wrap(wrapAt), dataSize(len)
67 {
68 init();
69 data = reinterpret_cast<const char*>(address);
70 if (len < 0)
71 dataSize = 0;
72 }
73
74 QWSHexDump(const char *str, int len = -1, int wrapAt = 16)
75 : wrap(wrapAt), dataSize(len)
76 {
77 init();
78 data = str;
79 if (len == -1)
80 dataSize = str ? strlen(str) : 0;
81 }
82
83 QWSHexDump(const QByteArray &array, int wrapAt = 16)
84 : wrap(wrapAt)
85 {
86 init();
87 data = array.data();
88 dataSize = array.size();
89 }
90
91 // Sets a customized prefix for the hexdump
92 void setPrefix(const char *str) { prefix = str; }
93
94 // Sets number of bytes to cluster together
95 void setClusterSize(uint num) { clustering = num; }
96
97 // Output hexdump to a text stream
98 void intoTextStream(QTextStream &strm) {
99 outstrm = &strm;
100 hexDump();
101 }
102
103 // Output hexdump to a QString
104 QString toString();
105
106protected:
107 void init();
108 void hexDump();
109 void sideviewDump(int at);
110
111private:
112 uint wrap;
113 uint clustering;
114 uint dataSize;
115 int dataWidth;
116 const char *data;
117 const char *prefix;
118 bool dirty;
119
120 char sideviewLayout[QWSHEXDUMP_MAX + 1];
121 char sideview[15];
122
123 QTextStream *outstrm;
124};
125
126void QWSHexDump::init()
127{
128 prefix = "> "; // Standard line prefix
129 clustering = 2; // Word-size clustering by default
130 if (wrap > QWSHEXDUMP_MAX) // No wider than QWSHexDump_MAX bytes
131 wrap = QWSHEXDUMP_MAX;
132}
133
134void QWSHexDump::hexDump()
135{
136 *outstrm << '(' << dataSize << " bytes):\n" << prefix;
137 sprintf(sideviewLayout, " [%%-%us]", wrap);
138 dataWidth = (2 * wrap) + (wrap / clustering);
139
140 dirty = false;
141 uint wrapIndex = 0;
142 for (uint i = 0; i < dataSize; i++) {
143 uint c = static_cast<uchar>(data[i]);
144 sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
145
146 if (wrapIndex && (wrapIndex % clustering == 0))
147 *outstrm << ' ';
148
149 outstrm->setFieldWidth(2);
150 outstrm->setPadChar('0');
151 outstrm->setNumberFlags( QTextStream::ShowBase );
152 *outstrm << hex << c;
153 dirty = true;
154
155 if (wrapIndex == wrap-1) {
156 sideviewDump(wrapIndex);
157 wrapIndex = 0;
158 if (i+1 < dataSize)
159 *outstrm << endl << prefix;
160 }
161
162 }
163 sideviewDump(wrapIndex);
164}
165
166void QWSHexDump::sideviewDump(int at)
167{
168 if (dirty) {
169 dirty = false;
170 ++at;
171 sideview[at] = '\0';
172 int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
173 int missing = qMax(dataWidth - currentWidth, 0);
174 while (missing--)
175 *outstrm << ' ';
176
177 *outstrm << " [";
178 outstrm->setPadChar(' ');
179 outstrm->setFieldWidth(wrap);
180 outstrm->setFieldAlignment( QTextStream::AlignLeft );
181 *outstrm << sideview;
182 *outstrm << ']';
183 }
184}
185
186// Output hexdump to a QString
187QString QWSHexDump::toString() {
188 QString result;
189 QTextStream strm(&result, QFile::WriteOnly);
190 outstrm = &strm;
191 hexDump();
192 return result;
193}
194
195#ifndef QT_NO_DEBUG
196QDebug &operator<<(QDebug &dbg, QWSHexDump *hd) {
197 if (!hd)
198 return dbg << "QWSHexDump(0x0)";
199 QString result = hd->toString();
200 dbg.nospace() << result;
201 return dbg.space();
202}
203
204// GCC & Intel wont handle references here
205QDebug operator<<(QDebug dbg, QWSHexDump hd) {
206 return dbg << &hd;
207}
208#endif
209// QWSHexDump -[ end ]-----------------------------------------------
210
211
212QDebug &operator<<(QDebug &dbg, QWSCommand::Type tp)
213{
214 dbg << qws_getCommandTypeString( tp );
215 return dbg;
216}
217
218#define N_EVENTS 19
219const char * eventNames[N_EVENTS] = {
220 "NoEvent",
221 "Connected",
222 "Mouse", "Focus", "Key",
223 "Region",
224 "Creation",
225 "PropertyNotify",
226 "PropertyReply",
227 "SelectionClear",
228 "SelectionRequest",
229 "SelectionNotify",
230 "MaxWindowRect",
231 "QCopMessage",
232 "WindowOperation",
233 "IMEvent",
234 "IMQuery",
235 "IMInit",
236 "Font"
237 };
238
239class QWSServer;
240extern QWSServer *qwsServer;
241#endif
242
243const char *qws_getCommandTypeString( QWSCommand::Type tp )
244{
245 const char *typeStr;
246 switch(tp) {
247 case QWSCommand::Create:
248 typeStr = "Create";
249 break;
250 case QWSCommand::Shutdown:
251 typeStr = "Shutdown";
252 break;
253 case QWSCommand::Region:
254 typeStr = "Region";
255 break;
256 case QWSCommand::RegionMove:
257 typeStr = "RegionMove";
258 break;
259 case QWSCommand::RegionDestroy:
260 typeStr = "RegionDestroy";
261 break;
262 case QWSCommand::SetProperty:
263 typeStr = "SetProperty";
264 break;
265 case QWSCommand::AddProperty:
266 typeStr = "AddProperty";
267 break;
268 case QWSCommand::RemoveProperty:
269 typeStr = "RemoveProperty";
270 break;
271 case QWSCommand::GetProperty:
272 typeStr = "GetProperty";
273 break;
274 case QWSCommand::SetSelectionOwner:
275 typeStr = "SetSelectionOwner";
276 break;
277 case QWSCommand::ConvertSelection:
278 typeStr = "ConvertSelection";
279 break;
280 case QWSCommand::RequestFocus:
281 typeStr = "RequestFocus";
282 break;
283 case QWSCommand::ChangeAltitude:
284 typeStr = "ChangeAltitude";
285 break;
286 case QWSCommand::SetOpacity:
287 typeStr = "SetOpacity";
288 break;
289 case QWSCommand::DefineCursor:
290 typeStr = "DefineCursor";
291 break;
292 case QWSCommand::SelectCursor:
293 typeStr = "SelectCursor";
294 break;
295 case QWSCommand::PositionCursor:
296 typeStr = "PositionCursor";
297 break;
298 case QWSCommand::GrabMouse:
299 typeStr = "GrabMouse";
300 break;
301 case QWSCommand::PlaySound:
302 typeStr = "PlaySound";
303 break;
304 case QWSCommand::QCopRegisterChannel:
305 typeStr = "QCopRegisterChannel";
306 break;
307 case QWSCommand::QCopSend:
308 typeStr = "QCopSend";
309 break;
310 case QWSCommand::RegionName:
311 typeStr = "RegionName";
312 break;
313 case QWSCommand::Identify:
314 typeStr = "Identify";
315 break;
316 case QWSCommand::GrabKeyboard:
317 typeStr = "GrabKeyboard";
318 break;
319 case QWSCommand::RepaintRegion:
320 typeStr = "RepaintRegion";
321 break;
322 case QWSCommand::IMMouse:
323 typeStr = "IMMouse";
324 break;
325 case QWSCommand::IMUpdate:
326 typeStr = "IMUpdate";
327 break;
328 case QWSCommand::IMResponse:
329 typeStr = "IMResponse";
330 break;
331 case QWSCommand::Font:
332 typeStr = "Font";
333 break;
334 case QWSCommand::Unknown:
335 default:
336 typeStr = "Unknown";
337 break;
338 }
339 return typeStr;
340}
341
342
343/*********************************************************************
344 *
345 * Functions to read/write commands on/from a socket
346 *
347 *********************************************************************/
348
349#ifndef QT_NO_QWS_MULTIPROCESS
350void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen,
351 char *rawData, int rawLen)
352{
353#ifdef QWSCOMMAND_DEBUG
354 if (simpleLen) qDebug() << "WRITE simpleData " << QWSHexDump(simpleData, simpleLen);
355 if (rawLen > 0) qDebug() << "WRITE rawData " << QWSHexDump(rawData, rawLen);
356#endif
357
358#ifndef QT_NO_SXE
359 QTransportAuth *a = QTransportAuth::getInstance();
360 // ###### as soon as public API can be modified get rid of horrible casts
361 QIODevice *ad = a->passThroughByClient(reinterpret_cast<QWSClient*>(socket));
362 if (ad)
363 socket = ad;
364#endif
365
366 qws_write_uint(socket, type);
367
368 if (rawLen > MAX_COMMAND_SIZE) {
369 qWarning("qws_write_command: Message of size %d too big. "
370 "Truncated to %d", rawLen, MAX_COMMAND_SIZE);
371 rawLen = MAX_COMMAND_SIZE;
372 }
373
374 qws_write_uint(socket, rawLen == -1 ? 0 : rawLen);
375
376 if (simpleData && simpleLen)
377 socket->write(simpleData, simpleLen);
378
379 if (rawLen && rawData)
380 socket->write(rawData, rawLen);
381}
382
383/*
384 command format: [type][rawLen][simpleData][rawData]
385 type is already read when entering this function
386*/
387
388bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen,
389 char *&rawData, int &rawLen, int &bytesRead)
390{
391
392 // read rawLen
393 if (rawLen == -1) {
394 rawLen = qws_read_uint(socket);
395 if (rawLen == -1)
396 return false;
397 }
398
399 // read simpleData, assumes socket is capable of buffering all the data
400 if (simpleLen && !rawData) {
401 if (socket->bytesAvailable() < uint(simpleLen))
402 return false;
403 int tmp = socket->read(simpleData, simpleLen);
404 Q_ASSERT(tmp == simpleLen);
405 Q_UNUSED(tmp);
406 }
407
408 if (rawLen > MAX_COMMAND_SIZE) {
409 socket->close();
410 qWarning("qws_read_command: Won't read command of length %d, "
411 "connection closed.", rawLen);
412 return false;
413 }
414
415 // read rawData
416 if (rawLen && !rawData) {
417 rawData = new char[rawLen];
418 bytesRead = 0;
419 }
420 if (bytesRead < rawLen && socket->bytesAvailable())
421 bytesRead += socket->read(rawData + bytesRead, rawLen - bytesRead);
422
423 return (bytesRead == rawLen);
424}
425#endif
426
427/*********************************************************************
428 *
429 * QWSCommand base class - only use derived classes from that
430 *
431 *********************************************************************/
432QWSProtocolItem::~QWSProtocolItem() {
433 if (deleteRaw)
434 delete []rawDataPtr;
435}
436
437#ifndef QT_NO_QWS_MULTIPROCESS
438void QWSProtocolItem::write(QIODevice *s) {
439#ifdef QWSCOMMAND_DEBUG
440 if (!qwsServer)
441 qDebug() << "QWSProtocolItem::write sending type " << static_cast<QWSCommand::Type>(type);
442 else
443 qDebug() << "QWSProtocolItem::write sending event " << (type < N_EVENTS ? eventNames[type] : "unknown");
444#endif
445 qws_write_command(s, type, simpleDataPtr, simpleLen, rawDataPtr, rawLen);
446}
447
448bool QWSProtocolItem::read(QIODevice *s) {
449#ifdef QWSCOMMAND_DEBUG
450 QLatin1String reread( (rawLen == -1) ? "" : "REREAD");
451 if (qwsServer)
452 qDebug() << "QWSProtocolItem::read reading type " << static_cast<QWSCommand::Type>(type) << reread;
453 else
454 qDebug() << "QWSProtocolItem::read reading event " << (type < N_EVENTS ? eventNames[type] : "unknown") << reread;
455 //qDebug("QWSProtocolItem::read reading event %s", type < N_EVENTS ? eventNames[type] : "unknown");
456#endif
457 bool b = qws_read_command(s, simpleDataPtr, simpleLen, rawDataPtr, rawLen, bytesRead);
458 if (b) {
459 setData(rawDataPtr, rawLen, false);
460 deleteRaw = true;
461 }
462#ifdef QWSCOMMAND_DEBUG
463 else
464 {
465 qDebug() << "error in reading command " << static_cast<QWSCommand::Type>(type);
466 }
467#endif
468 return b;
469}
470#endif // QT_NO_QWS_MULTIPROCESS
471
472void QWSProtocolItem::copyFrom(const QWSProtocolItem *item) {
473 if (this == item)
474 return;
475 simpleLen = item->simpleLen;
476 memcpy(simpleDataPtr, item->simpleDataPtr, simpleLen);
477 setData(item->rawDataPtr, item->rawLen);
478}
479
480void QWSProtocolItem::setData(const char *data, int len, bool allocateMem) {
481 if (deleteRaw)
482 delete [] rawDataPtr;
483 if (!data || len <= 0) {
484 rawDataPtr = 0;
485 rawLen = 0;
486 return;
487 }
488 if (allocateMem) {
489 rawDataPtr = new char[len];
490 memcpy(rawDataPtr, data, len);
491 deleteRaw = true;
492 } else {
493 rawDataPtr = const_cast<char *>(data);
494 deleteRaw = false;
495 }
496 rawLen = len;
497}
498
499QWSCommand *QWSCommand::factory(int type)
500{
501 QWSCommand *command = 0;
502 switch (type) {
503 case QWSCommand::Create:
504 command = new QWSCreateCommand;
505 break;
506 case QWSCommand::Shutdown:
507 command = new QWSCommand(type, 0, 0);
508 break;
509 case QWSCommand::Region:
510 command = new QWSRegionCommand;
511 break;
512 case QWSCommand::RegionMove:
513 command = new QWSRegionMoveCommand;
514 break;
515 case QWSCommand::RegionDestroy:
516 command = new QWSRegionDestroyCommand;
517 break;
518 case QWSCommand::AddProperty:
519 command = new QWSAddPropertyCommand;
520 break;
521 case QWSCommand::SetProperty:
522 command = new QWSSetPropertyCommand;
523 break;
524 case QWSCommand::RemoveProperty:
525 command = new QWSRemovePropertyCommand;
526 break;
527 case QWSCommand::GetProperty:
528 command = new QWSGetPropertyCommand;
529 break;
530 case QWSCommand::SetSelectionOwner:
531 command = new QWSSetSelectionOwnerCommand;
532 break;
533 case QWSCommand::RequestFocus:
534 command = new QWSRequestFocusCommand;
535 break;
536 case QWSCommand::ChangeAltitude:
537 command = new QWSChangeAltitudeCommand;
538 break;
539 case QWSCommand::SetOpacity:
540 command = new QWSSetOpacityCommand;
541 break;
542 case QWSCommand::DefineCursor:
543 command = new QWSDefineCursorCommand;
544 break;
545 case QWSCommand::SelectCursor:
546 command = new QWSSelectCursorCommand;
547 break;
548 case QWSCommand::GrabMouse:
549 command = new QWSGrabMouseCommand;
550 break;
551 case QWSCommand::GrabKeyboard:
552 command = new QWSGrabKeyboardCommand;
553 break;
554#ifndef QT_NO_SOUND
555 case QWSCommand::PlaySound:
556 command = new QWSPlaySoundCommand;
557 break;
558#endif
559#ifndef QT_NO_COP
560 case QWSCommand::QCopRegisterChannel:
561 command = new QWSQCopRegisterChannelCommand;
562 break;
563 case QWSCommand::QCopSend:
564 command = new QWSQCopSendCommand;
565 break;
566#endif
567 case QWSCommand::RegionName:
568 command = new QWSRegionNameCommand;
569 break;
570 case QWSCommand::Identify:
571 command = new QWSIdentifyCommand;
572 break;
573 case QWSCommand::RepaintRegion:
574 command = new QWSRepaintRegionCommand;
575 break;
576#ifndef QT_NO_QWS_INPUTMETHODS
577 case QWSCommand::IMUpdate:
578 command = new QWSIMUpdateCommand;
579 break;
580
581 case QWSCommand::IMMouse:
582 command = new QWSIMMouseCommand;
583 break;
584
585 case QWSCommand::IMResponse:
586 command = new QWSIMResponseCommand;
587 break;
588#endif
589 case QWSCommand::PositionCursor:
590 command = new QWSPositionCursorCommand;
591 break;
592#ifndef QT_NO_QWSEMBEDWIDGET
593 case QWSCommand::Embed:
594 command = new QWSEmbedCommand;
595 break;
596#endif
597 case QWSCommand::Font:
598 command = new QWSFontCommand;
599 break;
600 case QWSCommand::ScreenTransform:
601 command = new QWSScreenTransformCommand;
602 break;
603 default:
604 qWarning("QWSCommand::factory : Type error - got %08x!", type);
605 }
606 return command;
607}
608
609QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.