1 /*************************************************************************** 2 * Mechanized Assault and Exploration Reloaded Projectfile * 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 2 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, write to the * 16 * Free Software Foundation, Inc., * 17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 ***************************************************************************/ 19 #ifndef networkH 20 #define networkH 21 #include <SDL_net.h> 22 #include <string> 23 #include <memory> 24 #include "defines.h" 25 #include "utility/thread/mutex.h" 26 27 class cNetMessage; 28 29 #define MAX_CLIENTS 10 // maximal number of clients that can connect to the server 30 #define PACKAGE_LENGTH 1024 // maximal length of a TCP/IP package 31 #define START_CHAR ('\xFF') // start character in netmessages 32 33 // the first client message must be smaller then the first menu message! 34 #define FIRST_SERVER_MESSAGE 10 35 #define FIRST_CLIENT_MESSAGE 100 36 #define FIRST_MENU_MESSAGE 1000 37 38 /** 39 * Callback for the networkthread 40 *@author alzi alias DoctorDeath 41 */ 42 int CallbackHandleNetworkThread (void* arg); 43 44 enum SOCKET_TYPES 45 { 46 FREE_SOCKET, 47 SERVER_SOCKET, 48 CLIENT_SOCKET 49 }; 50 51 enum SOCKET_STATES 52 { 53 STATE_UNUSED, 54 STATE_READY, 55 STATE_NEW, 56 STATE_DYING, 57 STATE_DELETE 58 }; 59 60 //------------------------------------------------------------------------ 61 /** 62 * Structure with data and its length. 63 *@author alzi alias DoctorDeath 64 */ 65 struct sDataBuffer 66 { 67 uint32_t iLength; 68 char data[5 * PACKAGE_LENGTH]; 69 70 char* getWritePointer(); 71 int getFreeSpace() const; 72 void deleteFront (int n); 73 74 /** 75 * Clears the data buffer and sets his length to 0. 76 *@author alzi alias DoctorDeath 77 */ 78 void clear(); 79 }; 80 81 //------------------------------------------------------------------------ 82 /** 83 * Structure for Sockets used by the TCP-Class. 84 *@author alzi alias DoctorDeath 85 */ 86 struct sSocket 87 { 88 sSocket(); 89 ~sSocket(); 90 91 int iType; 92 int iState; 93 94 TCPsocket socket; 95 sDataBuffer buffer; 96 unsigned int messagelength; 97 }; 98 99 /** 100 * Interface called each time a message is received by network. 101 */ 102 class INetMessageReceiver 103 { 104 public: ~INetMessageReceiver()105 virtual ~INetMessageReceiver() {} 106 virtual void pushEvent (std::unique_ptr<cNetMessage> message) = 0; 107 108 // when switching the NetMessageReceiver in cTcp, the new receiver will get 109 // all remaining messages from the old receiver popEvent()110 virtual std::unique_ptr<cNetMessage> popEvent() { throw std::runtime_error("Method not implemented"); }; 111 }; 112 113 //------------------------------------------------------------------------ 114 /** 115 * Class for the handling of events over TCP/IP 116 *@author alzi alias DoctorDeath 117 */ 118 class cTCP 119 { 120 public: 121 /** 122 * Creates the mutexes, initialises some variables 123 * and the sockets and starts the network thread. 124 *@author alzi alias DoctorDeath 125 */ 126 cTCP(); 127 128 /** 129 * Destroys the mutexes, the sockets and exits the network thread. 130 *@author alzi alias DoctorDeath 131 */ 132 ~cTCP(); 133 134 /** 135 * Creates a new server on the port. 136 *@author alzi alias DoctorDeath 137 *return 0 on succes, -1 if an error occurs 138 */ 139 int create (int port); 140 /** 141 * Connects as client to the IP on the port. 142 *@author alzi alias DoctorDeath 143 *return 0 on succes, -1 if an error occurs 144 */ 145 int connect (const std::string& sIP, int port); 146 147 /** 148 * checks whether the given socket is connected 149 */ 150 bool isConnected (unsigned int socketIndex) const; 151 /** 152 * Closes the connection to the socket. 153 *@author alzi alias DoctorDeath 154 *param iClientNumber Number of client/socket 155 * to which the connection should be closed. 156 */ 157 void close (unsigned int iClientNumber); 158 159 /** 160 * Sends data of an given length to the client/socket. 161 *@author alzi alias DoctorDeath 162 *param iClientNumber Number of client/socket 163 * to which the data should be send. 164 *param iLength Length of data to be send. 165 *param buffer buffer with data to be send. 166 *return 0 on succes, -1 if an error occurs 167 */ 168 int sendTo (unsigned int iClientNumber, unsigned int iLength, const char* buffer); 169 /** 170 * Sends the data to all sockets to which this machine is connected. 171 *@author alzi alias DoctorDeath 172 *param iLength Length of data to be send. 173 *param buffer buffer with data to be send. 174 *return 0 on succes, -1 if an error occurs 175 */ 176 int send (unsigned int iLength, const char* buffer); 177 178 /** 179 * Set message receiver. 180 * @author joris alias Jarod 181 */ 182 void setMessageReceiver (INetMessageReceiver* messageReceiver); 183 184 /** 185 * Gets the number of currently connected sockets. 186 *@author alzi alias DoctorDeath 187 *return Number of sockets. 188 */ 189 int getSocketCount() const; 190 /** 191 * Gets the status of the connection. 192 *@author alzi alias DoctorDeath 193 *return 1 if connected, 0 if not. 194 */ 195 int getConnectionStatus() const; 196 /** 197 * looks if this machine is the host. 198 *@author alzi alias DoctorDeath 199 *return true if is host, false if not. 200 */ 201 bool isHost() const; 202 203 /** 204 * Thread function which handles new incoming connections and data. 205 *@author alzi alias DoctorDeath 206 */ 207 void HandleNetworkThread(); 208 209 private: 210 /** 211 * Searchs for the first unused socket and allocates memory 212 * for a new one if there are no free sockets. 213 *@author alzi alias DoctorDeath 214 *@return index of found socket 215 */ 216 int getFreeSocket(); 217 /** 218 * Deletes the socket, frees its memory 219 * and sorts the rest sockets in the list. 220 *@author alzi alias DoctorDeath 221 */ 222 void deleteSocket (int socketIndex); 223 224 void pushEvent (std::unique_ptr<cNetMessage> message); 225 226 void pushEventTCP_Close (unsigned int socketIndex); 227 228 void HandleNetworkThread_STATE_NEW (unsigned int socketIndex); 229 void HandleNetworkThread_SERVER (unsigned int socketIndex); 230 void HandleNetworkThread_CLIENT (unsigned int socketIndex); 231 void HandleNetworkThread_CLIENT_pushReadyMessage (unsigned int socketIndex); 232 233 private: 234 cMutex TCPMutex; 235 236 SDL_Thread* TCPHandleThread; 237 volatile bool bExit; 238 bool bHost; 239 240 unsigned int iLast_Socket; 241 sSocket Sockets[MAX_CLIENTS]; 242 SDLNet_SocketSet SocketSet; 243 IPaddress ipaddr; 244 INetMessageReceiver* messageReceiver; 245 }; 246 247 #endif // networkH 248