1 /*
2  *  Copyright (C) 2011-2016  OpenDungeons Team
3  *
4  *  This program 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 3 of the License, or
7  *  (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef ODSOCKETCLIENT_H
19 #define ODSOCKETCLIENT_H
20 
21 #include "network/ODPacket.h"
22 
23 #include <SFML/Network.hpp>
24 
25 #include <string>
26 #include <cstdint>
27 #include <fstream>
28 
29 class Player;
30 
31 enum class ServerNotificationType;
32 
33 class ODSocketClient
34 {
35     public:
36         enum ODComStatus
37         {
38             OK, NotReady, Error
39         };
40 
41         enum ODSource
42         {
43             none,
44             network,
45             file
46         };
47 
ODSocketClient()48         ODSocketClient():
49             mSource(ODSource::none),
50             mPlayer(nullptr),
51             mLastTurnAck(-1),
52             mPendingTimestamp(-1)
53         {}
54 
~ODSocketClient()55         virtual ~ODSocketClient()
56         {}
57 
58         // Client initialization
59         bool isConnected();
60 
61         //! \brief Disconnect the client and tell whether to keep the replay file.
62         virtual void disconnect(bool keepReplay = false);
63 
64         /*! \brief This function should be called periodically. It will
65          */
66         void processClientSocketMessages();
67 
getPlayer()68         Player* getPlayer() { return mPlayer; }
setPlayer(Player * player)69         void setPlayer(Player* player) { mPlayer = player; }
getLastTurnAck()70         int64_t getLastTurnAck() { return mLastTurnAck; }
setLastTurnAck(int64_t lastTurnAck)71         void setLastTurnAck(int64_t lastTurnAck) { mLastTurnAck = lastTurnAck; }
getState()72         const std::string& getState() {return mState;}
73         bool isDataAvailable();
getGameTimeMillis()74         int32_t getGameTimeMillis()
75         { return mGameClock.getElapsedTime().asMilliseconds(); }
76 
setState(const std::string & state)77         void setState(const std::string& state) {mState = state;}
78 
getSockClient()79         sf::TcpSocket& getSockClient()
80         { return mSockClient; }
81 
setSource(ODSource source)82         void setSource(ODSource source)
83         { mSource = source; }
84 
85         // Data Transimission
86         /*! \brief Sends a packet through the network
87          * ODPacket should preserve integrity. That means that if an ODSocketClient
88          * sends an ODPacket, the server should receive exactly 1 similar ODPacket (same data,
89          * nothing less, nothing more). It is up to ODSocketClient to do so.
90          */
91         ODComStatus send(ODPacket& s);
92 
93         /*! \brief Receives a packet through the network
94          * ODPacket should preserve integrity. That means that if an ODSocketClient
95          * sends an ODPacket, the server should receive exactly 1 similar ODPacket (same data,
96          * nothing less, nothing more). It is up to ODSocketClient to do so.
97          */
98         ODComStatus recv(ODPacket& s);
99 
100     protected:
101         virtual bool connect(const std::string& host, const int port, uint32_t timeout, const std::string& outputReplayFilename);
102         virtual bool replay(const std::string& filename);
getSource()103         inline ODSource getSource() const
104         { return mSource; }
105 
processMessage(ServerNotificationType cmd,ODPacket & packetReceived)106         virtual bool processMessage(ServerNotificationType cmd, ODPacket& packetReceived)
107         { return false; }
playerDisconnected()108         virtual void playerDisconnected()
109         {}
110 
111     private :
112         bool processOneClientSocketMessage();
113 
114         ODSource mSource;
115         sf::SocketSelector mSockSelector;
116         sf::TcpSocket mSockClient;
117         Player* mPlayer;
118         int64_t mLastTurnAck;
119         std::string mState;
120 
121         sf::Clock mGameClock;
122         std::ifstream mReplayInputStream;
123         std::ofstream mReplayOutputStream;
124         ODPacket mPendingPacket;
125         int32_t mPendingTimestamp;
126 
127         //! \brief the replay filename being written. Used to later optionally delete it
128         //! if asked to.
129         std::string mOutputReplayFilename;
130 };
131 
132 #endif // ODSOCKETCLIENT_H
133 
134