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 #ifndef NETWORKMANAGER_H
19 #define NETWORKMANAGER_H
20 
21 #include <Network/ENetPacketIStream.h>
22 #include <Network/ENetPacketOStream.h>
23 #include <Network/ChangeEventList.h>
24 #include <Network/CommandList.h>
25 
26 #include <Network/LANGameFinderAndAnnouncer.h>
27 #include <Network/MetaServerClient.h>
28 
29 #include <misc/string_util.h>
30 
31 #include <enet/enet.h>
32 #include <SDL.h>
33 #include <string>
34 #include <list>
35 #include <functional>
36 #include <stdarg.h>
37 
38 #define NETWORKDISCONNECT_QUIT              1
39 #define NETWORKDISCONNECT_TIMEOUT           2
40 #define NETWORKDISCONNECT_PLAYER_EXISTS     3
41 #define NETWORKDISCONNECT_GAME_FULL         4
42 
43 #define NETWORKPACKET_UNKNOWN               0
44 #define NETWORKPACKET_CONNECT               1
45 #define NETWORKPACKET_DISCONNECT            2
46 #define NETWORKPACKET_PEER_CONNECTED        3
47 #define NETWORKPACKET_SENDGAMEINFO          4
48 #define NETWORKPACKET_SENDNAME              5
49 #define NETWORKPACKET_CHATMESSAGE           6
50 #define NETWORKPACKET_CHANGEEVENTLIST       7
51 #define NETWORKPACKET_STARTGAME             8
52 #define NETWORKPACKET_COMMANDLIST           9
53 #define NETWORKPACKET_SELECTIONLIST         10
54 
55 #define AWAITING_CONNECTION_TIMEOUT     5000
56 
57 class GameInitSettings;
58 
59 class NetworkManager {
60 public:
61     NetworkManager(int port, const std::string& metaserver);
62     NetworkManager(const NetworkManager& o) = delete;
63     ~NetworkManager();
64 
isServer()65     bool isServer() const { return bIsServer; };
66 
67     void startServer(bool bLANServer, const std::string& serverName, const std::string& playerName, GameInitSettings* pGameInitSettings, int numPlayers, int maxPlayers);
68     void updateServer(int numPlayers);
69     void stopServer();
70 
71     void connect(const std::string& hostname, int port, const std::string& playerName);
72     void connect(ENetAddress address, const std::string& playerName);
73 
74     void disconnect();
75 
76     void update();
77 
78     void sendChatMessage(const std::string& message);
79 
80     void sendChangeEventList(const ChangeEventList& changeEventList);
81 
82     void sendStartGame(unsigned int timeLeft);
83 
84     void sendCommandList(const CommandList& commandList);
85 
86     void sendSelectedList(const std::set<Uint32>& selectedList, int groupListIndex = -1);
87 
getConnectedPeers()88     std::list<std::string> getConnectedPeers() const {
89         std::list<std::string> peerNameList;
90 
91         for(const ENetPeer* pPeer : peerList) {
92             PeerData* peerData = static_cast<PeerData*>(pPeer->data);
93             if(peerData != nullptr) {
94                 peerNameList.push_back(peerData->name);
95             }
96         }
97 
98         return peerNameList;
99     }
100 
101     int getMaxPeerRoundTripTime();
102 
getLANGameFinderAndAnnouncer()103     LANGameFinderAndAnnouncer* getLANGameFinderAndAnnouncer() {
104         return pLANGameFinderAndAnnouncer;
105     };
106 
getMetaServerClient()107     MetaServerClient* getMetaServerClient() {
108         return pMetaServerClient;
109     };
110 
111     /**
112         Sets the function that should be called when a chat message is received
113         \param  pOnReceiveChatMessage   function to call on new chat message
114     */
setOnReceiveChatMessage(std::function<void (const std::string &,const std::string &)> pOnReceiveChatMessage)115     inline void setOnReceiveChatMessage(std::function<void (const std::string&, const std::string&)> pOnReceiveChatMessage) {
116         this->pOnReceiveChatMessage = pOnReceiveChatMessage;
117     }
118 
119     /**
120         Sets the function that should be called when game infos are received after connecting to the server.
121         \param  pOnReceiveGameInfo  function to call on receive
122     */
setOnReceiveGameInfo(std::function<void (const GameInitSettings &,const ChangeEventList &)> pOnReceiveGameInfo)123     inline void setOnReceiveGameInfo(std::function<void (const GameInitSettings&, const ChangeEventList&)> pOnReceiveGameInfo) {
124         this->pOnReceiveGameInfo = pOnReceiveGameInfo;
125     }
126 
127 
128     /**
129         Sets the function that should be called when a change event is received.
130         \param  pOnReceiveChangeEventList   function to call on receive
131     */
setOnReceiveChangeEventList(std::function<void (const ChangeEventList &)> pOnReceiveChangeEventList)132     inline void setOnReceiveChangeEventList(std::function<void (const ChangeEventList&)> pOnReceiveChangeEventList) {
133         this->pOnReceiveChangeEventList = pOnReceiveChangeEventList;
134     }
135 
136 
137     /**
138         Sets the function that should be called when a peer disconnects.
139         \param  pOnPeerDisconnected function to call on disconnect
140     */
setOnPeerDisconnected(std::function<void (const std::string &,bool,int)> pOnPeerDisconnected)141     inline void setOnPeerDisconnected(std::function<void (const std::string&, bool, int)> pOnPeerDisconnected) {
142         this->pOnPeerDisconnected = pOnPeerDisconnected;
143     }
144 
145     /**
146         Sets the function that can be used to retreive all house/player changes to get the current state
147         \param  pGetGameInitSettingsCallback    function to call
148     */
setGetChangeEventListForNewPlayerCallback(std::function<ChangeEventList (const std::string &)> pGetChangeEventListForNewPlayerCallback)149     inline void setGetChangeEventListForNewPlayerCallback(std::function<ChangeEventList (const std::string&)> pGetChangeEventListForNewPlayerCallback) {
150         this->pGetChangeEventListForNewPlayerCallback = pGetChangeEventListForNewPlayerCallback;
151     }
152 
153     /**
154         Sets the function that should be called when the game is about to start and the time (in ms) left is received
155         \param  pOnStartGame    function to call on receive
156     */
setOnStartGame(std::function<void (unsigned int)> pOnStartGame)157     inline void setOnStartGame(std::function<void (unsigned int)> pOnStartGame) {
158         this->pOnStartGame = pOnStartGame;
159     }
160 
161     /**
162         Sets the function that should be called when a command list is received.
163         \param  pOnReceiveCommandList   function to call on receive
164     */
setOnReceiveCommandList(std::function<void (const std::string &,const CommandList &)> pOnReceiveCommandList)165     inline void setOnReceiveCommandList(std::function<void (const std::string&, const CommandList&)> pOnReceiveCommandList) {
166         this->pOnReceiveCommandList = pOnReceiveCommandList;
167     }
168 
169     /**
170         Sets the function that should be called when a selection list is received.
171         \param  pOnReceiveSelectionList function to call on receive
172     */
setOnReceiveSelectionList(std::function<void (const std::string &,const std::set<Uint32> &,int)> pOnReceiveSelectionList)173     inline void setOnReceiveSelectionList(std::function<void (const std::string&, const std::set<Uint32>&, int)> pOnReceiveSelectionList) {
174         this->pOnReceiveSelectionList = pOnReceiveSelectionList;
175     }
176 
177 private:
178     static void debugNetwork(PRINTF_FORMAT_STRING const char* fmt, ...) PRINTF_VARARG_FUNC(1);
179 
180     void sendPacketToHost(ENetPacketOStream& packetStream, int channel = 0);
181 
182     void sendPacketToPeer(ENetPeer* peer, ENetPacketOStream& packetStream, int channel = 0);
183 
184     void sendPacketToAllConnectedPeers(ENetPacketOStream& packetStream, int channel = 0);
185 
186     void handlePacket(ENetPeer* peer, ENetPacketIStream& packetStream);
187 
188     class PeerData {
189     public:
190         enum class PeerState {
191             WaitingForConnect,
192             WaitingForName,
193             ReadyForOtherPeersToConnect,
194             WaitingForOtherPeersToConnect,
195             Connected
196         };
197 
198 
PeerData(ENetPeer * pPeer,PeerState peerState)199         PeerData(ENetPeer* pPeer, PeerState peerState)
200          : pPeer(pPeer), peerState(peerState), timeout(0)  {
201         }
202 
203 
204         ENetPeer*               pPeer;
205 
206         PeerState               peerState;
207         Uint32                  timeout;
208 
209         std::string             name;
210         std::list<ENetPeer*>    notYetConnectedPeers;
211     };
212 
213     ENetHost* host = nullptr;
214     bool bIsServer = false;
215     bool bLANServer = false;
216     GameInitSettings* pGameInitSettings = nullptr;
217     int numPlayers = 0;
218     int maxPlayers = 0;
219 
220     std::string playerName;
221 
222     ENetPeer*   connectPeer = nullptr;
223 
224     std::list<ENetPeer*> peerList;
225 
226     std::list<ENetPeer*> awaitingConnectionList;
227 
228     std::function<void (const std::string&, const std::string&)>            pOnReceiveChatMessage;
229     std::function<void (const GameInitSettings&, const ChangeEventList&)>   pOnReceiveGameInfo;
230     std::function<void (const ChangeEventList&)>                            pOnReceiveChangeEventList;
231     std::function<void (const std::string&, bool, int)>                     pOnPeerDisconnected;
232     std::function<ChangeEventList (const std::string&)>                     pGetChangeEventListForNewPlayerCallback;
233     std::function<void (unsigned int)>                                      pOnStartGame;
234     std::function<void (const std::string&, const CommandList&)>            pOnReceiveCommandList;
235     std::function<void (const std::string&, const std::set<Uint32>&, int)>  pOnReceiveSelectionList;
236 
237     LANGameFinderAndAnnouncer*  pLANGameFinderAndAnnouncer = nullptr;
238     MetaServerClient*           pMetaServerClient = nullptr;
239 };
240 
241 #endif // NETWORKMANAGER_H
242