diff options
Diffstat (limited to 'pacman-c++/server.cpp')
| -rw-r--r-- | pacman-c++/server.cpp | 146 |
1 files changed, 134 insertions, 12 deletions
diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp index 51dcc24..50ee3b7 100644 --- a/pacman-c++/server.cpp +++ b/pacman-c++/server.cpp | |||
| @@ -1,18 +1,24 @@ | |||
| 1 | #include "server.h" | 1 | #include "server.h" |
| 2 | |||
| 3 | #include <QtNetwork/QTcpServer> | ||
| 4 | #include <QtNetwork/QTcpSocket> | ||
| 5 | #include "util.h" | 2 | #include "util.h" |
| 6 | #include "pacman.pb.h" | 3 | #include "pacman.pb.h" |
| 7 | #include "block.h" | 4 | #include "block.h" |
| 5 | #include "anyoption.h" | ||
| 6 | #include <QtNetwork/QTcpServer> | ||
| 7 | #include <QtNetwork/QTcpSocket> | ||
| 8 | #include <QTextStream> | ||
| 8 | 9 | ||
| 9 | Server::Server(QWidget *parent) | 10 | Server::Server(QWidget *parent) |
| 10 | : SceneHolder(parent) | 11 | : SceneHolder(parent), m_bindaddress(QHostAddress::Any), |
| 12 | m_port(Constants::Networking::port), m_numbots(0) | ||
| 11 | { | 13 | { |
| 14 | /* determine max players by using order array */ | ||
| 15 | for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers); | ||
| 16 | } | ||
| 12 | 17 | ||
| 13 | qDebug() << "[Server] Waiting for clients"; | 18 | bool Server::run() |
| 14 | waitForClientConnections(); | 19 | { |
| 15 | qDebug() << "[Server] All Clients connected"; | 20 | if (!waitForClientConnections()) |
| 21 | return false; | ||
| 16 | 22 | ||
| 17 | Transmission::map_t map = Util::createDemoMap(); | 23 | Transmission::map_t map = Util::createDemoMap(); |
| 18 | updateMap(map); | 24 | updateMap(map); |
| @@ -22,6 +28,7 @@ Server::Server(QWidget *parent) | |||
| 22 | QTimer *timer = new QTimer(this); | 28 | QTimer *timer = new QTimer(this); |
| 23 | connect(timer, SIGNAL(timeout()), this, SLOT(tick())); | 29 | connect(timer, SIGNAL(timeout()), this, SLOT(tick())); |
| 24 | timer->start(Constants::tick); | 30 | timer->start(Constants::tick); |
| 31 | return true; | ||
| 25 | } | 32 | } |
| 26 | 33 | ||
| 27 | void Server::tick() | 34 | void Server::tick() |
| @@ -147,12 +154,21 @@ invalid_direction: | |||
| 147 | return map; | 154 | return map; |
| 148 | } | 155 | } |
| 149 | 156 | ||
| 150 | void Server::waitForClientConnections() | 157 | bool Server::waitForClientConnections() |
| 151 | { | 158 | { |
| 152 | QTcpServer *tcpSrv = new QTcpServer(this); | ||
| 153 | // server must stay alive as long as sockets (qt parent mem mechanism) | 159 | // server must stay alive as long as sockets (qt parent mem mechanism) |
| 154 | tcpSrv->listen(QHostAddress::Any, Constants::Networking::port); | 160 | QTcpServer *tcpSrv = new QTcpServer(this); |
| 161 | tcpSrv->listen(m_bindaddress, m_port); | ||
| 162 | if (!tcpSrv->isListening()) | ||
| 163 | { | ||
| 164 | qCritical() << "Error while creating socket:" << qPrintable(tcpSrv->errorString()); | ||
| 165 | return false; | ||
| 166 | } | ||
| 155 | 167 | ||
| 168 | qDebug() << "[Server] Listening on:" | ||
| 169 | << qPrintable(QString("%1:%2").arg(tcpSrv->serverAddress().toString()) | ||
| 170 | .arg(tcpSrv->serverPort())); | ||
| 171 | qDebug() << "[Server] Waiting for clients"; | ||
| 156 | ProtoBuf::WhoAmI packet; | 172 | ProtoBuf::WhoAmI packet; |
| 157 | #define SINGLE | 173 | #define SINGLE |
| 158 | #ifdef SINGLE | 174 | #ifdef SINGLE |
| @@ -177,6 +193,9 @@ void Server::waitForClientConnections() | |||
| 177 | 193 | ||
| 178 | qDebug() << "[Connect] New Player: color=" << color; | 194 | qDebug() << "[Connect] New Player: color=" << color; |
| 179 | } | 195 | } |
| 196 | |||
| 197 | qDebug() << "[Server] All Clients connected"; | ||
| 198 | return true; | ||
| 180 | } | 199 | } |
| 181 | 200 | ||
| 182 | void Server::sendUpdate(Transmission::map_t map) | 201 | void Server::sendUpdate(Transmission::map_t map) |
| @@ -229,6 +248,103 @@ void Server::keyPressUpdate() | |||
| 229 | } | 248 | } |
| 230 | } | 249 | } |
| 231 | 250 | ||
| 251 | bool Server::parseCommandline() | ||
| 252 | { | ||
| 253 | AnyOption opt; | ||
| 254 | opt.setVerbose(); | ||
| 255 | |||
| 256 | /* usage strings must remain valid until parsing is done */ | ||
| 257 | QString exec = QFileInfo(qApp->applicationFilePath()).fileName(); | ||
| 258 | QByteArray usage; | ||
| 259 | QTextStream out(&usage, QIODevice::ReadWrite | QIODevice::Text); | ||
| 260 | out << "Usage: " << exec << " [OPTION]" << endl | ||
| 261 | << "Usage: " << exec << " -h" << endl | ||
| 262 | << endl; | ||
| 263 | out << " -b, --bind <bind_address>" << endl | ||
| 264 | << " Specifies the ip address on which the server listens for connections" << endl | ||
| 265 | << " Default: " << m_bindaddress.toString() << endl | ||
| 266 | << endl; | ||
| 267 | opt.setOption("bind", 'b'); | ||
| 268 | out << " -p, --port <port>" << endl | ||
| 269 | << " Specifies the port on which the server listens for connections" << endl | ||
| 270 | << " Default: " << m_port << endl | ||
| 271 | << endl; | ||
| 272 | opt.setOption("port", 'p'); | ||
| 273 | out << " -m, --maxplayers [1.." << m_maxplayers << "]" << endl | ||
| 274 | << " Specifies the maximum number of players/pacmans" << endl | ||
| 275 | << " Default: " << m_maxplayers << endl | ||
| 276 | << endl; | ||
| 277 | opt.setOption("maxplayers", 'm'); | ||
| 278 | out << " --bots [0..maxplayers-1]" << endl | ||
| 279 | << " Specifies the number of AI pacmans/bots" << endl | ||
| 280 | << " Default: " << m_numbots << endl | ||
| 281 | << endl; | ||
| 282 | opt.setOption("bots"); | ||
| 283 | out << " -h, --help" << endl | ||
| 284 | << " Prints this help message" << endl; | ||
| 285 | opt.setFlag("help", 'h'); | ||
| 286 | out.flush(); | ||
| 287 | opt.addUsage(usage.constData()); | ||
| 288 | opt.processCommandArgs(qApp->argc(), qApp->argv()); | ||
| 289 | |||
| 290 | if (opt.getFlag("help") || opt.getFlag('h')) | ||
| 291 | { | ||
| 292 | opt.printUsage(); | ||
| 293 | return false; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (opt.getValue("port") != NULL) | ||
| 297 | { | ||
| 298 | bool ok; | ||
| 299 | m_port = QString(opt.getValue("port")).toUInt(&ok); | ||
| 300 | if (!ok || m_port < 1 || m_port > 65535) | ||
| 301 | { | ||
| 302 | qCritical() << "Invalid port-option:" << opt.getValue("port") << endl | ||
| 303 | << "Port must be between 1 and 65535"; | ||
| 304 | return false; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | if (opt.getValue("bind") != NULL) | ||
| 309 | { | ||
| 310 | m_bindaddress = opt.getValue("bind"); | ||
| 311 | if (m_bindaddress.isNull()) | ||
| 312 | { | ||
| 313 | qCritical() << "Invalid bind-option:" << opt.getValue("bind") << endl | ||
| 314 | << "Bind address must be an ip address"; | ||
| 315 | return false; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | if (opt.getValue("maxplayers") != NULL) | ||
| 320 | { | ||
| 321 | bool ok; | ||
| 322 | unsigned int maxplayers = QString(opt.getValue("maxplayers")).toUInt(&ok); | ||
| 323 | if (!ok || maxplayers < 1 || maxplayers > m_maxplayers) | ||
| 324 | { | ||
| 325 | qCritical() << "Invalid maxplayers-option:" << opt.getValue("maxplayers") << endl | ||
| 326 | << "Maxplayers must be between 1 and" << m_maxplayers; | ||
| 327 | return false; | ||
| 328 | } | ||
| 329 | m_maxplayers = maxplayers; | ||
| 330 | } | ||
| 331 | |||
| 332 | if (opt.getValue("bots") != NULL) | ||
| 333 | { | ||
| 334 | bool ok; | ||
| 335 | unsigned int numbots = QString(opt.getValue("bots")).toUInt(&ok); | ||
| 336 | if (!ok || numbots >= m_maxplayers) | ||
| 337 | { | ||
| 338 | qCritical() << "Invalid numbots-options:" << opt.getValue("bots") << endl | ||
| 339 | << "AI pacmans/bots must be between 0 and" << m_maxplayers - 1; | ||
| 340 | return false; | ||
| 341 | } | ||
| 342 | m_numbots = numbots; | ||
| 343 | } | ||
| 344 | |||
| 345 | return true; | ||
| 346 | } | ||
| 347 | |||
| 232 | bool Constants::server = true; | 348 | bool Constants::server = true; |
| 233 | 349 | ||
| 234 | int main(int argc, char ** argv) | 350 | int main(int argc, char ** argv) |
| @@ -244,8 +360,14 @@ int main(int argc, char ** argv) | |||
| 244 | 360 | ||
| 245 | qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); | 361 | qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); |
| 246 | 362 | ||
| 247 | Server Server; | 363 | int ret = 0; |
| 248 | int ret = app.exec(); | 364 | Server server; |
| 365 | if (!ret && !server.parseCommandline()) | ||
| 366 | ret = 1; | ||
| 367 | if (!ret && !server.run()) | ||
| 368 | ret = 1; | ||
| 369 | if (!ret) | ||
| 370 | ret = app.exec(); | ||
| 249 | 371 | ||
| 250 | /* Delete all global objects allocated by libprotobuf */ | 372 | /* Delete all global objects allocated by libprotobuf */ |
| 251 | google::protobuf::ShutdownProtobufLibrary(); | 373 | google::protobuf::ShutdownProtobufLibrary(); |
