1 /******************************************************************************
2  *  Warmux is a convivial mass murder game.
3  *  Copyright (C) 2001-2011 Warmux Team.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  ******************************************************************************
19  * Socket abstraction
20  *****************************************************************************/
21 
22 #ifndef WARMUX_SOCKET_H
23 #define WARMUX_SOCKET_H
24 //-----------------------------------------------------------------------------
25 #include <string>
26 #include <SDL_net.h>
27 #include <list>
28 #include <WARMUX_network.h>
29 #include <WARMUX_types.h>
30 //-----------------------------------------------------------------------------
31 
32 class WSocket;
33 
34 class WSocketSet
35 {
36   friend class WSocket;
37 
38 private:
39   uint max_nb_sockets;
40   SDLNet_SocketSet socket_set;
41   std::list<WSocket*> sockets;
42   SDL_mutex* lock;
43 
44   void Lock();
45   void UnLock();
46 
47   WSocketSet(uint max_sockets, SDLNet_SocketSet socket_set);
48 
49 public:
50   // may return NULL in case of problem
51   static WSocketSet* GetSocketSet(uint max_sockets);
52 
53   ~WSocketSet();
54   bool AddSocket(WSocket* socket);
55   void RemoveSocket(WSocket* socket);
56 
57   int CheckActivity(int timeout);
58   uint MaxNbSockets() const;
59   uint NbSockets() const;
60 
61   std::list<WSocket*>& GetSockets();
62 };
63 
64 class WSocket
65 {
66   friend class WSocketSet;
67 
68 private:
69   TCPsocket socket;
70   WSocketSet* socket_set;
71   SDL_mutex* lock;
72 
73   bool using_tmp_socket_set;
74 
75   char *m_packet;
76   uint32_t m_packet_size;
77   uint32_t m_received;
78 
79   bool address_field_valid;
80   std::string address;
81 
82   bool AddToSocketSet(WSocketSet* _socket_set);
83   void RemoveFromSocketSet();
84   uint32_t ComputeCRC(const void* data, size_t len);
85 
86   bool NbBytesAvailable(size_t& nb_bytes);
87   bool ReceiveBuffer_NoLock(void* data, size_t len);
88   bool ReceiveBuffer(void* data, size_t len);
89 
90 public:
91   WSocket(TCPsocket _socket, WSocketSet* _socket_set);
92   WSocket(TCPsocket _socket);
93   WSocket();
94   ~WSocket();
95 
96   void Lock();
97   void UnLock();
98 
99   // For clients
100   connection_state_t ConnectTo(const std::string &host, const int &port);
101 
102   // For servers
103   bool AcceptIncoming(const int &port);
104   WSocket* LookForClient();
105 
106   void Disconnect();
IsConnected()107   bool IsConnected() const { return socket != NULL; }
108 
109   bool AddToTmpSocketSet();
110   void RemoveFromTmpSocketSet();
111 
112   const std::string GetAddress();
113   bool IsReady(int timeout = 0) const;
114   bool IsReady(int timeout, bool force_check_activity) const;
115 
116   bool SendInt_NoLock(const int& nbr);
117   bool SendInt(const int& nbr);
118 
119   bool SendStr_NoLock(const std::string &str);
120   bool SendStr(const std::string &str);
121 
122   bool SendBuffer_NoLock(const void* data, size_t len);
123   bool SendBuffer(const void* data, size_t len);
124 
125   bool ReceiveInt_NoLock(int& nbr);
126   bool ReceiveInt(int& nbr);
127 
128   bool ReceiveStr_NoLock(std::string &_str, size_t maxlen);
129   bool ReceiveStr(std::string &_str, size_t maxlen);
130 
131   // ReceivePacket may return true with *data = NULL and len = 0
132   // That means that client is still valid BUT there are not enough data CURRENTLY
133   bool ReceivePacket(char** data, size_t* len);
134 };
135 
136 //-----------------------------------------------------------------------------
137 #endif
138