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> // schroder 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 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 // static 00287 QCString DCOPClient::dcopServerFile(const QCString &hostname) 00288 { 00289 return ::dcopServerFile(hostname, false); 00290 } 00291 00292 00293 // static 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 /*swap*/, 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; // received a key from the server 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; // Reserved for local calls 00460 00461 if (!d->accept_calls) 00462 { 00463 QByteArray reply; 00464 QDataStream replyStream( reply, IO_WriteOnly ); 00465 // Call rejected. 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 // qWarning("DCOP: %s got call: %s:%s:%s key = %d currentKey = %d", d->appId.data(), app.data(), objId.data(), fun.data(), key, d->currentKey); 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 ) // DCOPSend doesn't change the current key 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 // set notifier back to previous state 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 // Call delayed. Send back the transaction ID. 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 // Call failed. No data send back. 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 // Call successful. Send back replyType and replyData. 00547 replyStream << d->appId << fromApp << replyType << replyData.size(); 00548 00549 00550 // we are calling, so we need to set up reply data 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 // use IceSendData not IceWriteData to avoid a copy. Output buffer 00557 // shouldn't need to be flushed. 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; // Try two times! 00636 return true; 00637 } 00638 00639 void DCOPClient::bindToApp() 00640 { 00641 // check if we have a qApp instantiated. If we do, 00642 // we can create a QSocketNotifier and use it for receiving data. 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); // Suspending makes no sense if we didn't had a qApp yet 00656 d->notifier->setEnabled(false); 00657 } 00658 00659 void DCOPClient::resume() 00660 { 00661 assert(d->notifier); // Should never happen 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 // Check whether the remote end is owned by the same user. 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 // Check whether the socket is owned by the same user. 00682 static bool isServerSocketOwnedByUser(const char*server) 00683 { 00684 if (strncmp(server, "local/", 6) != 0) 00685 return false; // Not a local socket -> foreign. 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; // from libICE 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 // first, check if serverAddr was ever set. 00731 if (!d->serverAddr) { 00732 // here, we obtain the list of possible DCOP connections, 00733 // and attach to them. 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() ); // protection against a huge file 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 // Should we abort ? 00749 } 00750 contents[size] = '\0'; 00751 int pos = contents.find('\n'); 00752 if ( pos == -1 ) // Shouldn't happen 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 //#ifndef NDEBUG 00761 // qDebug("dcopserver address: %s", dcopSrv.latin1()); 00762 //#endif 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, /* must authenticate */ 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 /* should not happen because 3rd arg to IceOpenConnection was 0. */ 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 // Detach before reregistering. 00916 if ( isRegistered() ) { 00917 detach(); 00918 } 00919 #endif 00920 00921 if ( !isAttached() ) { 00922 if (!attachInternal( false )) 00923 if (!attachInternal( false )) 00924 return result; // Try two times 00925 } 00926 00927 // register the application identifier with the server 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 { // Avoid bug in isalnum 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() ) // nothing to do 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; // Local call 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 // send() returns true if the data could be send to the DCOPServer, 01027 // regardles of receiving the data on the other application. 01028 // So we assume the data is successfully send to the (virtual) server 01029 // and return true in any case. 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; // DCOPSend always uses the magic 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 //IceFlush(d->iceConn); 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 // Find all apps that match 'app'. 01094 // NOTE: It would be more efficient to do the filtering in 01095 // the dcopserver itself. 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 // We do all the local clients in phase1 and the rest in phase2 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 // In phase 1 we do all local clients 01126 bool saveTransaction = d->transaction; 01127 Q_INT32 saveTransactionId = d->transactionId; 01128 QCString saveSenderId = d->senderId; 01129 01130 d->senderId = 0; // Local call 01131 result = localClient->find( remApp, remObj, remFun, data, replyType, replyData ); 01132 01133 Q_INT32 id = localClient->transactionId(); 01134 if (id) { 01135 // Call delayed. We have to wait till it has been processed. 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 // In phase 2 we do the other clients 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) // Consistency check 01161 { 01162 // replyType contains objId. 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 DCOP <-> Qt bridge 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 } // namespace 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 // Prefer an exact match, but fall-back on the first that contains the substring 01355 QObject* firstContains = 0L; 01356 for ( QValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) { 01357 if ( (*it).s == id ) // exact match 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 End of DCOP <-> Qt bridge 01510 */ 01511 01512 01513 bool DCOPClient::receive(const QCString &/*app*/, const QCString &objId, 01514 const QCString &fun, const QByteArray &data, 01515 QCString& replyType, QByteArray &replyData) 01516 { 01517 d->transaction = false; // Assume no transaction. 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"; // the Qt bridge object 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 // fall through and send to defaultObject if available 01560 01561 } else if (d->qt_bridge_enabled && 01562 (objId == "qt" || objId.left(3) == "qt/") ) { // dcop <-> qt bridge 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 // fall through and send to object proxies 01575 } 01576 01577 if (!objId.isEmpty() && objId[objId.length()-1] == '*') { 01578 // handle a multicast to several objects. 01579 // doesn't handle proxies currently. should it? 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 // TODO: it.current()->setCallingDcopClient(this); 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 // obj doesn't understand function or some other error. 01604 return false; 01605 } 01606 } 01607 01608 return true; 01609 } 01610 01611 // Check if the function result is a bool with the value "true" 01612 // If so set the function result to DCOPRef pointing to (app,objId) and 01613 // return true. Return false otherwise. 01614 static bool findResultOk(QCString &replyType, QByteArray &replyData) 01615 { 01616 Q_INT8 success; // Tsk.. why is there no operator>>(bool)? 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 // set the function result to DCOPRef pointing to (app,objId) and 01627 // return true. 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; // Transactions are not allowed. 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 // Message to application or single object... 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 // handle a multicast to several objects. 01667 // doesn't handle proxies currently. should it? 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; // Local call 01710 bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData ); 01711 01712 Q_INT32 id = localClient->transactionId(); 01713 if (id) { 01714 // Call delayed. We have to wait till it has been processed. 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) // Ensure that ids > 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 // Call is finished already 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; // no key yet, initiate new call 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 // qWarning("DCOP: %s made call %s:%s:%s key = %d", d->appId.data(), remApp.data(), remObjId.data(), remFun.data(), pMsg->key); 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 // useEventLoop needs a socket notifier and a qApp 01839 : timeout >= 0 ) { // !useEventLoop doesn't block only for timeout >= 0 01840 01841 int msecs = useEventLoop 01842 ? 100 // timeout for the GUI refresh 01843 : timeout; // timeout for the whole call 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 // nothing was available, we got a timeout. Reactivate 01853 // the GUI in blocked state. 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; // Call complete 01876 if (!replyStruct->replySlot.isEmpty()) 01877 break; // Async call 01878 } 01879 01880 if( !timed_out ) { // something is available 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; // Call complete 01894 if (!replyStruct->replySlot.isEmpty()) 01895 break; // Async call 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 ) { // timeout 01904 *(replyStruct->replyType) = QCString(); 01905 *(replyStruct->replyData) = QByteArray(); 01906 replyStruct->status = ReplyStruct::Failed; 01907 break; 01908 } 01909 } 01910 01911 // Wake up parent call, maybe it's reply is available already. 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 // Make sure there is data to read! 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) // Ensure that ids > 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; // No pending transactions! 02022 } 02023 02024 if ( !d->transactionList->removeRef( trans ) ) { 02025 qWarning("Transaction unknown: Not on list of pending transactions!"); 02026 return; // Transaction 02027 } 02028 02029 if (trans->senderId.isEmpty()) 02030 { 02031 // Local transaction 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 // We hack the sending object name into the signal name 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 ); // Process queued messages 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 { /*BASE::virtual_hook( id, data );*/ } 02213 02214 #include <dcopclient.moc> 02215
KDE Logo
This file is part of the documentation for dcop Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:13:47 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003