• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • libtdegames
 

libtdegames

  • libtdegames
  • kgame
kmessageio.cpp
1 /*
2  This file is part of the TDE 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 <tqsocket.h>
26 #include <kdebug.h>
27 #include <kprocess.h>
28 #include <tqfile.h>
29 
30 // ----------------------- KMessageIO -------------------------
31 
32 KMessageIO::KMessageIO (TQObject *parent, const char *name)
33  : TQObject (parent, name), m_id (0)
34 {}
35 
36 KMessageIO::~KMessageIO ()
37 {}
38 
39 void KMessageIO::setId (TQ_UINT32 id)
40 {
41  m_id = id;
42 }
43 
44 TQ_UINT32 KMessageIO::id ()
45 {
46  return m_id;
47 }
48 
49 // ----------------------KMessageSocket -----------------------
50 
51 KMessageSocket::KMessageSocket (TQString host, TQ_UINT16 port, TQObject *parent,
52 const char *name)
53  : KMessageIO (parent, name)
54 {
55  mSocket = new TQSocket ();
56  mSocket->connectToHost (host, port);
57  initSocket ();
58 }
59 
60 KMessageSocket::KMessageSocket (TQHostAddress host, TQ_UINT16 port, TQObject
61 *parent, const char *name)
62  : KMessageIO (parent, name)
63 {
64  mSocket = new TQSocket ();
65  mSocket->connectToHost (host.toString(), port);
66  initSocket ();
67 }
68 
69 KMessageSocket::KMessageSocket (TQSocket *socket, TQObject *parent, const char
70 *name)
71  : KMessageIO (parent, name)
72 {
73  mSocket = socket;
74  initSocket ();
75 }
76 
77 KMessageSocket::KMessageSocket (int socketFD, TQObject *parent, const char
78 *name)
79  : KMessageIO (parent, name)
80 {
81  mSocket = new TQSocket ();
82  mSocket->setSocket (socketFD);
83  initSocket ();
84 }
85 
86 KMessageSocket::~KMessageSocket ()
87 {
88  delete mSocket;
89 }
90 
91 bool KMessageSocket::isConnected () const
92 {
93  return mSocket->state() == TQSocket::Connection;
94 }
95 
96 void KMessageSocket::send (const TQByteArray &msg)
97 {
98  TQDataStream str (mSocket);
99  str << TQ_UINT8 ('M'); // magic number for begin of message
100  str.writeBytes (msg.data(), msg.size()); // writes the length (as TQ_UINT32) and the data
101 }
102 
103 void KMessageSocket::processNewData ()
104 {
105  if (isRecursive)
106  return;
107  isRecursive = true;
108 
109  TQDataStream str (mSocket);
110  while (mSocket->bytesAvailable() > 0)
111  {
112  if (mAwaitingHeader)
113  {
114  // Header = magic number + packet length = 5 bytes
115  if (mSocket->bytesAvailable() < 5)
116  {
117  isRecursive = false;
118  return;
119  }
120 
121  // Read the magic number first. If something unexpected is found,
122  // start over again, ignoring the data that was read up to then.
123 
124  TQ_UINT8 v;
125  str >> v;
126  if (v != 'M')
127  {
128  kdWarning(11001) << k_funcinfo << ": Received unexpected data, magic number wrong!" << endl;
129  continue;
130  }
131 
132  str >> mNextBlockLength;
133  mAwaitingHeader = false;
134  }
135  else
136  {
137  // Data not completely read => wait for more
138  if (mSocket->bytesAvailable() < (TQ_ULONG) mNextBlockLength)
139  {
140  isRecursive = false;
141  return;
142  }
143 
144  TQByteArray msg (mNextBlockLength);
145  str.readRawBytes (msg.data(), mNextBlockLength);
146 
147  // send the received message
148  emit received (msg);
149 
150  // Waiting for the header of the next message
151  mAwaitingHeader = true;
152  }
153  }
154 
155  isRecursive = false;
156 }
157 
158 void KMessageSocket::initSocket ()
159 {
160  connect (mSocket, TQ_SIGNAL (error(int)), TQ_SIGNAL (connectionBroken()));
161  connect (mSocket, TQ_SIGNAL (connectionClosed()), TQ_SIGNAL (connectionBroken()));
162  connect (mSocket, TQ_SIGNAL (readyRead()), TQ_SLOT (processNewData()));
163  mAwaitingHeader = true;
164  mNextBlockLength = 0;
165  isRecursive = false;
166 }
167 
168 TQ_UINT16 KMessageSocket::peerPort () const
169 {
170  return mSocket->peerPort();
171 }
172 
173 TQString KMessageSocket::peerName () const
174 {
175  return mSocket->peerName();
176 }
177 
178 // ----------------------KMessageDirect -----------------------
179 
180 KMessageDirect::KMessageDirect (KMessageDirect *partner, TQObject *parent,
181 const char *name)
182  : KMessageIO (parent, name), mPartner (0)
183 {
184  // 0 as first parameter leaves the object unconnected
185  if (!partner)
186  return;
187 
188  // Check if the other object is already connected
189  if (partner && partner->mPartner)
190  {
191  kdWarning(11001) << k_funcinfo << ": Object is already connected!" << endl;
192  return;
193  }
194 
195  // Connect from us to that object
196  mPartner = partner;
197 
198  // Connect the other object to us
199  partner->mPartner = this;
200 }
201 
202 KMessageDirect::~KMessageDirect ()
203 {
204  if (mPartner)
205  {
206  mPartner->mPartner = 0;
207  emit mPartner->connectionBroken();
208  }
209 }
210 
211 bool KMessageDirect::isConnected () const
212 {
213  return mPartner != 0;
214 }
215 
216 void KMessageDirect::send (const TQByteArray &msg)
217 {
218  if (mPartner)
219  emit mPartner->received (msg);
220  else
221  kdError(11001) << k_funcinfo << ": Not yet connected!" << endl;
222 }
223 
224 
225 // ----------------------- KMessageProcess ---------------------------
226 
227 KMessageProcess::~KMessageProcess()
228 {
229  kdDebug(11001) << "@@@KMessageProcess::Delete process" << endl;
230  if (mProcess)
231  {
232  mProcess->kill();
233  delete mProcess;
234  mProcess=0;
235  // Remove not send buffers
236  mQueue.setAutoDelete(true);
237  mQueue.clear();
238  // Maybe todo: delete mSendBuffer
239  }
240 }
241 KMessageProcess::KMessageProcess(TQObject *parent, TQString file) : KMessageIO(parent,0)
242 {
243  // Start process
244  kdDebug(11001) << "@@@KMessageProcess::Start process" << endl;
245  mProcessName=file;
246  mProcess=new TDEProcess;
247  int id=0;
248  *mProcess << mProcessName << TQString("%1").arg(id);
249  kdDebug(11001) << "@@@KMessageProcess::Init:Id= " << id << endl;
250  kdDebug(11001) << "@@@KMessgeProcess::Init:Processname: " << mProcessName << endl;
251  connect(mProcess, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int )),
252  this, TQ_SLOT(slotReceivedStdout(TDEProcess *, char * , int )));
253  connect(mProcess, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int )),
254  this, TQ_SLOT(slotReceivedStderr(TDEProcess *, char * , int )));
255  connect(mProcess, TQ_SIGNAL(processExited(TDEProcess *)),
256  this, TQ_SLOT(slotProcessExited(TDEProcess *)));
257  connect(mProcess, TQ_SIGNAL(wroteStdin(TDEProcess *)),
258  this, TQ_SLOT(slotWroteStdin(TDEProcess *)));
259  mProcess->start(TDEProcess::NotifyOnExit,TDEProcess::All);
260  mSendBuffer=0;
261  mReceiveCount=0;
262  mReceiveBuffer.resize(1024);
263 }
264 bool KMessageProcess::isConnected() const
265 {
266  kdDebug(11001) << "@@@KMessageProcess::Is conencted" << endl;
267  if (!mProcess) return false;
268  return mProcess->isRunning();
269 }
270 void KMessageProcess::send(const TQByteArray &msg)
271 {
272  kdDebug(11001) << "@@@KMessageProcess:: SEND("<<msg.size()<<") to process" << endl;
273  unsigned int size=msg.size()+2*sizeof(long);
274 
275  char *tmpbuffer=new char[size];
276  long *p1=(long *)tmpbuffer;
277  long *p2=p1+1;
278  kdDebug(11001) << "p1="<<p1 << "p2="<< p2 << endl;
279  memcpy(tmpbuffer+2*sizeof(long),msg.data(),msg.size());
280  *p1=0x4242aeae;
281  *p2=size;
282 
283  TQByteArray *buffer=new TQByteArray();
284  buffer->assign(tmpbuffer,size);
285  // buffer->duplicate(msg);
286  mQueue.enqueue(buffer);
287  writeToProcess();
288 }
289 void KMessageProcess::writeToProcess()
290 {
291  // Previous send ok and item in queue
292  if (mSendBuffer || mQueue.isEmpty()) return ;
293  mSendBuffer=mQueue.dequeue();
294  if (!mSendBuffer) return ;
295 
296  // write it out to the process
297  // kdDebug(11001) << " @@@@@@ writeToProcess::SEND to process " << mSendBuffer->size() << " BYTE " << endl;
298  // char *p=mSendBuffer->data();
299  // for (int i=0;i<16;i++) printf("%02x ",(unsigned char)(*(p+i)));printf("\n");
300  mProcess->writeStdin(mSendBuffer->data(),mSendBuffer->size());
301 
302 }
303 void KMessageProcess::slotWroteStdin(TDEProcess * )
304 {
305  kdDebug(11001) << k_funcinfo << endl;
306  if (mSendBuffer)
307  {
308  delete mSendBuffer;
309  mSendBuffer=0;
310  }
311  writeToProcess();
312 }
313 
314 void KMessageProcess::slotReceivedStderr(TDEProcess * proc, char *buffer, int buflen)
315 {
316  int pid=0;
317  int len;
318  char *p;
319  char *pos;
320 // kdDebug(11001)<<"############# Got stderr " << buflen << " bytes" << endl;
321 
322  if (!buffer || buflen==0) return ;
323  if (proc) pid=proc->pid();
324 
325 
326  pos=buffer;
327  do
328  {
329  p=(char *)memchr(pos,'\n',buflen);
330  if (!p) len=buflen;
331  else len=p-pos;
332 
333  TQByteArray a;
334  a.setRawData(pos,len);
335  TQString s(a);
336  kdDebug(11001) << "PID" <<pid<< ":" << s << endl;
337  a.resetRawData(pos,len);
338  if (p) pos=p+1;
339  buflen-=len+1;
340  }while(buflen>0);
341 }
342 
343 
344 void KMessageProcess::slotReceivedStdout(TDEProcess * , char *buffer, int buflen)
345 {
346  kdDebug(11001) << "$$$$$$ " << k_funcinfo << ": Received " << buflen << " bytes over inter process communication" << endl;
347 
348  // TODO Make a plausibility check on buflen to avoid memory overflow
349  while (mReceiveCount+buflen>=mReceiveBuffer.size()) mReceiveBuffer.resize(mReceiveBuffer.size()+1024);
350  memcpy(mReceiveBuffer.data()+mReceiveCount,buffer,buflen);
351  mReceiveCount+=buflen;
352 
353  // Possbile message
354  while (mReceiveCount>2*sizeof(long))
355  {
356  long *p1=(long *)mReceiveBuffer.data();
357  long *p2=p1+1;
358  unsigned int len;
359  if (*p1!=0x4242aeae)
360  {
361  kdDebug(11001) << k_funcinfo << ": Cookie error...transmission failure...serious problem..." << endl;
362 // for (int i=0;i<mReceiveCount;i++) fprintf(stderr,"%02x ",mReceiveBuffer[i]);fprintf(stderr,"\n");
363  }
364  len=(int)(*p2);
365  if (len<2*sizeof(long))
366  {
367  kdDebug(11001) << k_funcinfo << ": Message size error" << endl;
368  break;
369  }
370  if (len<=mReceiveCount)
371  {
372  kdDebug(11001) << k_funcinfo << ": Got message with len " << len << endl;
373 
374  TQByteArray msg;
375  // msg.setRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
376  msg.duplicate(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
377  emit received(msg);
378  // msg.resetRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
379  // Shift buffer
380  if (len<mReceiveCount)
381  {
382  memmove(mReceiveBuffer.data(),mReceiveBuffer.data()+len,mReceiveCount-len);
383  }
384  mReceiveCount-=len;
385  }
386  else break;
387  }
388 }
389 
390 void KMessageProcess::slotProcessExited(TDEProcess * /*p*/)
391 {
392  kdDebug(11001) << "Process exited (slot)" << endl;
393  emit connectionBroken();
394  delete mProcess;
395  mProcess=0;
396 }
397 
398 
399 // ----------------------- KMessageFilePipe ---------------------------
400 KMessageFilePipe::KMessageFilePipe(TQObject *parent,TQFile *readfile,TQFile *writefile) : KMessageIO(parent,0)
401 {
402  mReadFile=readfile;
403  mWriteFile=writefile;
404  mReceiveCount=0;
405  mReceiveBuffer.resize(1024);
406 }
407 
408 KMessageFilePipe::~KMessageFilePipe()
409 {
410 }
411 
412 bool KMessageFilePipe::isConnected () const
413 {
414  return (mReadFile!=0)&&(mWriteFile!=0);
415 }
416 
417 void KMessageFilePipe::send(const TQByteArray &msg)
418 {
419  unsigned int size=msg.size()+2*sizeof(long);
420 
421  char *tmpbuffer=new char[size];
422  long *p1=(long *)tmpbuffer;
423  long *p2=p1+1;
424  memcpy(tmpbuffer+2*sizeof(long),msg.data(),msg.size());
425  *p1=0x4242aeae;
426  *p2=size;
427 
428  TQByteArray buffer;
429  buffer.assign(tmpbuffer,size);
430  mWriteFile->writeBlock(buffer);
431  mWriteFile->flush();
432  /*
433  fprintf(stderr,"+++ KMessageFilePipe:: SEND(%d to parent) realsize=%d\n",msg.size(),buffer.size());
434  for (int i=0;i<buffer.size();i++) fprintf(stderr,"%02x ",buffer[i]);fprintf(stderr,"\n");
435  fflush(stderr);
436  */
437 }
438 
439 void KMessageFilePipe::exec()
440 {
441 
442  // According to BL: Blocking read is ok
443  // while(mReadFile->atEnd()) { usleep(100); }
444 
445  int ch=mReadFile->getch();
446 
447  while (mReceiveCount>=mReceiveBuffer.size()) mReceiveBuffer.resize(mReceiveBuffer.size()+1024);
448  mReceiveBuffer[mReceiveCount]=(char)ch;
449  mReceiveCount++;
450 
451  // Change for message
452  if (mReceiveCount>=2*sizeof(long))
453  {
454  long *p1=(long *)mReceiveBuffer.data();
455  long *p2=p1+1;
456  unsigned int len;
457  if (*p1!=0x4242aeae)
458  {
459  fprintf(stderr,"KMessageFilePipe::exec:: Cookie error...transmission failure...serious problem...\n");
460 // for (int i=0;i<16;i++) fprintf(stderr,"%02x ",mReceiveBuffer[i]);fprintf(stderr,"\n");
461  }
462  len=(int)(*p2);
463  if (len==mReceiveCount)
464  {
465  //fprintf(stderr,"KMessageFilePipe::exec:: Got Message with len %d\n",len);
466 
467  TQByteArray msg;
468  //msg.setRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
469  msg.duplicate(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
470  emit received(msg);
471  //msg.resetRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
472  mReceiveCount=0;
473  }
474  }
475 
476 
477  return ;
478 
479 
480 }
481 
482 #include "kmessageio.moc"
KMessageIO::~KMessageIO
~KMessageIO()
The usual destructor, does nothing special.
Definition: kmessageio.cpp:36
KMessageSocket::KMessageSocket
KMessageSocket(TQString host, TQ_UINT16 port, TQObject *parent=0, const char *name=0)
Connects to a server socket on /e host with /e port.
Definition: kmessageio.cpp:51
KMessageIO::received
void received(const TQByteArray &msg)
This signal is emitted when /e send() on the connected KMessageIO object is called.
KMessageSocket::peerName
virtual TQString peerName() const
Definition: kmessageio.cpp:173
KMessageSocket::send
void send(const TQByteArray &msg)
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:96
KMessageDirect
This class implements the message communication using function calls directly.
Definition: kmessageio.h:297
KMessageIO
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:56
KMessageIO::setId
void setId(TQ_UINT32 id)
Sets the ID number of this object.
Definition: kmessageio.cpp:39
KMessageDirect::isConnected
bool isConnected() const
Returns true, if the object is connected to another instance.
Definition: kmessageio.cpp:211
KMessageIO::KMessageIO
KMessageIO(TQObject *parent=0, const char *name=0)
The usual TQObject constructor, does nothing else.
Definition: kmessageio.cpp:32
KMessageSocket::~KMessageSocket
~KMessageSocket()
Destructor, closes the socket.
Definition: kmessageio.cpp:86
KMessageIO::connectionBroken
void connectionBroken()
This signal is emitted when the connection is closed.
KMessageSocket::isConnected
bool isConnected() const
Returns true if the socket is in state /e connected.
Definition: kmessageio.cpp:91
KMessageDirect::send
void send(const TQByteArray &msg)
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:216
KMessageDirect::KMessageDirect
KMessageDirect(KMessageDirect *partner=0, TQObject *parent=0, const char *name=0)
Creates an object and connects it to the object given in the first parameter.
Definition: kmessageio.cpp:180
KMessageDirect::~KMessageDirect
~KMessageDirect()
Destructor, closes the connection.
Definition: kmessageio.cpp:202
KMessageSocket::peerPort
virtual TQ_UINT16 peerPort() const
Definition: kmessageio.cpp:168
KMessageIO::id
TQ_UINT32 id()
Queries the ID of this object.
Definition: kmessageio.cpp:44

libtdegames

Skip menu "libtdegames"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

libtdegames

Skip menu "libtdegames"
  • libtdegames
Generated for libtdegames by doxygen 1.8.13
This website is maintained by Timothy Pearson.