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>
54 #ifndef QT_CLEAN_NAMESPACE
55 #define QT_CLEAN_NAMESPACE
57 #include <tqguardedptr.h>
58 #include <tqtextstream.h>
61 #include <tqapplication.h>
62 #include <tqsocketnotifier.h>
65 #include <tqucomextra_p.h>
67 #include <dcopglobal.h>
68 #include <dcopclient.h>
69 #include <dcopobject.h>
71 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
75 #include <KDE-ICE/ICElib.h>
76 #include <KDE-ICE/ICEutil.h>
77 #include <KDE-ICE/ICEmsg.h>
78 #include <KDE-ICE/ICEproto.h>
83 extern TQMap<TQCString, DCOPObject *> * kde_dcopObjMap;
88 typedef TQAsciiDict<DCOPClient> client_map_t;
89 static client_map_t *DCOPClient_CliMap = 0;
92 client_map_t *cliMap()
94 if (!DCOPClient_CliMap)
95 DCOPClient_CliMap =
new client_map_t;
96 return DCOPClient_CliMap;
101 return cliMap()->find(_appId.data());
105 void registerLocalClient(
const TQCString &_appId,
DCOPClient *client )
107 cliMap()->replace(_appId.data(), client);
111 void unregisterLocalClient(
const TQCString &_appId )
113 client_map_t *map = cliMap();
114 map->remove(_appId.data());
118 template class TQPtrList<DCOPObjectProxy>;
119 template class TQPtrList<DCOPClientTransaction>;
120 template class TQPtrList<_IceConn>;
122 struct DCOPClientMessage
129 class DCOPClient::ReplyStruct
132 enum ReplyStatus { Pending, Ok, Failed };
142 TQCString* replyType;
143 TQByteArray* replyData;
145 TQ_INT32 transactionId;
147 TQGuardedPtr<TQObject> replyObject;
151 class DCOPClientPrivate
159 int majorVersion, minorVersion;
161 static const char* serverAddr;
162 TQSocketNotifier *notifier;
163 bool non_blocking_call_lock;
167 bool accept_calls_override;
168 bool qt_bridge_enabled;
174 TQCString defaultObject;
175 TQPtrList<DCOPClientTransaction> *transactionList;
177 TQ_INT32 transactionId;
187 CARD32 currentKeySaved;
189 TQTimer postMessageTimer;
190 TQPtrList<DCOPClientMessage> messages;
192 TQPtrList<DCOPClient::ReplyStruct> pendingReplies;
193 TQPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
195 struct LocalTransactionResult
198 TQByteArray replyData;
201 TQIntDict<LocalTransactionResult> localTransActionList;
203 TQTimer eventLoopTimer;
206 class DCOPClientTransaction
216 #if defined(ICEAUTH_PATH)
218 #
if defined(Q_WS_WIN)
219 access(ICEAUTH_PATH, 0) == 0
221 access(ICEAUTH_PATH, X_OK) == 0
225 return TQCString(ICEAUTH_PATH);
228 #elif defined(Q_OS_WIN32)
232 ret = SearchPathA(NULL,
"iceauth.exe",NULL,
sizeof(szPath)/
sizeof(szPath[0]),szPath,&pszFilePart);
234 return TQCString(szPath);
237 TQCString path = ::getenv(
"PATH");
239 path =
"/bin:/usr/bin";
240 path +=
":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
241 TQCString fPath = strtok(path.data(),
":\b");
242 while (!fPath.isNull())
245 if (access(fPath.data(), X_OK) == 0)
249 fPath = strtok(NULL,
":\b");
256 static TQCString dcopServerFile(
const TQCString &hostname,
bool old)
258 TQCString fName = ::getenv(
"DCOPAUTHORITY");
259 if (!old && !fName.isEmpty())
262 fName = TQFile::encodeName( TQDir::homeDirPath() );
266 fprintf(stderr,
"Aborting. $HOME is not set.\n");
270 TQCString disp = getenv(
"DISPLAY");
271 #elif defined(Q_WS_QWS)
272 TQCString disp = getenv(
"QWS_DISPLAY");
280 if((i = disp.findRev(
'.')) > disp.findRev(KPATH_SEPARATOR) && i >= 0)
285 while( (i = disp.find(KPATH_SEPARATOR)) >= 0)
289 fName +=
"/.DCOPserver_";
290 if (hostname.isEmpty())
294 if (getenv(
"XAUTHLOCALHOSTNAME"))
295 fName += getenv(
"XAUTHLOCALHOSTNAME");
296 else if (gethostname(hostName,
sizeof(hostName)))
298 fName +=
"localhost";
302 hostName[
sizeof(hostName)-1] =
'\0';
329 const char* DCOPClientPrivate::serverAddr = 0;
331 static void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const TQByteArray& dataReceived,
bool canPost );
333 void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
335 if (replyStruct->replyObject)
337 TQObject::connect(
this, TQT_SIGNAL(callBack(
int,
const TQCString&,
const TQByteArray &)),
338 replyStruct->replyObject, replyStruct->replySlot);
339 emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
340 TQObject::disconnect(
this, TQT_SIGNAL(callBack(
int,
const TQCString&,
const TQByteArray &)),
341 replyStruct->replyObject, replyStruct->replySlot);
349 static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
350 int opcode,
unsigned long length, Bool ,
351 IceReplyWaitInfo *replyWait,
355 DCOPClientPrivate *d =
static_cast<DCOPClientPrivate *
>(clientObject);
356 DCOPClient::ReplyStruct *replyStruct = replyWait ?
static_cast<DCOPClient::ReplyStruct*
>(replyWait->reply) : 0;
358 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
359 CARD32
key = pMsg->key;
363 TQByteArray dataReceived( length );
364 IceReadData(iceConn, length, dataReceived.data() );
369 case DCOPReplyFailed:
371 replyStruct->status = DCOPClient::ReplyStruct::Failed;
372 replyStruct->transactionId = 0;
373 *replyWaitRet = True;
376 qWarning(
"Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
381 TQByteArray* b = replyStruct->replyData;
382 TQCString* t = replyStruct->replyType;
383 replyStruct->status = DCOPClient::ReplyStruct::Ok;
384 replyStruct->transactionId = 0;
386 TQCString calledApp, app;
387 TQDataStream ds( dataReceived, IO_ReadOnly );
388 ds >> calledApp >> app >> *t >> *b;
390 *replyWaitRet = True;
393 qWarning(
"Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
398 TQCString calledApp, app;
400 TQDataStream ds( dataReceived, IO_ReadOnly );
401 ds >> calledApp >> app >> id;
402 replyStruct->transactionId = id;
403 replyStruct->calledApp = calledApp;
404 d->pendingReplies.append(replyStruct);
405 *replyWaitRet = True;
408 qWarning(
"Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
411 case DCOPReplyDelayed:
413 TQDataStream ds( dataReceived, IO_ReadOnly );
414 TQCString calledApp, app;
417 ds >> calledApp >> app >> id;
418 if (replyStruct && (
id == replyStruct->transactionId) && (calledApp == replyStruct->calledApp))
420 *replyWaitRet = True;
423 for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
424 rs = d->pendingReplies.next())
426 if ((rs->transactionId ==
id) && (rs->calledApp == calledApp))
428 d->pendingReplies.remove();
429 TQByteArray* b = rs->replyData;
430 TQCString* t = rs->replyType;
433 rs->status = DCOPClient::ReplyStruct::Ok;
434 rs->transactionId = 0;
435 if (!rs->replySlot.isEmpty())
437 d->parent->handleAsyncReply(rs);
443 qWarning(
"Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
448 DCOPProcessInternal( d, opcode, key, dataReceived,
true );
452 void DCOPClient::processPostedMessagesInternal()
454 if ( d->messages.isEmpty() )
456 TQPtrListIterator<DCOPClientMessage> it (d->messages );
457 DCOPClientMessage* msg ;
458 while ( ( msg = it.current() ) ) {
460 if ( d->currentKey && msg->key != d->currentKey )
462 d->messages.removeRef( msg );
463 d->opcode = msg->opcode;
464 DCOPProcessInternal( d, msg->opcode, msg->key, msg->data,
false );
467 if ( !d->messages.isEmpty() )
468 d->postMessageTimer.start( 100,
true );
474 void DCOPProcessInternal( DCOPClientPrivate *d,
int opcode, CARD32 key,
const TQByteArray& dataReceived,
bool canPost )
476 if (!d->accept_calls && (opcode == DCOPSend))
479 IceConn iceConn = d->iceConn;
482 TQDataStream ds( dataReceived, IO_ReadOnly );
486 if (fromApp.isEmpty())
489 if (!d->accept_calls)
492 TQDataStream replyStream( reply, IO_WriteOnly );
494 replyStream << d->appId << fromApp;
495 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
496 sizeof(DCOPMsg), DCOPMsg, pMsg );
497 int datalen = reply.size();
499 pMsg->length += datalen;
500 IceSendData( iceConn, datalen, reply.data());
504 TQCString app, objId, fun;
506 ds >> app >> objId >> fun >> data;
507 d->senderId = fromApp;
513 if ( canPost && d->currentKey && key != d->currentKey ) {
514 DCOPClientMessage* msg =
new DCOPClientMessage;
515 msg->opcode = opcode;
517 msg->data = dataReceived;
518 d->messages.append( msg );
519 d->postMessageTimer.start( 0,
true );
527 TQByteArray replyData;
529 CARD32 oldCurrentKey = d->currentKey;
530 if ( opcode != DCOPSend )
533 if ( opcode == DCOPFind )
534 b = c->find(app, objId, fun, data, replyType, replyData );
536 b = c->receive( app, objId, fun, data, replyType, replyData );
539 if ( opcode == DCOPSend )
542 if ((d->currentKey == key) || (oldCurrentKey != 2))
543 d->currentKey = oldCurrentKey;
546 TQDataStream replyStream( reply, IO_WriteOnly );
551 replyStream << d->appId << fromApp << id;
553 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
554 sizeof(DCOPMsg), DCOPMsg, pMsg );
556 pMsg->length += reply.size();
557 IceSendData( iceConn, reply.size(),
const_cast<char *
>(reply.data()));
564 replyStream << d->appId << fromApp;
565 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
566 sizeof(DCOPMsg), DCOPMsg, pMsg );
567 int datalen = reply.size();
569 pMsg->length += datalen;
570 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
575 replyStream << d->appId << fromApp << replyType << replyData.size();
579 IceGetHeader( iceConn, d->majorOpcode,
DCOPReply,
580 sizeof(DCOPMsg), DCOPMsg, pMsg );
581 int datalen = reply.size() + replyData.size();
583 pMsg->length += datalen;
586 IceSendData( iceConn, reply.size(),
const_cast<char *
>(reply.data()));
587 IceSendData( iceConn, replyData.size(),
const_cast<char *
>(replyData.data()));
592 static IcePoVersionRec DCOPClientVersions[] = {
593 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
601 return dcop_main_client;
606 dcop_main_client = client;
612 d =
new DCOPClientPrivate;
620 d->non_blocking_call_lock =
false;
621 d->registered =
false;
622 d->foreign_server =
true;
623 d->accept_calls =
true;
624 d->accept_calls_override =
false;
625 d->qt_bridge_enabled =
true;
626 d->transactionList = 0L;
627 d->transactionId = 0;
628 TQObject::connect( &d->postMessageTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( processPostedMessagesInternal() ) );
629 TQObject::connect( &d->eventLoopTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( eventLoopTimeout() ) );
637 #ifdef DCOPCLIENT_DEBUG
638 qWarning(
"d->messages.count() = %d", d->messages.count());
639 TQPtrListIterator<DCOPClientMessage> it (d->messages );
640 DCOPClientMessage* msg ;
641 while ( ( msg = it.current() ) ) {
643 d->messages.removeRef( msg );
644 qWarning(
"DROPPING UNHANDLED DCOP MESSAGE:");
645 qWarning(
" opcode = %d key = %d", msg->opcode, msg->key);
646 TQDataStream ds( msg->data, IO_ReadOnly );
648 TQCString fromApp, app, objId, fun;
649 ds >> fromApp >> app >> objId >> fun;
650 qWarning(
" from = %s", fromApp.data());
651 qWarning(
" to = %s / %s / %s", app.data(), objId.data(), fun.data());
656 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
660 unregisterLocalClient( d->appId );
663 delete d->transactionList;
664 d->messages.setAutoDelete(
true);
673 TQCString env =
"DCOPSERVER=" + addr;
674 putenv(strdup(env.data()));
675 delete [] DCOPClientPrivate::serverAddr;
676 DCOPClientPrivate::serverAddr = qstrdup( addr.data() );
681 if (!attachInternal(
true ))
682 if (!attachInternal(
true ))
687 void DCOPClient::bindToApp()
694 d->notifier =
new TQSocketNotifier(
socket(),
695 TQSocketNotifier::Read, 0, 0);
696 TQObject::connect(d->notifier, TQT_SIGNAL(activated(
int)),
703 #ifdef Q_WS_WIN //TODO: remove (win32 ports sometimes do not create notifiers)
708 d->notifier->setEnabled(
false);
713 #ifdef Q_WS_WIN //TODO: remove
718 d->notifier->setEnabled(
true);
723 #if defined(Q_WS_WIN) || defined(Q_WS_MAC) //TODO: REMOVE
727 return !d->notifier->isEnabled();
730 #if defined(SO_PEERCRED) || defined(LOCAL_PEEREID)
731 #define USE_PEER_IS_US
733 static bool peerIsUs(
int sockfd)
736 #if defined(__OpenBSD__)
737 struct sockpeercred cred;
741 socklen_t siz =
sizeof(cred);
742 if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
744 return (cred.uid == getuid());
745 #elif defined LOCAL_PEEREID
747 socklen_t siz =
sizeof(cred);
748 if (getsockopt(sockfd, 0, LOCAL_PEEREID, &cred, &siz) != 0 || siz !=
sizeof(cred))
750 return (cred.unp_euid == geteuid());
755 static bool isServerSocketOwnedByUser(
const char*server)
758 if (strncmp(server,
"tcp/", 4) != 0)
763 if (strncmp(server,
"local/", 6) != 0)
765 const char *path = strchr(server, KPATH_SEPARATOR);
770 struct stat stat_buf;
771 if (stat(path, &stat_buf) != 0)
774 return (stat_buf.st_uid == getuid());
780 bool DCOPClient::attachInternal(
bool registerAsAnonymous )
787 if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>(
"DCOP"),
788 const_cast<char *>(DCOPVendorString),
789 const_cast<char *>(DCOPReleaseString),
790 1, DCOPClientVersions,
792 const_cast<char **>(DCOPAuthNames),
793 DCOPClientAuthProcs, 0L)) < 0) {
794 emit
attachFailed(TQString::fromLatin1(
"Communications could not be established." ));
798 bool bClearServerAddr =
false;
800 if (!d->serverAddr) {
804 dcopSrv = ::getenv(
"DCOPSERVER");
805 if (dcopSrv.isEmpty()) {
807 TQFile f(TQFile::decodeName(fName));
808 if (!f.open(IO_ReadOnly)) {
809 emit
attachFailed(TQString::fromLatin1(
"Could not read network connection list.\n" )+TQFile::decodeName(fName));
812 int size = QMIN( (qint64)1024, f.size() );
813 TQCString contents( size+1 );
814 if ( f.readBlock( contents.data(), size ) != size )
816 qDebug(
"Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
819 contents[size] =
'\0';
820 int pos = contents.find(
'\n');
823 qDebug(
"Only one line in dcopserver file !: %s", contents.data());
828 if(contents[pos - 1] ==
'\r')
830 dcopSrv = contents.left( pos );
836 d->serverAddr = qstrdup( const_cast<char *>(dcopSrv.data()) );
837 bClearServerAddr =
true;
840 if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
841 static_cast<IcePointer>(
this), False, d->majorOpcode,
842 sizeof(errBuf), errBuf)) == 0L) {
843 qDebug(
"DCOPClient::attachInternal. Attach failed %s", errBuf);
845 if (bClearServerAddr) {
846 delete [] d->serverAddr;
852 fcntl(
socket(), F_SETFL, FD_CLOEXEC);
854 IceSetShutdownNegotiation(d->iceConn, False);
859 setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
860 static_cast<IcePointer>(d),
862 &(d->majorVersion), &(d->minorVersion),
863 &(vendor), &(release), 1024, errBuf);
864 if (vendor) free(vendor);
865 if (release) free(release);
867 if (setupstat == IceProtocolSetupFailure ||
868 setupstat == IceProtocolSetupIOError) {
869 IceCloseConnection(d->iceConn);
871 if (bClearServerAddr) {
872 delete [] d->serverAddr;
877 }
else if (setupstat == IceProtocolAlreadyActive) {
878 if (bClearServerAddr) {
879 delete [] d->serverAddr;
883 emit
attachFailed(TQString::fromLatin1(
"internal error in IceOpenConnection" ));
888 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
889 if (bClearServerAddr) {
890 delete [] d->serverAddr;
893 emit
attachFailed(TQString::fromLatin1(
"DCOP server did not accept the connection." ));
897 #ifdef USE_PEER_IS_US
898 d->foreign_server = !peerIsUs(
socket());
900 d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
902 if (!d->accept_calls_override)
903 d->accept_calls = !d->foreign_server;
907 if ( registerAsAnonymous )
919 IceProtocolShutdown(d->iceConn, d->majorOpcode);
920 status = IceCloseConnection(d->iceConn);
921 if (status != IceClosedNow)
928 unregisterLocalClient(d->appId);
932 d->registered =
false;
933 d->foreign_server =
true;
942 return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
958 d->accept_calls_override =
true;
963 return d->qt_bridge_enabled;
968 d->qt_bridge_enabled = b;
975 TQCString _appId =
appId;
979 pid.sprintf(
"-%d", getpid());
980 _appId = _appId + pid;
983 if( d->appId == _appId )
986 #if 0 // no need to detach, dcopserver can handle renaming
994 if (!attachInternal(
false ))
995 if (!attachInternal(
false ))
1000 TQCString replyType;
1001 TQByteArray data, replyData;
1002 TQDataStream arg( data, IO_WriteOnly );
1004 if (
call(
"DCOPServer",
"",
"registerAs(TQCString)", data, replyType, replyData ) ) {
1005 TQDataStream reply( replyData, IO_ReadOnly );
1010 d->registered = !result.isNull();
1013 registerLocalClient( d->appId,
this );
1020 return d->registered;
1033 return IceConnectionNumber(d->iceConn);
1037 static inline bool isIdentChar(
char x )
1039 return x ==
'_' || (x >=
'0' && x <=
'9') ||
1040 (x >=
'a' && x <=
'z') || (x >=
'A' && x <=
'Z');
1044 if ( fun.isEmpty() )
1046 TQCString result( fun.size() );
1047 char *from =
const_cast<TQCString&
>(fun).data();
1048 char *to = result.data();
1052 while ( *from && isspace(*from) )
1054 if ( last && isIdentChar( last ) && isIdentChar( *from ) )
1056 while ( *from && !isspace(*from) ) {
1063 if ( to > first && *(to-1) == 0x20 )
1066 result.resize( (
int)((
long)to - (
long)result.data()) + 1 );
1078 const TQCString &remFun,
const TQByteArray &data)
1080 if (remApp.isEmpty())
1084 if ( localClient ) {
1085 bool saveTransaction = d->transaction;
1086 TQ_INT32 saveTransactionId = d->transactionId;
1087 TQCString saveSenderId = d->senderId;
1090 TQCString replyType;
1091 TQByteArray replyData;
1092 (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1094 d->transaction = saveTransaction;
1095 d->transactionId = saveTransactionId;
1096 d->senderId = saveSenderId;
1111 TQDataStream ds(ba, IO_WriteOnly);
1114 IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
1115 sizeof(DCOPMsg), DCOPMsg, pMsg);
1118 int datalen = ba.size() + data.size();
1119 pMsg->length += datalen;
1121 IceSendData( d->iceConn, ba.size(),
const_cast<char *
>(ba.data()) );
1122 IceSendData( d->iceConn, data.size(),
const_cast<char *
>(data.data()) );
1126 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
1132 const TQCString &remFun,
const TQString &data)
1135 TQDataStream ds(ba, IO_WriteOnly);
1137 return send(remApp, remObjId, remFun, ba);
1141 const TQCString &remFun,
const TQByteArray &data,
1142 TQCString &foundApp, TQCString &foundObj,
1145 return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
1149 const TQCString &remFun,
const TQByteArray &data,
1150 TQCString &foundApp, TQCString &foundObj,
1151 bool useEventLoop,
int timeout)
1153 QCStringList appList;
1154 TQCString app = remApp;
1161 if (app[app.length()-1] ==
'*')
1166 int len = app.length()-1;
1168 for( QCStringList::ConstIterator it = apps.begin();
1172 if ( strncmp( (*it).data(), app.data(), len) == 0)
1173 appList.append(*it);
1178 appList.append(app);
1182 for(
int phase=1; phase <= 2; phase++)
1184 for( QCStringList::ConstIterator it = appList.begin();
1185 it != appList.end();
1188 TQCString remApp = *it;
1189 TQCString replyType;
1190 TQByteArray replyData;
1191 bool result =
false;
1194 if ( (phase == 1) && localClient ) {
1196 bool saveTransaction = d->transaction;
1197 TQ_INT32 saveTransactionId = d->transactionId;
1198 TQCString saveSenderId = d->senderId;
1201 result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
1207 TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1208 }
while( !localClient->isLocalTransactionFinished(
id, replyType, replyData));
1211 d->transaction = saveTransaction;
1212 d->transactionId = saveTransactionId;
1213 d->senderId = saveSenderId;
1215 else if ((phase == 2) && !localClient)
1218 result = callInternal(remApp, remObj, remFun, data,
1219 replyType, replyData, useEventLoop, timeout, DCOPFind);
1224 if (replyType ==
"DCOPRef")
1227 TQDataStream reply( replyData, IO_ReadOnly );
1230 if (ref.app() == remApp)
1233 foundApp = ref.
app();
1234 foundObj = ref.object();
1245 TQCString&, TQByteArray &)
1252 TQCString replyType;
1253 TQByteArray data, replyData;
1254 TQDataStream arg( data, IO_WriteOnly );
1257 if (
call(
"DCOPServer",
"",
"isApplicationRegistered(TQCString)", data, replyType, replyData ) ) {
1258 TQDataStream reply( replyData, IO_ReadOnly );
1266 TQCString replyType;
1267 TQByteArray data, replyData;
1268 QCStringList result;
1269 if (
call(
"DCOPServer",
"",
"registeredApplications()", data, replyType, replyData ) ) {
1270 TQDataStream reply( replyData, IO_ReadOnly );
1278 TQCString replyType;
1279 TQByteArray data, replyData;
1280 QCStringList result;
1283 if (
call( remApp,
"DCOPClient",
"objects()", data, replyType, replyData ) ) {
1284 TQDataStream reply( replyData, IO_ReadOnly );
1294 TQCString replyType;
1295 TQByteArray data, replyData;
1296 QCStringList result;
1299 if (
call( remApp, remObj,
"interfaces()", data, replyType, replyData ) && replyType ==
"QCStringList") {
1300 TQDataStream reply( replyData, IO_ReadOnly );
1310 TQCString replyType;
1311 TQByteArray data, replyData;
1312 QCStringList result;
1315 if (
call( remApp, remObj,
"functions()", data, replyType, replyData ) && replyType ==
"QCStringList") {
1316 TQDataStream reply( replyData, IO_ReadOnly );
1327 TQDataStream ds(data, IO_WriteOnly);
1328 ds << static_cast<TQ_INT8>(enabled);
1330 TQCString replyType;
1332 if (!
call(
"DCOPServer",
"",
"setNotifications( bool )", data, replyType, reply))
1333 qWarning(
"I couldn't enable notifications at the dcopserver!");
1339 TQDataStream ds(data, IO_WriteOnly);
1340 ds << static_cast<TQ_INT8>( daemonMode );
1342 TQCString replyType;
1344 if (!
call(
"DCOPServer",
"",
"setDaemonMode(bool)", data, replyType, reply))
1345 qWarning(
"I couldn't enable daemon mode at the dcopserver!");
1355 static void fillQtObjects( QCStringList& l, TQObject* o, TQCString path )
1357 if ( !path.isEmpty() )
1361 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1362 if ( !list.isEmpty() ) {
1363 TQObjectListIt it( list );
1365 while ( (obj=it.current()) ) {
1367 TQCString n = obj->name();
1368 if ( n ==
"unnamed" || n.isEmpty() )
1370 n.sprintf(
"%p", (
void *) obj);
1371 n = TQString(TQString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1373 TQCString fn = path + n;
1375 if ( !obj->childrenListObject().isEmpty() )
1376 fillQtObjects( l, obj, fn );
1386 O (
const TQCString& str, TQObject* obj ):s(str), o(obj){}
1392 static void fillQtObjectsEx( TQValueList<O>& l, TQObject* o, TQCString path )
1394 if ( !path.isEmpty() )
1398 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1399 if ( !list.isEmpty() ) {
1400 TQObjectListIt it( list );
1402 while ( (obj=it.current()) ) {
1404 TQCString n = obj->name();
1405 if ( n ==
"unnamed" || n.isEmpty() )
1407 n.sprintf(
"%p", (
void *) obj);
1408 n = TQString(TQString(
"unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1410 TQCString fn = path + n;
1411 l.append( O( fn, obj ) );
1412 if ( !obj->childrenListObject().isEmpty() )
1413 fillQtObjectsEx( l, obj, fn );
1419 static TQObject* findQtObject( TQCString
id )
1421 TQRegExp expr(
id );
1423 fillQtObjectsEx( l, 0,
"qt" );
1425 TQObject* firstContains = 0L;
1426 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1427 if ( (*it).s ==
id )
1429 if ( !firstContains && (*it).s.contains( expr ) ) {
1430 firstContains = (*it).o;
1433 return firstContains;
1436 static QCStringList findQtObjects( TQCString
id )
1438 TQRegExp expr(
id );
1440 fillQtObjectsEx( l, 0,
"qt" );
1441 QCStringList result;
1442 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1443 if ( (*it).s.contains( expr ) )
1449 static bool receiveQtObject(
const TQCString &objId,
const TQCString &fun,
const TQByteArray &data,
1450 TQCString& replyType, TQByteArray &replyData)
1452 if ( objId ==
"qt" ) {
1453 if ( fun ==
"interfaces()" ) {
1454 replyType =
"QCStringList";
1455 TQDataStream reply( replyData, IO_WriteOnly );
1461 }
else if ( fun ==
"functions()" ) {
1462 replyType =
"QCStringList";
1463 TQDataStream reply( replyData, IO_WriteOnly );
1465 l <<
"QCStringList functions()";
1466 l <<
"QCStringList interfaces()";
1467 l <<
"QCStringList objects()";
1468 l <<
"QCStringList find(TQCString)";
1471 }
else if ( fun ==
"objects()" ) {
1472 replyType =
"QCStringList";
1473 TQDataStream reply( replyData, IO_WriteOnly );
1475 fillQtObjects( l, 0,
"qt" );
1478 }
else if ( fun ==
"find(TQCString)" ) {
1479 TQDataStream ds( data, IO_ReadOnly );
1482 replyType =
"QCStringList";
1483 TQDataStream reply( replyData, IO_WriteOnly );
1484 reply << findQtObjects(
id ) ;
1487 }
else if ( objId.left(3) ==
"qt/" ) {
1488 TQObject* o = findQtObject( objId );
1491 if ( fun ==
"functions()" ) {
1492 replyType =
"QCStringList";
1493 TQDataStream reply( replyData, IO_WriteOnly );
1495 l <<
"QCStringList functions()";
1496 l <<
"QCStringList interfaces()";
1497 l <<
"QCStringList properties()";
1498 l <<
"bool setProperty(TQCString,TQVariant)";
1499 l <<
"TQVariant property(TQCString)";
1500 TQStrList lst = o->metaObject()->slotNames(
true );
1502 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1503 if ( o->metaObject()->slot( i++,
true )->tqt_mo_access != TQMetaData::Public )
1505 TQCString slot = it.current();
1506 if ( slot.contains(
"()" ) ) {
1507 slot.prepend(
"void ");
1513 }
else if ( fun ==
"interfaces()" ) {
1514 replyType =
"QCStringList";
1515 TQDataStream reply( replyData, IO_WriteOnly );
1517 TQMetaObject *meta = o->metaObject();
1519 l.prepend( meta->className() );
1520 meta = meta->superClass();
1524 }
else if ( fun ==
"properties()" ) {
1525 replyType =
"QCStringList";
1526 TQDataStream reply( replyData, IO_WriteOnly );
1528 TQStrList lst = o->metaObject()->propertyNames(
true );
1529 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1530 TQMetaObject *mo = o->metaObject();
1531 const TQMetaProperty* p = mo->property( mo->findProperty( it.current(), true ),
true );
1534 TQCString prop = p->type();
1537 if ( !p->writable() )
1538 prop +=
" readonly";
1543 }
else if ( fun ==
"property(TQCString)" ) {
1544 replyType =
"TQVariant";
1545 TQDataStream ds( data, IO_ReadOnly );
1548 TQVariant result = o->property( name );
1549 TQDataStream reply( replyData, IO_WriteOnly );
1552 }
else if ( fun ==
"setProperty(TQCString,TQVariant)" ) {
1553 TQDataStream ds( data, IO_ReadOnly );
1556 ds >> name >> value;
1558 TQDataStream reply( replyData, IO_WriteOnly );
1559 reply << (TQ_INT8) o->setProperty( name, value );
1562 int slot = o->metaObject()->findSlot( fun,
true );
1566 o->qt_invoke( slot, uo );
1583 bool DCOPClient::receive(
const TQCString &,
const TQCString &objId,
1584 const TQCString &fun,
const TQByteArray &data,
1585 TQCString& replyType, TQByteArray &replyData)
1587 d->transaction =
false;
1588 if ( objId ==
"DCOPClient" ) {
1589 if ( fun ==
"objects()" ) {
1590 replyType =
"QCStringList";
1591 TQDataStream reply( replyData, IO_WriteOnly );
1593 if (d->qt_bridge_enabled)
1597 if ( kde_dcopObjMap ) {
1598 TQMap<TQCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
1599 for (; it != kde_dcopObjMap->end(); ++it) {
1600 if ( !it.key().isEmpty() ) {
1601 if ( it.key() == d->defaultObject )
1612 if ( objId.isEmpty() || objId ==
"DCOPClient" ) {
1613 if ( fun ==
"applicationRegistered(TQCString)" ) {
1614 TQDataStream ds( data, IO_ReadOnly );
1619 }
else if ( fun ==
"applicationRemoved(TQCString)" ) {
1620 TQDataStream ds( data, IO_ReadOnly );
1627 if (
process( fun, data, replyType, replyData ) )
1631 }
else if (d->qt_bridge_enabled &&
1632 (objId ==
"qt" || objId.left(3) ==
"qt/") ) {
1633 return receiveQtObject( objId, fun, data, replyType, replyData );
1636 if ( objId.isEmpty() || objId ==
"default" ) {
1639 objPtr->setCallingDcopClient(
this);
1640 if (objPtr->
process(fun, data, replyType, replyData))
1648 if (!objId.isEmpty() && ((objId.length()>0)?(objId[objId.length()-1] ==
'*'):0)) {
1651 TQPtrList<DCOPObject> matchList =
1654 objPtr != 0L; objPtr = matchList.next()) {
1655 objPtr->setCallingDcopClient(
this);
1656 if (!objPtr->
process(fun, data, replyType, replyData))
1661 if ( DCOPObjectProxy::proxies ) {
1662 for ( TQPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
1664 if ( it.current()->process( objId, fun, data, replyType, replyData ) )
1672 objPtr->setCallingDcopClient(
this);
1673 if (!objPtr->
process(fun, data, replyType, replyData)) {
1685 static bool findResultOk(TQCString &replyType, TQByteArray &replyData)
1688 if (replyType !=
"bool")
return false;
1690 TQDataStream reply( replyData, IO_ReadOnly );
1693 if (!success)
return false;
1699 static bool findSuccess(
const TQCString &app,
const TQCString objId, TQCString &replyType, TQByteArray &replyData)
1702 replyType =
"DCOPRef";
1704 replyData = TQByteArray();
1705 TQDataStream final_reply( replyData, IO_WriteOnly );
1711 bool DCOPClient::find(
const TQCString &app,
const TQCString &objId,
1712 const TQCString &fun,
const TQByteArray &data,
1713 TQCString& replyType, TQByteArray &replyData)
1715 d->transaction =
false;
1716 if ( !app.isEmpty() && app != d->appId && app[app.length()-1] !=
'*') {
1717 qWarning(
"WEIRD! we somehow received a DCOP message w/a different appId");
1721 if (objId.isEmpty() || objId[objId.length()-1] !=
'*')
1726 return findSuccess(app, objId, replyType, replyData);
1730 if (receive(app, objId, fun, data, replyType, replyData))
1732 if (findResultOk(replyType, replyData))
1733 return findSuccess(app, objId, replyType, replyData);
1739 TQPtrList<DCOPObject> matchList =
1742 objPtr != 0L; objPtr = matchList.next())
1745 replyData = TQByteArray();
1747 return findSuccess(app, objPtr->
objId(), replyType, replyData);
1748 objPtr->setCallingDcopClient(
this);
1749 if (objPtr->
process(fun, data, replyType, replyData))
1750 if (findResultOk(replyType, replyData))
1751 return findSuccess(app, objPtr->
objId(), replyType, replyData);
1759 const TQCString &remFun,
const TQByteArray &data,
1760 TQCString& replyType, TQByteArray &replyData,
1763 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1 );
1767 const TQCString &remFun,
const TQByteArray &data,
1768 TQCString& replyType, TQByteArray &replyData,
1769 bool useEventLoop,
int timeout)
1771 if (remApp.isEmpty())
1775 if ( localClient ) {
1776 bool saveTransaction = d->transaction;
1777 TQ_INT32 saveTransactionId = d->transactionId;
1778 TQCString saveSenderId = d->senderId;
1781 bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1787 TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1788 }
while( !localClient->isLocalTransactionFinished(
id, replyType, replyData));
1791 d->transaction = saveTransaction;
1792 d->transactionId = saveTransactionId;
1793 d->senderId = saveSenderId;
1797 return callInternal(remApp, remObjId, remFun, data,
1798 replyType, replyData, useEventLoop, timeout, DCOPCall);
1801 void DCOPClient::asyncReplyReady()
1803 while( d->asyncReplyQueue.count() )
1805 ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1806 handleAsyncReply(replyStruct);
1811 const TQCString &remFun,
const TQByteArray &data,
1812 TQObject *callBackObj,
const char *callBackSlot)
1814 TQCString replyType;
1815 TQByteArray replyData;
1817 ReplyStruct *replyStruct =
new ReplyStruct;
1818 replyStruct->replyType =
new TQCString;
1819 replyStruct->replyData =
new TQByteArray;
1820 replyStruct->replyObject = callBackObj;
1821 replyStruct->replySlot = callBackSlot;
1822 replyStruct->replyId = ++d->transactionId;
1823 if (d->transactionId < 0)
1824 d->transactionId = 0;
1826 bool b = callInternal(remApp, remObjId, remFun, data,
1827 replyStruct,
false, -1, DCOPCall);
1830 delete replyStruct->replyType;
1831 delete replyStruct->replyData;
1836 if (replyStruct->transactionId == 0)
1839 TQTimer::singleShot(0,
this, TQT_SLOT(asyncReplyReady()));
1840 d->asyncReplyQueue.append(replyStruct);
1843 return replyStruct->replyId;
1846 bool DCOPClient::callInternal(
const TQCString &remApp,
const TQCString &remObjId,
1847 const TQCString &remFun,
const TQByteArray &data,
1848 TQCString& replyType, TQByteArray &replyData,
1849 bool useEventLoop,
int timeout,
int minor_opcode)
1851 ReplyStruct replyStruct;
1852 replyStruct.replyType = &replyType;
1853 replyStruct.replyData = &replyData;
1854 return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
1857 bool DCOPClient::callInternal(
const TQCString &remApp,
const TQCString &remObjId,
1858 const TQCString &remFun,
const TQByteArray &data,
1859 ReplyStruct *replyStruct,
1860 bool useEventLoop,
int timeout,
int minor_opcode)
1867 CARD32 oldCurrentKey = d->currentKey;
1868 if ( !d->currentKey )
1869 d->currentKey = d->key;
1872 TQDataStream ds(ba, IO_WriteOnly);
1875 IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
1876 sizeof(DCOPMsg), DCOPMsg, pMsg);
1878 pMsg->key = d->currentKey;
1879 int datalen = ba.size() + data.size();
1880 pMsg->length += datalen;
1884 IceSendData(d->iceConn, ba.size(),
const_cast<char *
>(ba.data()));
1885 IceSendData(d->iceConn, data.size(),
const_cast<char *
>(data.data()));
1887 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
1890 IceFlush (d->iceConn);
1892 IceReplyWaitInfo waitInfo;
1893 waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
1894 waitInfo.major_opcode_of_request = d->majorOpcode;
1895 waitInfo.minor_opcode_of_request = minor_opcode;
1897 replyStruct->transactionId = -1;
1898 waitInfo.reply =
static_cast<IcePointer
>(replyStruct);
1900 Bool readyRet = False;
1901 IceProcessMessagesStatus s;
1907 gettimeofday( &time_start, NULL );
1908 time_left = timeout;
1911 bool checkMessages =
true;
1913 ? d->notifier != NULL
1915 const int guiTimeout = 100;
1916 checkMessages =
false;
1918 int msecs = useEventLoop
1924 FD_SET(
socket(), &fds );
1925 tv.tv_sec = msecs / 1000;
1926 tv.tv_usec = (msecs % 1000) * 1000;
1927 if ( select(
socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
1928 if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
1931 bool old_lock = d->non_blocking_call_lock;
1933 d->non_blocking_call_lock =
true;
1937 d->eventLoopTimer.start(time_left - guiTimeout,
true);
1938 tqApp->enter_loop();
1939 d->eventLoopTimer.stop();
1941 d->non_blocking_call_lock =
false;
1948 checkMessages =
true;
1954 if( replyStruct->transactionId != -1 )
1956 if (replyStruct->transactionId == 0)
1958 if (!replyStruct->replySlot.isEmpty())
1962 if( checkMessages ) {
1963 s = IceProcessMessages(d->iceConn, &waitInfo,
1965 if (s == IceProcessMessagesIOError) {
1967 d->currentKey = oldCurrentKey;
1972 if( replyStruct->transactionId != -1 )
1974 if (replyStruct->transactionId == 0)
1976 if (!replyStruct->replySlot.isEmpty())
1983 gettimeofday( &time_now, NULL );
1984 time_left = timeout -
1985 ((time_now.tv_sec - time_start.tv_sec) * 1000) -
1986 ((time_now.tv_usec - time_start.tv_usec) / 1000);
1993 useEventLoop =
false;
1996 *(replyStruct->replyType) = TQCString();
1997 *(replyStruct->replyData) = TQByteArray();
1998 replyStruct->status = ReplyStruct::Failed;
2004 if ( d->non_blocking_call_lock ) {
2008 d->currentKey = oldCurrentKey;
2009 return replyStruct->status != ReplyStruct::Failed;
2012 void DCOPClient::eventLoopTimeout()
2023 timeout.tv_usec = 0;
2026 int result = select(fd+1, &fds, 0, 0, &timeout);
2030 if ( d->non_blocking_call_lock ) {
2038 d->notifier->deleteLater();
2040 qWarning(
"received an error processing data from the DCOP server!");
2044 IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
2046 if (s == IceProcessMessagesIOError) {
2048 qWarning(
"received an error processing data from the DCOP server!");
2055 d->defaultObject = objId;
2061 return d->defaultObject;
2065 DCOPClient::isLocalTransactionFinished(TQ_INT32
id, TQCString &replyType, TQByteArray &replyData)
2067 DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(
id);
2071 replyType = result->replyType;
2072 replyData = result->replyData;
2078 DCOPClientTransaction *
2081 if (d->opcode == DCOPSend)
2083 if (!d->transactionList)
2084 d->transactionList =
new TQPtrList<DCOPClientTransaction>;
2086 d->transaction =
true;
2087 DCOPClientTransaction *trans =
new DCOPClientTransaction();
2088 trans->senderId = d->senderId;
2089 trans->id = ++d->transactionId;
2090 if (d->transactionId < 0)
2091 d->transactionId = 0;
2092 trans->key = d->currentKey;
2094 d->transactionList->append( trans );
2103 return d->transactionId;
2110 TQByteArray &replyData)
2118 if ( !d->transactionList) {
2119 qWarning(
"Transaction unknown: No pending transactions!");
2123 if ( !d->transactionList->removeRef( trans ) ) {
2124 qWarning(
"Transaction unknown: Not on list of pending transactions!");
2128 if (trans->senderId.isEmpty())
2131 DCOPClientPrivate::LocalTransactionResult *result =
new DCOPClientPrivate::LocalTransactionResult();
2132 result->replyType = replyType;
2133 result->replyData = replyData;
2135 d->localTransActionList.insert(trans->id, result);
2145 TQDataStream ds(ba, IO_WriteOnly);
2146 ds << d->appId << trans->senderId << trans->id << replyType << replyData;
2148 IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
2149 sizeof(DCOPMsg), DCOPMsg, pMsg);
2150 pMsg->key = trans->key;
2151 pMsg->length += ba.size();
2153 IceSendData( d->iceConn, ba.size(),
const_cast<char *
>(ba.data()) );
2173 const TQCString &signal,
2174 const TQCString &receiverObj,
const TQCString &slot,
bool Volatile)
2176 TQCString replyType;
2177 TQByteArray data, replyData;
2178 TQ_INT8 iVolatile = Volatile ? 1 : 0;
2180 TQDataStream args(data, IO_WriteOnly );
2183 if (!
call(
"DCOPServer", 0,
2184 "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
2185 data, replyType, replyData))
2190 if (replyType !=
"bool")
2193 TQDataStream reply(replyData, IO_ReadOnly );
2196 return (result != 0);
2201 const TQCString &receiverObj,
const TQCString &slot,
bool Volatile)
2208 const TQCString &signal,
2209 const TQCString &receiverObj,
const TQCString &slot)
2211 TQCString replyType;
2212 TQByteArray data, replyData;
2214 TQDataStream args(data, IO_WriteOnly );
2217 if (!
call(
"DCOPServer", 0,
2218 "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
2219 data, replyType, replyData))
2224 if (replyType !=
"bool")
2227 TQDataStream reply(replyData, IO_ReadOnly );
2230 return (result != 0);
2235 const TQCString &receiverObj,
const TQCString &slot)
2241 DCOPClient::setPriorityCall(
bool b)
2245 if (d->currentKey == 2)
2247 d->currentKeySaved = d->currentKey;
2252 if (d->currentKey != 2)
2254 d->currentKey = d->currentKeySaved;
2255 if ( !d->messages.isEmpty() )
2256 d->postMessageTimer.start( 0,
true );
2263 DCOPClient::emergencyClose()
2265 TQPtrList<DCOPClient> list;
2266 client_map_t *map = DCOPClient_CliMap;
2268 TQAsciiDictIterator<DCOPClient> it(*map);
2269 while(it.current()) {
2270 list.removeRef(it.current());
2271 list.append(it.current());
2274 for(
DCOPClient *cl = list.first(); cl; cl = list.next())
2276 if (cl->d->iceConn) {
2277 IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
2278 IceCloseConnection(cl->d->iceConn);
2279 cl->d->iceConn = 0L;
2285 DCOPClient::postMortemSender()
2287 if (!dcop_main_client)
2289 if (dcop_main_client->d->senderId.isEmpty())
2291 return dcop_main_client->d->senderId.data();
2295 DCOPClient::postMortemObject()
2297 if (!dcop_main_client)
2299 return dcop_main_client->d->objId.data();
2302 DCOPClient::postMortemFunction()
2304 if (!dcop_main_client)
2306 return dcop_main_client->d->function.data();
2309 void DCOPClient::virtual_hook(
int,
void* )
2312 #include <dcopclient.moc>