1 /*
2 * This file is part of Dune Legacy.
3 *
4 * Dune Legacy is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * Dune Legacy 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 Dune Legacy. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <Network/NetworkManager.h>
19
20 #include <Network/ENetHelper.h>
21
22 #include <GameInitSettings.h>
23
24 #include <misc/exceptions.h>
25
26 #include <globals.h>
27
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <algorithm>
32
NetworkManager(int port,const std::string & metaserver)33 NetworkManager::NetworkManager(int port, const std::string& metaserver) {
34
35 if(enet_initialize() != 0) {
36 THROW(std::runtime_error, "NetworkManager: An error occurred while initializing ENet.");
37 }
38
39 ENetAddress address;
40 address.host = ENET_HOST_ANY;
41 address.port = port;
42
43 host = enet_host_create(&address, 32, 2, 0, 0);
44 if(host == nullptr) {
45 enet_deinitialize();
46 THROW(std::runtime_error, "NetworkManager: An error occurred while trying to create a server host.");
47 }
48
49 if(enet_host_compress_with_range_coder(host) < 0) {
50 enet_deinitialize();
51 THROW(std::runtime_error, "NetworkManager: Cannot activate range coder.");
52 }
53
54 try {
55 pLANGameFinderAndAnnouncer = new LANGameFinderAndAnnouncer();
56 } catch (...) {
57 enet_deinitialize();
58 throw;
59 }
60
61 try {
62 pMetaServerClient = new MetaServerClient(metaserver);
63 } catch (...) {
64 delete pLANGameFinderAndAnnouncer;
65 enet_deinitialize();
66 throw;
67 }
68 }
69
70
~NetworkManager()71 NetworkManager::~NetworkManager() {
72 delete pMetaServerClient;
73 delete pLANGameFinderAndAnnouncer;
74 enet_host_destroy(host);
75 enet_deinitialize();
76 }
77
startServer(bool bLANServer,const std::string & serverName,const std::string & playerName,GameInitSettings * pGameInitSettings,int numPlayers,int maxPlayers)78 void NetworkManager::startServer(bool bLANServer, const std::string& serverName, const std::string& playerName, GameInitSettings* pGameInitSettings, int numPlayers, int maxPlayers) {
79 if(bLANServer == true) {
80 if(pLANGameFinderAndAnnouncer != nullptr) {
81 pLANGameFinderAndAnnouncer->startAnnounce(serverName, host->address.port, pGameInitSettings->getFilename(), numPlayers, maxPlayers);
82 }
83 } else {
84 if(pMetaServerClient != nullptr) {
85 pMetaServerClient->startAnnounce(serverName, host->address.port, pGameInitSettings->getFilename(), numPlayers, maxPlayers);
86 }
87 }
88
89 bIsServer = true;
90 this->bLANServer = bLANServer;
91 this->numPlayers = numPlayers;
92 this->maxPlayers = maxPlayers;
93 this->playerName = playerName;
94 this->pGameInitSettings = pGameInitSettings;
95 }
96
updateServer(int numPlayers)97 void NetworkManager::updateServer(int numPlayers) {
98 if(bLANServer == true) {
99 if(pLANGameFinderAndAnnouncer != nullptr) {
100 pLANGameFinderAndAnnouncer->updateAnnounce(numPlayers);
101 }
102 } else {
103 if(pMetaServerClient != nullptr) {
104 pMetaServerClient->updateAnnounce(numPlayers);
105 }
106 }
107
108 this->numPlayers = numPlayers;
109 }
110
stopServer()111 void NetworkManager::stopServer() {
112 if(bLANServer == true) {
113 if(pLANGameFinderAndAnnouncer != nullptr) {
114 pLANGameFinderAndAnnouncer->stopAnnounce();
115 }
116 } else {
117 if(pMetaServerClient != nullptr) {
118 pMetaServerClient->stopAnnounce();
119 }
120 }
121
122 bIsServer = false;
123 bLANServer = false;
124 pGameInitSettings = nullptr;
125 }
126
connect(const std::string & hostname,int port,const std::string & playerName)127 void NetworkManager::connect(const std::string& hostname, int port, const std::string& playerName) {
128 ENetAddress address;
129
130 if(enet_address_set_host(&address, hostname.c_str()) < 0) {
131 THROW(std::runtime_error, "NetworkManager: Resolving hostname '" + hostname + "' failed!");
132 }
133 address.port = port;
134
135 connect(address, playerName);
136 }
137
connect(ENetAddress address,const std::string & playerName)138 void NetworkManager::connect(ENetAddress address, const std::string& playerName) {
139 debugNetwork("Connecting to %s:%d\n", Address2String(address).c_str(), address.port);
140
141 connectPeer = enet_host_connect(host, &address, 2, 0);
142 if(connectPeer == nullptr) {
143 THROW(std::runtime_error, "NetworkManager: No available peers for initiating a connection.");
144 }
145
146 this->playerName = playerName;
147
148 connectPeer->data = new PeerData(connectPeer, PeerData::PeerState::WaitingForConnect);
149 awaitingConnectionList.push_back(connectPeer);
150 }
151
disconnect()152 void NetworkManager::disconnect() {
153 for(ENetPeer* pAwaitingConnectionPeer : awaitingConnectionList) {
154 enet_peer_disconnect_later(pAwaitingConnectionPeer, NETWORKDISCONNECT_QUIT);
155 }
156 for(ENetPeer* pCurrentPeer : peerList) {
157 enet_peer_disconnect_later(pCurrentPeer, NETWORKDISCONNECT_QUIT);
158 }
159 }
160
update()161 void NetworkManager::update()
162 {
163 if(pLANGameFinderAndAnnouncer != nullptr) {
164 pLANGameFinderAndAnnouncer->update();
165 }
166
167 if(pMetaServerClient != nullptr) {
168 pMetaServerClient->update();
169 }
170
171 if(bIsServer) {
172 // Check for timeout of one client
173 if(awaitingConnectionList.empty() == false) {
174 ENetPeer* pCurrentPeer = awaitingConnectionList.front();
175 PeerData* peerData = static_cast<PeerData*>(pCurrentPeer->data);
176
177 if(peerData->peerState == PeerData::PeerState::ReadyForOtherPeersToConnect) {
178 if(numPlayers >= maxPlayers) {
179 enet_peer_disconnect_later(pCurrentPeer, NETWORKDISCONNECT_GAME_FULL);
180 } else {
181 // only one peer should be in state 'PeerState::WaitingForOtherPeersToConnect'
182 peerData->peerState = PeerData::PeerState::WaitingForOtherPeersToConnect;
183 peerData->timeout = SDL_GetTicks() + AWAITING_CONNECTION_TIMEOUT;
184 peerData->notYetConnectedPeers = peerList;
185
186 if(peerData->notYetConnectedPeers.empty()) {
187 // first client on this server
188 // => change immediately to connected
189
190 // get change event list first
191 ChangeEventList changeEventList = pGetChangeEventListForNewPlayerCallback(peerData->name);
192
193 debugNetwork("Moving '%s' from awaiting connection list to peer list\n", peerData->name.c_str());
194 peerList.push_back(pCurrentPeer);
195 peerData->peerState = PeerData::PeerState::Connected;
196 peerData->timeout = 0;
197 awaitingConnectionList.remove(pCurrentPeer);
198
199 // send peer game settings
200 ENetPacketOStream packetOStream2(ENET_PACKET_FLAG_RELIABLE);
201 packetOStream2.writeUint32(NETWORKPACKET_SENDGAMEINFO);
202 pGameInitSettings->save(packetOStream2);
203
204 changeEventList.save(packetOStream2);
205
206 sendPacketToPeer(pCurrentPeer, packetOStream2);
207 } else {
208 // instruct all connected peers to connect
209
210 ENetPacketOStream packetOStream(ENET_PACKET_FLAG_RELIABLE);
211 packetOStream.writeUint32(NETWORKPACKET_CONNECT);
212 packetOStream.writeUint32(SDL_SwapBE32(pCurrentPeer->address.host));
213 packetOStream.writeUint16(pCurrentPeer->address.port);
214 packetOStream.writeString(peerData->name);
215
216 sendPacketToAllConnectedPeers(packetOStream);
217 }
218 }
219 }
220
221 if(peerData->timeout > 0 && SDL_GetTicks() > peerData->timeout) {
222 // timeout
223 switch(peerData->peerState) {
224 case PeerData::PeerState::WaitingForName: {
225 // nothing to do
226 } break;
227
228 case PeerData::PeerState::WaitingForOtherPeersToConnect: {
229 // the client awaiting connection has timed out => send everyone a disconnect message
230 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
231 packetStream.writeUint32(NETWORKPACKET_DISCONNECT);
232 packetStream.writeUint32(SDL_SwapBE32(pCurrentPeer->address.host));
233 packetStream.writeUint16(pCurrentPeer->address.port);
234
235 sendPacketToAllConnectedPeers(packetStream);
236
237 enet_peer_disconnect(pCurrentPeer, NETWORKDISCONNECT_TIMEOUT);
238
239 awaitingConnectionList.pop_front();
240 } break;
241
242 case PeerData::PeerState::Connected:
243 default: {
244 // should never happen
245 } break;
246 }
247 }
248 }
249 }
250
251 ENetEvent event;
252 while(enet_host_service(host, &event, 0) > 0) {
253
254 ENetPeer* peer = event.peer;
255
256 switch(event.type) {
257 case ENET_EVENT_TYPE_CONNECT: {
258 if(bIsServer) {
259 // Server
260 debugNetwork("NetworkManager: %s:%u connected.\n", Address2String(peer->address).c_str(), peer->address.port);
261
262 PeerData* newPeerData = new PeerData(peer, PeerData::PeerState::WaitingForName);
263 newPeerData->timeout = SDL_GetTicks() + AWAITING_CONNECTION_TIMEOUT;
264 peer->data = newPeerData;
265
266 debugNetwork("Adding '%s' to awaiting connection list\n", newPeerData->name.c_str());
267 awaitingConnectionList.push_back(peer);
268
269 // Send name
270 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
271 packetStream.writeUint32(NETWORKPACKET_SENDNAME);
272 packetStream.writeString(playerName);
273
274 sendPacketToPeer(peer, packetStream);
275 } else if(connectPeer != nullptr) {
276 // Client
277 PeerData* peerData = static_cast<PeerData*>(peer->data);
278
279 if(peer == connectPeer) {
280 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
281 packetStream.writeUint32(NETWORKPACKET_SENDNAME);
282 packetStream.writeString(playerName);
283
284 sendPacketToHost(packetStream);
285
286 peerData->peerState = PeerData::PeerState::WaitingForOtherPeersToConnect;
287 peerData->timeout = 0;
288 } else {
289 debugNetwork("NetworkManager: %s:%u connected.\n", Address2String(peer->address).c_str(), peer->address.port);
290
291 PeerData* pConnectPeerData = static_cast<PeerData*>(connectPeer->data);
292
293 if(pConnectPeerData->peerState == PeerData::PeerState::WaitingForOtherPeersToConnect) {
294 if(peerData == nullptr) {
295 peerData = new PeerData(peer, PeerData::PeerState::Connected);
296 peer->data = peerData;
297
298 debugNetwork("Adding '%s' to awaiting connection list\n", peerData->name.c_str());
299 awaitingConnectionList.push_back(peer);
300 }
301 } else {
302 ENetPacketOStream packetStream1(ENET_PACKET_FLAG_RELIABLE);
303 packetStream1.writeUint32(NETWORKPACKET_PEER_CONNECTED);
304 packetStream1.writeUint32(SDL_SwapBE32(peer->address.host));
305 packetStream1.writeUint16(peer->address.port);
306
307 sendPacketToHost(packetStream1);
308
309 ENetPacketOStream packetStream2(ENET_PACKET_FLAG_RELIABLE);
310 packetStream2.writeUint32(NETWORKPACKET_SENDNAME);
311 packetStream2.writeString(playerName);
312
313 sendPacketToPeer(peer, packetStream2);
314 }
315 }
316 } else {
317 enet_peer_disconnect(peer, NETWORKDISCONNECT_TIMEOUT);
318 }
319 } break;
320
321 case ENET_EVENT_TYPE_RECEIVE: {
322 //debugNetwork("NetworkManager: A packet of length %u was received from %s:%u on channel %u on this server.\n",
323 // (unsigned int) event.packet->dataLength, Address2String(peer->address).c_str(), peer->address.port, event.channelID);
324
325 ENetPacketIStream packetStream(event.packet);
326
327 handlePacket(peer, packetStream);
328 } break;
329
330 case ENET_EVENT_TYPE_DISCONNECT: {
331 PeerData* peerData = static_cast<PeerData*>(peer->data);
332
333 int disconnectCause = event.data;
334
335 debugNetwork("NetworkManager: %s:%u (%s) disconnected (%d).\n", Address2String(peer->address).c_str(), peer->address.port, (peerData != nullptr) ? peerData->name.c_str() : "unknown", disconnectCause);
336
337 if(std::find(awaitingConnectionList.begin(), awaitingConnectionList.end(), peer) != awaitingConnectionList.end()) {
338 if(peerData->peerState == PeerData::PeerState::WaitingForOtherPeersToConnect) {
339 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
340 packetStream.writeUint32(NETWORKPACKET_DISCONNECT);
341 packetStream.writeUint32(SDL_SwapBE32(peer->address.host));
342 packetStream.writeUint16(peer->address.port);
343
344 sendPacketToAllConnectedPeers(packetStream);
345 }
346
347 debugNetwork("Removing '%s' from awaiting connection list\n", peerData->name.c_str());
348 awaitingConnectionList.remove(peer);
349 }
350
351
352 if(std::find(peerList.begin(), peerList.end(), peer) != peerList.end()) {
353 debugNetwork("Removing '%s' from peer list\n", peerData->name.c_str());
354 peerList.remove(peer);
355
356 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
357 packetStream.writeUint32(NETWORKPACKET_DISCONNECT);
358 packetStream.writeUint32(SDL_SwapBE32(peer->address.host));
359 packetStream.writeUint16(peer->address.port);
360
361 sendPacketToAllConnectedPeers(packetStream);
362
363 if(pOnPeerDisconnected) {
364 pOnPeerDisconnected(peerData->name, (peer == connectPeer), disconnectCause);
365 }
366 } else {
367 if(peer == connectPeer) {
368 // host disconnected while establishing connection
369 if(pOnPeerDisconnected) {
370 pOnPeerDisconnected(peerData->name, true, disconnectCause);
371 }
372 }
373 }
374
375 // delete peer data
376 delete peerData;
377 peer->data = nullptr;
378
379 if(peer == connectPeer) {
380 connectPeer = nullptr;
381 }
382
383 } break;
384
385 default: {
386
387 } break;
388 }
389 }
390 }
391
handlePacket(ENetPeer * peer,ENetPacketIStream & packetStream)392 void NetworkManager::handlePacket(ENetPeer* peer, ENetPacketIStream& packetStream)
393 {
394 try {
395 Uint32 packetType = packetStream.readUint32();
396
397 switch(packetType) {
398 case NETWORKPACKET_CONNECT: {
399
400 if(bIsServer == false) {
401 ENetAddress address;
402
403 address.host = SDL_SwapBE32(packetStream.readUint32());
404 address.port = packetStream.readUint16();
405
406 debugNetwork("Connecting to %s:%d\n", Address2String(address).c_str(), address.port);
407
408 ENetPeer *newPeer = enet_host_connect(host, &address, 2, 0);
409 if(newPeer == nullptr) {
410 debugNetwork("NetworkManager: No available peers for initiating a connection.");
411 } else {
412 PeerData* peerData = new PeerData(newPeer, PeerData::PeerState::WaitingForOtherPeersToConnect);
413 peerData->name = packetStream.readString();
414
415 newPeer->data = peerData;
416 debugNetwork("Adding '%s' to awaiting connection list\n", peerData->name.c_str());
417 awaitingConnectionList.push_back(newPeer);
418 }
419 }
420 } break;
421
422 case NETWORKPACKET_DISCONNECT: {
423 ENetAddress address;
424
425 address.host = SDL_SwapBE32(packetStream.readUint32());
426 address.port = packetStream.readUint16();
427
428 for(ENetPeer* pCurrentPeer : peerList) {
429 if((pCurrentPeer->address.host == address.host) && (pCurrentPeer->address.port == address.port)) {
430 enet_peer_disconnect_later(pCurrentPeer, NETWORKDISCONNECT_QUIT);
431 break;
432 }
433 }
434
435 for(ENetPeer* pAwaitingConnectionPeer : awaitingConnectionList) {
436 if((pAwaitingConnectionPeer->address.host == address.host) && (pAwaitingConnectionPeer->address.port == address.port)) {
437 enet_peer_disconnect_later(pAwaitingConnectionPeer, NETWORKDISCONNECT_QUIT);
438 break;
439 }
440 }
441
442 } break;
443
444 case NETWORKPACKET_PEER_CONNECTED: {
445
446 ENetAddress address;
447
448 address.host = SDL_SwapBE32(packetStream.readUint32());
449 address.port = packetStream.readUint16();
450
451 if(isServer()) {
452
453 if(awaitingConnectionList.empty() == false) {
454 ENetPeer* pCurrentPeer = awaitingConnectionList.front();
455 PeerData* peerData = static_cast<PeerData*>(pCurrentPeer->data);
456
457 if((pCurrentPeer->address.host == address.host) && (pCurrentPeer->address.port == address.port)) {
458
459 peerData->notYetConnectedPeers.remove(peer);
460
461 if(peerData->notYetConnectedPeers.empty()) {
462 // send connected to all peers (excluding the new one)
463 ENetPacketOStream packetOStream(ENET_PACKET_FLAG_RELIABLE);
464 packetOStream.writeUint32(NETWORKPACKET_PEER_CONNECTED);
465 packetOStream.writeUint32(SDL_SwapBE32(pCurrentPeer->address.host));
466 packetOStream.writeUint16(pCurrentPeer->address.port);
467
468 sendPacketToAllConnectedPeers(packetOStream);
469
470 // get change event list first
471 ChangeEventList changeEventList = pGetChangeEventListForNewPlayerCallback(peerData->name);
472
473 // move peer to peer list
474 debugNetwork("Moving '%s' from awaiting connection list to peer list\n", peerData->name.c_str());
475 peerList.push_back(pCurrentPeer);
476 peerData->peerState = PeerData::PeerState::Connected;
477 peerData->timeout = 0;
478 awaitingConnectionList.remove(pCurrentPeer);
479
480 // send peer game settings
481 ENetPacketOStream packetOStream2(ENET_PACKET_FLAG_RELIABLE);
482 packetOStream2.writeUint32(NETWORKPACKET_SENDGAMEINFO);
483 pGameInitSettings->save(packetOStream2);
484
485 changeEventList.save(packetOStream2);
486
487 sendPacketToPeer(pCurrentPeer, packetOStream2);
488 }
489 }
490 }
491 } else {
492 for(auto iter = awaitingConnectionList.begin(); iter != awaitingConnectionList.end(); ++iter) {
493 ENetPeer* pCurrentPeer = *iter;
494
495 if((pCurrentPeer->address.host == address.host) && (pCurrentPeer->address.port == address.port)) {
496 PeerData* peerData = static_cast<PeerData*>(pCurrentPeer->data);
497 debugNetwork("Moving '%s' from awaiting connection list to peer list\n", peerData->name.c_str());
498 peerList.push_back(pCurrentPeer);
499 peerData->peerState = PeerData::PeerState::Connected;
500 peerData->timeout = 0;
501 awaitingConnectionList.erase(iter);
502 break;
503 }
504 }
505 }
506
507 } break;
508
509 case NETWORKPACKET_SENDGAMEINFO: {
510 PeerData* peerData = static_cast<PeerData*>(connectPeer->data);
511
512 peerList = awaitingConnectionList;
513 peerData->peerState = PeerData::PeerState::Connected;
514 peerData->timeout = 0;
515 awaitingConnectionList.clear();
516
517 GameInitSettings gameInitSettings(packetStream);
518 ChangeEventList changeEventList(packetStream);
519
520 if(pOnReceiveGameInfo) {
521 pOnReceiveGameInfo(gameInitSettings, changeEventList);
522 }
523 } break;
524
525 case NETWORKPACKET_SENDNAME: {
526 PeerData* peerData = static_cast<PeerData*>(peer->data);
527
528 std::string newName = packetStream.readString();
529 bool bFoundName = false;
530
531 //check if name already exists
532 if(bIsServer) {
533 if(playerName == newName) {
534 enet_peer_disconnect_later(peer, NETWORKDISCONNECT_PLAYER_EXISTS);
535 bFoundName = true;
536 }
537
538 if(bFoundName == false) {
539 for(ENetPeer* pCurrentPeer : peerList) {
540 PeerData* pCurrentPeerData = static_cast<PeerData*>(pCurrentPeer->data);
541 if(pCurrentPeerData->name == newName) {
542 enet_peer_disconnect_later(peer, NETWORKDISCONNECT_PLAYER_EXISTS);
543 bFoundName = true;
544 break;
545 }
546 }
547 }
548
549 if(bFoundName == false) {
550 for(ENetPeer* pAwaitingConnectionPeer : awaitingConnectionList) {
551 PeerData* pAwaitingConnectionPeerData = static_cast<PeerData*>(pAwaitingConnectionPeer->data);
552 if(pAwaitingConnectionPeerData->name == newName) {
553 enet_peer_disconnect_later(peer, NETWORKDISCONNECT_PLAYER_EXISTS);
554 bFoundName = true;
555 break;
556 }
557 }
558 }
559 }
560
561 if(bFoundName == false) {
562 peerData->name = newName;
563
564 if(peerData->peerState == PeerData::PeerState::WaitingForName) {
565 peerData->peerState = PeerData::PeerState::ReadyForOtherPeersToConnect;
566 }
567 }
568 } break;
569
570 case NETWORKPACKET_CHATMESSAGE: {
571 PeerData* peerData = static_cast<PeerData*>(peer->data);
572
573 std::string message = packetStream.readString();
574 if(pOnReceiveChatMessage) {
575 pOnReceiveChatMessage(peerData->name, message);
576 }
577 } break;
578
579 case NETWORKPACKET_CHANGEEVENTLIST: {
580 ChangeEventList changeEventList(packetStream);
581
582 if(pOnReceiveChangeEventList) {
583 pOnReceiveChangeEventList(changeEventList);
584 }
585 } break;
586
587 case NETWORKPACKET_STARTGAME: {
588 Uint32 timeLeft = packetStream.readUint32();
589
590 if(pOnStartGame) {
591 pOnStartGame(timeLeft);
592 }
593 } break;
594
595 case NETWORKPACKET_COMMANDLIST: {
596 PeerData* peerData = static_cast<PeerData*>(peer->data);
597
598 CommandList commandList(packetStream);
599
600 if(pOnReceiveCommandList) {
601 pOnReceiveCommandList(peerData->name, commandList);
602 }
603 } break;
604
605 case NETWORKPACKET_SELECTIONLIST: {
606 PeerData* peerData = static_cast<PeerData*>(peer->data);
607
608 int groupListIndex = packetStream.readSint32();
609 std::set<Uint32> selectedList = packetStream.readUint32Set();
610
611 if(pOnReceiveSelectionList) {
612 pOnReceiveSelectionList(peerData->name, selectedList, groupListIndex);
613 }
614 } break;
615
616 default: {
617 SDL_Log("NetworkManager: Unknown packet type %d", packetType);
618 };
619 }
620
621 } catch (InputStream::eof&) {
622 SDL_Log("NetworkManager: Received packet is too small");
623 return;
624 } catch (std::exception& e) {
625 SDL_Log("NetworkManager: %s", e.what());
626 }
627 }
628
629
sendPacketToHost(ENetPacketOStream & packetStream,int channel)630 void NetworkManager::sendPacketToHost(ENetPacketOStream& packetStream, int channel) {
631 if(connectPeer == nullptr) {
632 SDL_Log("NetworkManager: sendPacketToHost() called on server!");
633 return;
634 }
635
636 ENetPacket* enetPacket = packetStream.getPacket();
637
638 if(enet_peer_send(connectPeer, channel, enetPacket) < 0) {
639 SDL_Log("NetworkManager: Cannot send packet!");
640 }
641 }
642
sendPacketToPeer(ENetPeer * peer,ENetPacketOStream & packetStream,int channel)643 void NetworkManager::sendPacketToPeer(ENetPeer* peer, ENetPacketOStream& packetStream, int channel) {
644 ENetPacket* enetPacket = packetStream.getPacket();
645
646 if(enet_peer_send(peer, channel, enetPacket) < 0) {
647 SDL_Log("NetworkManager: Cannot send packet!");
648 }
649
650 if(enetPacket->referenceCount == 0) {
651 enet_packet_destroy(enetPacket);
652 }
653 }
654
655
sendPacketToAllConnectedPeers(ENetPacketOStream & packetStream,int channel)656 void NetworkManager::sendPacketToAllConnectedPeers(ENetPacketOStream& packetStream, int channel) {
657 ENetPacket* enetPacket = packetStream.getPacket();
658
659 for(ENetPeer* pCurrentPeer : peerList) {
660 if(enet_peer_send(pCurrentPeer, channel, enetPacket) < 0) {
661 SDL_Log("NetworkManager: Cannot send packet!");
662 continue;
663 }
664 }
665
666 if(enetPacket->referenceCount == 0) {
667 enet_packet_destroy(enetPacket);
668 }
669 }
670
671
sendChatMessage(const std::string & message)672 void NetworkManager::sendChatMessage(const std::string& message)
673 {
674 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
675 packetStream.writeUint32(NETWORKPACKET_CHATMESSAGE);
676 packetStream.writeString(message);
677
678 sendPacketToAllConnectedPeers(packetStream);
679 }
680
sendChangeEventList(const ChangeEventList & changeEventList)681 void NetworkManager::sendChangeEventList(const ChangeEventList& changeEventList)
682 {
683 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
684 packetStream.writeUint32(NETWORKPACKET_CHANGEEVENTLIST);
685 changeEventList.save(packetStream);
686
687 if(bIsServer) {
688 sendPacketToAllConnectedPeers(packetStream);
689 } else {
690 sendPacketToHost(packetStream);
691 }
692 }
693
sendStartGame(unsigned int timeLeft)694 void NetworkManager::sendStartGame(unsigned int timeLeft) {
695 for(ENetPeer* pCurrentPeer : peerList) {
696 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
697 packetStream.writeUint32(NETWORKPACKET_STARTGAME);
698
699 packetStream.writeUint32(timeLeft - pCurrentPeer->roundTripTime/2);
700
701 sendPacketToPeer(pCurrentPeer, packetStream);
702 }
703 }
704
sendCommandList(const CommandList & commandList)705 void NetworkManager::sendCommandList(const CommandList& commandList) {
706 ENetPacketOStream packetStream(ENET_PACKET_FLAG_UNSEQUENCED);
707 packetStream.writeUint32(NETWORKPACKET_COMMANDLIST);
708 commandList.save(packetStream);
709
710 sendPacketToAllConnectedPeers(packetStream, 1);
711 }
712
sendSelectedList(const std::set<Uint32> & selectedList,int groupListIndex)713 void NetworkManager::sendSelectedList(const std::set<Uint32>& selectedList, int groupListIndex) {
714 ENetPacketOStream packetStream(ENET_PACKET_FLAG_RELIABLE);
715 packetStream.writeUint32(NETWORKPACKET_SELECTIONLIST);
716 packetStream.writeSint32(groupListIndex);
717 packetStream.writeUint32Set(selectedList);
718
719 sendPacketToAllConnectedPeers(packetStream, 0);
720 }
721
getMaxPeerRoundTripTime()722 int NetworkManager::getMaxPeerRoundTripTime() {
723 int maxPeerRTT = 0;
724
725 for(ENetPeer* pCurrentPeer : peerList) {
726 maxPeerRTT = std::max(maxPeerRTT, (int) (pCurrentPeer->roundTripTime));
727 }
728
729 return maxPeerRTT;
730 }
731
debugNetwork(const char * fmt,...)732 void NetworkManager::debugNetwork(const char* fmt, ...) {
733 if(settings.network.debugNetwork) {
734 va_list args;
735 va_start(args, fmt);
736 vfprintf(stderr, fmt, args);
737 va_end(args);
738 }
739 }
740