00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include <qobjectlist.h>
00027
#include <qmetaobject.h>
00028
#include <qvariant.h>
00029
#include <qtimer.h>
00030
#include <qintdict.h>
00031
#include <qeventloop.h>
00032
00033
00034
#include "config.h"
00035
00036
#include <config.h>
00037
#include <dcopref.h>
00038
00039
#include <sys/types.h>
00040
#include <sys/stat.h>
00041
#include <sys/file.h>
00042
#include <sys/socket.h>
00043
00044
#include <ctype.h>
00045
#include <unistd.h>
00046
#include <stdlib.h>
00047
#include <assert.h>
00048
#include <string.h>
00049
00050
#ifndef QT_CLEAN_NAMESPACE
00051
#define QT_CLEAN_NAMESPACE
00052
#endif
00053
#include <qguardedptr.h>
00054
#include <qtextstream.h>
00055
#include <qfile.h>
00056
#include <qapplication.h>
00057
#include <qsocketnotifier.h>
00058
#include <qregexp.h>
00059
00060
#include <private/qucomextra_p.h>
00061
00062
#include <dcopglobal.h>
00063
#include <dcopclient.h>
00064
#include <dcopobject.h>
00065
00066
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00067
#include <X11/Xmd.h>
00068
#endif
00069
extern "C" {
00070
#include <KDE-ICE/ICElib.h>
00071
#include <KDE-ICE/ICEutil.h>
00072
#include <KDE-ICE/ICEmsg.h>
00073
#include <KDE-ICE/ICEproto.h>
00074
00075
00076
#include <sys/time.h>
00077
#include <sys/types.h>
00078
#include <unistd.h>
00079 }
00080
00081
extern QMap<QCString, DCOPObject *> * kde_dcopObjMap;
00082
00083
00084
00085
00086
typedef QAsciiDict<DCOPClient> client_map_t;
00087
static client_map_t *DCOPClient_CliMap = 0;
00088
00089
static
00090 client_map_t *cliMap()
00091 {
00092
if (!DCOPClient_CliMap)
00093 DCOPClient_CliMap =
new client_map_t;
00094
return DCOPClient_CliMap;
00095 }
00096
00097 DCOPClient *
DCOPClient::findLocalClient(
const QCString &_appId )
00098 {
00099
return cliMap()->find(_appId.data());
00100 }
00101
00102
static
00103
void registerLocalClient(
const QCString &_appId,
DCOPClient *client )
00104 {
00105 cliMap()->replace(_appId.data(), client);
00106 }
00107
00108
static
00109
void unregisterLocalClient(
const QCString &_appId )
00110 {
00111 client_map_t *map = cliMap();
00112 map->remove(_appId.data());
00113 }
00115
00116
template class QPtrList<DCOPObjectProxy>;
00117
template class QPtrList<DCOPClientTransaction>;
00118
template class QPtrList<_IceConn>;
00119
00120
struct DCOPClientMessage
00121 {
00122
int opcode;
00123 CARD32
key;
00124
QByteArray data;
00125 };
00126
00127
class DCOPClient::ReplyStruct
00128 {
00129
public:
00130
enum ReplyStatus { Pending, Ok, Failed };
00131 ReplyStruct() {
00132 status = Pending;
00133 replyType = 0;
00134 replyData = 0;
00135 replyId = -1;
00136 transactionId = -1;
00137 replyObject = 0;
00138 }
00139 ReplyStatus status;
00140
QCString* replyType;
00141
QByteArray* replyData;
00142
int replyId;
00143 Q_INT32 transactionId;
00144
QCString calledApp;
00145
QGuardedPtr<QObject> replyObject;
00146
QCString replySlot;
00147 };
00148
00149
class DCOPClientPrivate
00150 {
00151
public:
00152
DCOPClient *parent;
00153
QCString appId;
00154 IceConn iceConn;
00155
int majorOpcode;
00156
00157
int majorVersion, minorVersion;
00158
00159
static const char* serverAddr;
00160
QSocketNotifier *notifier;
00161
bool non_blocking_call_lock;
00162
bool registered;
00163
bool foreign_server;
00164
bool accept_calls;
00165
bool accept_calls_override;
00166
bool qt_bridge_enabled;
00167
00168
QCString senderId;
00169
QCString objId;
00170
QCString function;
00171
00172
QCString defaultObject;
00173
QPtrList<DCOPClientTransaction> *transactionList;
00174
bool transaction;
00175 Q_INT32 transactionId;
00176
int opcode;
00177
00178
00179
00180
00181
00182
00183 CARD32
key;
00184 CARD32 currentKey;
00185 CARD32 currentKeySaved;
00186
00187
QTimer postMessageTimer;
00188
QPtrList<DCOPClientMessage> messages;
00189
00190
QPtrList<DCOPClient::ReplyStruct> pendingReplies;
00191
QPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
00192
00193
struct LocalTransactionResult
00194 {
00195
QCString replyType;
00196
QByteArray replyData;
00197 };
00198
00199
QIntDict<LocalTransactionResult> localTransActionList;
00200 };
00201
00202
class DCOPClientTransaction
00203 {
00204
public:
00205 Q_INT32
id;
00206 CARD32
key;
00207
QCString senderId;
00208 };
00209
00210 QCString DCOPClient::iceauthPath()
00211 {
00212
QCString path = ::getenv(
"PATH");
00213
if (path.isEmpty())
00214 path =
"/bin:/usr/bin";
00215 path +=
":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
00216
QCString fPath = strtok(path.data(),
":\b");
00217
while (!fPath.isNull())
00218 {
00219 fPath +=
"/iceauth";
00220
if (access(fPath.data(), X_OK) == 0)
00221 {
00222
return fPath;
00223 }
00224
00225 fPath = strtok(NULL,
":\b");
00226 }
00227
return 0;
00228 }
00229
00230
static QCString dcopServerFile(
const QCString &hostname,
bool old)
00231 {
00232
QCString fName = ::getenv(
"DCOPAUTHORITY");
00233
if (!old && !fName.isEmpty())
00234
return fName;
00235
00236 fName = ::getenv(
"HOME");
00237
if (fName.isEmpty())
00238 {
00239 fprintf(stderr,
"Aborting. $HOME is not set.\n");
00240 exit(1);
00241 }
00242
#ifdef Q_WS_X11
00243
QCString disp = getenv(
"DISPLAY");
00244
#elif defined(Q_WS_QWS)
00245
QCString disp = getenv(
"QWS_DISPLAY");
00246
#else
00247
QCString disp;
00248
#endif
00249
if (disp.isEmpty())
00250 disp =
"NODISPLAY";
00251
00252
int i;
00253
if((i = disp.findRev(
'.')) > disp.findRev(
':') && i >= 0)
00254 disp.truncate(i);
00255
00256
if (!old)
00257 {
00258
while( (i = disp.find(
':')) >= 0)
00259 disp[i] =
'_';
00260 }
00261
00262 fName +=
"/.DCOPserver_";
00263
if (hostname.isEmpty())
00264 {
00265
char hostName[256];
00266 hostName[0] =
'\0';
00267
if (gethostname(hostName,
sizeof(hostName)))
00268 {
00269 fName +=
"localhost";
00270 }
00271
else
00272 {
00273 hostName[
sizeof(hostName)-1] =
'\0';
00274 fName += hostName;
00275 }
00276 }
00277
else
00278 {
00279 fName += hostname;
00280 }
00281 fName +=
"_"+disp;
00282
return fName;
00283 }
00284
00285
00286
00287 QCString DCOPClient::dcopServerFile(
const QCString &hostname)
00288 {
00289 return ::dcopServerFile(hostname,
false);
00290 }
00291
00292
00293
00294 QCString DCOPClient::dcopServerFileOld(
const QCString &hostname)
00295 {
00296 return ::dcopServerFile(hostname,
true);
00297 }
00298
00299
00300
const char* DCOPClientPrivate::serverAddr = 0;
00301
00302
static void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const QByteArray& dataReceived,
bool canPost );
00303
00304
void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
00305 {
00306
if (replyStruct->replyObject)
00307 {
00308 QObject::connect(
this, SIGNAL(callBack(
int,
const QCString&,
const QByteArray &)),
00309 replyStruct->replyObject, replyStruct->replySlot);
00310 emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
00311 QObject::disconnect(
this, SIGNAL(callBack(
int,
const QCString&,
const QByteArray &)),
00312 replyStruct->replyObject, replyStruct->replySlot);
00313 }
00314
delete replyStruct;
00315 }
00316
00320
static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
00321
int opcode,
unsigned long length, Bool ,
00322 IceReplyWaitInfo *replyWait,
00323 Bool *replyWaitRet)
00324 {
00325 DCOPMsg *pMsg = 0;
00326 DCOPClientPrivate *d = static_cast<DCOPClientPrivate *>(clientObject);
00327 DCOPClient::ReplyStruct *replyStruct = replyWait ? static_cast<DCOPClient::ReplyStruct*>(replyWait->reply) : 0;
00328
00329 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
00330 CARD32
key = pMsg->key;
00331
if ( d->key == 0 )
00332 d->key =
key;
00333
00334
QByteArray dataReceived( length );
00335 IceReadData(iceConn, length, dataReceived.data() );
00336
00337 d->opcode = opcode;
00338
switch (opcode ) {
00339
00340
case DCOPReplyFailed:
00341
if ( replyStruct ) {
00342 replyStruct->status = DCOPClient::ReplyStruct::Failed;
00343 replyStruct->transactionId = 0;
00344 *replyWaitRet = True;
00345
return;
00346 }
else {
00347 qWarning(
"Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
00348
return;
00349 }
00350
case DCOPReply:
00351
if ( replyStruct ) {
00352
QByteArray* b = replyStruct->replyData;
00353
QCString* t = replyStruct->replyType;
00354 replyStruct->status = DCOPClient::ReplyStruct::Ok;
00355 replyStruct->transactionId = 0;
00356
00357
QCString calledApp, app;
00358
QDataStream ds( dataReceived, IO_ReadOnly );
00359 ds >> calledApp >> app >> *t >> *b;
00360
00361 *replyWaitRet = True;
00362
return;
00363 }
else {
00364 qWarning(
"Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
00365
return;
00366 }
00367
case DCOPReplyWait:
00368
if ( replyStruct ) {
00369
QCString calledApp, app;
00370 Q_INT32
id;
00371
QDataStream ds( dataReceived, IO_ReadOnly );
00372 ds >> calledApp >> app >>
id;
00373 replyStruct->transactionId =
id;
00374 replyStruct->calledApp = calledApp;
00375 d->pendingReplies.append(replyStruct);
00376 *replyWaitRet = True;
00377
return;
00378 }
else {
00379 qWarning(
"Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
00380
return;
00381 }
00382
case DCOPReplyDelayed:
00383 {
00384
QDataStream ds( dataReceived, IO_ReadOnly );
00385
QCString calledApp, app;
00386 Q_INT32
id;
00387
00388 ds >> calledApp >> app >>
id;
00389
if (replyStruct && (
id == replyStruct->transactionId) && (calledApp = replyStruct->calledApp))
00390 {
00391 *replyWaitRet = True;
00392 }
00393
00394
for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
00395 rs = d->pendingReplies.next())
00396 {
00397
if ((rs->transactionId ==
id) && (rs->calledApp == calledApp))
00398 {
00399 d->pendingReplies.remove();
00400
QByteArray* b = rs->replyData;
00401
QCString* t = rs->replyType;
00402 ds >> *t >> *b;
00403
00404 rs->status = DCOPClient::ReplyStruct::Ok;
00405 rs->transactionId = 0;
00406
if (!rs->replySlot.isEmpty())
00407 {
00408 d->parent->handleAsyncReply(rs);
00409 }
00410
return;
00411 }
00412 }
00413 }
00414 qWarning(
"Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
00415
return;
00416
case DCOPCall:
00417
case DCOPFind:
00418
case DCOPSend:
00419 DCOPProcessInternal( d, opcode, key, dataReceived,
true );
00420 }
00421 }
00422
00423
00424
void DCOPClient::processPostedMessagesInternal()
00425 {
00426
if ( d->messages.isEmpty() )
00427
return;
00428
QPtrListIterator<DCOPClientMessage> it (d->messages );
00429 DCOPClientMessage* msg ;
00430
while ( ( msg = it.current() ) ) {
00431 ++it;
00432
if ( d->currentKey && msg->key != d->currentKey )
00433
continue;
00434 d->messages.removeRef( msg );
00435 d->opcode = msg->opcode;
00436 DCOPProcessInternal( d, msg->opcode, msg->key, msg->data,
false );
00437
delete msg;
00438 }
00439
if ( !d->messages.isEmpty() )
00440 d->postMessageTimer.start( 100,
true );
00441 }
00442
00446
void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const QByteArray& dataReceived,
bool canPost )
00447 {
00448
if (!d->accept_calls && (opcode == DCOPSend))
00449
return;
00450
00451 IceConn iceConn = d->iceConn;
00452 DCOPMsg *pMsg = 0;
00453
DCOPClient *c = d->parent;
00454
QDataStream ds( dataReceived, IO_ReadOnly );
00455
00456
QCString fromApp;
00457 ds >> fromApp;
00458
if (fromApp.isEmpty())
00459
return;
00460
00461
if (!d->accept_calls)
00462 {
00463
QByteArray reply;
00464
QDataStream replyStream( reply, IO_WriteOnly );
00465
00466 replyStream << d->appId << fromApp;
00467 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
00468
sizeof(DCOPMsg), DCOPMsg, pMsg );
00469
int datalen = reply.size();
00470 pMsg->key =
key;
00471 pMsg->length += datalen;
00472 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
00473
return;
00474 }
00475
00476
QCString app, objId, fun;
00477
QByteArray data;
00478 ds >> app >> objId >> fun >> data;
00479 d->senderId = fromApp;
00480 d->objId = objId;
00481 d->function = fun;
00482
00483
00484
00485
if ( canPost && d->currentKey &&
key != d->currentKey ) {
00486 DCOPClientMessage* msg =
new DCOPClientMessage;
00487 msg->opcode = opcode;
00488 msg->key =
key;
00489 msg->data = dataReceived;
00490 d->messages.append( msg );
00491 d->postMessageTimer.start( 0,
true );
00492
return;
00493 }
00494
00495 d->objId = objId;
00496 d->function = fun;
00497
00498
QCString replyType;
00499
QByteArray replyData;
00500
bool b;
00501 CARD32 oldCurrentKey = d->currentKey;
00502
if ( opcode != DCOPSend )
00503 d->currentKey =
key;
00504
00505
if ( opcode == DCOPFind )
00506 b = c->
find(app, objId, fun, data, replyType, replyData );
00507
else
00508 b = c->
receive( app, objId, fun, data, replyType, replyData );
00509
00510
00511
if ( opcode == DCOPSend )
00512
return;
00513
00514
if ((d->currentKey ==
key) || (oldCurrentKey != 2))
00515 d->currentKey = oldCurrentKey;
00516
00517
QByteArray reply;
00518
QDataStream replyStream( reply, IO_WriteOnly );
00519
00520 Q_INT32
id = c->
transactionId();
00521
if (
id) {
00522
00523 replyStream << d->appId << fromApp <<
id;
00524
00525 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
00526
sizeof(DCOPMsg), DCOPMsg, pMsg );
00527 pMsg->key =
key;
00528 pMsg->length += reply.size();
00529 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
00530
return;
00531 }
00532
00533
if ( !b ) {
00534
00535
00536 replyStream << d->appId << fromApp;
00537 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
00538
sizeof(DCOPMsg), DCOPMsg, pMsg );
00539
int datalen = reply.size();
00540 pMsg->key =
key;
00541 pMsg->length += datalen;
00542 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
00543
return;
00544 }
00545
00546
00547 replyStream << d->appId << fromApp << replyType << replyData.size();
00548
00549
00550
00551 IceGetHeader( iceConn, d->majorOpcode,
DCOPReply,
00552
sizeof(DCOPMsg), DCOPMsg, pMsg );
00553
int datalen = reply.size() + replyData.size();
00554 pMsg->key =
key;
00555 pMsg->length += datalen;
00556
00557
00558 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
00559 IceSendData( iceConn, replyData.size(), const_cast<char *>(replyData.data()));
00560 }
00561
00562
00563
00564
static IcePoVersionRec DCOPClientVersions[] = {
00565 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
00566 };
00567
00568
00569
static DCOPClient* dcop_main_client = 0;
00570
00571 DCOPClient*
DCOPClient::mainClient()
00572 {
00573
return dcop_main_client;
00574 }
00575
00576 void DCOPClient::setMainClient(
DCOPClient* client )
00577 {
00578 dcop_main_client = client;
00579 }
00580
00581
00582 DCOPClient::DCOPClient()
00583 {
00584 d =
new DCOPClientPrivate;
00585 d->parent =
this;
00586 d->iceConn = 0L;
00587 d->majorOpcode = 0;
00588 d->key = 0;
00589 d->currentKey = 0;
00590 d->appId = 0;
00591 d->notifier = 0L;
00592 d->non_blocking_call_lock =
false;
00593 d->registered =
false;
00594 d->foreign_server =
true;
00595 d->accept_calls =
true;
00596 d->accept_calls_override =
false;
00597 d->qt_bridge_enabled =
true;
00598 d->transactionList = 0L;
00599 d->transactionId = 0;
00600 QObject::connect( &d->postMessageTimer, SIGNAL( timeout() ),
this, SLOT( processPostedMessagesInternal() ) );
00601
00602
if ( !
mainClient() )
00603
setMainClient(
this );
00604 }
00605
00606 DCOPClient::~DCOPClient()
00607 {
00608
if (d->iceConn)
00609
if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
00610
detach();
00611
00612
if (d->registered)
00613 unregisterLocalClient( d->appId );
00614
00615
delete d->notifier;
00616
delete d->transactionList;
00617
delete d;
00618
00619
if (
mainClient() ==
this )
00620
setMainClient( 0 );
00621 }
00622
00623 void DCOPClient::setServerAddress(
const QCString &addr)
00624 {
00625
QCString env =
"DCOPSERVER=" + addr;
00626 putenv(strdup(env.data()));
00627
delete [] DCOPClientPrivate::serverAddr;
00628 DCOPClientPrivate::serverAddr = qstrdup( addr.data() );
00629 }
00630
00631 bool DCOPClient::attach()
00632 {
00633
if (!attachInternal(
true ))
00634
if (!attachInternal(
true ))
00635
return false;
00636
return true;
00637 }
00638
00639
void DCOPClient::bindToApp()
00640 {
00641
00642
00643
if (qApp) {
00644
if ( d->notifier )
00645
delete d->notifier;
00646 d->notifier =
new QSocketNotifier(
socket(),
00647 QSocketNotifier::Read, 0, 0);
00648 QObject::connect(d->notifier, SIGNAL(activated(
int)),
00649 SLOT(processSocketData(
int)));
00650 }
00651 }
00652
00653 void DCOPClient::suspend()
00654 {
00655 assert(d->notifier);
00656 d->notifier->setEnabled(
false);
00657 }
00658
00659 void DCOPClient::resume()
00660 {
00661 assert(d->notifier);
00662 d->notifier->setEnabled(
true);
00663 }
00664
00665 bool DCOPClient::isSuspended()
const
00666
{
00667
return !d->notifier->isEnabled();
00668 }
00669
00670
#ifdef SO_PEERCRED
00671
00672
static bool peerIsUs(
int sockfd)
00673 {
00674
struct ucred cred;
00675 socklen_t siz =
sizeof(cred);
00676
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
00677
return false;
00678
return (cred.uid == getuid());
00679 }
00680
#else
00681
00682
static bool isServerSocketOwnedByUser(
const char*server)
00683 {
00684
if (strncmp(server,
"local/", 6) != 0)
00685
return false;
00686
const char *path = strchr(server,
':');
00687
if (!path)
00688
return false;
00689 path++;
00690
00691
struct stat stat_buf;
00692
if (stat(path, &stat_buf) != 0)
00693
return false;
00694
00695
return (stat_buf.st_uid == getuid());
00696 }
00697
#endif
00698
00699
00700
bool DCOPClient::attachInternal(
bool registerAsAnonymous )
00701 {
00702
char errBuf[1024];
00703
00704
if (
isAttached() )
00705
detach();
00706
00707
extern int _kde_IceLastMajorOpcode;
00708
if (_kde_IceLastMajorOpcode < 1 )
00709 IceRegisterForProtocolSetup(const_cast<char *>(
"DUMMY"),
00710 const_cast<char *>(
"DUMMY"),
00711 const_cast<char *>(
"DUMMY"),
00712 1, DCOPClientVersions,
00713 DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
00714 DCOPClientAuthProcs, 0);
00715
if (_kde_IceLastMajorOpcode < 1 )
00716 qWarning(
"DCOPClient Error: incorrect major opcode!");
00717
00718
if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>(
"DCOP"),
00719 const_cast<char *>(DCOPVendorString),
00720 const_cast<char *>(DCOPReleaseString),
00721 1, DCOPClientVersions,
00722 DCOPAuthCount,
00723 const_cast<char **>(DCOPAuthNames),
00724 DCOPClientAuthProcs, 0L)) < 0) {
00725 emit
attachFailed(QString::fromLatin1(
"Communications could not be established." ));
00726
return false;
00727 }
00728
00729
bool bClearServerAddr =
false;
00730
00731
if (!d->serverAddr) {
00732
00733
00734
QString dcopSrv;
00735 dcopSrv = ::getenv(
"DCOPSERVER");
00736
if (dcopSrv.isEmpty()) {
00737
QString fName = dcopServerFile();
00738
QFile f(fName);
00739
if (!f.open(IO_ReadOnly)) {
00740 emit attachFailed(QString::fromLatin1(
"Could not read network connection list.\n" )+fName);
00741
return false;
00742 }
00743
int size = QMIN( 1024, f.size() );
00744
QCString contents( size+1 );
00745
if ( f.readBlock( contents.data(), size ) != size )
00746 {
00747 qDebug(
"Error reading from %s, didn't read the expected %d bytes", fName.latin1(), size);
00748
00749 }
00750 contents[size] =
'\0';
00751
int pos = contents.find(
'\n');
00752
if ( pos == -1 )
00753 {
00754 qDebug(
"Only one line in dcopserver file !: %s", contents.data());
00755 dcopSrv = QString::fromLatin1(contents);
00756 }
00757
else
00758 {
00759 dcopSrv = QString::fromLatin1(contents.left( pos ));
00760
00761
00762
00763 }
00764 }
00765 d->serverAddr = qstrdup( const_cast<char *>(dcopSrv.latin1()) );
00766 bClearServerAddr =
true;
00767 }
00768
00769
if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
00770 static_cast<IcePointer>(
this), False, d->majorOpcode,
00771
sizeof(errBuf), errBuf)) == 0L) {
00772 qDebug(
"DCOPClient::attachInternal. Attach failed %s", errBuf ? errBuf :
"");
00773 d->iceConn = 0;
00774
if (bClearServerAddr) {
00775
delete [] d->serverAddr;
00776 d->serverAddr = 0;
00777 }
00778 emit attachFailed(QString::fromLatin1( errBuf ));
00779
return false;
00780 }
00781
00782 IceSetShutdownNegotiation(d->iceConn, False);
00783
00784
int setupstat;
00785
char* vendor = 0;
00786
char* release = 0;
00787 setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
00788 static_cast<IcePointer>(d),
00789 False,
00790 &(d->majorVersion), &(d->minorVersion),
00791 &(vendor), &(release), 1024, errBuf);
00792
if (vendor) free(vendor);
00793
if (release) free(release);
00794
00795
if (setupstat == IceProtocolSetupFailure ||
00796 setupstat == IceProtocolSetupIOError) {
00797 IceCloseConnection(d->iceConn);
00798 d->iceConn = 0;
00799
if (bClearServerAddr) {
00800
delete [] d->serverAddr;
00801 d->serverAddr = 0;
00802 }
00803 emit attachFailed(QString::fromLatin1( errBuf ));
00804
return false;
00805 }
else if (setupstat == IceProtocolAlreadyActive) {
00806
if (bClearServerAddr) {
00807
delete [] d->serverAddr;
00808 d->serverAddr = 0;
00809 }
00810
00811 emit attachFailed(QString::fromLatin1(
"internal error in IceOpenConnection" ));
00812
return false;
00813 }
00814
00815
00816
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
00817
if (bClearServerAddr) {
00818
delete [] d->serverAddr;
00819 d->serverAddr = 0;
00820 }
00821 emit attachFailed(QString::fromLatin1(
"DCOP server did not accept the connection." ));
00822
return false;
00823 }
00824
00825
#ifdef SO_PEERCRED
00826
d->foreign_server = !peerIsUs(
socket());
00827
#else
00828
d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
00829
#endif
00830
if (!d->accept_calls_override)
00831 d->accept_calls = !d->foreign_server;
00832
00833 bindToApp();
00834
00835
if ( registerAsAnonymous )
00836
registerAs(
"anonymous",
true );
00837
00838
return true;
00839 }
00840
00841
00842 bool DCOPClient::detach()
00843 {
00844
int status;
00845
00846
if (d->iceConn) {
00847 IceProtocolShutdown(d->iceConn, d->majorOpcode);
00848 status = IceCloseConnection(d->iceConn);
00849
if (status != IceClosedNow)
00850
return false;
00851
else
00852 d->iceConn = 0L;
00853 }
00854
00855
if (d->registered)
00856 unregisterLocalClient(d->appId);
00857
00858
delete d->notifier;
00859 d->notifier = 0L;
00860 d->registered =
false;
00861 d->foreign_server =
true;
00862
return true;
00863 }
00864
00865 bool DCOPClient::isAttached()
const
00866
{
00867
if (!d->iceConn)
00868
return false;
00869
00870
return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
00871 }
00872
00873 bool DCOPClient::isAttachedToForeignServer()
const
00874
{
00875
return isAttached() && d->foreign_server;
00876 }
00877
00878 bool DCOPClient::acceptCalls()
const
00879
{
00880
return isAttached() && d->accept_calls;
00881 }
00882
00883 void DCOPClient::setAcceptCalls(
bool b)
00884 {
00885 d->accept_calls = b;
00886 d->accept_calls_override =
true;
00887 }
00888
00889 bool DCOPClient::qtBridgeEnabled()
00890 {
00891
return d->qt_bridge_enabled;
00892 }
00893
00894 void DCOPClient::setQtBridgeEnabled(
bool b)
00895 {
00896 d->qt_bridge_enabled = b;
00897 }
00898
00899 QCString DCOPClient::registerAs(
const QCString &appId,
bool addPID )
00900 {
00901
QCString result;
00902
00903
QCString _appId = appId;
00904
00905
if (addPID) {
00906
QCString pid;
00907 pid.sprintf(
"-%d", getpid());
00908 _appId = _appId + pid;
00909 }
00910
00911
if( d->appId == _appId )
00912
return d->appId;
00913
00914
#if 0 // no need to detach, dcopserver can handle renaming
00915
00916
if (
isRegistered() ) {
00917
detach();
00918 }
00919
#endif
00920
00921
if ( !
isAttached() ) {
00922
if (!attachInternal(
false ))
00923
if (!attachInternal(
false ))
00924
return result;
00925 }
00926
00927
00928
QCString replyType;
00929
QByteArray data, replyData;
00930
QDataStream arg( data, IO_WriteOnly );
00931 arg << _appId;
00932
if (
call(
"DCOPServer",
"",
"registerAs(QCString)", data, replyType, replyData ) ) {
00933
QDataStream reply( replyData, IO_ReadOnly );
00934 reply >> result;
00935 }
00936
00937 d->appId = result;
00938 d->registered = !result.isNull();
00939
00940
if (d->registered)
00941 registerLocalClient( d->appId,
this );
00942
00943
return result;
00944 }
00945
00946 bool DCOPClient::isRegistered()
const
00947
{
00948
return d->registered;
00949 }
00950
00951
00952 QCString DCOPClient::appId()
const
00953
{
00954
return d->appId;
00955 }
00956
00957
00958 int DCOPClient::socket()
const
00959
{
00960
if (d->iceConn)
00961
return IceConnectionNumber(d->iceConn);
00962
else
00963
return 0;
00964 }
00965
00966
static inline bool isIdentChar(
char x )
00967 {
00968
return x ==
'_' || (x >=
'0' && x <=
'9') ||
00969 (x >=
'a' && x <= 'z') || (x >=
'A' && x <=
'Z');
00970 }
00971
00972 QCString DCOPClient::normalizeFunctionSignature(
const QCString& fun ) {
00973
if ( fun.isEmpty() )
00974
return fun.copy();
00975
QCString result( fun.size() );
00976
char *from = fun.data();
00977
char *to = result.data();
00978
char *first = to;
00979
char last = 0;
00980
while (
true ) {
00981
while ( *from && isspace(*from) )
00982 from++;
00983
if ( last && isIdentChar( last ) && isIdentChar( *from ) )
00984 *to++ = 0x20;
00985
while ( *from && !isspace(*from) ) {
00986 last = *from++;
00987 *to++ = last;
00988 }
00989
if ( !*from )
00990
break;
00991 }
00992
if ( to > first && *(to-1) == 0x20 )
00993 to--;
00994 *to =
'\0';
00995 result.resize( (
int)((
long)to - (
long)result.data()) + 1 );
00996
return result;
00997 }
00998
00999
01000 QCString DCOPClient::senderId()
const
01001
{
01002
return d->senderId;
01003 }
01004
01005
01006 bool DCOPClient::send(
const QCString &remApp,
const QCString &remObjId,
01007
const QCString &remFun,
const QByteArray &data)
01008 {
01009
if (remApp.isEmpty())
01010
return false;
01011
DCOPClient *localClient =
findLocalClient( remApp );
01012
01013
if ( localClient ) {
01014
bool saveTransaction = d->transaction;
01015 Q_INT32 saveTransactionId = d->transactionId;
01016
QCString saveSenderId = d->senderId;
01017
01018 d->senderId = 0;
01019
QCString replyType;
01020
QByteArray replyData;
01021 (
void) localClient->
receive( remApp, remObjId, remFun, data, replyType, replyData );
01022
01023 d->transaction = saveTransaction;
01024 d->transactionId = saveTransactionId;
01025 d->senderId = saveSenderId;
01026
01027
01028
01029
01030
return true;
01031 }
01032
01033
if ( !
isAttached() )
01034
return false;
01035
01036
01037 DCOPMsg *pMsg;
01038
01039
QByteArray ba;
01040
QDataStream ds(ba, IO_WriteOnly);
01041 ds << d->appId << remApp << remObjId <<
normalizeFunctionSignature(remFun) << data.size();
01042
01043 IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
01044
sizeof(DCOPMsg), DCOPMsg, pMsg);
01045
01046 pMsg->key = 1;
01047
int datalen = ba.size() + data.size();
01048 pMsg->length += datalen;
01049
01050 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
01051 IceSendData( d->iceConn, data.size(), const_cast<char *>(data.data()) );
01052
01053
01054
01055
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
01056
return false;
01057
else
01058
return true;
01059 }
01060
01061 bool DCOPClient::send(
const QCString &remApp,
const QCString &remObjId,
01062
const QCString &remFun,
const QString &data)
01063 {
01064
QByteArray ba;
01065
QDataStream ds(ba, IO_WriteOnly);
01066 ds << data;
01067
return send(remApp, remObjId, remFun, ba);
01068 }
01069
01070 bool DCOPClient::findObject(
const QCString &remApp,
const QCString &remObj,
01071
const QCString &remFun,
const QByteArray &data,
01072
QCString &foundApp,
QCString &foundObj,
01073
bool useEventLoop)
01074 {
01075
return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
01076 }
01077
01078 bool DCOPClient::findObject(
const QCString &remApp,
const QCString &remObj,
01079
const QCString &remFun,
const QByteArray &data,
01080
QCString &foundApp,
QCString &foundObj,
01081
bool useEventLoop,
int timeout)
01082 {
01083
QCStringList appList;
01084
QCString app = remApp;
01085
if (app.isEmpty())
01086 app =
"*";
01087
01088 foundApp = 0;
01089 foundObj = 0;
01090
01091
if (app[app.length()-1] ==
'*')
01092 {
01093
01094
01095
01096
int len = app.length()-1;
01097
QCStringList apps=
registeredApplications();
01098
for( QCStringList::ConstIterator it = apps.begin();
01099 it != apps.end();
01100 ++it)
01101 {
01102
if ( strncmp( (*it).data(), app.data(), len) == 0)
01103 appList.append(*it);
01104 }
01105 }
01106
else
01107 {
01108 appList.append(app);
01109 }
01110
01111
01112
for(
int phase=1; phase <= 2; phase++)
01113 {
01114
for( QCStringList::ConstIterator it = appList.begin();
01115 it != appList.end();
01116 ++it)
01117 {
01118
QCString remApp = *it;
01119
QCString replyType;
01120
QByteArray replyData;
01121
bool result;
01122
DCOPClient *localClient =
findLocalClient( remApp );
01123
01124
if ( (phase == 1) && localClient ) {
01125
01126
bool saveTransaction = d->transaction;
01127 Q_INT32 saveTransactionId = d->transactionId;
01128
QCString saveSenderId = d->senderId;
01129
01130 d->senderId = 0;
01131 result = localClient->
find( remApp, remObj, remFun, data, replyType, replyData );
01132
01133 Q_INT32
id = localClient->
transactionId();
01134
if (
id) {
01135
01136
do {
01137 QApplication::eventLoop()->processEvents( QEventLoop::WaitForMore);
01138 }
while( !localClient->
isLocalTransactionFinished(
id, replyType, replyData));
01139 result =
true;
01140 }
01141 d->transaction = saveTransaction;
01142 d->transactionId = saveTransactionId;
01143 d->senderId = saveSenderId;
01144 }
01145
else if ((phase == 2) && !localClient)
01146 {
01147
01148 result = callInternal(remApp, remObj, remFun, data,
01149 replyType, replyData, useEventLoop, timeout, DCOPFind);
01150 }
01151
01152
if (result)
01153 {
01154
if (replyType ==
"DCOPRef")
01155 {
01156
DCOPRef ref;
01157
QDataStream reply( replyData, IO_ReadOnly );
01158 reply >> ref;
01159
01160
if (ref.app() == remApp)
01161 {
01162
01163 foundApp = ref.app();
01164 foundObj = ref.object();
01165
return true;
01166 }
01167 }
01168 }
01169 }
01170 }
01171
return false;
01172 }
01173
01174 bool DCOPClient::process(
const QCString &,
const QByteArray &,
01175
QCString&,
QByteArray &)
01176 {
01177
return false;
01178 }
01179
01180 bool DCOPClient::isApplicationRegistered(
const QCString& remApp)
01181 {
01182
QCString replyType;
01183
QByteArray data, replyData;
01184
QDataStream arg( data, IO_WriteOnly );
01185 arg << remApp;
01186
int result =
false;
01187
if (
call(
"DCOPServer",
"",
"isApplicationRegistered(QCString)", data, replyType, replyData ) ) {
01188
QDataStream reply( replyData, IO_ReadOnly );
01189 reply >> result;
01190 }
01191
return result;
01192 }
01193
01194 QCStringList DCOPClient::registeredApplications()
01195 {
01196
QCString replyType;
01197
QByteArray data, replyData;
01198
QCStringList result;
01199
if (
call(
"DCOPServer",
"",
"registeredApplications()", data, replyType, replyData ) ) {
01200
QDataStream reply( replyData, IO_ReadOnly );
01201 reply >> result;
01202 }
01203
return result;
01204 }
01205
01206 QCStringList DCOPClient::remoteObjects(
const QCString& remApp,
bool *ok )
01207 {
01208
QCString replyType;
01209
QByteArray data, replyData;
01210
QCStringList result;
01211
if ( ok )
01212 *ok =
false;
01213
if (
call( remApp,
"DCOPClient",
"objects()", data, replyType, replyData ) ) {
01214
QDataStream reply( replyData, IO_ReadOnly );
01215 reply >> result;
01216
if ( ok )
01217 *ok =
true;
01218 }
01219
return result;
01220 }
01221
01222 QCStringList DCOPClient::remoteInterfaces(
const QCString& remApp,
const QCString& remObj,
bool *ok )
01223 {
01224
QCString replyType;
01225
QByteArray data, replyData;
01226
QCStringList result;
01227
if ( ok )
01228 *ok =
false;
01229
if (
call( remApp, remObj,
"interfaces()", data, replyType, replyData ) && replyType ==
"QCStringList") {
01230
QDataStream reply( replyData, IO_ReadOnly );
01231 reply >> result;
01232
if ( ok )
01233 *ok =
true;
01234 }
01235
return result;
01236 }
01237
01238 QCStringList DCOPClient::remoteFunctions(
const QCString& remApp,
const QCString& remObj,
bool *ok )
01239 {
01240
QCString replyType;
01241
QByteArray data, replyData;
01242
QCStringList result;
01243
if ( ok )
01244 *ok =
false;
01245
if (
call( remApp, remObj,
"functions()", data, replyType, replyData ) && replyType ==
"QCStringList") {
01246
QDataStream reply( replyData, IO_ReadOnly );
01247 reply >> result;
01248
if ( ok )
01249 *ok =
true;
01250 }
01251
return result;
01252 }
01253
01254 void DCOPClient::setNotifications(
bool enabled)
01255 {
01256
QByteArray data;
01257
QDataStream ds(data, IO_WriteOnly);
01258 ds << static_cast<Q_INT8>(enabled);
01259
01260
QCString replyType;
01261
QByteArray reply;
01262
if (!
call(
"DCOPServer",
"",
"setNotifications( bool )", data, replyType, reply))
01263 qWarning(
"I couldn't enable notifications at the dcopserver!");
01264 }
01265
01266 void DCOPClient::setDaemonMode(
bool daemonMode )
01267 {
01268
QByteArray data;
01269
QDataStream ds(data, IO_WriteOnly);
01270 ds << static_cast<Q_INT8>( daemonMode );
01271
01272
QCString replyType;
01273
QByteArray reply;
01274
if (!
call(
"DCOPServer",
"",
"setDaemonMode(bool)", data, replyType, reply))
01275 qWarning(
"I couldn't enable daemon mode at the dcopserver!");
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285
static void fillQtObjects(
QCStringList& l,
QObject* o,
QCString path )
01286 {
01287
if ( !path.isEmpty() )
01288 path +=
'/';
01289
01290
int unnamed = 0;
01291
const QObjectList *list = o ? o->children() :
QObject::objectTrees();
01292
if ( list ) {
01293 QObjectListIt it( *list );
01294
QObject *obj;
01295
while ( (obj=it.current()) ) {
01296 ++it;
01297
QCString n = obj->name();
01298
if ( n ==
"unnamed" || n.isEmpty() )
01299 {
01300 n.sprintf(
"%p", (
void *) obj);
01301 n =
QString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(n).latin1();
01302 }
01303
QCString fn = path + n;
01304 l.append( fn );
01305
if ( obj->children() )
01306 fillQtObjects( l, obj, fn );
01307 }
01308 }
01309 }
01310
01311
namespace
01312
{
01313
struct O
01314 {
01315 O(): o(0) {}
01316 O (
const QCString& str,
QObject* obj ):s(str), o(obj){}
01317
QCString s;
01318
QObject* o;
01319 };
01320 }
01321
01322
static void fillQtObjectsEx(
QValueList<O>& l,
QObject* o,
QCString path )
01323 {
01324
if ( !path.isEmpty() )
01325 path +=
'/';
01326
01327
int unnamed = 0;
01328
const QObjectList *list = o ? o->children() :
QObject::objectTrees();
01329
if ( list ) {
01330 QObjectListIt it( *list );
01331
QObject *obj;
01332
while ( (obj=it.current()) ) {
01333 ++it;
01334
QCString n = obj->name();
01335
if ( n ==
"unnamed" || n.isEmpty() )
01336 {
01337 n.sprintf(
"%p", (
void *) obj);
01338 n =
QString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(n).latin1();
01339 }
01340
QCString fn = path + n;
01341 l.append( O( fn, obj ) );
01342
if ( obj->children() )
01343 fillQtObjectsEx( l, obj, fn );
01344 }
01345 }
01346 }
01347
01348
01349
static QObject* findQtObject(
QCString id )
01350 {
01351
QRegExp expr(
id );
01352
QValueList<O> l;
01353 fillQtObjectsEx( l, 0,
"qt" );
01354
01355
QObject* firstContains = 0L;
01356
for (
QValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
01357
if ( (*it).s ==
id )
01358
return (*it).o;
01359
if ( !firstContains && (*it).s.contains( expr ) ) {
01360 firstContains = (*it).o;
01361 }
01362 }
01363
return firstContains;
01364 }
01365
01366
static QCStringList findQtObjects(
QCString id )
01367 {
01368
QRegExp expr(
id );
01369
QValueList<O> l;
01370 fillQtObjectsEx( l, 0,
"qt" );
01371
QCStringList result;
01372
for (
QValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
01373
if ( (*it).s.contains( expr ) )
01374 result << (*it).s;
01375 }
01376
return result;
01377 }
01378
01379
static bool receiveQtObject(
const QCString &objId,
const QCString &fun,
const QByteArray &data,
01380
QCString& replyType,
QByteArray &replyData)
01381 {
01382
if ( objId ==
"qt" ) {
01383
if ( fun ==
"interfaces()" ) {
01384 replyType =
"QCStringList";
01385
QDataStream reply( replyData, IO_WriteOnly );
01386
QCStringList l;
01387 l <<
"DCOPObject";
01388 l <<
"Qt";
01389 reply << l;
01390
return true;
01391 }
else if ( fun ==
"functions()" ) {
01392 replyType =
"QCStringList";
01393
QDataStream reply( replyData, IO_WriteOnly );
01394
QCStringList l;
01395 l <<
"QCStringList functions()";
01396 l <<
"QCStringList interfaces()";
01397 l <<
"QCStringList objects()";
01398 l <<
"QCStringList find(QCString)";
01399 reply << l;
01400
return true;
01401 }
else if ( fun ==
"objects()" ) {
01402 replyType =
"QCStringList";
01403
QDataStream reply( replyData, IO_WriteOnly );
01404
QCStringList l;
01405 fillQtObjects( l, 0,
"qt" );
01406 reply << l;
01407
return true;
01408 }
else if ( fun ==
"find(QCString)" ) {
01409
QDataStream ds( data, IO_ReadOnly );
01410
QCString id;
01411 ds >>
id ;
01412 replyType =
"QCStringList";
01413
QDataStream reply( replyData, IO_WriteOnly );
01414 reply << findQtObjects(
id ) ;
01415
return true;
01416 }
01417 }
else if ( objId.left(3) ==
"qt/" ) {
01418
QObject* o = findQtObject( objId );
01419
if ( !o )
01420
return false;
01421
if ( fun ==
"functions()" ) {
01422 replyType =
"QCStringList";
01423
QDataStream reply( replyData, IO_WriteOnly );
01424
QCStringList l;
01425 l <<
"QCStringList functions()";
01426 l <<
"QCStringList interfaces()";
01427 l <<
"QCStringList properties()";
01428 l <<
"bool setProperty(QCString,QVariant)";
01429 l <<
"QVariant property(QCString)";
01430
QStrList lst = o->metaObject()->slotNames(
true );
01431
int i = 0;
01432
for (
QPtrListIterator<char> it( lst ); it.current(); ++it ) {
01433
if ( o->metaObject()->slot( i++,
true )->access != QMetaData::Public )
01434
continue;
01435
QCString slot = it.current();
01436
if ( slot.contains(
"()" ) ) {
01437 slot.prepend(
"void ");
01438 l << slot;
01439 }
01440 }
01441 reply << l;
01442
return true;
01443 }
else if ( fun ==
"interfaces()" ) {
01444 replyType =
"QCStringList";
01445
QDataStream reply( replyData, IO_WriteOnly );
01446
QCStringList l;
01447
QMetaObject *meta = o->metaObject();
01448
while ( meta ) {
01449 l.prepend( meta->
className() );
01450 meta = meta->
superClass();
01451 }
01452 reply << l;
01453
return true;
01454 }
else if ( fun ==
"properties()" ) {
01455 replyType =
"QCStringList";
01456
QDataStream reply( replyData, IO_WriteOnly );
01457
QCStringList l;
01458
QStrList lst = o->metaObject()->propertyNames(
true );
01459
for (
QPtrListIterator<char> it( lst ); it.current(); ++it ) {
01460
QMetaObject *mo = o->metaObject();
01461
const QMetaProperty* p = mo->
property( mo->findProperty( it.current(),
true ),
true );
01462
if ( !p )
01463
continue;
01464
QCString prop = p->type();
01465 prop +=
' ';
01466 prop += p->name();
01467
if ( !p->writable() )
01468 prop +=
" readonly";
01469 l << prop;
01470 }
01471 reply << l;
01472
return true;
01473 }
else if ( fun ==
"property(QCString)" ) {
01474 replyType =
"QVariant";
01475
QDataStream ds( data, IO_ReadOnly );
01476
QCString name;
01477 ds >>
name ;
01478
QVariant result = o->property( name );
01479
QDataStream reply( replyData, IO_WriteOnly );
01480 reply << result;
01481
return true;
01482 }
else if ( fun ==
"setProperty(QCString,QVariant)" ) {
01483
QDataStream ds( data, IO_ReadOnly );
01484
QCString name;
01485
QVariant value;
01486 ds >>
name >> value;
01487 replyType =
"bool";
01488
QDataStream reply( replyData, IO_WriteOnly );
01489 reply << (Q_INT8) o->setProperty( name, value );
01490
return true;
01491 }
else {
01492
int slot = o->metaObject()->findSlot( fun,
true );
01493
if ( slot != -1 ) {
01494 replyType =
"void";
01495 QUObject uo[ 1 ];
01496 o->qt_invoke( slot, uo );
01497
return true;
01498 }
01499 }
01500
01501
01502 }
01503
return false;
01504 }
01505
01506
01507
01508
01509
01510
01511
01512
01513
bool DCOPClient::receive(
const QCString &,
const QCString &objId,
01514
const QCString &fun,
const QByteArray &data,
01515
QCString& replyType,
QByteArray &replyData)
01516 {
01517 d->transaction =
false;
01518
if ( objId ==
"DCOPClient" ) {
01519
if ( fun ==
"objects()" ) {
01520 replyType =
"QCStringList";
01521
QDataStream reply( replyData, IO_WriteOnly );
01522
QCStringList l;
01523
if (d->qt_bridge_enabled)
01524 {
01525 l <<
"qt";
01526 }
01527
if ( kde_dcopObjMap ) {
01528
QMap<QCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
01529
for (; it != kde_dcopObjMap->end(); ++it) {
01530
if ( !it.key().isEmpty() ) {
01531
if ( it.key() == d->defaultObject )
01532 l <<
"default";
01533 l << it.key();
01534 }
01535 }
01536 }
01537 reply << l;
01538
return true;
01539 }
01540 }
01541
01542
if ( objId.isEmpty() || objId ==
"DCOPClient" ) {
01543
if ( fun ==
"applicationRegistered(QCString)" ) {
01544
QDataStream ds( data, IO_ReadOnly );
01545
QCString r;
01546 ds >> r;
01547 emit
applicationRegistered( r );
01548
return true;
01549 }
else if ( fun ==
"applicationRemoved(QCString)" ) {
01550
QDataStream ds( data, IO_ReadOnly );
01551
QCString r;
01552 ds >> r;
01553 emit
applicationRemoved( r );
01554
return true;
01555 }
01556
01557
if (
process( fun, data, replyType, replyData ) )
01558
return true;
01559
01560
01561 }
else if (d->qt_bridge_enabled &&
01562 (objId ==
"qt" || objId.left(3) ==
"qt/") ) {
01563
return receiveQtObject( objId, fun, data, replyType, replyData );
01564 }
01565
01566
if ( objId.isEmpty() || objId ==
"default" ) {
01567
if ( !d->defaultObject.isEmpty() &&
DCOPObject::hasObject( d->defaultObject ) ) {
01568
DCOPObject *objPtr =
DCOPObject::find( d->defaultObject );
01569 objPtr->
setCallingDcopClient(
this);
01570
if (objPtr->
process(fun, data, replyType, replyData))
01571
return true;
01572 }
01573
01574
01575 }
01576
01577
if (!objId.isEmpty() && objId[objId.length()-1] ==
'*') {
01578
01579
01580
QPtrList<DCOPObject> matchList =
01581
DCOPObject::match(objId.left(objId.length()-1));
01582
for (
DCOPObject *objPtr = matchList.first();
01583 objPtr != 0L; objPtr = matchList.next()) {
01584 objPtr->
setCallingDcopClient(
this);
01585
if (!objPtr->
process(fun, data, replyType, replyData))
01586
return false;
01587 }
01588
return true;
01589 }
else if (!
DCOPObject::hasObject(objId)) {
01590
if ( DCOPObjectProxy::proxies ) {
01591
for (
QPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
01592
01593
if ( it.current()->process( objId, fun, data, replyType, replyData ) )
01594
return true;
01595 }
01596 }
01597
return false;
01598
01599 }
else {
01600
DCOPObject *objPtr =
DCOPObject::find(objId);
01601 objPtr->
setCallingDcopClient(
this);
01602
if (!objPtr->
process(fun, data, replyType, replyData)) {
01603
01604
return false;
01605 }
01606 }
01607
01608
return true;
01609 }
01610
01611
01612
01613
01614
static bool findResultOk(
QCString &replyType,
QByteArray &replyData)
01615 {
01616 Q_INT8 success;
01617
if (replyType !=
"bool")
return false;
01618
01619
QDataStream reply( replyData, IO_ReadOnly );
01620 reply >> success;
01621
01622
if (!success)
return false;
01623
return true;
01624 }
01625
01626
01627
01628
static bool findSuccess(
const QCString &app,
const QCString objId,
QCString &replyType,
QByteArray &replyData)
01629 {
01630
DCOPRef ref(app, objId);
01631 replyType =
"DCOPRef";
01632
01633 replyData =
QByteArray();
01634
QDataStream final_reply( replyData, IO_WriteOnly );
01635 final_reply << ref;
01636
return true;
01637 }
01638
01639
01640
bool DCOPClient::find(
const QCString &app,
const QCString &objId,
01641
const QCString &fun,
const QByteArray &data,
01642
QCString& replyType,
QByteArray &replyData)
01643 {
01644 d->transaction =
false;
01645
if ( !app.isEmpty() && app != d->appId && app[app.length()-1] !=
'*') {
01646 qWarning(
"WEIRD! we somehow received a DCOP message w/a different appId");
01647
return false;
01648 }
01649
01650
if (objId.isEmpty() || objId[objId.length()-1] !=
'*')
01651 {
01652
if (fun.isEmpty())
01653 {
01654
if (objId.isEmpty() ||
DCOPObject::hasObject(objId))
01655
return findSuccess(app, objId, replyType, replyData);
01656
return false;
01657 }
01658
01659
if (receive(app, objId, fun, data, replyType, replyData))
01660 {
01661
if (findResultOk(replyType, replyData))
01662
return findSuccess(app, objId, replyType, replyData);
01663 }
01664 }
01665
else {
01666
01667
01668
QPtrList<DCOPObject> matchList =
01669
DCOPObject::match(objId.left(objId.length()-1));
01670
for (
DCOPObject *objPtr = matchList.first();
01671 objPtr != 0L; objPtr = matchList.next())
01672 {
01673 replyType = 0;
01674 replyData =
QByteArray();
01675
if (fun.isEmpty())
01676
return findSuccess(app, objPtr->
objId(), replyType, replyData);
01677 objPtr->
setCallingDcopClient(
this);
01678
if (objPtr->
process(fun, data, replyType, replyData))
01679
if (findResultOk(replyType, replyData))
01680
return findSuccess(app, objPtr->
objId(), replyType, replyData);
01681 }
01682 }
01683
return false;
01684 }
01685
01686
01687 bool DCOPClient::call(
const QCString &remApp,
const QCString &remObjId,
01688
const QCString &remFun,
const QByteArray &data,
01689
QCString& replyType,
QByteArray &replyData,
01690
bool useEventLoop)
01691 {
01692
return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1 );
01693 }
01694
01695 bool DCOPClient::call(
const QCString &remApp,
const QCString &remObjId,
01696
const QCString &remFun,
const QByteArray &data,
01697
QCString& replyType,
QByteArray &replyData,
01698
bool useEventLoop,
int timeout)
01699 {
01700
if (remApp.isEmpty())
01701
return false;
01702
DCOPClient *localClient =
findLocalClient( remApp );
01703
01704
if ( localClient ) {
01705
bool saveTransaction = d->transaction;
01706 Q_INT32 saveTransactionId = d->transactionId;
01707
QCString saveSenderId = d->senderId;
01708
01709 d->senderId = 0;
01710
bool b = localClient->
receive( remApp, remObjId, remFun, data, replyType, replyData );
01711
01712 Q_INT32
id = localClient->
transactionId();
01713
if (
id) {
01714
01715
do {
01716 QApplication::eventLoop()->processEvents( QEventLoop::WaitForMore);
01717 }
while( !localClient->
isLocalTransactionFinished(
id, replyType, replyData));
01718 b =
true;
01719 }
01720 d->transaction = saveTransaction;
01721 d->transactionId = saveTransactionId;
01722 d->senderId = saveSenderId;
01723
return b;
01724 }
01725
01726
return callInternal(remApp, remObjId, remFun, data,
01727 replyType, replyData, useEventLoop, timeout, DCOPCall);
01728 }
01729
01730
void DCOPClient::asyncReplyReady()
01731 {
01732
while( d->asyncReplyQueue.count() )
01733 {
01734 ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
01735 handleAsyncReply(replyStruct);
01736 }
01737 }
01738
01739 int DCOPClient::callAsync(
const QCString &remApp,
const QCString &remObjId,
01740
const QCString &remFun,
const QByteArray &data,
01741
QObject *callBackObj,
const char *callBackSlot)
01742 {
01743
QCString replyType;
01744
QByteArray replyData;
01745
01746 ReplyStruct *replyStruct =
new ReplyStruct;
01747 replyStruct->replyType =
new QCString;
01748 replyStruct->replyData =
new QByteArray;
01749 replyStruct->replyObject = callBackObj;
01750 replyStruct->replySlot = callBackSlot;
01751 replyStruct->replyId = ++d->transactionId;
01752
if (d->transactionId < 0)
01753 d->transactionId = 0;
01754
01755
bool b = callInternal(remApp, remObjId, remFun, data,
01756 replyStruct,
false, -1, DCOPCall);
01757
if (!b)
01758 {
01759
delete replyStruct->replyType;
01760
delete replyStruct->replyData;
01761
delete replyStruct;
01762
return 0;
01763 }
01764
01765
if (replyStruct->transactionId == 0)
01766 {
01767
01768 QTimer::singleShot(0,
this, SLOT(asyncReplyReady()));
01769 d->asyncReplyQueue.append(replyStruct);
01770 }
01771
01772
return replyStruct->replyId;
01773 }
01774
01775
bool DCOPClient::callInternal(
const QCString &remApp,
const QCString &remObjId,
01776
const QCString &remFun,
const QByteArray &data,
01777
QCString& replyType,
QByteArray &replyData,
01778
bool useEventLoop,
int timeout,
int minor_opcode)
01779 {
01780 ReplyStruct replyStruct;
01781 replyStruct.replyType = &replyType;
01782 replyStruct.replyData = &replyData;
01783
return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
01784 }
01785
01786
bool DCOPClient::callInternal(
const QCString &remApp,
const QCString &remObjId,
01787
const QCString &remFun,
const QByteArray &data,
01788 ReplyStruct *replyStruct,
01789
bool useEventLoop,
int timeout,
int minor_opcode)
01790 {
01791
if ( !
isAttached() )
01792
return false;
01793
01794 DCOPMsg *pMsg;
01795
01796 CARD32 oldCurrentKey = d->currentKey;
01797
if ( !d->currentKey )
01798 d->currentKey = d->key;
01799
01800
QByteArray ba;
01801
QDataStream ds(ba, IO_WriteOnly);
01802 ds << d->appId << remApp << remObjId <<
normalizeFunctionSignature(remFun) << data.size();
01803
01804 IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
01805
sizeof(DCOPMsg), DCOPMsg, pMsg);
01806
01807 pMsg->key = d->currentKey;
01808
int datalen = ba.size() + data.size();
01809 pMsg->length += datalen;
01810
01811
01812
01813 IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
01814 IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
01815
01816
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
01817
return false;
01818
01819 IceFlush (d->iceConn);
01820
01821 IceReplyWaitInfo waitInfo;
01822 waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
01823 waitInfo.major_opcode_of_request = d->majorOpcode;
01824 waitInfo.minor_opcode_of_request = minor_opcode;
01825
01826 replyStruct->transactionId = -1;
01827 waitInfo.reply = static_cast<IcePointer>(replyStruct);
01828
01829 Bool readyRet = False;
01830 IceProcessMessagesStatus s;
01831
01832 timeval time_start;
01833
if( timeout >= 0 )
01834 gettimeofday( &time_start, NULL );
01835
for(;;) {
01836
bool timed_out =
false;
01837
if ( useEventLoop
01838 ? d->notifier != NULL
01839 : timeout >= 0 ) {
01840
01841
int msecs = useEventLoop
01842 ? 100
01843 : timeout;
01844 fd_set fds;
01845
struct timeval tv;
01846 FD_ZERO( &fds );
01847 FD_SET(
socket(), &fds );
01848 tv.tv_sec = msecs / 1000;
01849 tv.tv_usec = (msecs % 1000) * 1000;
01850
if ( select(
socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
01851
if( useEventLoop ) {
01852
01853
01854
bool old_lock = d->non_blocking_call_lock;
01855
if ( !old_lock ) {
01856 d->non_blocking_call_lock =
true;
01857 emit
blockUserInput(
true );
01858 }
01859 qApp->enter_loop();
01860
if ( !old_lock ) {
01861 d->non_blocking_call_lock =
false;
01862 emit
blockUserInput(
false );
01863 }
01864 }
01865
else
01866 timed_out =
true;
01867 }
01868 }
01869
if (!d->iceConn)
01870
return false;
01871
01872
if( replyStruct->transactionId != -1 )
01873 {
01874
if (replyStruct->transactionId == 0)
01875
break;
01876
if (!replyStruct->replySlot.isEmpty())
01877
break;
01878 }
01879
01880
if( !timed_out ) {
01881 s = IceProcessMessages(d->iceConn, &waitInfo,
01882 &readyRet);
01883
if (s == IceProcessMessagesIOError) {
01884
detach();
01885 d->currentKey = oldCurrentKey;
01886
return false;
01887 }
01888 }
01889
01890
if( replyStruct->transactionId != -1 )
01891 {
01892
if (replyStruct->transactionId == 0)
01893
break;
01894
if (!replyStruct->replySlot.isEmpty())
01895
break;
01896 }
01897
01898
if( timeout < 0 )
01899
continue;
01900 timeval time_now;
01901 gettimeofday( &time_now, NULL );
01902
if( time_start.tv_sec * 1000000 + time_start.tv_usec + timeout * 1000
01903 < time_now.tv_sec * 1000000 + time_now.tv_usec ) {
01904 *(replyStruct->replyType) =
QCString();
01905 *(replyStruct->replyData) =
QByteArray();
01906 replyStruct->status = ReplyStruct::Failed;
01907
break;
01908 }
01909 }
01910
01911
01912
if ( d->non_blocking_call_lock ) {
01913 qApp->exit_loop();
01914 }
01915
01916 d->currentKey = oldCurrentKey;
01917
return replyStruct->status != ReplyStruct::Failed;
01918 }
01919
01920 void DCOPClient::processSocketData(
int fd)
01921 {
01922
01923 fd_set fds;
01924 timeval timeout;
01925 timeout.tv_sec = 0;
01926 timeout.tv_usec = 0;
01927 FD_ZERO(&fds);
01928 FD_SET(fd, &fds);
01929
int result = select(fd+1, &fds, 0, 0, &timeout);
01930
if (result == 0)
01931
return;
01932
01933
if ( d->non_blocking_call_lock ) {
01934 qApp->exit_loop();
01935
return;
01936 }
01937
01938
if (!d->iceConn) {
01939 d->notifier->deleteLater();
01940 d->notifier = 0;
01941 qWarning(
"received an error processing data from the DCOP server!");
01942
return;
01943 }
01944
01945 IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
01946
01947
if (s == IceProcessMessagesIOError) {
01948
detach();
01949 qWarning(
"received an error processing data from the DCOP server!");
01950
return;
01951 }
01952 }
01953
01954 void DCOPClient::setDefaultObject(
const QCString& objId )
01955 {
01956 d->defaultObject = objId;
01957 }
01958
01959
01960 QCString DCOPClient::defaultObject()
const
01961
{
01962
return d->defaultObject;
01963 }
01964
01965
bool
01966 DCOPClient::isLocalTransactionFinished(Q_INT32
id,
QCString &replyType,
QByteArray &replyData)
01967 {
01968 DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(
id);
01969
if (!result)
01970
return false;
01971
01972 replyType = result->replyType;
01973 replyData = result->replyData;
01974
delete result;
01975
01976
return true;
01977 }
01978
01979 DCOPClientTransaction *
01980 DCOPClient::beginTransaction()
01981 {
01982
if (d->opcode == DCOPSend)
01983
return 0;
01984
if (!d->transactionList)
01985 d->transactionList =
new QPtrList<DCOPClientTransaction>;
01986
01987 d->transaction =
true;
01988 DCOPClientTransaction *trans =
new DCOPClientTransaction();
01989 trans->senderId = d->senderId;
01990 trans->id = ++d->transactionId;
01991
if (d->transactionId < 0)
01992 d->transactionId = 0;
01993 trans->key = d->currentKey;
01994
01995 d->transactionList->append( trans );
01996
01997
return trans;
01998 }
01999
02000 Q_INT32
02001 DCOPClient::transactionId()
const
02002
{
02003
if (d->transaction)
02004
return d->transactionId;
02005
else
02006
return 0;
02007 }
02008
02009
void
02010 DCOPClient::endTransaction( DCOPClientTransaction *trans,
QCString& replyType,
02011
QByteArray &replyData)
02012 {
02013
if ( !trans )
02014
return;
02015
02016
if ( !
isAttached() )
02017
return;
02018
02019
if ( !d->transactionList) {
02020 qWarning(
"Transaction unknown: No pending transactions!");
02021
return;
02022 }
02023
02024
if ( !d->transactionList->removeRef( trans ) ) {
02025 qWarning(
"Transaction unknown: Not on list of pending transactions!");
02026
return;
02027 }
02028
02029
if (trans->senderId.isEmpty())
02030 {
02031
02032 DCOPClientPrivate::LocalTransactionResult *result =
new DCOPClientPrivate::LocalTransactionResult();
02033 result->replyType = replyType;
02034 result->replyData = replyData;
02035
02036 d->localTransActionList.insert(trans->id, result);
02037
02038
delete trans;
02039
02040
return;
02041 }
02042
02043 DCOPMsg *pMsg;
02044
02045
QByteArray ba;
02046
QDataStream ds(ba, IO_WriteOnly);
02047 ds << d->appId << trans->senderId << trans->id << replyType << replyData;
02048
02049 IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
02050
sizeof(DCOPMsg), DCOPMsg, pMsg);
02051
02052 pMsg->key = trans->key;
02053 pMsg->length += ba.size();
02054
02055 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
02056
02057
delete trans;
02058 }
02059
02060
void
02061 DCOPClient::emitDCOPSignal(
const QCString &object,
const QCString &signal,
const QByteArray &data)
02062 {
02063
02064
send(
"DCOPServer",
"emit", object+
"#"+normalizeFunctionSignature(signal), data);
02065 }
02066
02067
void
02068 DCOPClient::emitDCOPSignal(
const QCString &signal,
const QByteArray &data)
02069 {
02070 emitDCOPSignal(0, signal, data);
02071 }
02072
02073
bool
02074 DCOPClient::connectDCOPSignal(
const QCString &sender,
const QCString &senderObj,
02075
const QCString &signal,
02076
const QCString &receiverObj,
const QCString &slot,
bool Volatile)
02077 {
02078
QCString replyType;
02079
QByteArray data, replyData;
02080 Q_INT8 iVolatile = Volatile ? 1 : 0;
02081
02082
QDataStream args(data, IO_WriteOnly );
02083 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
02084
02085
if (!
call(
"DCOPServer", 0,
02086
"connectSignal(QCString,QCString,QCString,QCString,QCString,bool)",
02087 data, replyType, replyData))
02088 {
02089
return false;
02090 }
02091
02092
if (replyType !=
"bool")
02093
return false;
02094
02095
QDataStream reply(replyData, IO_ReadOnly );
02096 Q_INT8 result;
02097 reply >> result;
02098
return (result != 0);
02099 }
02100
02101
bool
02102 DCOPClient::connectDCOPSignal(
const QCString &sender,
const QCString &signal,
02103
const QCString &receiverObj,
const QCString &slot,
bool Volatile)
02104 {
02105
return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
02106 }
02107
02108
bool
02109 DCOPClient::disconnectDCOPSignal(
const QCString &sender,
const QCString &senderObj,
02110
const QCString &signal,
02111
const QCString &receiverObj,
const QCString &slot)
02112 {
02113
QCString replyType;
02114
QByteArray data, replyData;
02115
02116
QDataStream args(data, IO_WriteOnly );
02117 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
02118
02119
if (!
call(
"DCOPServer", 0,
02120
"disconnectSignal(QCString,QCString,QCString,QCString,QCString)",
02121 data, replyType, replyData))
02122 {
02123
return false;
02124 }
02125
02126
if (replyType !=
"bool")
02127
return false;
02128
02129
QDataStream reply(replyData, IO_ReadOnly );
02130 Q_INT8 result;
02131 reply >> result;
02132
return (result != 0);
02133 }
02134
02135
bool
02136 DCOPClient::disconnectDCOPSignal(
const QCString &sender,
const QCString &signal,
02137
const QCString &receiverObj,
const QCString &slot)
02138 {
02139
return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
02140 }
02141
02142
void
02143 DCOPClient::setPriorityCall(
bool b)
02144 {
02145
if (b)
02146 {
02147
if (d->currentKey == 2)
02148
return;
02149 d->currentKeySaved = d->currentKey;
02150 d->currentKey = 2;
02151 }
02152
else
02153 {
02154
if (d->currentKey != 2)
02155
return;
02156 d->currentKey = d->currentKeySaved;
02157
if ( !d->messages.isEmpty() )
02158 d->postMessageTimer.start( 0,
true );
02159 }
02160 }
02161
02162
02163
02164
void
02165 DCOPClient::emergencyClose()
02166 {
02167
QPtrList<DCOPClient> list;
02168 client_map_t *map = DCOPClient_CliMap;
02169
if (!map)
return;
02170
QAsciiDictIterator<DCOPClient> it(*map);
02171
while(it.current()) {
02172 list.removeRef(it.current());
02173 list.append(it.current());
02174 ++it;
02175 }
02176
for(
DCOPClient *cl = list.first(); cl; cl = list.next())
02177 {
02178
if (cl->
d->iceConn) {
02179 IceProtocolShutdown(cl->
d->iceConn, cl->
d->majorOpcode);
02180 IceCloseConnection(cl->
d->iceConn);
02181 cl->
d->iceConn = 0L;
02182 }
02183 }
02184 }
02185
02186
const char *
02187 DCOPClient::postMortemSender()
02188 {
02189
if (!dcop_main_client)
02190
return "";
02191
if (dcop_main_client->
d->senderId.isEmpty())
02192
return "";
02193
return dcop_main_client->
d->senderId.data();
02194 }
02195
02196
const char *
02197 DCOPClient::postMortemObject()
02198 {
02199
if (!dcop_main_client)
02200
return "";
02201
return dcop_main_client->
d->objId.data();
02202 }
02203
const char *
02204 DCOPClient::postMortemFunction()
02205 {
02206
if (!dcop_main_client)
02207
return "";
02208
return dcop_main_client->
d->function.data();
02209 }
02210
02211
void DCOPClient::virtual_hook(
int,
void* )
02212 { }
02213
02214
#include <dcopclient.moc>
02215