dcop Library API Documentation

dcopclient.cpp

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