Warning, file /games/libkdegames/src/private/kgame/kmessageio.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     This file is part of the KDE games library
0003     SPDX-FileCopyrightText: 2001 Burkhard Lehner <Burkhard.Lehner@gmx.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 /*
0009      KMessageIO class and subclasses KMessageSocket and KMessageDirect
0010 */
0011 
0012 #ifndef _KMESSAGEIO_H_
0013 #define _KMESSAGEIO_H_
0014 
0015 // own
0016 #include "kdegamesprivate_export.h"
0017 // Qt
0018 #include <QHostAddress>
0019 #include <QObject>
0020 #include <QProcess>
0021 #include <QString>
0022 
0023 class QTcpSocket;
0024 class KProcess;
0025 
0026 /**
0027   \class KMessageIO kmessageio.h <KGame/KMessageIO>
0028 
0029   This abstract base class represents one end of a message connections
0030   between two clients. Each client has one object of a subclass of
0031   KMessageIO. Calling /e send() on one object will emit the signal
0032   /e received() on the other object, and vice versa.
0033 
0034   For each type of connection (TCP/IP socket, COM port, direct connection
0035   within the same class) a subclass of KMessageIO must be defined that
0036   implements the pure virtual methods /e send() and /e isConnected(),
0037   and sends the signals. (See /e KMessageSocket for an example implementation.)
0038 
0039   Two subclasses are already included: /e KMessageSocket (connection using
0040   TCP/IP sockets) and /e KMessageDirect (connection using method calls, both
0041   sides must be within the same process).
0042 */
0043 class KDEGAMESPRIVATE_EXPORT KMessageIO : public QObject
0044 {
0045     Q_OBJECT
0046 
0047 public:
0048     /**
0049      * The usual QObject constructor, does nothing else.
0050      */
0051     explicit KMessageIO(QObject *parent = nullptr);
0052 
0053     /**
0054      * The usual destructor, does nothing special.
0055      */
0056     ~KMessageIO() override;
0057 
0058     /**
0059      * The runtime identification
0060      */
0061     virtual int rtti() const
0062     {
0063         return 0;
0064     }
0065 
0066     /**
0067      * @return Whether this KMessageIO is a network IO or not.
0068      */
0069     // virtual bool isNetwork () const = 0;
0070     virtual bool isNetwork() const;
0071 
0072     /**
0073       This method returns the status of the object, whether it is already
0074       (or still) connected to another KMessageIO object or not.
0075 
0076       This is a pure virtual method, so it has to be implemented in a subclass
0077       of KMessageIO.
0078     */
0079     // virtual bool isConnected () const = 0;
0080     virtual bool isConnected() const;
0081 
0082     /**
0083       Sets the ID number of this object. This number can for example be used to
0084       distinguish several objects in a server.
0085 
0086       NOTE: Sometimes it is useful to let two connected KMessageIO objects
0087       have the same ID number. You have to do so yourself, KMessageIO doesn't
0088       change this value on its own!
0089     */
0090     void setId(quint32 id);
0091 
0092     /**
0093       Queries the ID of this object.
0094     */
0095     quint32 id();
0096 
0097     /**
0098       @return 0 in the default implementation. Reimplemented in @ref KMessageSocket.
0099     */
0100     virtual quint16 peerPort() const;
0101 
0102     /**
0103       @return "localhost" in the default implementation. Reimplemented in @ref KMessageSocket
0104     */
0105     virtual QString peerName() const;
0106 
0107 Q_SIGNALS:
0108     /**
0109       This signal is emitted when /e send() on the connected KMessageIO
0110       object is called. The parameter contains the same data array in /e msg
0111       as was used in /e send().
0112     */
0113     void received(const QByteArray &msg);
0114 
0115     /**
0116       This signal is emitted when the connection is closed. This can be caused
0117       by a hardware error (e.g. broken internet connection) or because the other
0118       object was killed.
0119 
0120       Note: Sometimes a broken connection can be undetected for a long time,
0121       or may never be detected at all. So don't rely on this signal!
0122     */
0123     void connectionBroken();
0124 
0125 public Q_SLOTS:
0126 
0127     /**
0128       This slot sends the data block in /e msg to the connected object, that will
0129       emit /e received().
0130 
0131       For a concrete class, you have to subclass /e KMessageIO and overwrite this
0132       method. In the subclass, implement this method as an ordinary method, not
0133       as a slot! (Otherwise another slot would be defined. It would work, but uses
0134       more memory and time.) See /e KMessageSocket for an example implementation.
0135     */
0136     virtual void send(const QByteArray &msg) = 0;
0137 
0138 protected:
0139     quint32 m_id;
0140 };
0141 
0142 /**
0143   \class KMessageSocket kmessageio.h <KGame/KMessageIO>
0144 
0145   This class implements the message communication using a TCP/IP socket. The
0146   object can connect to a server socket, or can use an already connected socket.
0147 */
0148 
0149 class KMessageSocket : public KMessageIO
0150 {
0151     Q_OBJECT
0152 
0153 public:
0154     /**
0155       Connects to a server socket on /e host with /e port. host can be an
0156       numerical (e.g. "192.168.0.212") or symbolic (e.g. "wave.peter.org")
0157       IP address. You can immediately use the /e sendSystem() and
0158       /e sendBroadcast() methods. The messages are stored and sent to the
0159       receiver after the connection is established.
0160 
0161       If the connection could not be established (e.g. unknown host or no server
0162       socket at this port), the signal /e connectionBroken is emitted.
0163     */
0164     KMessageSocket(const QString &host, quint16 port, QObject *parent = nullptr);
0165 
0166     /**
0167       Connects to a server socket on /e host with /e port. You can immediately
0168       use the /e sendSystem() and /e sendBroadcast() methods. The messages are
0169       stored and sent to the receiver after the connection is established.
0170 
0171       If the connection could not be established (e.g. unknown host or no server
0172       socket at this port), the signal /e connectionBroken is emitted.
0173     */
0174     KMessageSocket(const QHostAddress &host, quint16 port, QObject *parent = nullptr);
0175 
0176     /**
0177       Uses /e socket to do the communication.
0178 
0179       The socket should already be connected, or at least be in /e connecting
0180       state.
0181 
0182       Note: The /e socket object is then owned by the /e KMessageSocket object.
0183       So don't use it otherwise any more and don't delete it. It is deleted
0184       together with this KMessageSocket object. (Use 0 as parent for the QSocket
0185       object t ensure it is not deleted.)
0186     */
0187     explicit KMessageSocket(QTcpSocket *socket, QObject *parent = nullptr);
0188 
0189     /**
0190       Uses the socket specified by the socket descriptor socketFD to do the
0191       communication. The socket must already be connected.
0192 
0193       This constructor can be used with a QServerSocket within the (pure
0194       virtual) method /e newConnection.
0195 
0196       Note: The socket is then owned by the /e KMessageSocket object. So don't
0197       manipulate the socket afterwards, especially don't close it. The socket is
0198       automatically closed when KMessageSocket is deleted.
0199     */
0200     explicit KMessageSocket(int socketFD, QObject *parent = nullptr);
0201 
0202     /**
0203       Destructor, closes the socket.
0204     */
0205     ~KMessageSocket() override;
0206 
0207     /**
0208      * The runtime identification
0209      */
0210     int rtti() const override
0211     {
0212         return 1;
0213     }
0214 
0215     /**
0216       @return The port that this object is connected to. See QSocket::peerPort
0217     */
0218     quint16 peerPort() const override;
0219 
0220     /**
0221       @return The hostname this object is connected to. See QSocket::peerName.
0222     */
0223     QString peerName() const override;
0224 
0225     /**
0226       @return TRUE as this is a network IO.
0227     */
0228     bool isNetwork() const override
0229     {
0230         return true;
0231     }
0232 
0233     /**
0234       Returns true if the socket is in state /e connected.
0235     */
0236     bool isConnected() const override;
0237 
0238     /**
0239       Overwritten slot method from KMessageIO.
0240 
0241       Note: It is not declared as a slot method, since the slot is already
0242       defined in KMessageIO as a virtual method.
0243     */
0244     void send(const QByteArray &msg) override;
0245 
0246 protected Q_SLOTS:
0247     virtual void processNewData();
0248 
0249 protected:
0250     void initSocket();
0251     QTcpSocket *mSocket;
0252     bool mAwaitingHeader;
0253     quint32 mNextBlockLength;
0254 
0255     bool isRecursive; // workaround for "bug" in QSocket, Qt 2.2.3 or older
0256 };
0257 
0258 /**
0259   \class KMessageDirect kmessageio.h <KGame/KMessageIO>
0260 
0261   This class implements the message communication using function calls
0262   directly. It can only be used when both sides of the message pipe are
0263   within the same process. The communication is very fast.
0264 
0265   To establish a communication, you have to create two instances of
0266   KMessageDirect, the first one with no parameters in the constructor,
0267   the second one with the first as parameter:
0268 
0269   /code
0270     KMessageDirect *peer1, *peer2;
0271     peer1 = new KMessageDirect ();       // unconnected
0272     peer2 = new KMessageDirect (peer1);  // connect with peer1
0273   /endcode
0274 
0275   The connection is only closed when one of the instances is deleted.
0276 */
0277 
0278 class KMessageDirect : public KMessageIO
0279 {
0280     Q_OBJECT
0281 
0282 public:
0283     /**
0284       Creates an object and connects it to the object given in the first
0285       parameter. Use 0 as first parameter to create an unconnected object,
0286       that is later connected.
0287 
0288       If that object is already connected, the object remains unconnected.
0289     */
0290     explicit KMessageDirect(KMessageDirect *partner = nullptr, QObject *parent = nullptr);
0291 
0292     /**
0293       Destructor, closes the connection.
0294     */
0295     ~KMessageDirect() override;
0296 
0297     /**
0298      * The runtime identification
0299      */
0300     int rtti() const override
0301     {
0302         return 2;
0303     }
0304 
0305     /**
0306       @return FALSE as this is no network IO.
0307     */
0308     bool isNetwork() const override
0309     {
0310         return false;
0311     }
0312 
0313     /**
0314       Returns true, if the object is connected to another instance.
0315 
0316       If you use the first constructor, the object is unconnected unless another
0317       object is created with this one as parameter.
0318 
0319       The connection can only be closed by deleting one of the objects.
0320     */
0321     bool isConnected() const override;
0322 
0323     /**
0324       Overwritten slot method from KMessageIO.
0325 
0326       Note: It is not declared as a slot method, since the slot is already
0327       defined in KMessageIO as a virtual method.
0328     */
0329     void send(const QByteArray &msg) override;
0330 
0331 protected:
0332     KMessageDirect *mPartner;
0333 };
0334 
0335 /**
0336  * \class KMessageProcess kmessageio.h <KGame/KMessageIO>
0337  */
0338 class KMessageProcess : public KMessageIO
0339 {
0340     Q_OBJECT
0341 
0342 public:
0343     KMessageProcess(QObject *parent, const QString &file);
0344     ~KMessageProcess() override;
0345     bool isConnected() const override;
0346     void send(const QByteArray &msg) override;
0347 
0348     /**
0349       @return FALSE as this is no network IO.
0350     */
0351     bool isNetwork() const override
0352     {
0353         return false;
0354     }
0355 
0356     /**
0357      * The runtime identification
0358      */
0359     int rtti() const override
0360     {
0361         return 3;
0362     }
0363 
0364 public Q_SLOTS:
0365     void slotReceivedStdout();
0366     void slotReceivedStderr();
0367     void slotProcessExited(int, QProcess::ExitStatus);
0368 
0369 Q_SIGNALS:
0370     void signalReceivedStderr(const QString &msg);
0371 
0372 private:
0373     QString mProcessName;
0374     KProcess *mProcess;
0375     QByteArray *mSendBuffer;
0376     QByteArray mReceiveBuffer;
0377     int mReceiveCount;
0378 };
0379 
0380 #endif