ManaPlus
sdltcpnet.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2013-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "logger.h"
23 
24 #if defined __linux__ || defined __linux
25 
26 #include <sys/socket.h>
27 
28 #if defined(M_TCPOK) && !defined(ANDROID)
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include <linux/tcp.h>
32 #else // defined(M_TCPOK) && !defined(ANDROID)
33 #include <netinet/in.h>
34 #include <netinet/tcp.h>
35 #include <netdb.h>
36 #include <netinet/tcp.h>
37 // Use linear timeouts for thin streams
38 #define TCP_THIN_LINEAR_TIMEOUTS 16
39 // Fast retrans. after 1 dupack
40 #define TCP_THIN_DUPACK 17
41 #endif // defined(M_TCPOK) && !defined(ANDROID)
42 
43 #endif // defined __linux__ || defined __linux
44 
45 PRAGMACLANG6GCC(GCC diagnostic push)
46 PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
47 #include "net/sdltcpnet.h"
48 PRAGMACLANG6GCC(GCC diagnostic pop)
49 
50 #include "debug.h"
51 
52 #if !defined(__native_client__) \
53  && (defined(TCP_THIN_LINEAR_TIMEOUTS) \
54  || defined(TCP_THIN_DUPACK))
55 // because actual struct is hidden in SDL_net we reinroducing it here
56 struct TCPsocketHack final
57 {
58  TCPsocketHack() :
59  ready(0),
60  channel(0),
61  remoteAddress(),
62  localAddress(),
63  sflag()
64  { }
65 
66  A_DELETE_COPY(TCPsocketHack)
67 
68  int ready;
69  int channel;
70  IPaddress remoteAddress;
71  IPaddress localAddress;
72  int sflag;
73 };
74 #endif // !defined(__native_client__)
75  // && (defined(TCP_THIN_LINEAR_TIMEOUTS)
76  // || defined(TCP_THIN_DUPACK))
77 
79 {
80  SDLNet_Init();
81 }
82 
84 {
85  SDLNet_Quit();
86 }
87 
89 {
90  SDLNet_TCP_Close(socket);
91 }
92 
93 int TcpNet::send(const TcpNet::Socket sock, const void *const data,
94  const int len)
95 {
96  return SDLNet_TCP_Send(sock, data, len);
97 }
98 
99 const char *TcpNet::getError()
100 {
101  return SDL_GetError();
102 }
103 
104 int TcpNet::resolveHost(IPaddress *const address, const char *const host,
105  const Uint16 port)
106 {
107  return SDLNet_ResolveHost(address, host, port);
108 }
109 
110 TcpNet::Socket TcpNet::open(IPaddress *const ip)
111 {
112  const TcpNet::Socket sock = SDLNet_TCP_Open(ip);
113 #if !defined(__native_client__) \
114  && (defined(TCP_THIN_LINEAR_TIMEOUTS) \
115  || defined(TCP_THIN_DUPACK))
116  if ((sock != nullptr) && (ip != nullptr))
117  {
118  const TCPsocketHack *const hack
119  = reinterpret_cast<const TCPsocketHack *>(sock);
120  // here we using some magic to compare TCPsocket and own padding
121  // because actual struct TCPsocket not in headers
122  if (hack != nullptr)
123  {
124  const IPaddress &addr = hack->remoteAddress;
125  if (addr.host == ip->host && addr.port == ip->port)
126  {
127  const int val = 1;
128 #ifdef TCP_THIN_LINEAR_TIMEOUTS
129  if (setsockopt(hack->channel, IPPROTO_TCP,
130  TCP_THIN_LINEAR_TIMEOUTS, &val, sizeof(val)) != 0)
131  {
132  logger->log_r("error on set TCP_THIN_LINEAR_TIMEOUTS");
133  }
134 #endif // TCP_THIN_LINEAR_TIMEOUTS
135 #ifdef TCP_THIN_DUPACK
136  if (setsockopt(hack->channel, IPPROTO_TCP,
137  TCP_THIN_DUPACK, &val, sizeof(val)) != 0)
138  {
139  logger->log_r("error on set TCP_THIN_DUPACK");
140  }
141 #endif // TCP_THIN_DUPACK
142  }
143  }
144  }
145 #endif // !defined(__native_client__)
146  // && (defined(TCP_THIN_LINEAR_TIMEOUTS)
147  // || defined(TCP_THIN_DUPACK))
148  return sock;
149 }
150 
152 {
153  return SDLNet_AllocSocketSet(maxsockets);
154 }
155 
157 {
158  PRAGMACLANG6GCC(GCC diagnostic push)
159  PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
160  return SDLNet_TCP_AddSocket(set, sock);
161  PRAGMACLANG6GCC(GCC diagnostic pop)
162 }
163 
165 {
166  PRAGMACLANG5(GCC diagnostic push)
167  PRAGMACLANG5(GCC diagnostic ignored "-Wzero-as-null-pointer-constant")
168  PRAGMACLANG6GCC(GCC diagnostic push)
169  PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
170  return SDLNet_SocketReady(sock);
171  PRAGMACLANG6GCC(GCC diagnostic pop)
172  PRAGMACLANG5(GCC diagnostic pop)
173 }
174 
175 int TcpNet::checkSockets(const TcpNet::SocketSet set, const Uint32 timeout)
176 {
177  return SDLNet_CheckSockets(set, timeout);
178 }
179 
180 int TcpNet::recv(const TcpNet::Socket sock, void *const data, const int maxlen)
181 {
182  return SDLNet_TCP_Recv(sock, data, maxlen);
183 }
184 
186 {
187  PRAGMACLANG6GCC(GCC diagnostic push)
188  PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
189  return SDLNet_TCP_DelSocket(set, sock);
190  PRAGMACLANG6GCC(GCC diagnostic pop)
191 }
192 
194 {
195  SDLNet_FreeSocketSet(set);
196 }
197 
199 {
200  return SDLNet_TCP_Accept(sock);
201 }
void log_r(const char *const log_text,...)
Definition: logger.cpp:365
#define final
Definition: localconsts.h:46
#define A_DELETE_COPY(func)
Definition: localconsts.h:53
#define PRAGMACLANG5(str)
Definition: localconsts.h:230
#define PRAGMACLANG6GCC(str)
Definition: localconsts.h:240
Logger * logger
Definition: logger.cpp:89
uint32_t data
bool hack(InputEvent &event)
Definition: commands.cpp:76
int delSocket(const TcpNet::SocketSet set, const TcpNet::Socket sock)
Definition: sdltcpnet.cpp:185
::SDLNet_SocketSet SocketSet
Definition: sdltcpnet.h:37
int send(const TcpNet::Socket sock, const void *const data, const int len)
Definition: sdltcpnet.cpp:93
int resolveHost(IPaddress *const address, const char *const host, const Uint16 port)
Definition: sdltcpnet.cpp:104
void quit()
Definition: sdltcpnet.cpp:83
void freeSocketSet(const TcpNet::SocketSet set)
Definition: sdltcpnet.cpp:193
int socketReady(const TcpNet::Socket sock)
Definition: sdltcpnet.cpp:164
TcpNet::Socket open(IPaddress *const ip)
Definition: sdltcpnet.cpp:110
void init()
Definition: sdltcpnet.cpp:78
::TCPsocket Socket
Definition: sdltcpnet.h:38
int addSocket(const TcpNet::SocketSet set, const TcpNet::Socket sock)
Definition: sdltcpnet.cpp:156
SocketSet allocSocketSet(const int maxsockets)
Definition: sdltcpnet.cpp:151
const char * getError()
Definition: sdltcpnet.cpp:99
int checkSockets(const TcpNet::SocketSet set, const Uint32 timeout)
Definition: sdltcpnet.cpp:175
void closeSocket(const TcpNet::Socket socket)
Definition: sdltcpnet.cpp:88
int recv(const TcpNet::Socket sock, void *const data, const int maxlen)
Definition: sdltcpnet.cpp:180
TcpNet::Socket accept(const TcpNet::Socket sock)
Definition: sdltcpnet.cpp:198