1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2015 Joerg Henrichs
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the License, or (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 #include "network/network_config.hpp"
20 #include "config/stk_config.hpp"
21 #include "config/user_config.hpp"
22 #include "input/device_manager.hpp"
23 #include "modes/world.hpp"
24 #include "network/network.hpp"
25 #include "network/network_string.hpp"
26 #include "network/rewind_manager.hpp"
27 #include "network/server_config.hpp"
28 #include "network/socket_address.hpp"
29 #include "network/stk_host.hpp"
30 #include "network/stk_ipv6.hpp"
31 #include "online/xml_request.hpp"
32 #include "states_screens/main_menu_screen.hpp"
33 #include "states_screens/online/networking_lobby.hpp"
34 #include "states_screens/online/online_lan.hpp"
35 #include "states_screens/online/online_profile_servers.hpp"
36 #include "states_screens/online/online_screen.hpp"
37 #include "states_screens/state_manager.hpp"
38 #include "utils/string_utils.hpp"
39 #include "utils/time.hpp"
40 #include "utils/utf8/unchecked.h"
41
42 #ifdef WIN32
43 # include <windns.h>
44 # include <ws2tcpip.h>
45 #ifndef __MINGW32__
46 # pragma comment(lib, "dnsapi.lib")
47 #endif
48 #else
49 # include <arpa/nameser.h>
50 # include <arpa/nameser_compat.h>
51 # include <netdb.h>
52 # include <netinet/in.h>
53 # include <resolv.h>
54 #endif
55
56 #ifdef ANDROID
57 #include <jni.h>
58 #include "SDL_system.h"
59
60 std::vector<std::pair<std::string, int> >* g_list = NULL;
61
62 #define MAKE_ADD_DNS_SRV_RECORD_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_SuperTuxKartActivity_addDNSSrvRecords(JNIEnv* env, jobject this_obj, jstring name, jint weight)
63 #define ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(PKG_NAME) MAKE_ADD_DNS_SRV_RECORD_CALLBACK(PKG_NAME)
64
65 extern "C"
ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)66 ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
67 {
68 if (!g_list || name == NULL)
69 return;
70 const uint16_t* utf16_text =
71 (const uint16_t*)env->GetStringChars(name, NULL);
72 if (utf16_text == NULL)
73 return;
74 const size_t str_len = env->GetStringLength(name);
75 std::string tmp;
76 utf8::unchecked::utf16to8(
77 utf16_text, utf16_text + str_len, std::back_inserter(tmp));
78 g_list->emplace_back(tmp, weight);
79 env->ReleaseStringChars(name, utf16_text);
80 }
81
82 #endif
83
84 NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
85 bool NetworkConfig::m_system_ipv4 = false;
86 bool NetworkConfig::m_system_ipv6 = false;
87
88 /** Initialize detection of system IPv4 or IPv6 support. */
initSystemIP()89 void NetworkConfig::initSystemIP()
90 {
91 // It calls WSAStartup in enet, for the rest new Network function we don't
92 // need this because request manager runs curl_global_init which will do
93 // WSAStartup too
94 if (enet_initialize() != 0)
95 {
96 Log::error("NetworkConfig", "Could not initialize enet.");
97 return;
98 }
99 ENetAddress eaddr = {};
100 setIPv6Socket(0);
101 auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
102 setIPv6Socket(1);
103 auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
104 setIPv6Socket(0);
105 if (ipv4 && ipv4->getENetHost())
106 m_system_ipv4 = true;
107 if (ipv6 && ipv6->getENetHost())
108 m_system_ipv6 = true;
109 // If any 1 of them is missing set default network setting accordingly
110 if (!m_system_ipv4)
111 {
112 Log::warn("NetworkConfig", "System doesn't support IPv4");
113 if (m_system_ipv6)
114 {
115 UserConfigParams::m_ipv6_lan = true;
116 ServerConfig::m_ipv6_connection = true;
117 }
118 }
119 else if (!m_system_ipv6)
120 {
121 Log::warn("NetworkConfig", "System doesn't support IPv6");
122 UserConfigParams::m_ipv6_lan = false;
123 ServerConfig::m_ipv6_connection = false;
124 }
125 enet_deinitialize();
126 } // initSystemIP
127
128 /** \class NetworkConfig
129 * This class is the interface between STK and the online code, particularly
130 * STKHost. It stores all online related properties (e.g. if this is a server
131 * or a host, name of the server, maximum number of players, ip address, ...).
132 * They can either be set from the GUI code, or via the command line (for a
133 * stand-alone server).
134 * When STKHost is created, it takes all necessary information from this
135 * instance.
136 */
137 // ============================================================================
138 /** Constructor.
139 */
NetworkConfig()140 NetworkConfig::NetworkConfig()
141 {
142 m_ip_type = IP_NONE;
143 m_network_type = NETWORK_NONE;
144 m_auto_connect = false;
145 m_is_server = false;
146 m_is_public_server = false;
147 m_done_adding_network_players = false;
148 m_cur_user_id = 0;
149 m_cur_user_token = "";
150 m_client_port = 0;
151 m_joined_server_version = 0;
152 m_network_ai_instance = false;
153 m_state_frequency = 10;
154 m_nat64_prefix_data.fill(-1);
155 m_num_fixed_ai = 0;
156 m_tux_hitbox_addon = false;
157 } // NetworkConfig
158
159 // ----------------------------------------------------------------------------
160 /** Separated from constructor because this needs to be run after user config
161 * is load.
162 */
initClientPort()163 void NetworkConfig::initClientPort()
164 {
165 m_client_port = UserConfigParams::m_random_client_port ?
166 0 : stk_config->m_client_port;
167 } // initClientPort
168
169 // ----------------------------------------------------------------------------
170 /** Set that this is not a networked game.
171 */
unsetNetworking()172 void NetworkConfig::unsetNetworking()
173 {
174 clearServerCapabilities();
175 m_network_type = NETWORK_NONE;
176 ServerConfig::m_private_server_password = "";
177 } // unsetNetworking
178
179 // ----------------------------------------------------------------------------
setUserDetails(std::shared_ptr<Online::XMLRequest> r,const std::string & name)180 void NetworkConfig::setUserDetails(std::shared_ptr<Online::XMLRequest> r,
181 const std::string& name)
182 {
183 assert(!m_cur_user_token.empty());
184 r->setApiURL(Online::API::USER_PATH, name);
185 r->addParameter("userid", m_cur_user_id);
186 r->addParameter("token", m_cur_user_token);
187 } // setUserDetails
188
189 // ----------------------------------------------------------------------------
setServerDetails(std::shared_ptr<Online::XMLRequest> r,const std::string & name)190 void NetworkConfig::setServerDetails(std::shared_ptr<Online::XMLRequest> r,
191 const std::string& name)
192 {
193 assert(!m_cur_user_token.empty());
194 r->setApiURL(Online::API::SERVER_PATH, name);
195 r->addParameter("userid", m_cur_user_id);
196 r->addParameter("token", m_cur_user_token);
197 } // setServerDetails
198
199 // ----------------------------------------------------------------------------
200 std::vector<GUIEngine::Screen*>
getResetScreens(bool lobby) const201 NetworkConfig::getResetScreens(bool lobby) const
202 {
203 if (lobby)
204 {
205 if (isWAN())
206 {
207 return
208 {
209 MainMenuScreen::getInstance(),
210 OnlineScreen::getInstance(),
211 OnlineProfileServers::getInstance(),
212 NetworkingLobby::getInstance(),
213 nullptr
214 };
215 }
216 else
217 {
218 return
219 {
220 MainMenuScreen::getInstance(),
221 OnlineScreen::getInstance(),
222 OnlineLanScreen::getInstance(),
223 NetworkingLobby::getInstance(),
224 nullptr
225 };
226 }
227 }
228 else
229 {
230 if (isWAN())
231 {
232 return
233 {
234 MainMenuScreen::getInstance(),
235 OnlineScreen::getInstance(),
236 OnlineProfileServers::getInstance(),
237 nullptr
238 };
239 }
240 else
241 {
242 return
243 {
244 MainMenuScreen::getInstance(),
245 OnlineScreen::getInstance(),
246 OnlineLanScreen::getInstance(),
247 nullptr
248 };
249 }
250 }
251 } // getResetScreens
252
253 // ----------------------------------------------------------------------------
254 /** Called before (re)starting network race, must be used before adding
255 * split screen players. */
clearActivePlayersForClient() const256 void NetworkConfig::clearActivePlayersForClient() const
257 {
258 if (!isClient())
259 return;
260 StateManager::get()->resetActivePlayers();
261 if (input_manager)
262 {
263 input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
264 input_manager->getDeviceManager()->setSinglePlayer(NULL);
265 input_manager->setMasterPlayerOnly(false);
266 input_manager->getDeviceManager()->clearLatestUsedDevice();
267 }
268 } // clearActivePlayersForClient
269
270 // ----------------------------------------------------------------------------
271 /** True when client needs to round the bodies phyiscal info for current
272 * ticks, server doesn't as it will be done implictly in save state. */
roundValuesNow() const273 bool NetworkConfig::roundValuesNow() const
274 {
275 return isNetworking() && !isServer() && RewindManager::get()
276 ->shouldSaveState(World::getWorld()->getTicksSinceStart());
277 } // roundValuesNow
278
279 // ----------------------------------------------------------------------------
280 /** Use stun servers to detect current ip type.
281 */
detectIPType()282 void NetworkConfig::detectIPType()
283 {
284 if (UserConfigParams::m_default_ip_type != IP_NONE)
285 {
286 int ip_type = UserConfigParams::m_default_ip_type;
287 m_nat64_prefix.clear();
288 m_nat64_prefix_data.fill(-1);
289 m_ip_type.store((IPType)ip_type);
290 return;
291 }
292 #ifdef ENABLE_IPV6
293 if (!m_system_ipv4 || !m_system_ipv6)
294 {
295 // Don't test connection if only IPv4 or IPv6 system support
296 if (m_system_ipv4)
297 m_ip_type.store(IP_V4);
298 else if (m_system_ipv6)
299 m_ip_type.store(IP_V6);
300 return;
301 }
302
303 ENetAddress eaddr = {};
304 // We don't need to result of stun, just to check if the socket can be
305 // used in ipv4 or ipv6
306 uint8_t stun_tansaction_id[16] = {};
307 BareNetworkString s = STKHost::getStunRequest(stun_tansaction_id);
308 setIPv6Socket(0);
309 auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
310 setIPv6Socket(1);
311 auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
312 setIPv6Socket(0);
313
314 // This should only happen if system doesn't support all socket types
315 if (!ipv4->getENetHost() || !ipv6->getENetHost())
316 return;
317
318 auto& stunv4_map = UserConfigParams::m_stun_servers_v4;
319 for (auto& s : getStunList(true/*ipv4*/))
320 {
321 if (s.second == 0)
322 stunv4_map.erase(s.first);
323 else if (stunv4_map.find(s.first) == stunv4_map.end())
324 stunv4_map[s.first] = 0;
325 }
326 if (stunv4_map.empty())
327 return;
328 auto ipv4_it = stunv4_map.begin();
329 int adv = StkTime::getMonoTimeMs() % stunv4_map.size();
330 std::advance(ipv4_it, adv);
331
332 auto& stunv6_map = UserConfigParams::m_stun_servers;
333 for (auto& s : getStunList(false/*ipv4*/))
334 {
335 if (s.second == 0)
336 stunv6_map.erase(s.first);
337 else if (stunv6_map.find(s.first) == stunv6_map.end())
338 stunv6_map[s.first] = 0;
339 }
340 if (stunv6_map.empty())
341 return;
342 auto ipv6_it = stunv6_map.begin();
343 adv = StkTime::getMonoTimeMs() % stunv6_map.size();
344 std::advance(ipv6_it, adv);
345
346 SocketAddress::g_ignore_error_message = true;
347 SocketAddress stun_v4(ipv4_it->first, 0/*port specified in addr*/,
348 AF_INET);
349 bool sent_ipv4 = false;
350 if (!stun_v4.isUnset() && stun_v4.getFamily() == AF_INET)
351 {
352 sendto(ipv4->getENetHost()->socket, s.getData(), s.size(), 0,
353 stun_v4.getSockaddr(), stun_v4.getSocklen());
354 sent_ipv4 = true;
355 }
356
357 SocketAddress stun_v6(ipv6_it->first, 0/*port specified in addr*/,
358 AF_INET6);
359 bool sent_ipv6 = false;
360 if (!stun_v6.isUnset() && stun_v6.getFamily() == AF_INET6)
361 {
362 sendto(ipv6->getENetHost()->socket, s.getData(), s.size(), 0,
363 stun_v6.getSockaddr(), stun_v6.getSocklen());
364 sent_ipv6 = true;
365 }
366 SocketAddress::g_ignore_error_message = false;
367
368 bool has_ipv4 = false;
369 bool has_ipv6 = false;
370
371 ENetSocketSet socket_set;
372 ENET_SOCKETSET_EMPTY(socket_set);
373 ENET_SOCKETSET_ADD(socket_set, ipv4->getENetHost()->socket);
374 if (sent_ipv4)
375 {
376 // 1.5 second timeout
377 has_ipv4 = enet_socketset_select(
378 ipv4->getENetHost()->socket, &socket_set, NULL, 1500) > 0;
379 }
380
381 ENET_SOCKETSET_EMPTY(socket_set);
382 ENET_SOCKETSET_ADD(socket_set, ipv6->getENetHost()->socket);
383 if (sent_ipv6 && enet_socketset_select(
384 ipv6->getENetHost()->socket, &socket_set, NULL, 1500) > 0)
385 {
386 has_ipv6 = true;
387 // For non dual stack IPv6 we try to get a NAT64 prefix to connect
388 // to IPv4 only servers
389 if (!has_ipv4)
390 {
391 // Detect NAT64 prefix by using ipv4only.arpa (RFC 7050)
392 m_nat64_prefix.clear();
393 m_nat64_prefix_data.fill(-1);
394 SocketAddress nat64("ipv4only.arpa", 0/*port*/, AF_INET6);
395 if (nat64.getFamily() == AF_INET6)
396 {
397 // Remove last 4 bytes which is IPv4 format
398 struct sockaddr_in6* in6 =
399 (struct sockaddr_in6*)nat64.getSockaddr();
400 uint8_t* byte = &(in6->sin6_addr.s6_addr[0]);
401 byte[12] = 0;
402 byte[13] = 0;
403 byte[14] = 0;
404 byte[15] = 0;
405 m_nat64_prefix_data[0] = ((uint32_t)(byte[0]) << 8) | byte[1];
406 m_nat64_prefix_data[1] = ((uint32_t)(byte[2]) << 8) | byte[3];
407 m_nat64_prefix_data[2] = ((uint32_t)(byte[4]) << 8) | byte[5];
408 m_nat64_prefix_data[3] = ((uint32_t)(byte[6]) << 8) | byte[7];
409 m_nat64_prefix_data[4] = ((uint32_t)(byte[8]) << 8) | byte[9];
410 m_nat64_prefix_data[5] = ((uint32_t)(byte[10]) << 8) | byte[11];
411 m_nat64_prefix_data[6] = 0;
412 m_nat64_prefix_data[7] = 0;
413 m_nat64_prefix = getIPV6ReadableFromIn6(in6);
414 }
415 }
416 }
417
418 if (has_ipv4 && has_ipv6)
419 {
420 Log::info("NetworkConfig", "System is dual stack network.");
421 m_nat64_prefix.clear();
422 m_nat64_prefix_data.fill(-1);
423 m_ip_type = IP_DUAL_STACK;
424 }
425 else if (has_ipv4)
426 {
427 Log::info("NetworkConfig", "System is IPv4 only.");
428 m_nat64_prefix.clear();
429 m_nat64_prefix_data.fill(-1);
430 m_ip_type = IP_V4;
431 }
432 else if (has_ipv6)
433 {
434 Log::info("NetworkConfig", "System is IPv6 only.");
435 if (m_nat64_prefix.empty())
436 m_ip_type = IP_V6;
437 }
438 else
439 {
440 Log::error("NetworkConfig", "Cannot detect network type using stun, "
441 "using previously detected type: %d", (int)m_ip_type.load());
442 }
443 if (has_ipv6)
444 {
445 if (!has_ipv4 && m_nat64_prefix.empty())
446 {
447 Log::warn("NetworkConfig", "NAT64 prefix not found, "
448 "you may not be able to join any IPv4 only servers.");
449 }
450 if (!m_nat64_prefix.empty())
451 {
452 m_ip_type = IP_V6_NAT64;
453 Log::info("NetworkConfig",
454 "NAT64 prefix is %s.", m_nat64_prefix.c_str());
455 }
456 }
457 #else
458 m_ip_type = IP_V4;
459 #endif
460 } // detectIPType
461
462 // ----------------------------------------------------------------------------
fillStunList(std::vector<std::pair<std::string,int>> * l,const std::string & dns)463 void NetworkConfig::fillStunList(std::vector<std::pair<std::string, int> >* l,
464 const std::string& dns)
465 {
466 #if defined(WIN32)
467 PDNS_RECORD dns_record = NULL;
468 DnsQuery(StringUtils::utf8ToWide(dns).c_str(), DNS_TYPE_SRV,
469 DNS_QUERY_STANDARD, NULL, &dns_record, NULL);
470 if (dns_record)
471 {
472 for (PDNS_RECORD curr = dns_record; curr; curr = curr->pNext)
473 {
474 if (curr->wType == DNS_TYPE_SRV)
475 {
476 l->emplace_back(
477 StringUtils::wideToUtf8(curr->Data.SRV.pNameTarget) +
478 ":" + StringUtils::toString(curr->Data.SRV.wPort),
479 curr->Data.SRV.wWeight);
480 }
481 }
482 DnsRecordListFree(dns_record, DnsFreeRecordListDeep);
483 }
484
485 #elif defined(ANDROID)
486 JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
487 if (env == NULL)
488 {
489 Log::error("NetworkConfig",
490 "getDNSSrvRecords unable to SDL_AndroidGetJNIEnv.");
491 return;
492 }
493
494 jobject native_activity = (jobject)SDL_AndroidGetActivity();
495 if (native_activity == NULL)
496 {
497 Log::error("NetworkConfig",
498 "getDNSSrvRecords unable to SDL_AndroidGetActivity.");
499 return;
500 }
501
502 jclass class_native_activity = env->GetObjectClass(native_activity);
503 if (class_native_activity == NULL)
504 {
505 Log::error("NetworkConfig",
506 "getDNSSrvRecords unable to find object class.");
507 env->DeleteLocalRef(native_activity);
508 return;
509 }
510
511 jmethodID method_id = env->GetMethodID(class_native_activity,
512 "getDNSSrvRecords", "(Ljava/lang/String;)V");
513
514 if (method_id == NULL)
515 {
516 Log::error("NetworkConfig",
517 "getDNSSrvRecords unable to find method id.");
518 env->DeleteLocalRef(class_native_activity);
519 env->DeleteLocalRef(native_activity);
520 return;
521 }
522
523 std::vector<uint16_t> jstr_data;
524 utf8::unchecked::utf8to16(
525 dns.c_str(), dns.c_str() + dns.size(), std::back_inserter(jstr_data));
526 jstring text =
527 env->NewString((const jchar*)jstr_data.data(), jstr_data.size());
528 if (text == NULL)
529 {
530 Log::error("NetworkConfig",
531 "Failed to create text for domain name.");
532 env->DeleteLocalRef(class_native_activity);
533 env->DeleteLocalRef(native_activity);
534 return;
535 }
536
537 g_list = l;
538 env->CallVoidMethod(native_activity, method_id, text);
539 env->DeleteLocalRef(text);
540 env->DeleteLocalRef(class_native_activity);
541 env->DeleteLocalRef(native_activity);
542 g_list = NULL;
543
544 #elif !defined(__CYGWIN__)
545 #define SRV_WEIGHT (RRFIXEDSZ+2)
546 #define SRV_PORT (RRFIXEDSZ+4)
547 #define SRV_SERVER (RRFIXEDSZ+6)
548 #define SRV_FIXEDSZ (RRFIXEDSZ+6)
549
550 unsigned char response[512] = {};
551 int response_len = res_query(dns.c_str(), C_IN, T_SRV, response, 512);
552 if (response_len > 0)
553 {
554 HEADER* header = (HEADER*)response;
555 unsigned char* start = response + NS_HFIXEDSZ;
556
557 if ((header->tc) || (response_len < NS_HFIXEDSZ))
558 return;
559
560 if (header->rcode >= 1 && header->rcode <= 5)
561 return;
562
563 int ancount = ntohs(header->ancount);
564 int qdcount = ntohs(header->qdcount);
565 if (ancount == 0)
566 return;
567
568 if (ancount > NS_PACKETSZ)
569 return;
570
571 for (int count = qdcount; count > 0; count--)
572 {
573 int str_len = dn_skipname(start, response + response_len);
574 start += str_len + NS_QFIXEDSZ;
575 }
576
577 std::vector<unsigned char*> srv;
578 for (int count = ancount; count > 0; count--)
579 {
580 int str_len = dn_skipname(start, response + response_len);
581 start += str_len;
582 srv.push_back(start);
583 start += SRV_FIXEDSZ;
584 start += dn_skipname(start, response + response_len);
585 }
586
587 for (unsigned i = 0; i < srv.size(); i++)
588 {
589 char server_name[512] = {};
590 if (ns_name_ntop(srv[i] + SRV_SERVER, server_name, 512) < 0)
591 continue;
592 uint16_t port = ns_get16(srv[i] + SRV_PORT);
593 uint16_t weight = ns_get16(srv[i] + SRV_WEIGHT);
594 l->emplace_back(std::string(server_name) + ":" +
595 StringUtils::toString(port), weight);
596 }
597 }
598 #endif
599 } // fillStunList
600
601 // ----------------------------------------------------------------------------
602 const std::vector<std::pair<std::string, int> >&
getStunList(bool ipv4)603 NetworkConfig::getStunList(bool ipv4)
604 {
605 static std::vector<std::pair<std::string, int> > ipv4_list;
606 static std::vector<std::pair<std::string, int> > ipv6_list;
607 if (ipv4)
608 {
609 if (ipv4_list.empty())
610 NetworkConfig::fillStunList(&ipv4_list, stk_config->m_stun_ipv4);
611 return ipv4_list;
612 }
613 else
614 {
615 if (ipv6_list.empty())
616 NetworkConfig::fillStunList(&ipv6_list, stk_config->m_stun_ipv6);
617 return ipv6_list;
618 }
619 } // getStunList
620