26 #include <tqobjectlist.h>
27 #include <tqmetaobject.h>
28 #include <tqvariant.h>
30 #include <tqintdict.h>
31 #include <tqeventloop.h>
40 #include <sys/types.h>
43 #include <sys/socket.h>
53 #ifndef QT_CLEAN_NAMESPACE
54 #define QT_CLEAN_NAMESPACE
56 #include <tqguardedptr.h>
57 #include <tqtextstream.h>
60 #include <tqapplication.h>
61 #include <tqsocketnotifier.h>
64 #include <tqucomextra_p.h>
66 #include <dcopglobal.h>
67 #include <dcopclient.h>
68 #include <dcopobject.h>
70 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
74 #include <KDE-ICE/ICElib.h>
75 #include <KDE-ICE/ICEutil.h>
76 #include <KDE-ICE/ICEmsg.h>
77 #include <KDE-ICE/ICEproto.h>
82 extern TQMap<TQCString, DCOPObject *> * kde_dcopObjMap;
87 typedef TQAsciiDict<DCOPClient> client_map_t;
88 static client_map_t *DCOPClient_CliMap = 0;
91 client_map_t *cliMap()
93 if (!DCOPClient_CliMap)
94 DCOPClient_CliMap =
new client_map_t;
95 return DCOPClient_CliMap;
100 return cliMap()->find(_appId.data());
104 void registerLocalClient(
const TQCString &_appId,
DCOPClient *client )
106 cliMap()->replace(_appId.data(), client);
110 void unregisterLocalClient(
const TQCString &_appId )
112 client_map_t *map = cliMap();
113 map->remove(_appId.data());
117 template class TQPtrList<DCOPObjectProxy>;
118 template class TQPtrList<DCOPClientTransaction>;
119 template class TQPtrList<_IceConn>;
121 struct DCOPClientMessage
128 class DCOPClient::ReplyStruct
131 enum ReplyStatus { Pending, Ok, Failed };
141 TQCString* replyType;
142 TQByteArray* replyData;
144 TQ_INT32 transactionId;
146 TQGuardedPtr<TQObject> replyObject;
150 class DCOPClientPrivate
158 int majorVersion, minorVersion;
160 static const char* serverAddr;
161 TQSocketNotifier *notifier;
162 bool non_blocking_call_lock;
166 bool accept_calls_override;
167 bool qt_bridge_enabled;
173 TQCString defaultObject;
174 TQPtrList<DCOPClientTransaction> *transactionList;
176 TQ_INT32 transactionId;
186 CARD32 currentKeySaved;
188 TQTimer postMessageTimer;
189 TQPtrList<DCOPClientMessage> messages;
191 TQPtrList<DCOPClient::ReplyStruct> pendingReplies;
192 TQPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
194 struct LocalTransactionResult
197 TQByteArray replyData;
200 TQIntDict<LocalTransactionResult> localTransActionList;
202 TQTimer eventLoopTimer;
205 class DCOPClientTransaction
219 ret = SearchPathA(NULL,
"iceauth.exe",NULL,
sizeof(szPath)/
sizeof(szPath[0]),szPath,&pszFilePart);
221 return TQCString(szPath);
223 TQCString path = ::getenv(
"PATH");
225 path =
"/bin:/usr/bin";
226 path +=
":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
227 TQCString fPath = strtok(path.data(),
":\b");
228 while (!fPath.isNull())
231 if (access(fPath.data(), X_OK) == 0)
236 fPath = strtok(NULL,
":\b");
242 static TQCString dcopServerFile(
const TQCString &hostname,
bool old)
244 TQCString fName = ::getenv(
"DCOPAUTHORITY");
245 if (!old && !fName.isEmpty())
248 fName = TQFile::encodeName( TQDir::homeDirPath() );
252 fprintf(stderr,
"Aborting. $HOME is not set.\n");
256 TQCString disp = getenv(
"DISPLAY");
257 #elif defined(Q_WS_QWS)
258 TQCString disp = getenv(
"QWS_DISPLAY");
266 if((i = disp.findRev(
'.')) > disp.findRev(KPATH_SEPARATOR) && i >= 0)
271 while( (i = disp.find(KPATH_SEPARATOR)) >= 0)
275 fName +=
"/.DCOPserver_";
276 if (hostname.isEmpty())
280 if (getenv(
"XAUTHLOCALHOSTNAME"))
281 fName += getenv(
"XAUTHLOCALHOSTNAME");
282 else if (gethostname(hostName,
sizeof(hostName)))
284 fName +=
"localhost";
288 hostName[
sizeof(hostName)-1] =
'\0';
315 const char* DCOPClientPrivate::serverAddr = 0;
317 static void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const TQByteArray& dataReceived,
bool canPost );
319 void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
321 if (replyStruct->replyObject)
323 TQObject::connect(
this, TQT_SIGNAL(callBack(
int,
const TQCString&,
const TQByteArray &)),
324 replyStruct->replyObject, replyStruct->replySlot);
325 emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
326 TQObject::disconnect(
this, TQT_SIGNAL(callBack(
int,
const TQCString&,
const TQByteArray &)),
327 replyStruct->replyObject, replyStruct->replySlot);
335 static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
336 int opcode,
unsigned long length, Bool ,
337 IceReplyWaitInfo *replyWait,
341 DCOPClientPrivate *d =
static_cast<DCOPClientPrivate *
>(clientObject);
342 DCOPClient::ReplyStruct *replyStruct = replyWait ?
static_cast<DCOPClient::ReplyStruct*
>(replyWait->reply) : 0;
344 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
345 CARD32
key = pMsg->key;
349 TQByteArray dataReceived( length );
350 IceReadData(iceConn, length, dataReceived.data() );
355 case DCOPReplyFailed:
357 replyStruct->status = DCOPClient::ReplyStruct::Failed;
358 replyStruct->transactionId = 0;
359 *replyWaitRet = True;
362 tqWarning(
"Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
367 TQByteArray* b = replyStruct->replyData;
368 TQCString* t = replyStruct->replyType;
369 replyStruct->status = DCOPClient::ReplyStruct::Ok;
370 replyStruct->transactionId = 0;
372 TQCString calledApp, app;
373 TQDataStream ds( dataReceived, IO_ReadOnly );
374 ds >> calledApp >> app >> *t >> *b;
376 *replyWaitRet = True;
379 tqWarning(
"Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
384 TQCString calledApp, app;
386 TQDataStream ds( dataReceived, IO_ReadOnly );
387 ds >> calledApp >> app >> id;
388 replyStruct->transactionId = id;
389 replyStruct->calledApp = calledApp;
390 d->pendingReplies.append(replyStruct);
391 *replyWaitRet = True;
394 tqWarning(
"Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
397 case DCOPReplyDelayed:
399 TQDataStream ds( dataReceived, IO_ReadOnly );
400 TQCString calledApp, app;
403 ds >> calledApp >> app >> id;
404 if (replyStruct && (
id == replyStruct->transactionId) && (calledApp == replyStruct->calledApp))
406 *replyWaitRet = True;
409 for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
410 rs = d->pendingReplies.next())
412 if ((rs->transactionId ==
id) && (rs->calledApp == calledApp))
414 d->pendingReplies.remove();
415 TQByteArray* b = rs->replyData;
416 TQCString* t = rs->replyType;
419 rs->status = DCOPClient::ReplyStruct::Ok;
420 rs->transactionId = 0;
421 if (!rs->replySlot.isEmpty())
423 d->parent->handleAsyncReply(rs);
429 tqWarning(
"Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
434 DCOPProcessInternal( d, opcode, key, dataReceived,
true );
438 void DCOPClient::processPostedMessagesInternal()
440 if ( d->messages.isEmpty() )
442 TQPtrListIterator<DCOPClientMessage> it (d->messages );
443 DCOPClientMessage* msg ;
444 while ( ( msg = it.current() ) ) {
446 if ( d->currentKey && msg->key != d->currentKey )
448 d->messages.removeRef( msg );
449 d->opcode = msg->opcode;
450 DCOPProcessInternal( d, msg->opcode, msg->key, msg->data,
false );
453 if ( !d->messages.isEmpty() )
454 d->postMessageTimer.start( 100,
true );
460 void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const TQByteArray& dataReceived,
bool canPost )
462 if (!d->accept_calls && (opcode == DCOPSend))
465 IceConn iceConn = d->iceConn;
468 TQDataStream ds( dataReceived, IO_ReadOnly );
472 if (fromApp.isEmpty())
475 if (!d->accept_calls)
478 TQDataStream replyStream( reply, IO_WriteOnly );
480 replyStream << d->appId << fromApp;
481 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
482 sizeof(DCOPMsg), DCOPMsg, pMsg );
483 int datalen = reply.size();
485 pMsg->length += datalen;
486 IceSendData( iceConn, datalen, reply.data());
490 TQCString app, objId, fun;
492 ds >> app >> objId >> fun >> data;
493 d->senderId = fromApp;
499 if ( canPost && d->currentKey && key != d->currentKey ) {
500 DCOPClientMessage* msg =
new DCOPClientMessage;
501 msg->opcode = opcode;
503 msg->data = dataReceived;
504 d->messages.append( msg );
505 d->postMessageTimer.start( 0,
true );
513 TQByteArray replyData;
515 CARD32 oldCurrentKey = d->currentKey;
516 if ( opcode != DCOPSend )
519 if ( opcode == DCOPFind )
520 b = c->find(app, objId, fun, data, replyType, replyData );
522 b = c->receive( app, objId, fun, data, replyType, replyData );
525 if ( opcode == DCOPSend )
528 if ((d->currentKey == key) || (oldCurrentKey != 2))
529 d->currentKey = oldCurrentKey;
532 TQDataStream replyStream( reply, IO_WriteOnly );
537 replyStream << d->appId << fromApp << id;
539 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
540 sizeof(DCOPMsg), DCOPMsg, pMsg );
542 pMsg->length += reply.size();
543 IceSendData( iceConn, reply.size(),
const_cast<char *
>(reply.data()));
550 replyStream << d->appId << fromApp;
551 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
552 sizeof(DCOPMsg), DCOPMsg, pMsg );
553 int datalen = reply.size();
555 pMsg->length += datalen;
556 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
561 replyStream << d->appId << fromApp << replyType << replyData.size();
565 IceGetHeader( iceConn, d->majorOpcode,
DCOPReply,
566 sizeof(DCOPMsg), DCOPMsg, pMsg );
567 int datalen = reply.size() + replyData.size();
569 pMsg->length += datalen;
572 IceSendData( iceConn, reply.size(),
const_cast<char *
>(reply.data()));
573 IceSendData( iceConn, replyData.size(),
const_cast<char *
>(replyData.data()));
578 static IcePoVersionRec DCOPClientVersions[] = {
579 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
587 return dcop_main_client;
592 dcop_main_client = client;
598 d =
new DCOPClientPrivate;
606 d->non_blocking_call_lock =
false;
607 d->registered =
false;
608 d->foreign_server =
true;
609 d->accept_calls =
true;
610 d->accept_calls_override =
false;
611 d->qt_bridge_enabled =
true;
612 d->transactionList = 0L;
613 d->transactionId = 0;
614 TQObject::connect( &d->postMessageTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( processPostedMessagesInternal() ) );
615 TQObject::connect( &d->eventLoopTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( eventLoopTimeout() ) );
623 #ifdef DCOPCLIENT_DEBUG
624 tqWarning(
"d->messages.count() = %d", d->messages.count());
625 TQPtrListIterator<DCOPClientMessage> it (d->messages );
626 DCOPClientMessage* msg ;
627 while ( ( msg = it.current() ) ) {
629 d->messages.removeRef( msg );
630 tqWarning(
"DROPPING UNHANDLED DCOP MESSAGE:");
631 tqWarning(
" opcode = %d key = %d", msg->opcode, msg->key);
632 TQDataStream ds( msg->data, IO_ReadOnly );
634 TQCString fromApp, app, objId, fun;
635 ds >> fromApp >> app >> objId >> fun;
636 tqWarning(
" from = %s", fromApp.data());
637 tqWarning(
" to = %s / %s / %s", app.data(), objId.data(), fun.data());
642 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
646 unregisterLocalClient( d->appId );
649 delete d->transactionList;
650 d->messages.setAutoDelete(
true);
659 TQCString env =
"DCOPSERVER=" + addr;
660 putenv(strdup(env.data()));
661 delete [] DCOPClientPrivate::serverAddr;
662 DCOPClientPrivate::serverAddr = tqstrdup( addr.data() );
667 if (!attachInternal(
true ))
668 if (!attachInternal(
true ))
673 void DCOPClient::bindToApp()
680 d->notifier =
new TQSocketNotifier(
socket(),
681 TQSocketNotifier::Read, 0, 0);
682 TQObject::connect(d->notifier, TQT_SIGNAL(activated(
int)),
689 #ifdef Q_WS_WIN //TODO: remove (win32 ports sometimes do not create notifiers)
694 d->notifier->setEnabled(
false);
699 #ifdef Q_WS_WIN //TODO: remove
704 d->notifier->setEnabled(
true);
709 #if defined(Q_WS_WIN) || defined(Q_WS_MAC) //TODO: REMOVE
713 return !d->notifier->isEnabled();
718 static bool peerIsUs(
int sockfd)
720 #if defined(__OpenBSD__)
721 struct sockpeercred cred;
725 socklen_t siz =
sizeof(cred);
726 if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
728 return (cred.uid == getuid());
732 static bool isServerSocketOwnedByUser(
const char*server)
735 if (strncmp(server,
"tcp/", 4) != 0)
740 if (strncmp(server,
"local/", 6) != 0)
742 const char *path = strchr(server, KPATH_SEPARATOR);
747 struct stat stat_buf;
748 if (stat(path, &stat_buf) != 0)
751 return (stat_buf.st_uid == getuid());
757 bool DCOPClient::attachInternal(
bool registerAsAnonymous )
764 if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>(
"DCOP"),
765 const_cast<char *>(DCOPVendorString),
766 const_cast<char *>(DCOPReleaseString),
767 1, DCOPClientVersions,
769 const_cast<char **>(DCOPAuthNames),
770 DCOPClientAuthProcs, 0L)) < 0) {
771 emit
attachFailed(TQString::fromLatin1(
"Communications could not be established." ));
775 bool bClearServerAddr =
false;
777 if (!d->serverAddr) {
781 dcopSrv = ::getenv(
"DCOPSERVER");
782 if (dcopSrv.isEmpty()) {
784 TQFile f(TQFile::decodeName(fName));
785 if (!f.open(IO_ReadOnly)) {
786 emit
attachFailed(TQString::fromLatin1(
"Could not read network connection list.\n" )+TQFile::decodeName(fName));
789 int size = TQMIN( (qint64)1024, f.size() );
790 TQCString contents( size+1 );
791 if ( f.readBlock( contents.data(), size ) != size )
793 tqDebug(
"Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
796 contents[size] =
'\0';
797 int pos = contents.find(
'\n');
800 tqDebug(
"Only one line in dcopserver file !: %s", contents.data());
805 if(contents[pos - 1] ==
'\r')
807 dcopSrv = contents.left( pos );
813 d->serverAddr = tqstrdup( const_cast<char *>(dcopSrv.data()) );
814 bClearServerAddr =
true;
817 if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
818 static_cast<IcePointer>(
this), False, d->majorOpcode,
819 sizeof(errBuf), errBuf)) == 0L) {
820 tqDebug(
"DCOPClient::attachInternal. Attach failed %s", errBuf);
822 if (bClearServerAddr) {
823 delete [] d->serverAddr;
829 fcntl(
socket(), F_SETFL, FD_CLOEXEC);
831 IceSetShutdownNegotiation(d->iceConn, False);
836 setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
837 static_cast<IcePointer>(d),
839 &(d->majorVersion), &(d->minorVersion),
840 &(vendor), &(release), 1024, errBuf);
841 if (vendor) free(vendor);
842 if (release) free(release);
844 if (setupstat == IceProtocolSetupFailure ||
845 setupstat == IceProtocolSetupIOError) {
846 IceCloseConnection(d->iceConn);
848 if (bClearServerAddr) {
849 delete [] d->serverAddr;
854 }
else if (setupstat == IceProtocolAlreadyActive) {
855 if (bClearServerAddr) {
856 delete [] d->serverAddr;
860 emit
attachFailed(TQString::fromLatin1(
"internal error in IceOpenConnection" ));
865 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
866 if (bClearServerAddr) {
867 delete [] d->serverAddr;
870 emit
attachFailed(TQString::fromLatin1(
"DCOP server did not accept the connection." ));
875 d->foreign_server = !peerIsUs(
socket());
877 d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
879 if (!d->accept_calls_override)
880 d->accept_calls = !d->foreign_server;
884 if ( registerAsAnonymous )
896 IceProtocolShutdown(d->iceConn, d->majorOpcode);
897 status = IceCloseConnection(d->iceConn);
898 if (status != IceClosedNow)
905 unregisterLocalClient(d->appId);
909 d->registered =
false;
910 d->foreign_server =
true;
919 return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
935 d->accept_calls_override =
true;
940 return d->qt_bridge_enabled;
945 d->qt_bridge_enabled = b;
952 TQCString _appId =
appId;
956 pid.sprintf(
"-%d", getpid());
957 _appId = _appId + pid;
960 if( d->appId == _appId )
963 #if 0 // no need to detach, dcopserver can handle renaming
971 if (!attachInternal(
false ))
972 if (!attachInternal(
false ))
978 TQByteArray data, replyData;
979 TQDataStream arg( data, IO_WriteOnly );
981 if (
call(
"DCOPServer",
"",
"registerAs(TQCString)", data, replyType, replyData ) ) {
982 TQDataStream reply( replyData, IO_ReadOnly );
987 d->registered = !result.isNull();
990 registerLocalClient( d->appId,
this );
997 return d->registered;
1010 return IceConnectionNumber(d->iceConn);
1014 static inline bool isIdentChar(
char x )
1016 return x ==
'_' || (x >=
'0' && x <=
'9') ||
1017 (x >=
'a' && x <=
'z') || (x >=
'A' && x <=
'Z');
1021 if ( fun.isEmpty() )
1023 TQCString result( fun.size() );
1024 char *from =
const_cast<TQCString&
>(fun).data();
1025 char *to = result.data();
1029 while ( *from && isspace(*from) )
1031 if ( last && isIdentChar( last ) && isIdentChar( *from ) )
1033 while ( *from && !isspace(*from) ) {
1040 if ( to > first && *(to-1) == 0x20 )
1043 result.resize( (
int)((
long)to - (
long)result.data()) + 1 );
1055 const TQCString &remFun,
const TQByteArray &data)
1057 if (remApp.isEmpty())
1061 if ( localClient ) {
1062 bool saveTransaction = d->transaction;
1063 TQ_INT32 saveTransactionId = d->transactionId;
1064 TQCString saveSenderId = d->senderId;
1067 TQCString replyType;
1068 TQByteArray replyData;
1069 (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1071 d->transaction = saveTransaction;
1072 d->transactionId = saveTransactionId;
1073 d->senderId = saveSenderId;
1088 TQDataStream ds(ba, IO_WriteOnly);
1091 IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
1092 sizeof(DCOPMsg), DCOPMsg, pMsg);
1095 int datalen = ba.size() + data.size();
1096 pMsg->length += datalen;
1098 IceSendData( d->iceConn, ba.size(),
const_cast<char *
>(ba.data()) );
1099 IceSendData( d->iceConn, data.size(),
const_cast<char *
>(data.data()) );
1103 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
1109 const TQCString &remFun,
const TQString &data)
1112 TQDataStream ds(ba, IO_WriteOnly);
1114 return send(remApp, remObjId, remFun, ba);
1118 const TQCString &remFun,
const TQByteArray &data,
1119 TQCString &foundApp, TQCString &foundObj,
1122 return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
1126 const TQCString &remFun,
const TQByteArray &data,
1127 TQCString &foundApp, TQCString &foundObj,
1128 bool useEventLoop,
int timeout)
1130 QCStringList appList;
1131 TQCString app = remApp;
1138 if (app[app.length()-1] ==
'*')
1143 int len = app.length()-1;
1145 for( QCStringList::ConstIterator it = apps.begin();
1149 if ( strncmp( (*it).data(), app.data(), len) == 0)
1150 appList.append(*it);
1155 appList.append(app);
1159 for(
int phase=1; phase <= 2; phase++)
1161 for( QCStringList::ConstIterator it = appList.begin();
1162 it != appList.end();
1165 TQCString remApp = *it;
1166 TQCString replyType;
1167 TQByteArray replyData;
1168 bool result =
false;
1171 if ( (phase == 1) && localClient ) {
1173 bool saveTransaction = d->transaction;
1174 TQ_INT32 saveTransactionId = d->transactionId;
1175 TQCString saveSenderId = d->senderId;
1178 result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
1184 TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1185 }
while( !localClient->isLocalTransactionFinished(
id, replyType, replyData));
1188 d->transaction = saveTransaction;
1189 d->transactionId = saveTransactionId;
1190 d->senderId = saveSenderId;
1192 else if ((phase == 2) && !localClient)
1195 result = callInternal(remApp, remObj, remFun, data,
1196 replyType, replyData, useEventLoop, timeout, DCOPFind);
1201 if (replyType ==
"DCOPRef")
1204 TQDataStream reply( replyData, IO_ReadOnly );
1207 if (ref.app() == remApp)
1210 foundApp = ref.
app();
1211 foundObj = ref.object();
1222 TQCString&, TQByteArray &)
1229 TQCString replyType;
1230 TQByteArray data, replyData;
1231 TQDataStream arg( data, IO_WriteOnly );
1234 if (
call(
"DCOPServer",
"",
"isApplicationRegistered(TQCString)", data, replyType, replyData ) ) {
1235 TQDataStream reply( replyData, IO_ReadOnly );
1243 TQCString replyType;
1244 TQByteArray data, replyData;
1245 QCStringList result;
1246 if (
call(
"DCOPServer",
"",
"registeredApplications()", data, replyType, replyData ) ) {
1247 TQDataStream reply( replyData, IO_ReadOnly );
1255 TQCString replyType;
1256 TQByteArray data, replyData;
1257 QCStringList result;
1260 if (
call( remApp,
"DCOPClient",
"objects()", data, replyType, replyData ) ) {
1261 TQDataStream reply( replyData, IO_ReadOnly );
1271 TQCString replyType;
1272 TQByteArray data, replyData;
1273 QCStringList result;
1276 if (
call( remApp, remObj,
"interfaces()", data, replyType, replyData ) && replyType ==
"QCStringList") {
1277 TQDataStream reply( replyData, IO_ReadOnly );
1287 TQCString replyType;
1288 TQByteArray data, replyData;
1289 QCStringList result;
1292 if (
call( remApp, remObj,
"functions()", data, replyType, replyData ) && replyType ==
"QCStringList") {
1293 TQDataStream reply( replyData, IO_ReadOnly );
1304 TQDataStream ds(data, IO_WriteOnly);
1305 ds << static_cast<TQ_INT8>(enabled);
1307 TQCString replyType;
1309 if (!
call(
"DCOPServer",
"",
"setNotifications( bool )", data, replyType, reply))
1310 tqWarning(
"I couldn't enable notifications at the dcopserver!");
1316 TQDataStream ds(data, IO_WriteOnly);
1317 ds << static_cast<TQ_INT8>( daemonMode );
1319 TQCString replyType;
1321 if (!
call(
"DCOPServer",
"",
"setDaemonMode(bool)", data, replyType, reply))
1322 tqWarning(
"I couldn't enable daemon mode at the dcopserver!");
1332 static void fillQtObjects( QCStringList& l, TQObject* o, TQCString path )
1334 if ( !path.isEmpty() )
1338 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1339 if ( !list.isEmpty() ) {
1340 TQObjectListIt it( list );
1342 while ( (obj=it.current()) ) {
1344 TQCString n = obj->name();
1345 if ( n ==
"unnamed" || n.isEmpty() )
1347 n.sprintf(
"%p", (
void *) obj);
1348 n = TQString(TQString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1350 TQCString fn = path + n;
1352 if ( !obj->childrenListObject().isEmpty() )
1353 fillQtObjects( l, obj, fn );
1363 O (
const TQCString& str, TQObject* obj ):s(str), o(obj){}
1369 static void fillQtObjectsEx( TQValueList<O>& l, TQObject* o, TQCString path )
1371 if ( !path.isEmpty() )
1375 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1376 if ( !list.isEmpty() ) {
1377 TQObjectListIt it( list );
1379 while ( (obj=it.current()) ) {
1381 TQCString n = obj->name();
1382 if ( n ==
"unnamed" || n.isEmpty() )
1384 n.sprintf(
"%p", (
void *) obj);
1385 n = TQString(TQString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1387 TQCString fn = path + n;
1388 l.append( O( fn, obj ) );
1389 if ( !obj->childrenListObject().isEmpty() )
1390 fillQtObjectsEx( l, obj, fn );
1396 static TQObject* findQtObject( TQCString
id )
1398 TQRegExp expr(
id );
1400 fillQtObjectsEx( l, 0,
"qt" );
1402 TQObject* firstContains = 0L;
1403 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1404 if ( (*it).s ==
id )
1406 if ( !firstContains && (*it).s.contains( expr ) ) {
1407 firstContains = (*it).o;
1410 return firstContains;
1413 static QCStringList findQtObjects( TQCString
id )
1415 TQRegExp expr(
id );
1417 fillQtObjectsEx( l, 0,
"qt" );
1418 QCStringList result;
1419 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1420 if ( (*it).s.contains( expr ) )
1426 static bool receiveQtObject(
const TQCString &objId,
const TQCString &fun,
const TQByteArray &data,
1427 TQCString& replyType, TQByteArray &replyData)
1429 if ( objId ==
"qt" ) {
1430 if ( fun ==
"interfaces()" ) {
1431 replyType =
"QCStringList";
1432 TQDataStream reply( replyData, IO_WriteOnly );
1438 }
else if ( fun ==
"functions()" ) {
1439 replyType =
"QCStringList";
1440 TQDataStream reply( replyData, IO_WriteOnly );
1442 l <<
"QCStringList functions()";
1443 l <<
"QCStringList interfaces()";
1444 l <<
"QCStringList objects()";
1445 l <<
"QCStringList find(TQCString)";
1448 }
else if ( fun ==
"objects()" ) {
1449 replyType =
"QCStringList";
1450 TQDataStream reply( replyData, IO_WriteOnly );
1452 fillQtObjects( l, 0,
"qt" );
1455 }
else if ( fun ==
"find(TQCString)" ) {
1456 TQDataStream ds( data, IO_ReadOnly );
1459 replyType =
"QCStringList";
1460 TQDataStream reply( replyData, IO_WriteOnly );
1461 reply << findQtObjects(
id ) ;
1464 }
else if ( objId.left(3) ==
"qt/" ) {
1465 TQObject* o = findQtObject( objId );
1468 if ( fun ==
"functions()" ) {
1469 replyType =
"QCStringList";
1470 TQDataStream reply( replyData, IO_WriteOnly );
1472 l <<
"QCStringList functions()";
1473 l <<
"QCStringList interfaces()";
1474 l <<
"QCStringList properties()";
1475 l <<
"bool setProperty(TQCString,TQVariant)";
1476 l <<
"TQVariant property(TQCString)";
1477 TQStrList lst = o->metaObject()->slotNames(
true );
1479 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1480 if ( o->metaObject()->slot( i++,
true )->tqt_mo_access != TQMetaData::Public )
1482 TQCString slot = it.current();
1483 if ( slot.contains(
"()" ) ) {
1484 slot.prepend(
"void ");
1490 }
else if ( fun ==
"interfaces()" ) {
1491 replyType =
"QCStringList";
1492 TQDataStream reply( replyData, IO_WriteOnly );
1494 TQMetaObject *meta = o->metaObject();
1496 l.prepend( meta->className() );
1497 meta = meta->superClass();
1501 }
else if ( fun ==
"properties()" ) {
1502 replyType =
"QCStringList";
1503 TQDataStream reply( replyData, IO_WriteOnly );
1505 TQStrList lst = o->metaObject()->propertyNames(
true );
1506 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1507 TQMetaObject *mo = o->metaObject();
1508 const TQMetaProperty* p = mo->property( mo->findProperty( it.current(), true ),
true );
1511 TQCString prop = p->type();
1514 if ( !p->writable() )
1515 prop +=
" readonly";
1520 }
else if ( fun ==
"property(TQCString)" ) {
1521 replyType =
"TQVariant";
1522 TQDataStream ds( data, IO_ReadOnly );
1525 TQVariant result = o->property( name );
1526 TQDataStream reply( replyData, IO_WriteOnly );
1529 }
else if ( fun ==
"setProperty(TQCString,TQVariant)" ) {
1530 TQDataStream ds( data, IO_ReadOnly );
1533 ds >> name >> value;
1535 TQDataStream reply( replyData, IO_WriteOnly );
1536 reply << (TQ_INT8) o->setProperty( name, value );
1539 int slot = o->metaObject()->findSlot( fun,
true );
1543 o->tqt_invoke( slot, uo );
1560 bool DCOPClient::receive(
const TQCString &,
const TQCString &objId,
1561 const TQCString &fun,
const TQByteArray &data,
1562 TQCString& replyType, TQByteArray &replyData)
1564 d->transaction =
false;
1565 if ( objId ==
"DCOPClient" ) {
1566 if ( fun ==
"objects()" ) {
1567 replyType =
"QCStringList";
1568 TQDataStream reply( replyData, IO_WriteOnly );
1570 if (d->qt_bridge_enabled)
1574 if ( kde_dcopObjMap ) {
1575 TQMap<TQCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
1576 for (; it != kde_dcopObjMap->end(); ++it) {
1577 if ( !it.key().isEmpty() ) {
1578 if ( it.key() == d->defaultObject )
1589 if ( objId.isEmpty() || objId ==
"DCOPClient" ) {
1590 if ( fun ==
"applicationRegistered(TQCString)" ) {
1591 TQDataStream ds( data, IO_ReadOnly );
1596 }
else if ( fun ==
"applicationRemoved(TQCString)" ) {
1597 TQDataStream ds( data, IO_ReadOnly );
1604 if (
process( fun, data, replyType, replyData ) )
1608 }
else if (d->qt_bridge_enabled &&
1609 (objId ==
"qt" || objId.left(3) ==
"qt/") ) {
1610 return receiveQtObject( objId, fun, data, replyType, replyData );
1613 if ( objId.isEmpty() || objId ==
"default" ) {
1616 objPtr->setCallingDcopClient(
this);
1617 if (objPtr->
process(fun, data, replyType, replyData))
1625 if (!objId.isEmpty() && ((objId.length()>0)?(objId[objId.length()-1] ==
'*'):0)) {
1628 TQPtrList<DCOPObject> matchList =
1631 objPtr != 0L; objPtr = matchList.next()) {
1632 objPtr->setCallingDcopClient(
this);
1633 if (!objPtr->
process(fun, data, replyType, replyData))
1638 if ( DCOPObjectProxy::proxies ) {
1639 for ( TQPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
1641 if ( it.current()->process( objId, fun, data, replyType, replyData ) )
1649 objPtr->setCallingDcopClient(
this);
1650 if (!objPtr->
process(fun, data, replyType, replyData)) {
1662 static bool findResultOk(TQCString &replyType, TQByteArray &replyData)
1665 if (replyType !=
"bool")
return false;
1667 TQDataStream reply( replyData, IO_ReadOnly );
1670 if (!success)
return false;
1676 static bool findSuccess(
const TQCString &app,
const TQCString objId, TQCString &replyType, TQByteArray &replyData)
1679 replyType =
"DCOPRef";
1681 replyData = TQByteArray();
1682 TQDataStream final_reply( replyData, IO_WriteOnly );
1688 bool DCOPClient::find(
const TQCString &app,
const TQCString &objId,
1689 const TQCString &fun,
const TQByteArray &data,
1690 TQCString& replyType, TQByteArray &replyData)
1692 d->transaction =
false;
1693 if ( !app.isEmpty() && app != d->appId && app[app.length()-1] !=
'*') {
1694 tqWarning(
"WEIRD! we somehow received a DCOP message w/a different appId");
1698 if (objId.isEmpty() || objId[objId.length()-1] !=
'*')
1703 return findSuccess(app, objId, replyType, replyData);
1707 if (receive(app, objId, fun, data, replyType, replyData))
1709 if (findResultOk(replyType, replyData))
1710 return findSuccess(app, objId, replyType, replyData);
1716 TQPtrList<DCOPObject> matchList =
1719 objPtr != 0L; objPtr = matchList.next())
1722 replyData = TQByteArray();
1724 return findSuccess(app, objPtr->
objId(), replyType, replyData);
1725 objPtr->setCallingDcopClient(
this);
1726 if (objPtr->
process(fun, data, replyType, replyData))
1727 if (findResultOk(replyType, replyData))
1728 return findSuccess(app, objPtr->
objId(), replyType, replyData);
1736 const TQCString &remFun,
const TQByteArray &data,
1737 TQCString& replyType, TQByteArray &replyData,
1740 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1,
false );
1744 const TQCString &remFun,
const TQByteArray &data,
1745 TQCString& replyType, TQByteArray &replyData,
1746 bool useEventLoop,
int timeout)
1748 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, timeout,
false );
1752 const TQCString &remFun,
const TQByteArray &data,
1753 TQCString& replyType, TQByteArray &replyData,
1754 bool useEventLoop,
int timeout,
bool forceRemote)
1756 if (remApp.isEmpty())
1760 if ( localClient && !forceRemote ) {
1761 bool saveTransaction = d->transaction;
1762 TQ_INT32 saveTransactionId = d->transactionId;
1763 TQCString saveSenderId = d->senderId;
1766 bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1772 TQApplication::eventLoop()->processEvents(TQEventLoop::WaitForMore);
1773 }
while( !localClient->isLocalTransactionFinished(
id, replyType, replyData));
1776 d->transaction = saveTransaction;
1777 d->transactionId = saveTransactionId;
1778 d->senderId = saveSenderId;
1782 return callInternal(remApp, remObjId, remFun, data,
1783 replyType, replyData, useEventLoop, timeout, DCOPCall);
1786 void DCOPClient::asyncReplyReady()
1788 while( d->asyncReplyQueue.count() )
1790 ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1791 handleAsyncReply(replyStruct);
1796 const TQCString &remFun,
const TQByteArray &data,
1797 TQObject *callBackObj,
const char *callBackSlot)
1799 TQCString replyType;
1800 TQByteArray replyData;
1802 ReplyStruct *replyStruct =
new ReplyStruct;
1803 replyStruct->replyType =
new TQCString;
1804 replyStruct->replyData =
new TQByteArray;
1805 replyStruct->replyObject = callBackObj;
1806 replyStruct->replySlot = callBackSlot;
1807 replyStruct->replyId = ++d->transactionId;
1808 if (d->transactionId < 0)
1809 d->transactionId = 0;
1811 bool b = callInternal(remApp, remObjId, remFun, data,
1812 replyStruct,
false, -1, DCOPCall);
1815 delete replyStruct->replyType;
1816 delete replyStruct->replyData;
1821 if (replyStruct->transactionId == 0)
1824 TQTimer::singleShot(0,
this, TQT_SLOT(asyncReplyReady()));
1825 d->asyncReplyQueue.append(replyStruct);
1828 return replyStruct->replyId;
1831 bool DCOPClient::callInternal(
const TQCString &remApp,
const TQCString &remObjId,
1832 const TQCString &remFun,
const TQByteArray &data,
1833 TQCString& replyType, TQByteArray &replyData,
1834 bool useEventLoop,
int timeout,
int minor_opcode)
1836 ReplyStruct replyStruct;
1837 replyStruct.replyType = &replyType;
1838 replyStruct.replyData = &replyData;
1839 return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
1842 bool DCOPClient::callInternal(
const TQCString &remApp,
const TQCString &remObjId,
1843 const TQCString &remFun,
const TQByteArray &data,
1844 ReplyStruct *replyStruct,
1845 bool useEventLoop,
int timeout,
int minor_opcode)
1852 CARD32 oldCurrentKey = d->currentKey;
1853 if ( !d->currentKey )
1854 d->currentKey = d->key;
1857 TQDataStream ds(ba, IO_WriteOnly);
1860 IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
1861 sizeof(DCOPMsg), DCOPMsg, pMsg);
1863 pMsg->key = d->currentKey;
1864 int datalen = ba.size() + data.size();
1865 pMsg->length += datalen;
1869 IceSendData(d->iceConn, ba.size(),
const_cast<char *
>(ba.data()));
1870 IceSendData(d->iceConn, data.size(),
const_cast<char *
>(data.data()));
1872 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
1875 IceFlush (d->iceConn);
1877 IceReplyWaitInfo waitInfo;
1878 waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
1879 waitInfo.major_opcode_of_request = d->majorOpcode;
1880 waitInfo.minor_opcode_of_request = minor_opcode;
1882 replyStruct->transactionId = -1;
1883 waitInfo.reply =
static_cast<IcePointer
>(replyStruct);
1885 Bool readyRet = False;
1886 IceProcessMessagesStatus s;
1892 gettimeofday( &time_start, NULL );
1893 time_left = timeout;
1896 bool checkMessages =
true;
1898 ? d->notifier != NULL
1900 const int guiTimeout = 100;
1901 checkMessages =
false;
1903 int msecs = useEventLoop
1909 FD_SET(
socket(), &fds );
1910 tv.tv_sec = msecs / 1000;
1911 tv.tv_usec = (msecs % 1000) * 1000;
1912 if ( select(
socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
1913 if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
1916 bool old_lock = d->non_blocking_call_lock;
1918 d->non_blocking_call_lock =
true;
1922 d->eventLoopTimer.start(time_left - guiTimeout,
true);
1923 tqApp->enter_loop();
1924 d->eventLoopTimer.stop();
1926 d->non_blocking_call_lock =
false;
1933 checkMessages =
true;
1939 if( replyStruct->transactionId != -1 )
1941 if (replyStruct->transactionId == 0)
1943 if (!replyStruct->replySlot.isEmpty())
1947 if( checkMessages ) {
1948 s = IceProcessMessages(d->iceConn, &waitInfo,
1950 if (s == IceProcessMessagesIOError) {
1952 d->currentKey = oldCurrentKey;
1957 if( replyStruct->transactionId != -1 )
1959 if (replyStruct->transactionId == 0)
1961 if (!replyStruct->replySlot.isEmpty())
1968 gettimeofday( &time_now, NULL );
1969 time_left = timeout -
1970 ((time_now.tv_sec - time_start.tv_sec) * 1000) -
1971 ((time_now.tv_usec - time_start.tv_usec) / 1000);
1978 useEventLoop =
false;
1981 *(replyStruct->replyType) = TQCString();
1982 *(replyStruct->replyData) = TQByteArray();
1983 replyStruct->status = ReplyStruct::Failed;
1989 if ( d->non_blocking_call_lock ) {
1993 d->currentKey = oldCurrentKey;
1994 return replyStruct->status != ReplyStruct::Failed;
1997 void DCOPClient::eventLoopTimeout()
2008 timeout.tv_usec = 0;
2011 int result = select(fd+1, &fds, 0, 0, &timeout);
2015 if ( d->non_blocking_call_lock ) {
2023 d->notifier->deleteLater();
2025 tqWarning(
"received an error processing data from the DCOP server!");
2029 IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
2031 if (s == IceProcessMessagesIOError) {
2033 tqWarning(
"received an error processing data from the DCOP server!");
2040 d->defaultObject = objId;
2046 return d->defaultObject;
2050 DCOPClient::isLocalTransactionFinished(TQ_INT32
id, TQCString &replyType, TQByteArray &replyData)
2052 DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(
id);
2056 replyType = result->replyType;
2057 replyData = result->replyData;
2063 DCOPClientTransaction *
2066 if (d->opcode == DCOPSend)
2068 if (!d->transactionList)
2069 d->transactionList =
new TQPtrList<DCOPClientTransaction>;
2071 d->transaction =
true;
2072 DCOPClientTransaction *trans =
new DCOPClientTransaction();
2073 trans->senderId = d->senderId;
2074 trans->id = ++d->transactionId;
2075 if (d->transactionId < 0)
2076 d->transactionId = 0;
2077 trans->key = d->currentKey;
2079 d->transactionList->append( trans );
2088 return d->transactionId;
2095 TQByteArray &replyData)
2103 if ( !d->transactionList) {
2104 tqWarning(
"Transaction unknown: No pending transactions!");
2108 if ( !d->transactionList->removeRef( trans ) ) {
2109 tqWarning(
"Transaction unknown: Not on list of pending transactions!");
2113 if (trans->senderId.isEmpty())
2116 DCOPClientPrivate::LocalTransactionResult *result =
new DCOPClientPrivate::LocalTransactionResult();
2117 result->replyType = replyType;
2118 result->replyData = replyData;
2120 d->localTransActionList.insert(trans->id, result);
2130 TQDataStream ds(ba, IO_WriteOnly);
2131 ds << d->appId << trans->senderId << trans->id << replyType << replyData;
2133 IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
2134 sizeof(DCOPMsg), DCOPMsg, pMsg);
2135 pMsg->key = trans->key;
2136 pMsg->length += ba.size();
2138 IceSendData( d->iceConn, ba.size(),
const_cast<char *
>(ba.data()) );
2158 const TQCString &signal,
2159 const TQCString &receiverObj,
const TQCString &slot,
bool Volatile)
2161 TQCString replyType;
2162 TQByteArray data, replyData;
2163 TQ_INT8 iVolatile = Volatile ? 1 : 0;
2165 TQDataStream args(data, IO_WriteOnly );
2168 if (!
call(
"DCOPServer", 0,
2169 "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
2170 data, replyType, replyData))
2175 if (replyType !=
"bool")
2178 TQDataStream reply(replyData, IO_ReadOnly );
2181 return (result != 0);
2186 const TQCString &receiverObj,
const TQCString &slot,
bool Volatile)
2193 const TQCString &signal,
2194 const TQCString &receiverObj,
const TQCString &slot)
2196 TQCString replyType;
2197 TQByteArray data, replyData;
2199 TQDataStream args(data, IO_WriteOnly );
2202 if (!
call(
"DCOPServer", 0,
2203 "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
2204 data, replyType, replyData))
2209 if (replyType !=
"bool")
2212 TQDataStream reply(replyData, IO_ReadOnly );
2215 return (result != 0);
2220 const TQCString &receiverObj,
const TQCString &slot)
2226 DCOPClient::setPriorityCall(
bool b)
2230 if (d->currentKey == 2)
2232 d->currentKeySaved = d->currentKey;
2237 if (d->currentKey != 2)
2239 d->currentKey = d->currentKeySaved;
2240 if ( !d->messages.isEmpty() )
2241 d->postMessageTimer.start( 0,
true );
2248 DCOPClient::emergencyClose()
2250 TQPtrList<DCOPClient> list;
2251 client_map_t *map = DCOPClient_CliMap;
2253 TQAsciiDictIterator<DCOPClient> it(*map);
2254 while(it.current()) {
2255 list.removeRef(it.current());
2256 list.append(it.current());
2259 for(
DCOPClient *cl = list.first(); cl; cl = list.next())
2261 if (cl->d->iceConn) {
2262 IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
2263 IceCloseConnection(cl->d->iceConn);
2264 cl->d->iceConn = 0L;
2270 DCOPClient::postMortemSender()
2272 if (!dcop_main_client)
2274 if (dcop_main_client->d->senderId.isEmpty())
2276 return dcop_main_client->d->senderId.data();
2280 DCOPClient::postMortemObject()
2282 if (!dcop_main_client)
2284 return dcop_main_client->d->objId.data();
2287 DCOPClient::postMortemFunction()
2289 if (!dcop_main_client)
2291 return dcop_main_client->d->function.data();
2294 void DCOPClient::virtual_hook(
int,
void* )
2297 #include <dcopclient.moc>