• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegames API Reference
  • KDE Home
  • Contact Us
 

libkdegames/libkdegamesprivate/kgame

  • sources
  • kde-4.14
  • kdegames
  • libkdegames
  • libkdegamesprivate
  • kgame
kmessageio.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE games library
3  Copyright (C) 2001 Burkhard Lehner (Burkhard.Lehner@gmx.de)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License version 2 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 /*
21  KMessageIO class and subclasses KMessageSocket and KMessageDirect
22 */
23 
24 #include "kmessageio.h"
25 #include <QTcpSocket>
26 #include <kdebug.h>
27 #include <kprocess.h>
28 #include <QFile>
29 #include <QDataStream>
30 // ----------------------- KMessageIO -------------------------
31 
32 KMessageIO::KMessageIO (QObject *parent)
33  : QObject (parent), m_id (0)
34 {}
35 
36 KMessageIO::~KMessageIO ()
37 {}
38 
39 void KMessageIO::setId (quint32 id)
40 {
41  m_id = id;
42 }
43 
44 quint32 KMessageIO::id ()
45 {
46  return m_id;
47 }
48 
49 // ----------------------KMessageSocket -----------------------
50 
51 KMessageSocket::KMessageSocket (const QString& host, quint16 port, QObject *parent)
52  : KMessageIO (parent)
53 {
54  mSocket = new QTcpSocket ();
55  mSocket->connectToHost (host, port);
56  initSocket ();
57 }
58 
59 KMessageSocket::KMessageSocket (QHostAddress host, quint16 port, QObject *parent)
60  : KMessageIO (parent)
61 {
62  mSocket = new QTcpSocket ();
63  mSocket->connectToHost (host.toString(), port);
64  initSocket ();
65 }
66 
67 KMessageSocket::KMessageSocket (QTcpSocket *socket, QObject *parent)
68  : KMessageIO (parent)
69 {
70  mSocket = socket;
71  initSocket ();
72 }
73 
74 KMessageSocket::KMessageSocket (int socketFD, QObject *parent)
75  : KMessageIO (parent)
76 {
77  mSocket = new QTcpSocket ();
78  mSocket->setSocketDescriptor (socketFD);
79  initSocket ();
80 }
81 
82 KMessageSocket::~KMessageSocket ()
83 {
84  delete mSocket;
85 }
86 
87 bool KMessageSocket::isConnected () const
88 {
89  return mSocket->state() == QAbstractSocket::ConnectedState;
90 }
91 
92 void KMessageSocket::send (const QByteArray &msg)
93 {
94  QDataStream str (mSocket);
95  str << quint8 ('M'); // magic number for begin of message
96  str.writeBytes (msg.data(), msg.size()); // writes the length (as quint32) and the data
97 }
98 
99 void KMessageSocket::processNewData ()
100 {
101  if (isRecursive)
102  return;
103  isRecursive = true;
104 
105  QDataStream str (mSocket);
106  while (mSocket->bytesAvailable() > 0)
107  {
108  if (mAwaitingHeader)
109  {
110  // Header = magic number + packet length = 5 bytes
111  if (mSocket->bytesAvailable() < 5)
112  {
113  isRecursive = false;
114  return;
115  }
116 
117  // Read the magic number first. If something unexpected is found,
118  // start over again, ignoring the data that was read up to then.
119 
120  quint8 v;
121  str >> v;
122  if (v != 'M')
123  {
124  kWarning(11001) << ": Received unexpected data, magic number wrong!";
125  continue;
126  }
127 
128  str >> mNextBlockLength;
129  mAwaitingHeader = false;
130  }
131  else
132  {
133  // Data not completely read => wait for more
134  if (mSocket->bytesAvailable() < (qint64) mNextBlockLength)
135  {
136  isRecursive = false;
137  return;
138  }
139 
140  QByteArray msg (mNextBlockLength, 0);
141  str.readRawData (msg.data(), mNextBlockLength);
142 
143  // send the received message
144  emit received (msg);
145 
146  // Waiting for the header of the next message
147  mAwaitingHeader = true;
148  }
149  }
150 
151  isRecursive = false;
152 }
153 
154 void KMessageSocket::initSocket ()
155 {
156  connect (mSocket, SIGNAL (error(QAbstractSocket::SocketError)), this, SIGNAL (connectionBroken()));
157  connect (mSocket, SIGNAL (disconnected()), this, SIGNAL (connectionBroken()));
158  connect (mSocket, SIGNAL (readyRead()), this, SLOT (processNewData()));
159  mAwaitingHeader = true;
160  mNextBlockLength = 0;
161  isRecursive = false;
162 }
163 
164 quint16 KMessageSocket::peerPort () const
165 {
166  return mSocket->peerPort();
167 }
168 
169 QString KMessageSocket::peerName () const
170 {
171  return mSocket->peerName();
172 }
173 
174 // ----------------------KMessageDirect -----------------------
175 
176 KMessageDirect::KMessageDirect (KMessageDirect *partner, QObject *parent)
177  : KMessageIO (parent), mPartner (0)
178 {
179  // 0 as first parameter leaves the object unconnected
180  if (!partner)
181  return;
182 
183  // Check if the other object is already connected
184  if (partner && partner->mPartner)
185  {
186  kWarning(11001) << ": Object is already connected!";
187  return;
188  }
189 
190  // Connect from us to that object
191  mPartner = partner;
192 
193  // Connect the other object to us
194  partner->mPartner = this;
195 }
196 
197 KMessageDirect::~KMessageDirect ()
198 {
199  if (mPartner)
200  {
201  mPartner->mPartner = 0;
202  emit mPartner->connectionBroken();
203  }
204 }
205 
206 bool KMessageDirect::isConnected () const
207 {
208  return mPartner != 0;
209 }
210 
211 void KMessageDirect::send (const QByteArray &msg)
212 {
213  if (mPartner)
214  emit mPartner->received (msg);
215  else
216  kError(11001) << ": Not yet connected!";
217 }
218 
219 
220 // ----------------------- KMessageProcess ---------------------------
221 
222 KMessageProcess::~KMessageProcess()
223 {
224  kDebug(11001) << "@@@KMessageProcess::Delete process";
225  if (mProcess)
226  {
227  mProcess->kill();
228  mProcess->deleteLater();
229  mProcess=0;
230  // Maybe todo: delete mSendBuffer
231  }
232 }
233 KMessageProcess::KMessageProcess(QObject *parent, const QString& file) : KMessageIO(parent)
234 {
235  // Start process
236  kDebug(11001) << "@@@KMessageProcess::Start process";
237  mProcessName=file;
238  mProcess=new KProcess;
239  // Need both stdout and stderr as separate channels in the communication
240  mProcess-> setOutputChannelMode(KProcess::SeparateChannels);
241  int id=0;
242  *mProcess << mProcessName << QString::fromLatin1( "%1").arg(id);
243  kDebug(11001) << "@@@KMessageProcess::Init:Id=" << id;
244  kDebug(11001) << "@@@KMessgeProcess::Init:Processname:" << mProcessName;
245  connect(mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(slotReceivedStdout()));
246  connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(slotReceivedStderr()));
247  connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
248  this, SLOT(slotProcessExited(int,QProcess::ExitStatus)));
249  mProcess->start();
250  mSendBuffer=0;
251  mReceiveCount=0;
252  mReceiveBuffer.resize(1024);
253 }
254 bool KMessageProcess::isConnected() const
255 {
256  kDebug(11001) << "@@@KMessageProcess::Is conencted";
257  if (!mProcess)
258  return false;
259  return (mProcess->state() == QProcess::Running);
260 }
261 
262 // Send to process
263 void KMessageProcess::send(const QByteArray &msg)
264 {
265  kDebug(11001) << "@@@KMessageProcess:: SEND("<<msg.size()<<") to process";
266  unsigned int size=msg.size()+2*sizeof(long);
267 
268  if (mProcess == 0) {
269  kDebug(11001) << "@@@KMessageProcess:: cannot write to stdin, no process available";
270  return;
271  }
272 
273  char *tmpbuffer=new char[size];
274  long *p1=(long *)tmpbuffer;
275  long *p2=p1+1;
276  kDebug(11001) << "p1="<<p1 << "p2="<< p2;
277  memcpy(tmpbuffer+2*sizeof(long),msg.data(),msg.size());
278  *p1=0x4242aeae;
279  *p2=size;
280 
281  // no need to add it to a queue -> qiodevice is buffered
282  mProcess->write(tmpbuffer,size);
283  delete [] tmpbuffer;
284 }
285 
286 void KMessageProcess::slotReceivedStderr()
287 {
288  QByteArray ba;
289  kDebug(11001)<<"@@@ KMessageProcess::slotReceivedStderr";
290 
291  mProcess->setReadChannel(QProcess::StandardError);
292  while(mProcess->canReadLine())
293  {
294  ba = mProcess->readLine();
295  if( ba.isEmpty() )
296  return;
297  ba.chop( 1 ); // remove QLatin1Char( '\n' )
298 
299  kDebug(11001) << "KProcess (" << ba.size() << "):" << ba.constData();
300  emit signalReceivedStderr(QLatin1String( ba ));
301  ba.clear();
302  };
303 }
304 
305 
306 void KMessageProcess::slotReceivedStdout()
307 {
308  mProcess->setReadChannel(QProcess::StandardOutput);
309  QByteArray ba = mProcess->readAll();
310  kDebug(11001) << "$$$$$$ " << ": Received" << ba.size() << "bytes over inter process communication";
311 
312  // Resize receive buffer
313  while (mReceiveCount+ba.size()>=mReceiveBuffer.size()) mReceiveBuffer.resize(mReceiveBuffer.size()+1024);
314  // was 08/2007: mReceiveBuffer += ba;
315  qCopy(ba.begin(), ba.begin()+ba.size(), mReceiveBuffer.begin()+mReceiveCount);
316  mReceiveCount += ba.size();
317 
318  // Possbile message
319  while (mReceiveCount>int(2*sizeof(long)))
320  {
321  long *p1=(long *)mReceiveBuffer.data();
322  long *p2=p1+1;
323  int len;
324  if (*p1!=0x4242aeae)
325  {
326  kDebug(11001) << ": Cookie error...transmission failure...serious problem...";
327  }
328  len=(int)(*p2);
329  if (len<int(2*sizeof(long)))
330  {
331  kDebug(11001) << ": Message size error";
332  break;
333  }
334  if (len<=mReceiveCount)
335  {
336  kDebug(11001) << ": Got message with len" << len;
337 
338  QByteArray msg ;
339  msg.resize(len);
340  // msg.setRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
341 
342  qCopy(mReceiveBuffer.begin()+2*sizeof(long),mReceiveBuffer.begin()+len, msg.begin());
343 // msg.duplicate(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
344  emit received(msg);
345  // msg.resetRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
346  // Shift buffer
347  if (len<mReceiveCount)
348  {
349  memmove(mReceiveBuffer.data(),mReceiveBuffer.data()+len,mReceiveCount-len);
350  }
351  mReceiveCount-=len;
352  }
353  else break;
354  }
355 }
356 
357 void KMessageProcess::slotProcessExited(int exitCode, QProcess::ExitStatus)
358 {
359  kDebug(11001) << "Process exited (slot) with code" << exitCode;
360  emit connectionBroken();
361  delete mProcess;
362  mProcess=0;
363 }
364 
365 #include "kmessageio.moc"
366 
KMessageIO::~KMessageIO
~KMessageIO()
The usual destructor, does nothing special.
Definition: kmessageio.cpp:36
KMessageProcess::send
void send(const QByteArray &msg)
This slot sends the data block in /e msg to the connected object, that will emit /e received()...
Definition: kmessageio.cpp:263
KMessageProcess::signalReceivedStderr
void signalReceivedStderr(QString msg)
QByteArray::clear
void clear()
QHostAddress
QAbstractSocket::state
SocketState state() const
QByteArray
QDataStream
KMessageProcess::~KMessageProcess
~KMessageProcess()
Definition: kmessageio.cpp:222
KMessageIO::setId
void setId(quint32 id)
Sets the ID number of this object.
Definition: kmessageio.cpp:39
KMessageProcess::slotReceivedStdout
void slotReceivedStdout()
Definition: kmessageio.cpp:306
KMessageIO::received
void received(const QByteArray &msg)
This signal is emitted when /e send() on the connected KMessageIO object is called.
QByteArray::chop
void chop(int n)
QByteArray::isEmpty
bool isEmpty() const
KMessageDirect::mPartner
KMessageDirect * mPartner
Definition: kmessageio.h:343
QHostAddress::toString
QString toString() const
QAbstractSocket::setSocketDescriptor
bool setSocketDescriptor(int socketDescriptor, SocketState socketState, QFlags< QIODevice::OpenModeFlag > openMode)
KMessageSocket::send
void send(const QByteArray &msg)
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:92
KMessageProcess::slotProcessExited
void slotProcessExited(int, QProcess::ExitStatus)
Definition: kmessageio.cpp:357
KMessageSocket::mAwaitingHeader
bool mAwaitingHeader
Definition: kmessageio.h:267
QDataStream::readRawData
int readRawData(char *s, int len)
KMessageIO::id
quint32 id()
Queries the ID of this object.
Definition: kmessageio.cpp:44
KMessageIO::m_id
quint32 m_id
Definition: kmessageio.h:159
QByteArray::resize
void resize(int size)
KMessageDirect
This class implements the message communication using function calls directly.
Definition: kmessageio.h:294
QAbstractSocket::connectToHost
void connectToHost(const QString &hostName, quint16 port, QFlags< QIODevice::OpenModeFlag > openMode)
KMessageDirect::send
void send(const QByteArray &msg)
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:211
KMessageIO::KMessageIO
KMessageIO(QObject *parent=0)
The usual QObject constructor, does nothing else.
Definition: kmessageio.cpp:32
QObject
KMessageProcess::isConnected
bool isConnected() const
This method returns the status of the object, whether it is already (or still) connected to another K...
Definition: kmessageio.cpp:254
KMessageDirect::isConnected
bool isConnected() const
Returns true, if the object is connected to another instance.
Definition: kmessageio.cpp:206
KMessageIO
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:57
QByteArray::constData
const char * constData() const
KMessageSocket::isConnected
bool isConnected() const
Returns true if the socket is in state /e connected.
Definition: kmessageio.cpp:87
QAbstractSocket::bytesAvailable
virtual qint64 bytesAvailable() const
QString
KMessageSocket::mNextBlockLength
quint32 mNextBlockLength
Definition: kmessageio.h:268
KMessageSocket::isRecursive
bool isRecursive
Definition: kmessageio.h:270
KMessageDirect::KMessageDirect
KMessageDirect(KMessageDirect *partner=0, QObject *parent=0)
Creates an object and connects it to the object given in the first parameter.
Definition: kmessageio.cpp:176
KMessageSocket::peerPort
virtual quint16 peerPort() const
Definition: kmessageio.cpp:164
KMessageProcess::KMessageProcess
KMessageProcess(QObject *parent, const QString &file)
Definition: kmessageio.cpp:233
KMessageSocket::~KMessageSocket
~KMessageSocket()
Destructor, closes the socket.
Definition: kmessageio.cpp:82
KMessageIO::connectionBroken
void connectionBroken()
This signal is emitted when the connection is closed.
KMessageSocket::processNewData
virtual void processNewData()
Definition: kmessageio.cpp:99
QLatin1String
KMessageSocket::peerName
virtual QString peerName() const
Definition: kmessageio.cpp:169
QAbstractSocket::peerName
QString peerName() const
KMessageSocket::initSocket
void initSocket()
Definition: kmessageio.cpp:154
QByteArray::data
char * data()
QDataStream::writeBytes
QDataStream & writeBytes(const char *s, uint len)
KMessageSocket::KMessageSocket
KMessageSocket(const QString &host, quint16 port, QObject *parent=0)
Connects to a server socket on /e host with /e port.
Definition: kmessageio.cpp:51
QString::fromLatin1
QString fromLatin1(const char *str, int size)
kmessageio.h
QAbstractSocket::peerPort
quint16 peerPort() const
QTcpSocket
QByteArray::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KMessageDirect::~KMessageDirect
~KMessageDirect()
Destructor, closes the connection.
Definition: kmessageio.cpp:197
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
KMessageProcess::slotReceivedStderr
void slotReceivedStderr()
Definition: kmessageio.cpp:286
KMessageSocket::mSocket
QTcpSocket * mSocket
Definition: kmessageio.h:266
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:18:54 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkdegames/libkdegamesprivate/kgame

Skip menu "libkdegames/libkdegamesprivate/kgame"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdegames API Reference

Skip menu "kdegames API Reference"
  • granatier
  • kapman
  • kblackbox
  • kgoldrunner
  • kigo
  • kmahjongg
  • KShisen
  • ksquares
  • libkdegames
  •   highscore
  •   libkdegamesprivate
  •     kgame
  • libkmahjongg
  • palapeli
  •   libpala

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal