QTfrontend/netserver.cpp
changeset 315 73003488240b
child 317 e95340dbfc1d
equal deleted inserted replaced
314:83773ccf4f09 315:73003488240b
       
     1 /*
       
     2  * Hedgewars, a worms-like game
       
     3  * Copyright (c) 2006 Ulyanov Igor <iulyanov@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include "netserver.h"
       
    20 
       
    21 #include <QTcpServer>
       
    22 #include <QTcpSocket>
       
    23 #include <QMessageBox>
       
    24 
       
    25 #include <algorithm>
       
    26 
       
    27 #include <QDebug>
       
    28 
       
    29 const quint16 HWNetServer::ds_port=46631;
       
    30 
       
    31 extern char delimeter;
       
    32 
       
    33 void HWNetServer::StartServer()
       
    34 {
       
    35   IPCServer = new QTcpServer(this);
       
    36   if (!IPCServer->listen(QHostAddress::LocalHost, ds_port)) {
       
    37     QMessageBox::critical(0, tr("Error"),
       
    38 			  tr("Unable to start the server: %1.")
       
    39 			  .arg(IPCServer->errorString()));
       
    40   }
       
    41   
       
    42   connect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
       
    43 }
       
    44 
       
    45 void HWNetServer::StopServer()
       
    46 {
       
    47   IPCServer->close();
       
    48 }
       
    49 
       
    50 void HWNetServer::NewConnection()
       
    51 {
       
    52   QTcpSocket* client = IPCServer->nextPendingConnection();
       
    53   if(!client) return;
       
    54   connclients.push_back(new HWConnectedClient(this, client));
       
    55   connect(connclients.back(), SIGNAL(HWClientDisconnected(HWConnectedClient*)), 
       
    56 	  this, SLOT(ClientDisconnect(HWConnectedClient*)));
       
    57 }
       
    58 
       
    59 void HWNetServer::ClientDisconnect(HWConnectedClient* client)
       
    60 {
       
    61   QList<HWConnectedClient*>::iterator it=std::find(connclients.begin(), connclients.end(), client);
       
    62   connclients.erase(it);
       
    63   teamChanged();
       
    64 }
       
    65 
       
    66 QString HWNetServer::getRunningHostName() const
       
    67 {
       
    68   return IPCServer->serverAddress().toString();
       
    69 }
       
    70 
       
    71 quint16 HWNetServer::getRunningPort() const
       
    72 {
       
    73   return ds_port;
       
    74 }
       
    75 
       
    76 bool HWNetServer::haveNick(const QString& nick) const
       
    77 {
       
    78   for(QList<HWConnectedClient*>::const_iterator it=connclients.begin(); it!=connclients.end(); ++it) {
       
    79     if((*it)->getClientNick()==nick) {
       
    80       return true;
       
    81     }
       
    82   }
       
    83   return false;
       
    84 }
       
    85 
       
    86 QStringList HWNetServer::getTeams() const
       
    87 {
       
    88   QStringList lst;
       
    89   for(QList<HWConnectedClient*>::const_iterator it=connclients.begin(); it!=connclients.end(); ++it) {
       
    90     try {
       
    91       lst.push_back((*it)->getTeamName());
       
    92     } catch(HWConnectedClient::NoTeamNameException& e) {
       
    93     }
       
    94   }
       
    95   return lst;
       
    96 }
       
    97 
       
    98 void HWNetServer::teamChanged()
       
    99 {
       
   100   for(QList<HWConnectedClient*>::const_iterator it=connclients.begin(); it!=connclients.end(); ++it) {
       
   101     (*it)->teamChangedNotify();
       
   102   }
       
   103 }
       
   104 
       
   105 bool HWNetServer::shouldStart(HWConnectedClient* client)
       
   106 {
       
   107   QList<HWConnectedClient*>::iterator it=std::find(connclients.begin(), connclients.end(), client);
       
   108   if(it==connclients.end() || *it!=client) return false;
       
   109   for(it=connclients.begin(); it!=connclients.end(); ++it) {
       
   110     if(!(*it)->isReady()) return false;
       
   111   }
       
   112   return true;
       
   113 }
       
   114 
       
   115 QString HWNetServer::prepareConfig(QStringList lst)
       
   116 {
       
   117   QString msg=lst.join((QString)delimeter)+delimeter;
       
   118   for(QList<HWConnectedClient*>::iterator it=connclients.begin(); it!=connclients.end(); ++it) {
       
   119     if(!(*it)->isReady()) continue;
       
   120     msg+=(*it)->getHedgehogsDescription()+delimeter;
       
   121   }
       
   122   qDebug() << msg;
       
   123   return msg;
       
   124 }
       
   125 
       
   126 HWConnectedClient::HWConnectedClient(HWNetServer* hwserver, QTcpSocket* client) :
       
   127   readyToStart(false),
       
   128   m_hwserver(hwserver),
       
   129   m_client(client),
       
   130   pclent_team(0)
       
   131 {
       
   132   connect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnect()));
       
   133   connect(client, SIGNAL(readyRead()), this, SLOT(ClientRead()));
       
   134 }
       
   135 
       
   136 HWConnectedClient::~HWConnectedClient()
       
   137 {
       
   138   if(pclent_team) delete pclent_team;
       
   139 }
       
   140 
       
   141 void HWConnectedClient::ClientDisconnect()
       
   142 {
       
   143   emit(HWClientDisconnected(this));
       
   144 }
       
   145 
       
   146 void HWConnectedClient::ClientRead()
       
   147 {
       
   148   try {
       
   149     while (m_client->canReadLine()) {
       
   150       ParseLine(m_client->readLine().trimmed());
       
   151     }
       
   152   } catch(ShouldDisconnectException& e) {
       
   153     m_client->close();
       
   154   }
       
   155 }
       
   156 
       
   157 void HWConnectedClient::ParseLine(const QByteArray & line)
       
   158 {
       
   159   QString msg = QString::fromUtf8 (line.data(), line.size());
       
   160 
       
   161   qDebug() << "line " << msg << " received";
       
   162 
       
   163   QStringList lst = msg.split(delimeter);
       
   164   if(lst.size()<2) return;
       
   165   if (lst[0] == "NICK") {
       
   166     if(m_hwserver->haveNick(lst[1])) {
       
   167       RawSendNet(QString("ERRONEUSNICKNAME"));
       
   168       throw ShouldDisconnectException();
       
   169     }
       
   170 
       
   171     client_nick=lst[1];
       
   172     qDebug() << "send connected";
       
   173     RawSendNet(QString("CONNECTED"));
       
   174     m_hwserver->teamChanged();
       
   175     return;
       
   176   }
       
   177   if(client_nick=="") return;
       
   178 
       
   179   if (lst[0]=="START:") {
       
   180     readyToStart=true;
       
   181     if(m_hwserver->shouldStart(this)) {
       
   182       // start
       
   183       RawSendNet(QString("CONFIGASKED"));
       
   184     }
       
   185     return;
       
   186   }
       
   187 
       
   188   if(lst[0]=="CONFIGANSWER") {
       
   189     lst.pop_front();
       
   190     RawSendNet(QString("CONFIGURED")+QString(delimeter)+m_hwserver->prepareConfig(lst)+delimeter+"!"+delimeter);
       
   191     return;
       
   192   }
       
   193 
       
   194   if(lst.size()<10) return;
       
   195   if(lst[0]=="ADDTEAM:") {
       
   196     lst.pop_front();
       
   197     if(pclent_team) delete pclent_team;
       
   198     pclent_team=new HWTeam(lst);
       
   199     m_hwserver->teamChanged();
       
   200     return;
       
   201   }
       
   202 }
       
   203 
       
   204 void HWConnectedClient::teamChangedNotify()
       
   205 {
       
   206   QString teams;
       
   207   QStringList lst=m_hwserver->getTeams();
       
   208   for(int i=0; i<lst.size(); i++) {
       
   209     teams+=delimeter+lst[i];
       
   210   }
       
   211   RawSendNet(QString("TEAMCHANGED")+teams);
       
   212 }
       
   213 
       
   214 void HWConnectedClient::RawSendNet(const QString & str)
       
   215 {
       
   216   RawSendNet(str.toUtf8());
       
   217 }
       
   218 
       
   219 void HWConnectedClient::RawSendNet(const QByteArray & buf)
       
   220 {
       
   221   m_client->write(buf);
       
   222   m_client->write("\n", 1);
       
   223 }
       
   224 
       
   225 QString HWConnectedClient::getClientNick() const
       
   226 {
       
   227   return client_nick;
       
   228 }
       
   229 
       
   230 QString HWConnectedClient::getTeamName() const
       
   231 {
       
   232   if(!pclent_team) throw NoTeamNameException();
       
   233   return pclent_team->TeamName;
       
   234 }
       
   235 
       
   236 bool HWConnectedClient::isReady() const
       
   237 {
       
   238   return readyToStart;
       
   239 }
       
   240 
       
   241 QString HWConnectedClient::getHedgehogsDescription() const
       
   242 {
       
   243   return pclent_team->TeamGameConfig(65535, 4, 100).join((QString)delimeter);
       
   244 }