QTfrontend/net/tcpBase.cpp
changeset 6060 fdfc01419815
parent 5213 a86768368309
child 6616 f77bb02b669f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/net/tcpBase.cpp	Wed Sep 28 19:27:56 2011 +0200
@@ -0,0 +1,166 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
+ * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "tcpBase.h"
+
+#include <QMessageBox>
+#include <QList>
+
+#include <QImage>
+
+#include "hwconsts.h"
+
+QList<TCPBase*> srvsList;
+QPointer<QTcpServer> TCPBase::IPCServer(0);
+
+TCPBase::~TCPBase()
+{
+}
+
+TCPBase::TCPBase(bool demoMode) :
+  m_isDemoMode(demoMode),
+  IPCSocket(0)
+{
+  if(!IPCServer) {
+    IPCServer = new QTcpServer(0);
+    IPCServer->setMaxPendingConnections(1);
+    if (!IPCServer->listen(QHostAddress::LocalHost)) {
+      QMessageBox::critical(0, tr("Error"),
+                tr("Unable to start the server: %1.")
+                .arg(IPCServer->errorString()));
+      exit(0); // FIXME - should be graceful exit here
+    }
+  }
+  ipc_port=IPCServer->serverPort();
+}
+
+void TCPBase::NewConnection()
+{
+  if(IPCSocket) {
+    // connection should be already finished
+    return;
+  }
+  disconnect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
+  IPCSocket = IPCServer->nextPendingConnection();
+  if(!IPCSocket) return;
+  connect(IPCSocket, SIGNAL(disconnected()), this, SLOT(ClientDisconnect()));
+  connect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
+  SendToClientFirst();
+}
+
+void TCPBase::RealStart()
+{
+  connect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
+  IPCSocket = 0;
+
+  QProcess * process;
+  process = new QProcess;
+  connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError)));
+  QStringList arguments=getArguments();
+
+  // redirect everything written on stdout/stderr
+  if(isDevBuild)
+    process->setProcessChannelMode(QProcess::ForwardedChannels);
+  process->start(bindir->absolutePath() + "/hwengine", arguments);
+}
+
+void TCPBase::ClientDisconnect()
+{
+  disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
+  onClientDisconnect();
+
+  if(srvsList.size()==1) srvsList.pop_front();
+  emit isReadyNow();
+  IPCSocket->deleteLater();
+  deleteLater();
+}
+
+void TCPBase::ClientRead()
+{
+  QByteArray readed=IPCSocket->readAll();
+  if(readed.isEmpty()) return;
+  readbuffer.append(readed);
+  onClientRead();
+}
+
+void TCPBase::StartProcessError(QProcess::ProcessError error)
+{
+  QMessageBox::critical(0, tr("Error"),
+            tr("Unable to run engine: %1 (")
+            .arg(error) + bindir->absolutePath() + "/hwengine)");
+}
+
+void TCPBase::tcpServerReady()
+{
+  disconnect(srvsList.takeFirst(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
+
+  RealStart();
+}
+
+void TCPBase::Start()
+{
+  if(srvsList.isEmpty()) {
+    srvsList.push_back(this);
+  } else {
+    connect(srvsList.back(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
+    srvsList.push_back(this);
+    return;
+  }
+
+  RealStart();
+}
+
+void TCPBase::onClientRead()
+{
+}
+
+void TCPBase::onClientDisconnect()
+{
+}
+
+void TCPBase::SendToClientFirst()
+{
+}
+
+void TCPBase::SendIPC(const QByteArray & buf)
+{
+    if (buf.size() > MAXMSGCHARS) return;
+    quint8 len = buf.size();
+    RawSendIPC(QByteArray::fromRawData((char *)&len, 1) + buf);
+}
+
+void TCPBase::RawSendIPC(const QByteArray & buf)
+{
+    if (!IPCSocket)
+    {
+        toSendBuf += buf;
+    } else
+    {
+        if (toSendBuf.size() > 0)
+        {
+            IPCSocket->write(toSendBuf);
+            if(m_isDemoMode) demo.append(toSendBuf);
+            toSendBuf.clear();
+        }
+        if(!buf.isEmpty()) {
+          IPCSocket->write(buf);
+          if(m_isDemoMode) demo.append(buf);
+        }
+    }
+}