QTfrontend/tcpBase.cpp
author displacer
Sun, 04 Feb 2007 21:30:23 +0000
changeset 390 dca6bd77d71d
parent 389 9628e69b609f
child 419 fdeed9718e6b
permissions -rw-r--r--
memory leak fixed (tanks unC0Rr)

/*
 * Hedgewars, a worms-like game
 * Copyright (c) 2006 Igor Ulyanov <iulyanov@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(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(disconnected()), IPCSocket, SLOT(deleteLater()));
  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=setArguments();
  process->start(bindir->absolutePath() + "/hwengine", arguments);
}

void TCPBase::ClientDisconnect()
{
  onClientDisconnect();

  readbuffer.clear();

  if(srvsList.size()==1) srvsList.pop_front();
  emit isReadyNow();
  deleteLater();
}

void TCPBase::ClientRead()
{
  readbuffer.append(IPCSocket->readAll());
  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) demo->append(buf);
		}
	}
}