1 /*
2     This file is part of the KDE games library
3     SPDX-FileCopyrightText: 2001 Martin Heni (kde at heni-online.de)
4     SPDX-FileCopyrightText: 2001 Andreas Beckermann (b_mann@gmx.de)
5 
6     SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #include "kgameprocess.h"
10 
11 // Qt
12 #include <QRandomGenerator>
13 #include <QBuffer>
14 #include <QDataStream>
15 // Std
16 #include <cassert>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string>
20 
21 #define READ_BUFFER_SIZE  1024
22 
23 class KGameProcessPrivate
24 {
25 public:
26     QFile rFile;
27     QFile wFile;
28     QRandomGenerator* mRandom;
29 };
30 
31 // ----------------------- Process Child ---------------------------
32 
KGameProcess()33 KGameProcess::KGameProcess()
34     : QObject(), d(new KGameProcessPrivate)
35 {
36   mTerminate=false;
37   // Check whether a player is set. If not create one!
38   d->rFile.open(stdin, QIODevice::ReadOnly|QIODevice::Unbuffered);
39   d->wFile.open(stdout, QIODevice::WriteOnly|QIODevice::Unbuffered);
40   mMessageIO = new KMessageFilePipe(this, &d->rFile, &d->wFile);
41 //  mMessageClient=new KMessageClient(this);
42 //  mMessageClient->setServer(mMessageIO);
43 //  connect (mMessageClient, SIGNAL(broadcastReceived(QByteArray,quint32)),
44 //          this, SLOT(receivedMessage(QByteArray,quint32)));
45   connect(mMessageIO, &KMessageFilePipe::received, this, &KGameProcess::receivedMessage);
46 
47   d->mRandom = new QRandomGenerator(QRandomGenerator::global()->generate());
48 }
~KGameProcess()49 KGameProcess::~KGameProcess()
50 {
51   delete d->mRandom;
52   //delete mMessageClient;
53   //delete mMessageServer;
54   fprintf(stderr,"KGameProcess::destructor\n");
55   fflush(stderr);
56   delete mMessageIO;
57   d->rFile.close();
58   d->wFile.close();
59   delete d;
60 }
61 
62 
exec()63 bool KGameProcess::exec()
64 {
65   do
66   {
67     mMessageIO->exec();
68   }  while(!mTerminate);
69   return true;
70 }
71 
72 //    You have to do this to create a message
73 //    QByteArray buffer;
74 //    QDataStream wstream(buffer,QIODevice::WriteOnly);
75 //    then stream data into the stream and call this function
sendSystemMessage(QDataStream & stream,int msgid,quint32 receiver)76 void KGameProcess::sendSystemMessage(QDataStream &stream,int msgid,quint32 receiver)
77 {
78   fprintf(stderr,"KGameProcess::sendSystemMessage to parent id=%d recv=%ld\n",msgid,(unsigned long)receiver);
79   QByteArray a;
80   QDataStream outstream(&a,QIODevice::WriteOnly);
81 
82   QBuffer *device=(QBuffer *)stream.device();
83   QByteArray data=device->buffer();
84 
85   KGameMessage::createHeader(outstream,0,receiver,msgid);
86   outstream.writeRawData(data.data(),data.size());
87 
88   //  if (mMessageClient) mMessageClient->sendForward(a,2);
89   if (mMessageIO) mMessageIO->send(a);
90   else fprintf(stderr,"KGameProcess::sendSystemMessage:: NO IO DEVICE ... WILL FAIL\n");
91 }
92 
sendMessage(QDataStream & stream,int msgid,quint32 receiver)93 void KGameProcess::sendMessage(QDataStream &stream,int msgid,quint32 receiver)
94 {
95   sendSystemMessage(stream,msgid+KGameMessage::IdUser,receiver);
96 }
97 
receivedMessage(const QByteArray & receiveBuffer)98 void KGameProcess::receivedMessage(const QByteArray& receiveBuffer)
99 {
100  QDataStream stream(receiveBuffer);
101  int msgid;
102  quint32 sender;
103  quint32 receiver;
104  KGameMessage::extractHeader(stream, sender, receiver, msgid);
105  fprintf(stderr,"--- KGameProcess::receivedMessage(): id=%d sender=%ld,recv=%ld\n",
106          msgid,(unsigned long)sender,(unsigned long)receiver);
107  switch(msgid)
108  {
109    case KGameMessage::IdTurn:
110      qint8 b;
111      stream >> b;
112      Q_EMIT signalTurn(stream,(bool)b);
113    break;
114    case KGameMessage::IdIOAdded:
115      qint16 id;
116      stream >> id;
117      Q_EMIT signalInit(stream,(int)id);
118    break;
119    default:
120       Q_EMIT signalCommand(stream,msgid-KGameMessage::IdUser,receiver,sender);
121    break;
122  }
123 }
124 
random()125 QRandomGenerator* KGameProcess::random()
126 {
127   return d->mRandom;
128 }
129 
130 // ----------------------- KMessageFilePipe ---------------------------
KMessageFilePipe(QObject * parent,QFile * readfile,QFile * writefile)131 KMessageFilePipe::KMessageFilePipe(QObject *parent,QFile *readfile,QFile *writefile) : KMessageIO(parent)
132 {
133   mReadFile=readfile;
134   mWriteFile=writefile;
135   mReceiveCount=0;
136   mReceiveBuffer.resize(1024);
137 }
138 
~KMessageFilePipe()139 KMessageFilePipe::~KMessageFilePipe()
140 {
141 }
142 
isConnected() const143 bool KMessageFilePipe::isConnected () const
144 {
145   return (mReadFile!=nullptr)&&(mWriteFile!=nullptr);
146 }
147 
148 // Send to parent
send(const QByteArray & msg)149 void KMessageFilePipe::send(const QByteArray &msg)
150 {
151   unsigned int size=msg.size()+2*sizeof(long);
152 
153   char *tmpbuffer=new char[size];
154   long *p1=(long *)tmpbuffer;
155   long *p2=p1+1;
156   memcpy(tmpbuffer+2*sizeof(long),msg.data(),msg.size());
157   *p1=0x4242aeae;
158   *p2=size;
159 
160   QByteArray buffer(tmpbuffer,size);
161   mWriteFile->write(buffer);
162   mWriteFile->flush();
163   delete [] tmpbuffer;
164 
165   /* DEBUG:
166   fprintf(stderr,"+++ KMessageFilePipe:: SEND(%d to parent) realsize=%d\n",msg.size(),buffer.size());
167   for (int i=0;i<buffer.size();i++) fprintf(stderr,"%02x ",(unsigned char)buffer.at(i));fprintf(stderr,"\n");
168   fflush(stderr);
169   */
170 
171 
172 }
173 
exec()174 void KMessageFilePipe::exec()
175 {
176 
177   // According to BL: Blocking read is ok
178   // while(mReadFile->atEnd()) { usleep(100); }
179    char ch;
180    mReadFile->getChar(&ch);
181 
182    while (mReceiveCount>=mReceiveBuffer.size()) mReceiveBuffer.resize(mReceiveBuffer.size()+1024);
183    mReceiveBuffer[mReceiveCount]=ch;
184    mReceiveCount++;
185 
186    // Change for message
187    if (mReceiveCount>=int(2*sizeof(long)))
188    {
189      long *p1=(long *)mReceiveBuffer.data();
190      long *p2=p1+1;
191      int len;
192      if (*p1!=0x4242aeae)
193      {
194        fprintf(stderr,"KMessageFilePipe::exec:: Cookie error...transmission failure...serious problem...\n");
195        fflush(stderr);
196 //       for (int i=0;i<16;i++) fprintf(stderr,"%02x ",mReceiveBuffer[i]);fprintf(stderr,"\n");
197      }
198      len=(int)(*p2);
199      if (len==mReceiveCount)
200      {
201        //fprintf(stderr,"KMessageFilePipe::exec:: Got Message with len %d\n",len);
202 
203        QByteArray msg;
204        msg.resize(len);
205        //msg.setRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
206        std::copy(mReceiveBuffer.begin()+2*sizeof(long),mReceiveBuffer.begin()+len, msg.begin());
207 //  msg.duplicate(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
208        Q_EMIT received(msg);
209        //msg.resetRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long));
210        mReceiveCount=0;
211      }
212    }
213 
214 
215    return ;
216 
217 
218 }
219 
220 
221