File indexing completed on 2025-04-27 06:58:30
0001 /* 0002 This file is part of the KDE games library 0003 SPDX-FileCopyrightText: 2001 Martin Heni (kde at heni-online.de) 0004 SPDX-FileCopyrightText: 2001 Andreas Beckermann (b_mann@gmx.de) 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "kgameprocess.h" 0010 0011 // Qt 0012 #include <QBuffer> 0013 #include <QDataStream> 0014 #include <QRandomGenerator> 0015 // Std 0016 #include <cassert> 0017 #include <cstdio> 0018 #include <cstdlib> 0019 #include <string> 0020 0021 #define READ_BUFFER_SIZE 1024 0022 0023 class KGameProcessPrivate 0024 { 0025 public: 0026 QFile rFile; 0027 QFile wFile; 0028 QRandomGenerator *mRandom; 0029 }; 0030 0031 // ----------------------- Process Child --------------------------- 0032 0033 KGameProcess::KGameProcess() 0034 : QObject() 0035 , d(new KGameProcessPrivate) 0036 { 0037 mTerminate = false; 0038 // Check whether a player is set. If not create one! 0039 d->rFile.open(stdin, QIODevice::ReadOnly | QIODevice::Unbuffered); 0040 d->wFile.open(stdout, QIODevice::WriteOnly | QIODevice::Unbuffered); 0041 mMessageIO = new KMessageFilePipe(this, &d->rFile, &d->wFile); 0042 // mMessageClient=new KMessageClient(this); 0043 // mMessageClient->setServer(mMessageIO); 0044 // connect (mMessageClient, SIGNAL(broadcastReceived(QByteArray,quint32)), 0045 // this, SLOT(receivedMessage(QByteArray,quint32))); 0046 connect(mMessageIO, &KMessageFilePipe::received, this, &KGameProcess::receivedMessage); 0047 0048 d->mRandom = new QRandomGenerator(QRandomGenerator::global()->generate()); 0049 } 0050 KGameProcess::~KGameProcess() 0051 { 0052 delete d->mRandom; 0053 // delete mMessageClient; 0054 // delete mMessageServer; 0055 fprintf(stderr, "KGameProcess::destructor\n"); 0056 fflush(stderr); 0057 delete mMessageIO; 0058 d->rFile.close(); 0059 d->wFile.close(); 0060 delete d; 0061 } 0062 0063 bool KGameProcess::exec() 0064 { 0065 do { 0066 mMessageIO->exec(); 0067 } while (!mTerminate); 0068 return true; 0069 } 0070 0071 // You have to do this to create a message 0072 // QByteArray buffer; 0073 // QDataStream wstream(buffer,QIODevice::WriteOnly); 0074 // then stream data into the stream and call this function 0075 void KGameProcess::sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver) 0076 { 0077 fprintf(stderr, "KGameProcess::sendSystemMessage to parent id=%d recv=%ld\n", msgid, (unsigned long)receiver); 0078 QByteArray a; 0079 QDataStream outstream(&a, QIODevice::WriteOnly); 0080 0081 QBuffer *device = (QBuffer *)stream.device(); 0082 QByteArray data = device->buffer(); 0083 0084 KGameMessage::createHeader(outstream, 0, receiver, msgid); 0085 outstream.writeRawData(data.data(), data.size()); 0086 0087 // if (mMessageClient) mMessageClient->sendForward(a,2); 0088 if (mMessageIO) 0089 mMessageIO->send(a); 0090 else 0091 fprintf(stderr, "KGameProcess::sendSystemMessage:: NO IO DEVICE ... WILL FAIL\n"); 0092 } 0093 0094 void KGameProcess::sendMessage(QDataStream &stream, int msgid, quint32 receiver) 0095 { 0096 sendSystemMessage(stream, msgid + KGameMessage::IdUser, receiver); 0097 } 0098 0099 void KGameProcess::receivedMessage(const QByteArray &receiveBuffer) 0100 { 0101 QDataStream stream(receiveBuffer); 0102 int msgid; 0103 quint32 sender; 0104 quint32 receiver; 0105 KGameMessage::extractHeader(stream, sender, receiver, msgid); 0106 fprintf(stderr, "--- KGameProcess::receivedMessage(): id=%d sender=%ld,recv=%ld\n", msgid, (unsigned long)sender, (unsigned long)receiver); 0107 switch (msgid) { 0108 case KGameMessage::IdTurn: 0109 qint8 b; 0110 stream >> b; 0111 Q_EMIT signalTurn(stream, (bool)b); 0112 break; 0113 case KGameMessage::IdIOAdded: 0114 qint16 id; 0115 stream >> id; 0116 Q_EMIT signalInit(stream, (int)id); 0117 break; 0118 default: 0119 Q_EMIT signalCommand(stream, msgid - KGameMessage::IdUser, receiver, sender); 0120 break; 0121 } 0122 } 0123 0124 QRandomGenerator *KGameProcess::random() 0125 { 0126 return d->mRandom; 0127 } 0128 0129 // ----------------------- KMessageFilePipe --------------------------- 0130 KMessageFilePipe::KMessageFilePipe(QObject *parent, QFile *readfile, QFile *writefile) 0131 : KMessageIO(parent) 0132 { 0133 mReadFile = readfile; 0134 mWriteFile = writefile; 0135 mReceiveCount = 0; 0136 mReceiveBuffer.resize(1024); 0137 } 0138 0139 KMessageFilePipe::~KMessageFilePipe() 0140 { 0141 } 0142 0143 bool KMessageFilePipe::isConnected() const 0144 { 0145 return (mReadFile != nullptr) && (mWriteFile != nullptr); 0146 } 0147 0148 // Send to parent 0149 void KMessageFilePipe::send(const QByteArray &msg) 0150 { 0151 unsigned int size = msg.size() + 2 * sizeof(long); 0152 0153 char *tmpbuffer = new char[size]; 0154 long *p1 = (long *)tmpbuffer; 0155 long *p2 = p1 + 1; 0156 memcpy(tmpbuffer + 2 * sizeof(long), msg.data(), msg.size()); 0157 *p1 = 0x4242aeae; 0158 *p2 = size; 0159 0160 QByteArray buffer(tmpbuffer, size); 0161 mWriteFile->write(buffer); 0162 mWriteFile->flush(); 0163 delete[] tmpbuffer; 0164 0165 /* DEBUG: 0166 fprintf(stderr,"+++ KMessageFilePipe:: SEND(%d to parent) realsize=%d\n",msg.size(),buffer.size()); 0167 for (int i=0;i<buffer.size();i++) fprintf(stderr,"%02x ",(unsigned char)buffer.at(i));fprintf(stderr,"\n"); 0168 fflush(stderr); 0169 */ 0170 } 0171 0172 void KMessageFilePipe::exec() 0173 { 0174 // According to BL: Blocking read is ok 0175 // while(mReadFile->atEnd()) { usleep(100); } 0176 char ch; 0177 mReadFile->getChar(&ch); 0178 0179 while (mReceiveCount >= mReceiveBuffer.size()) 0180 mReceiveBuffer.resize(mReceiveBuffer.size() + 1024); 0181 mReceiveBuffer[mReceiveCount] = ch; 0182 mReceiveCount++; 0183 0184 // Change for message 0185 if (mReceiveCount >= int(2 * sizeof(long))) { 0186 long *p1 = (long *)mReceiveBuffer.data(); 0187 long *p2 = p1 + 1; 0188 int len; 0189 if (*p1 != 0x4242aeae) { 0190 fprintf(stderr, "KMessageFilePipe::exec:: Cookie error...transmission failure...serious problem...\n"); 0191 fflush(stderr); 0192 // for (int i=0;i<16;i++) fprintf(stderr,"%02x ",mReceiveBuffer[i]);fprintf(stderr,"\n"); 0193 } 0194 len = (int)(*p2); 0195 if (len == mReceiveCount) { 0196 // fprintf(stderr,"KMessageFilePipe::exec:: Got Message with len %d\n",len); 0197 0198 QByteArray msg; 0199 msg.resize(len); 0200 // msg.setRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long)); 0201 std::copy(mReceiveBuffer.begin() + 2 * sizeof(long), mReceiveBuffer.begin() + len, msg.begin()); 0202 // msg.duplicate(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long)); 0203 Q_EMIT received(msg); 0204 // msg.resetRawData(mReceiveBuffer.data()+2*sizeof(long),len-2*sizeof(long)); 0205 mReceiveCount = 0; 0206 } 0207 } 0208 0209 return; 0210 } 0211 0212 #include "moc_kgameprocess.cpp"