3ff8784aa6692e53f8c7272421fc9a412ef88d7a
[quassel.git] / src / contrib / qxt / qxtrpcpeer.h
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtNetwork module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE. 
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 ** 
21 ** <http://libqxt.sourceforge.net>  <foundation@libqxt.org>
22 **
23 *****************************************************************************
24 **
25 ** This file has been modified from its original state to suit the needs of
26 ** Quassel IRC. We have virtualized some methods.
27 **
28 *****************************************************************************/
29
30 #ifndef QXTRPCPEER
31 #define QXTRPCPEER
32
33 #include <QObject>
34 #include <QList>
35 #include <QVariant>
36 #include <QPair>
37 #include <QString>
38 #include <QHostAddress>
39 #include <qxtpimpl.h>
40 #include <qxtglobal.h>
41
42 class QxtRPCPeerPrivate;
43 /*!
44  * \class QxtRPCPeer QxtRPCPeer
45  * \ingroup network
46  * \brief Transmits Qt signals over a network connection
47  *
48  * QxtRPCPeer is a tool that encapsulates Qt signals and transmits them over a network connection.
49  * The signal is subsequently re-emitted on the receiving end of the connection.
50  * 
51  * QxtRPCPeer can operate in peer-to-peer mode (that is, one-to-one) or client-server (that is, one-to-many) mode.
52  * In peer or server mode, QxtRPCPeer can listen for and accept incoming connections. In peer or client mode,
53  * QxtRPCPeer can connect to a listening peer or server.
54  * 
55  * All data types used in attached signals and slots must be declared and registered with QMetaType using
56  * Q_DECLARE_METATYPE and qRegisterMetaType, and they must have stream operators registered with qRegisterMetaTypeStreamOperators.
57  *
58  * The limits on the number of parameters passed to call() and related functions are a restriction of Qt,
59  * which limits parameters on a signal or slot to 10.
60  */ 
61 class QXT_NETWORK_EXPORT QxtRPCPeer : public QObject {
62 Q_OBJECT
63 public:
64
65     /*!
66      * This enum is used with the \a setRPCType() to describe the role played in a connection. It is also returned by \a rpcType().
67      */
68     enum RPCTypes {
69         Server, /**< Listen for clients and accept multiple connections. */
70         Client, /**< Connect to a server. */
71         Peer    /**< Listen for a connection or connect to a peer. */
72     };
73
74     /*!
75     * Creates a QxtRPCPeer object with the given parent. Unless changed later, this object will use Peer mode and QTcpSocket for its I/O device.
76     */
77     QxtRPCPeer(QObject* parent = 0);
78
79     /*!
80     * Creates a QxtRPCPeer object with the given parent and type. Unless changed later, this object will use QTcpSocket for its I/O device.
81     */
82     QxtRPCPeer(RPCTypes type, QObject* parent = 0);
83
84     /*!
85     * Creates a QxtRPCPeer object with the given parent and type and connects it to the specified I/O device.
86     * 
87     * Note that the I/O device must already be opened for reading and writing. This constructor cannot be used for Server mode.
88     */
89     QxtRPCPeer(QIODevice* device, RPCTypes type = QxtRPCPeer::Peer, QObject* parent = 0);
90
91     /*!
92      * Sets the RPC type. 
93      *
94      * Attempting to change the RPC type while listening or connected will be ignored with a warning.
95      */
96     void setRPCType(RPCTypes type);
97
98     /*!
99      * Returns the current RPC type.
100      */
101     RPCTypes rpcType() const;
102
103     /*!
104      * Connects to the specified peer or server on the selected port.
105      *
106      * When the connection is complete, the \a peerConnected() signal will be emitted.  If an error occurs, the \a peerError() signal will be emitted.
107      */
108     void connect(QHostAddress addr, int port = 80);
109
110     /*!
111      * Listens on the specified interface on the specified port for connections. 
112      *
113      * Attempting to listen while in Client mode or while connected in Peer mode will be ignored with a warning.  In Peer mode, only one connection
114      * can be active at a time. Additional incoming connections while connected to a peer will be dropped. When a peer connects, the \a peerConnected()
115      * signal will be emitted. In Server mode, multiple connections can be active at a time. Each client that connects will be provided a unique ID,
116      * included in the \a clientConnected() signal that will be emitted.
117      */
118     bool listen(QHostAddress iface = QHostAddress::Any, int port = 80);
119
120     /*!
121      * Disconnects from a server, client, or peer.
122      *
123      * Servers must provide a client ID, provided by the \a clientConnected() signal; clients and peers must not.
124      */
125     void disconnectPeer(quint64 id = -1);
126
127     /*!
128      * Disconnects from all clients, or from the server or peer.
129      */
130     void disconnectAll();
131
132     /*!
133      * Stops listening for connections. Any connections still open will remain connected.
134      */
135     void stopListening();
136         
137     /*!
138      * Returns a list of client IDs for all connected clients.
139      */
140     QList<quint64> clients() const;
141
142     /*!
143      * Attaches the given signal. 
144      *
145      * When the attached signal is emitted, it will be transmitted to all connected servers, clients, or peers.
146      * If an optional rpcFunction is provided, it will be used in place of the name of the transmitted signal.
147      * Use the SIGNAL() macro to specify the signal, just as you would for QObject::connect().
148      *
149      * Like QObject::connect(), attachSignal returns false if the connection cannot be established.
150      */
151     bool attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction = QByteArray());
152
153     /*!
154      * Attaches the given slot. 
155      *
156      * When a signal with the name given by rpcFunction is received from the network, the attached slot is executed. 
157      * Use the SLOT() macro to specify the slot, just as you would for QObject::connect(). 
158      *
159      * Like QObject::connect(), attachSignal returns false if the connection cannot be established.
160      *
161      * \Note In Server mode, the first parameter of the slot must be int id. The parameters of the signal follow.
162      * For example, SIGNAL(mySignal(QString)) from the client connects to SLOT(mySlot(int, QString)) on the server.
163      */
164     bool attachSlot(const QByteArray& rpcFunction, QObject* recv, const char* slot);
165
166     /*!
167      * Detaches all signals and slots for the given object.
168      */
169     void detachObject(QObject* obj);
170
171 public slots:
172     /*!
173      * Sends the signal fn with the given parameter list to the server or peer. 
174      *
175      * This function accepts up to 9 QVariant parameters. 
176      *
177      * The receiver is not obligated to act upon the signal. If no server or peer is connected, the call is ignored.
178      * In particular, this function does nothing in Server mode.
179      */
180     void call(const char *signal, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
181               QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant(), QVariant p9 = QVariant());
182
183     /*!
184      * Sends the signal with the given parameter list to the provided list of clients.
185      *
186      * This function accepts up to 8 QVariant parameters.
187      *
188      * The receivers are not obligated to act upon the signal. If no client is connected with a provided ID, the ID
189      * is ignored with a warning.
190      */
191     void callClientList(QList<quint64> ids, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
192               QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
193
194     /*!
195      * Sends the signal fn with the given parameter list to the specified client.
196      *
197      * This function accepts up to 8 QVariant parameters. 
198      * 
199      * The receiver is not obligated to act upon the signal. If no client with the given ID is connected, the call will be ignored with a warning.
200      */
201     void callClient(quint64 id, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
202               QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
203
204     /*!
205      * Sends the signal fn with the given parameter list to all connected clients except for the client specified.
206      *
207      * This function accepts up to 8 QVariant parameters.
208      *
209      * The receiver is not obligated to act upon the signal. This function is useful for rebroadcasting a signal from one client
210      * to all other connected clients.
211      */
212     void callClientsExcept(quint64 id, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
213               QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
214
215     /*!
216      * Detaches all signals and slots for the object that emitted the signal connected to detachSender().
217      */
218     void detachSender();
219
220 signals:
221     /*!
222      * This signal is emitted after a successful connection to or from a peer or server.
223      */
224     void peerConnected();
225
226     /*!
227      * This signal is emitted after a successful connection from a client. 
228      *
229      * The given ID is used for disconnectPeer(), callClient(), and related functions.
230      */
231     void clientConnected(quint64 id);
232
233     /*!
234      * This signal is emitted when a peer or server is disconnected.
235      */
236     void peerDisconnected();
237
238     /*!
239      * This signal is emitted when a client disconnects. The given ID is no longer valid.
240      */
241     void clientDisconnected(quint64 id);
242
243     /*!
244      * This signal is emitted whenever an error occurs on a socket.
245      *
246      * Currently, no information about the socket that raised the error is available.
247      */
248     void peerError(QAbstractSocket::SocketError);
249
250 protected:
251     /*!
252      * Serializes a signal into a form suitable for transmitting over the network.
253      *
254      * Reimplement this function in a subclass to allow QxtRPCPeer to use a different protocol.
255      */
256     virtual QByteArray serialize(QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) const;
257
258     /*!
259      * Deserializes network data into a signal name and a list of parameters.
260      *
261      * Reimplement this function in a subclass to allow QxtRPCPeer to understand a different protocol.
262      * If you reimplement it, be sure to remove the processed portion of the data from the reference parameter.
263      * Return "qMakePair(QString(), QList<QVariant>())" if the deserialized data doesn't invoke a signal.
264      * Return "qMakePair(QString(), QList<QVariant>() << QVariant())" if the protocol has been violated and
265      * the connection should be severed.
266      */
267     virtual QPair<QString, QList<QVariant> > deserialize(QByteArray& data);
268
269     /*!
270      * Indicates whether the data currently received from the network can be deserialized.
271      *
272      * The default behavior of this function returns true if the buffer contains a newline character.
273      *
274      * Reimplement this function in a subclass to allow QxtRPCPeer to understand a different protocol.
275      */
276     virtual bool canDeserialize(const QByteArray& buffer) const;
277
278 //protected:
279 //    void newConnection();
280
281 private:
282     QXT_DECLARE_PRIVATE(QxtRPCPeer);
283
284 private slots:
285     void newConnection();
286     void dataAvailable();
287     void disconnectSender();
288 };
289 #endif