• 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
32KMessageIO::KMessageIO (TQObject *parent, const char *name)
33 : TQObject (parent, name), m_id (0)
34{}
35
36KMessageIO::~KMessageIO ()
37{}
38
39void KMessageIO::setId (TQ_UINT32 id)
40{
41 m_id = id;
42}
43
44TQ_UINT32 KMessageIO::id ()
45{
46 return m_id;
47}
48
49// ----------------------KMessageSocket -----------------------
50
51KMessageSocket::KMessageSocket (TQString host, TQ_UINT16 port, TQObject *parent,
52const char *name)
53 : KMessageIO (parent, name)
54{
55 mSocket = new TQSocket ();
56 mSocket->connectToHost (host, port);
57 initSocket ();
58}
59
60KMessageSocket::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
69KMessageSocket::KMessageSocket (TQSocket *socket, TQObject *parent, const char
70*name)
71 : KMessageIO (parent, name)
72{
73 mSocket = socket;
74 initSocket ();
75}
76
77KMessageSocket::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
86KMessageSocket::~KMessageSocket ()
87{
88 delete mSocket;
89}
90
91bool KMessageSocket::isConnected () const
92{
93 return mSocket->state() == TQSocket::Connection;
94}
95
96void 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
103void 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
158void 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
168TQ_UINT16 KMessageSocket::peerPort () const
169{
170 return mSocket->peerPort();
171}
172
173TQString KMessageSocket::peerName () const
174{
175 return mSocket->peerName();
176}
177
178// ----------------------KMessageDirect -----------------------
179
180KMessageDirect::KMessageDirect (KMessageDirect *partner, TQObject *parent,
181const 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
202KMessageDirect::~KMessageDirect ()
203{
204 if (mPartner)
205 {
206 mPartner->mPartner = 0;
207 emit mPartner->connectionBroken();
208 }
209}
210
211bool KMessageDirect::isConnected () const
212{
213 return mPartner != 0;
214}
215
216void 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
227KMessageProcess::~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}
241KMessageProcess::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}
264bool KMessageProcess::isConnected() const
265{
266 kdDebug(11001) << "@@@KMessageProcess::Is conencted" << endl;
267 if (!mProcess) return false;
268 return mProcess->isRunning();
269}
270void 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}
289void 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}
303void 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
314void 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
344void 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
390void 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 ---------------------------
400KMessageFilePipe::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
408KMessageFilePipe::~KMessageFilePipe()
409{
410}
411
412bool KMessageFilePipe::isConnected () const
413{
414 return (mReadFile!=0)&&(mWriteFile!=0);
415}
416
417void 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
439void 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"
KMessageDirect
This class implements the message communication using function calls directly.
Definition: kmessageio.h:298
KMessageDirect::~KMessageDirect
~KMessageDirect()
Destructor, closes the connection.
Definition: kmessageio.cpp:202
KMessageDirect::send
void send(const TQByteArray &msg)
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:216
KMessageDirect::isConnected
bool isConnected() const
Returns true, if the object is connected to another instance.
Definition: kmessageio.cpp:211
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
KMessageIO
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:57
KMessageIO::KMessageIO
KMessageIO(TQObject *parent=0, const char *name=0)
The usual TQObject constructor, does nothing else.
Definition: kmessageio.cpp:32
KMessageIO::connectionBroken
void connectionBroken()
This signal is emitted when the connection is closed.
KMessageIO::received
void received(const TQByteArray &msg)
This signal is emitted when /e send() on the connected KMessageIO object is called.
KMessageIO::id
TQ_UINT32 id()
Queries the ID of this object.
Definition: kmessageio.cpp:44
KMessageIO::setId
void setId(TQ_UINT32 id)
Sets the ID number of this object.
Definition: kmessageio.cpp:39
KMessageIO::~KMessageIO
~KMessageIO()
The usual destructor, does nothing special.
Definition: kmessageio.cpp:36
KMessageSocket::isConnected
bool isConnected() const
Returns true if the socket is in state /e connected.
Definition: kmessageio.cpp:91
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
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
KMessageSocket::peerPort
virtual TQ_UINT16 peerPort() const
Definition: kmessageio.cpp:168
KMessageSocket::~KMessageSocket
~KMessageSocket()
Destructor, closes the socket.
Definition: kmessageio.cpp:86

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.9.4
This website is maintained by Timothy Pearson.