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