summaryrefslogtreecommitdiff
path: root/src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt')
-rw-r--r--src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt559
1 files changed, 0 insertions, 559 deletions
diff --git a/src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt b/src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt
deleted file mode 100644
index dfd3bcf8f4..0000000000
--- a/src/3rd_party/dbus-1.7.8/doc/dcop-howto.txt
+++ /dev/null
@@ -1,559 +0,0 @@
- DCOP: Desktop COmmunications Protocol
-
- Preston Brown <pbrown@kde.org>
- October 14, 1999
-
- Revised and extended by Matthias Ettrich <ettrich@kde.org>
- Mar 29, 2000
-
- Extended with DCOP Signals by Waldo Bastian <bastian@kde.org>
- Feb 19, 2001
-
-
-Motivation and Background:
---------------------------
-
-The motivation behind building a protocol like DCOP is simple. For
-the past year, we have been attempting to enable interprocess
-communication between KDE applications. KDE already has an extremely
-simple IPC mechanism called KWMcom, which is (was!) used for communicating
-between the panel and the window manager for instance. It is about as
-simple as it gets, passing messages via X Atoms. For this reason it
-is limited in the size and complexity of the data that can be passed
-(X atoms must be small to remain efficient) and it also makes it so
-that X is required. CORBA was thought to be a more effective IPC/RPC
-solution. However, after a year of attempting to make heavy use of
-CORBA in KDE, we have realized that it is a bit slow and memory
-intensive for simple use. It also has no authentication available.
-
-What we really needed was an extremely simple protocol with basic
-authorization, along the lines of MIT-MAGIC-COOKIE, as used by X. It
-would not be able to do NEARLY what CORBA was able to do, but for the
-simple tasks required it would be sufficient. Some examples of such
-tasks might be an application sending a message to the panel saying,
-"I have started, stop displaying the 'application starting' wait
-state," or having a new application that starts query to see if any
-other applications of the same name are running. If they are, simply
-call a function on the remote application to create a new window,
-rather than starting a new process.
-
-Implementation:
----------------
-
-DCOP is a simple IPC/RPC mechanism built to operate over sockets.
-Either unix domain sockets or tcp/ip sockets are supported. DCOP is
-built on top of the Inter Client Exchange (ICE) protocol, which comes
-standard as a part of X11R6 and later. It also depends on Qt, but
-beyond that it does not require any other libraries. Because of this,
-it is extremely lightweight, enabling it to be linked into all KDE
-applications with low overhead.
-
-Model:
-------
-
-The model is simple. Each application using DCOP is a client. They
-communicate to each other through a DCOP server, which functions like
-a traffic director, dispatching messages/calls to the proper
-destinations. All clients are peers of each other.
-
-Two types of actions are possible with DCOP: "send and forget"
-messages, which do not block, and "calls," which block waiting for
-some data to be returned.
-
-Any data that will be sent is serialized (marshalled, for you CORBA
-types) using the built-in QDataStream operators available in all of
-the Qt classes. This is fast and easy. In fact it's so little work
-that you can easily write the marshalling code by hand. In addition,
-there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp)
-that generates stubs and skeletons for you. Using the dcopidl compiler
-has the additional benefit of type safety.
-
-This HOWTO describes the manual method first and covers the dcopidl
-compiler later.
-
-Establishing the Connection:
-----------------------------
-
-KApplication has gained a method called "KApplication::dcopClient()"
-which returns a pointer to a DCOPClient instance. The first time this
-method is called, the client class will be created. DCOPClients have
-unique identifiers attached to them which are based on what
-KApplication::name() returns. In fact, if there is only a single
-instance of the program running, the appId will be equal to
-KApplication::name().
-
-To actually enable DCOP communication to begin, you must use
-DCOPClient::attach(). This will attempt to attach to the DCOP server.
-If no server is found or there is any other type of error, attach()
-will return false. KApplication will catch a dcop signal and display an
-appropriate error message box in that case.
-
-After connecting with the server via DCOPClient::attach(), you need to
-register this appId with the server so it knows about you. Otherwise,
-you are communicating anonymously. Use the
-DCOPClient::registerAs(const QCString &name) to do so. In the simple
-case:
-
-/*
- * returns the appId that is actually registered, which _may_ be
- * different from what you passed
- */
-appId = client->registerAs(kApp->name());
-
-If you never retrieve the DCOPClient pointer from KApplication, the
-object will not be created and thus there will be no memory overhead.
-
-You may also detach from the server by calling DCOPClient::detach().
-If you wish to attach again you will need to re-register as well. If
-you only wish to change the ID under which you are registered, simply
-call DCOPClient::registerAs() with the new name.
-
-KUniqueApplication automatically registers itself to DCOP. If you
-are using KUniqueApplication you should not attach or register
-yourself, this is already done. The appId is by definition
-equal to kapp->name(). You can retrieve the registered DCOP client
-by calling kapp->dcopClient().
-
-Sending Data to a Remote Application:
--------------------------------------
-
-To actually communicate, you have one of two choices. You may either
-call the "send" or the "call" method. Both methods require three
-identification parameters: an application identifier, a remote object,
-a remote function. Sending is asynchronous (i.e. it returns immediately)
-and may or may not result in your own application being sent a message at
-some point in the future. Then "send" requires one and "call" requires
-two data parameters.
-
-The remote object must be specified as an object hierarchy. That is,
-if the toplevel object is called "fooObject" and has the child
-"barObject", you would reference this object as "fooObject/barObject".
-Functions must be described by a full function signature. If the
-remote function is called "doIt", and it takes an int, it would be
-described as "doIt(int)". Please note that the return type is not
-specified here, as it is not part of the function signature (or at
-least the C++ understanding of a function signature). You will get
-the return type of a function back as an extra parameter to
-DCOPClient::call(). See the section on call() for more details.
-
-In order to actually get the data to the remote client, it must be
-"serialized" via a QDataStream operating on a QByteArray. This is how
-the data parameter is "built". A few examples will make clear how this
-works.
-
-Say you want to call "doIt" as described above, and not block (or wait
-for a response). You will not receive the return value of the remotely
-called function, but you will not hang while the RPC is processed either.
-The return value of send() indicates whether DCOP communication succeeded
-or not.
-
-QByteArray data;
-QDataStream arg(data, IO_WriteOnly);
-arg << 5;
-if (!client->send("someAppId", "fooObject/barObject", "doIt(int)",
- data))
- qDebug("there was some error using DCOP.");
-
-OK, now let's say we wanted to get the data back from the remotely
-called function. You have to execute a call() instead of a send().
-The returned value will then be available in the data parameter "reply".
-The actual return value of call() is still whether or not DCOP
-communication was successful.
-
-QByteArray data, replyData;
-QCString replyType;
-QDataStream arg(data, IO_WriteOnly);
-arg << 5;
-if (!client->call("someAppId", "fooObject/barObject", "doIt(int)",
- data, replyType, replyData))
- qDebug("there was some error using DCOP.");
-else {
- QDataStream reply(replyData, IO_ReadOnly);
- if (replyType == "QString") {
- QString result;
- reply >> result;
- print("the result is: %s",result.latin1());
- } else
- qDebug("doIt returned an unexpected type of reply!");
-}
-
-N.B.: You cannot call() a method belonging to an application which has
-registered with an unique numeric id appended to its textual name (see
-dcopclient.h for more info). In this case, DCOP would not know which
-application it should connect with to call the method. This is not an issue
-with send(), as you can broadcast to all applications that have registered
-with appname-<numeric_id> by using a wildcard (e.g. 'konsole-*'), which
-will send your signal to all applications called 'konsole'.
-
-Receiving Data via DCOP:
-------------------------
-
-Currently the only real way to receive data from DCOP is to multiply
-inherit from the normal class that you are inheriting (usually some
-sort of QWidget subclass or QObject) as well as the DCOPObject class.
-DCOPObject provides one very important method: DCOPObject::process().
-This is a pure virtual method that you must implement in order to
-process DCOP messages that you receive. It takes a function
-signature, QByteArray of parameters, and a reference to a QByteArray
-for the reply data that you must fill in.
-
-Think of DCOPObject::process() as a sort of dispatch agent. In the
-future, there will probably be a precompiler for your sources to write
-this method for you. However, until that point you need to examine
-the incoming function signature and take action accordingly. Here is
-an example implementation.
-
-bool BarObject::process(const QCString &fun, const QByteArray &data,
- QCString &replyType, QByteArray &replyData)
-{
- if (fun == "doIt(int)") {
- QDataStream arg(data, IO_ReadOnly);
- int i; // parameter
- arg >> i;
- QString result = self->doIt (i);
- QDataStream reply(replyData, IO_WriteOnly);
- reply << result;
- replyType = "QString";
- return true;
- } else {
- qDebug("unknown function call to BarObject::process()");
- return false;
- }
-}
-
-Receiving Calls and processing them:
-------------------------------------
-
-If your applications is able to process incoming function calls
-right away the above code is all you need. When your application
-needs to do more complex tasks you might want to do the processing
-out of 'process' function call and send the result back later when
-it becomes available.
-
-For this you can ask your DCOPClient for a transactionId. You can
-then return from the 'process' function and when the result is
-available finish the transaction. In the mean time your application
-can receive incoming DCOP function calls from other clients.
-
-Such code could like this:
-
-bool BarObject::process(const QCString &fun, const QByteArray &data,
- QCString &, QByteArray &)
-{
- if (fun == "doIt(int)") {
- QDataStream arg(data, IO_ReadOnly);
- int i; // parameter
- arg >> i;
- QString result = self->doIt(i);
-
- DCOPClientTransaction *myTransaction;
- myTransaction = kapp->dcopClient()->beginTransaction();
-
- // start processing...
- // Calls slotProcessingDone when finished.
- startProcessing( myTransaction, i);
-
- return true;
- } else {
- qDebug("unknown function call to BarObject::process()");
- return false;
- }
-}
-
-slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result)
-{
- QCString replyType = "QString";
- QByteArray replyData;
- QDataStream reply(replyData, IO_WriteOnly);
- reply << result;
- kapp->dcopClient()->endTransaction( myTransaction, replyType, replyData );
-}
-
-DCOP Signals
-------------
-
-Sometimes a component wants to send notifications via DCOP to other
-components but does not know which components will be interested in these
-notifications. One could use a broadcast in such a case but this is a very
-crude method. For a more sophisticated method DCOP signals have been invented.
-
-DCOP signals are very similair to Qt signals, there are some differences
-though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP
-signal gets emitted, the DCOP functions to which the signal is connected are
-being called. DCOP signals are, just like Qt signals, one way. They do not
-provide a return value.
-
-A DCOP signal originates from a DCOP Object/DCOP Client combination (sender).
-It can be connected to a function of another DCOP Object/DCOP Client
-combination (receiver).
-
-There are two major differences between connections of Qt signals and
-connections of DCOP signals. In DCOP, unlike Qt, a signal connections can
-have an anonymous sender and, unlike Qt, a DCOP signal connection can be
-non-volatile.
-
-With DCOP one can connect a signal without specifying the sending DCOP Object
-or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client
-will be delivered. This allows the specification of certain events without
-tying oneself to a certain object that implementes the events.
-
-Another DCOP feature are so called non-volatile connections. With Qt signal
-connections, the connection gets deleted when either sender or receiver of
-the signal gets deleted. A volatile DCOP signal connection will behave the
-same. However, a non-volatile DCOP signal connection will not get deleted
-when the sending object gets deleted. Once a new object gets created with
-the same name as the original sending object, the connection will be restored.
-There is no difference between the two when the receiving object gets deleted,
-in that case the signal connection will always be deleted.
-
-A receiver can create a non-volatile connection while the sender doesn't (yet)
-exist. An anonymous DCOP connection should always be non-volatile.
-
-The following example shows how KLauncher emits a signal whenever it notices
-that an application that was started via KLauncher terminates.
-
- QByteArray params;
- QDataStream stream(params, IO_WriteOnly);
- stream << pid;
- kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params);
-
-The task manager of the KDE panel connects to this signal. It uses an
-anonymous connection (it doesn't require that the signal is being emitted
-by KLauncher) that is non-volatile:
-
- connectDCOPSignal(0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false);
-
-It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP
-function. In this case the signal and the function to call have the same name.
-This isn't needed as long as the arguments of both signal and receiving function
-match. The receiving function may ignore one or more of the trailing arguments
-of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to
-a clientDied(void) DCOP function.
-
-Using the dcopidl compiler
----------------------
-
-dcopidl makes setting up a DCOP server easy. Instead of having to implement
-the process() method and unmarshalling (retrieving from QByteArray) parameters
-manually, you can let dcopidl create the necessary code on your behalf.
-
-This also allows you to describe the interface for your class in a
-single, separate header file.
-
-Writing an IDL file is very similar to writing a normal C++ header. An
-exception is the keyword 'ASYNC'. It indicates that a call to this
-function shall be processed asynchronously. For the C++ compiler, it
-expands to 'void'.
-
-Example:
-
-#ifndef MY_INTERFACE_H
-#define MY_INTERFACE_H
-
-#include <dcopobject.h>
-
-class MyInterface : virtual public DCOPObject
-{
- K_DCOP
-
- k_dcop:
-
- virtual ASYNC myAsynchronousMethod(QString someParameter) = 0;
- virtual QRect mySynchronousMethod() = 0;
-};
-
-#endif
-
-As you can see, you're essentially declaring an abstract base class, which
-virtually inherits from DCOPObject.
-
-If you're using the standard KDE build scripts, then you can simply
-add this file (which you would call MyInterface.h) to your sources
-directory. Then you edit your Makefile.am, adding 'MyInterface.skel'
-to your SOURCES list and MyInterface.h to include_HEADERS.
-
-The build scripts will use dcopidl to parse MyInterface.h, converting
-it to an XML description in MyInterface.kidl. Next, a file called
-MyInterface_skel.cpp will automatically be created, compiled and
-linked with your binary.
-
-The next thing you have to do is to choose which of your classes will
-implement the interface described in MyInterface.h. Alter the inheritance
-of this class such that it virtually inherits from MyInterface. Then
-add declarations to your class interface similar to those on MyInterface.h,
-but virtual, not pure virtual.
-
-Example:
-
-class MyClass: public QObject, virtual public MyInterface
-{
- Q_OBJECT
-
- public:
- MyClass();
- ~MyClass();
-
- ASYNC myAsynchronousMethod(QString someParameter);
- QRect mySynchronousMethod();
-};
-
-Note: (Qt issue) Remember that if you are inheriting from QObject, you must
-place it first in the list of inherited classes.
-
-In the implementation of your class' ctor, you must explicitly initialize
-those classes from which you are inheriting from. This is, of course, good
-practise, but it is essential here as you need to tell DCOPObject the name of
-the interface which your are implementing.
-
-Example:
-
-MyClass::MyClass()
- : QObject(),
- DCOPObject("MyInterface")
-{
- // whatever...
-}
-
-Now you can simply implement the methods you have declared in your interface,
-exactly the same as you would normally.
-
-Example:
-
-void MyClass::myAsynchronousMethod(QString someParameter)
-{
- qDebug("myAsyncMethod called with param `" + someParameter + "'");
-}
-
-
-It is not necessary (though very clean) to define an interface as an
-abstract class of its own, like we did in the example above. We could
-just as well have defined a k_dcop section directly within MyClass:
-
-class MyClass: public QObject, virtual public DCOPObject
-{
- Q_OBJECT
- K_DCOP
-
- public:
- MyClass();
- ~MyClass();
-
- k_dcop:
- ASYNC myAsynchronousMethod(QString someParameter);
- QRect mySynchronousMethod();
-};
-
-In addition to skeletons, dcopidl2cpp also generate stubs. Those make
-it easy to call a DCOP interface without doing the marshalling
-manually. To use a stub, add MyInterface.stub to the SOURCES list of
-your Makefile.am. The stub class will then be called MyInterface_stub.
-
-Conclusion:
------------
-
-Hopefully this document will get you well on your way into the world
-of inter-process communication with KDE! Please direct all comments
-and/or suggestions to Preston Brown <pbrown@kde.org> and Matthias
-Ettrich <ettrich@kde.org>.
-
-
-Inter-user communication
-------------------------
-
-Sometimes it might be interesting to use DCOP between processes
-belonging to different users, e.g. a frontend process running
-with the user's id, and a backend process running as root.
-
-To do this, two steps have to be taken:
-
-a) both processes need to talk to the same DCOP server
-b) the authentication must be ensured
-
-For the first step, you simply pass the server address (as
-found in .DCOPserver) to the second process. For the authentication,
-you can use the ICEAUTHORITY environment variable to tell the
-second process where to find the authentication information.
-(Note that this implies that the second process is able to
-read the authentication file, so it will probably only work
-if the second process runs as root. If it should run as another
-user, a similar approach to what kdesu does with xauth must
-be taken. In fact, it would be a very good idea to add DCOP
-support to kdesu!)
-
-For example
-
-ICEAUTHORITY=~user/.ICEauthority kdesu root -c kcmroot -dcopserver `cat ~user/.DCOPserver`
-
-will, after kdesu got the root password, execute kcmroot as root, talking
-to the user's dcop server.
-
-
-NOTE: DCOP communication is not encrypted, so please do not
-pass important information around this way.
-
-
-Performance Tests:
-------------------
-A few back-of-the-napkin tests folks:
-
-Code:
-
-#include <kapplication.h>
-
-int main(int argc, char **argv)
-{
- KApplication *app;
-
- app = new KApplication(argc, argv, "testit");
- return app->exec();
-}
-
-Compiled with:
-
-g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore
-
-on Linux yields the following memory use statistics:
-
-VmSize: 8076 kB
-VmLck: 0 kB
-VmRSS: 4532 kB
-VmData: 208 kB
-VmStk: 20 kB
-VmExe: 4 kB
-VmLib: 6588 kB
-
-If I create the KApplication's DCOPClient, and call attach() and
-registerAs(), it changes to this:
-
-VmSize: 8080 kB
-VmLck: 0 kB
-VmRSS: 4624 kB
-VmData: 208 kB
-VmStk: 20 kB
-VmExe: 4 kB
-VmLib: 6588 kB
-
-Basically it appears that using DCOP causes 100k more memory to be
-resident, but no more data or stack. So this will be shared between all
-processes, right? 100k to enable DCOP in all apps doesn't seem bad at
-all. :)
-
-OK now for some timings. Just creating a KApplication and then exiting
-(i.e. removing the call to KApplication::exec) takes this much time:
-
-0.28user 0.02system 0:00.32elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (1084major+62minor)pagefaults 0swaps
-
-I.e. about 1/3 of a second on my PII-233. Now, if we create our DCOP
-object and attach to the server, it takes this long:
-
-0.27user 0.03system 0:00.34elapsed 87%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (1107major+65minor)pagefaults 0swaps
-
-I.e. about 1/3 of a second. Basically DCOPClient creation and attaching
-gets lost in the statistical variation ("noise"). I was getting times
-between .32 and .48 over several runs for both of the example programs, so
-obviously system load is more relevant than the extra two calls to
-DCOPClient::attach and DCOPClient::registerAs, as well as the actual
-DCOPClient constructor time.
-