QTfrontend/tcpBase.cpp
branchhedgeroid
changeset 6224 42b256eca362
parent 6055 88cfcd9161d3
parent 6223 cc3eb9b7230f
child 6226 3106add9a5bf
equal deleted inserted replaced
6055:88cfcd9161d3 6224:42b256eca362
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
       
     4  * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
       
     5  *
       
     6  * This program is free software; you can redistribute it and/or modify
       
     7  * it under the terms of the GNU General Public License as published by
       
     8  * the Free Software Foundation; version 2 of the License
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    18  */
       
    19 
       
    20 #include "tcpBase.h"
       
    21 
       
    22 #include <QMessageBox>
       
    23 #include <QList>
       
    24 
       
    25 #include <QImage>
       
    26 
       
    27 #include "hwconsts.h"
       
    28 
       
    29 QList<TCPBase*> srvsList;
       
    30 QPointer<QTcpServer> TCPBase::IPCServer(0);
       
    31 
       
    32 TCPBase::~TCPBase()
       
    33 {
       
    34 }
       
    35 
       
    36 TCPBase::TCPBase(bool demoMode) :
       
    37   m_isDemoMode(demoMode),
       
    38   IPCSocket(0)
       
    39 {
       
    40   if(!IPCServer) {
       
    41     IPCServer = new QTcpServer(0);
       
    42     IPCServer->setMaxPendingConnections(1);
       
    43     if (!IPCServer->listen(QHostAddress::LocalHost)) {
       
    44       QMessageBox::critical(0, tr("Error"),
       
    45                 tr("Unable to start the server: %1.")
       
    46                 .arg(IPCServer->errorString()));
       
    47       exit(0); // FIXME - should be graceful exit here
       
    48     }
       
    49   }
       
    50   ipc_port=IPCServer->serverPort();
       
    51 }
       
    52 
       
    53 void TCPBase::NewConnection()
       
    54 {
       
    55   if(IPCSocket) {
       
    56     // connection should be already finished
       
    57     return;
       
    58   }
       
    59   disconnect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
       
    60   IPCSocket = IPCServer->nextPendingConnection();
       
    61   if(!IPCSocket) return;
       
    62   connect(IPCSocket, SIGNAL(disconnected()), this, SLOT(ClientDisconnect()));
       
    63   connect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
       
    64   SendToClientFirst();
       
    65 }
       
    66 
       
    67 void TCPBase::RealStart()
       
    68 {
       
    69   connect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
       
    70   IPCSocket = 0;
       
    71 
       
    72   QProcess * process;
       
    73   process = new QProcess;
       
    74   connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError)));
       
    75   QStringList arguments=getArguments();
       
    76 
       
    77   // redirect everything written on stdout/stderr
       
    78   if(isDevBuild)
       
    79     process->setProcessChannelMode(QProcess::ForwardedChannels);
       
    80   process->start(bindir->absolutePath() + "/hwengine", arguments);
       
    81 }
       
    82 
       
    83 void TCPBase::ClientDisconnect()
       
    84 {
       
    85   disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
       
    86   onClientDisconnect();
       
    87 
       
    88   if(srvsList.size()==1) srvsList.pop_front();
       
    89   emit isReadyNow();
       
    90   IPCSocket->deleteLater();
       
    91   deleteLater();
       
    92 }
       
    93 
       
    94 void TCPBase::ClientRead()
       
    95 {
       
    96   QByteArray readed=IPCSocket->readAll();
       
    97   if(readed.isEmpty()) return;
       
    98   readbuffer.append(readed);
       
    99   onClientRead();
       
   100 }
       
   101 
       
   102 void TCPBase::StartProcessError(QProcess::ProcessError error)
       
   103 {
       
   104   QMessageBox::critical(0, tr("Error"),
       
   105             tr("Unable to run engine: %1 (")
       
   106             .arg(error) + bindir->absolutePath() + "/hwengine)");
       
   107 }
       
   108 
       
   109 void TCPBase::tcpServerReady()
       
   110 {
       
   111   disconnect(srvsList.takeFirst(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
       
   112 
       
   113   RealStart();
       
   114 }
       
   115 
       
   116 void TCPBase::Start()
       
   117 {
       
   118   if(srvsList.isEmpty()) {
       
   119     srvsList.push_back(this);
       
   120   } else {
       
   121     connect(srvsList.back(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
       
   122     srvsList.push_back(this);
       
   123     return;
       
   124   }
       
   125 
       
   126   RealStart();
       
   127 }
       
   128 
       
   129 void TCPBase::onClientRead()
       
   130 {
       
   131 }
       
   132 
       
   133 void TCPBase::onClientDisconnect()
       
   134 {
       
   135 }
       
   136 
       
   137 void TCPBase::SendToClientFirst()
       
   138 {
       
   139 }
       
   140 
       
   141 void TCPBase::SendIPC(const QByteArray & buf)
       
   142 {
       
   143     if (buf.size() > MAXMSGCHARS) return;
       
   144     quint8 len = buf.size();
       
   145     RawSendIPC(QByteArray::fromRawData((char *)&len, 1) + buf);
       
   146 }
       
   147 
       
   148 void TCPBase::RawSendIPC(const QByteArray & buf)
       
   149 {
       
   150     if (!IPCSocket)
       
   151     {
       
   152         toSendBuf += buf;
       
   153     } else
       
   154     {
       
   155         if (toSendBuf.size() > 0)
       
   156         {
       
   157             IPCSocket->write(toSendBuf);
       
   158             if(m_isDemoMode) demo.append(toSendBuf);
       
   159             toSendBuf.clear();
       
   160         }
       
   161         if(!buf.isEmpty()) {
       
   162           IPCSocket->write(buf);
       
   163           if(m_isDemoMode) demo.append(buf);
       
   164         }
       
   165     }
       
   166 }