// called from ---GUI--- thread NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, const NetTraversalConfig& traversal_config) { //--use server time if (enet_initialize() != 0) { PanicAlertT("Enet Didn't Initialize"); } m_pad_map.fill(-1); m_wiimote_map.fill(-1); if (traversal_config.use_traversal) { if (!EnsureTraversalClient(traversal_config.traversal_host, traversal_config.traversal_port, port)) return; g_TraversalClient->m_Client = this; m_traversal_client = g_TraversalClient.get(); m_server = g_MainNetHost.get(); if (g_TraversalClient->GetState() == TraversalClient::Failure) g_TraversalClient->ReconnectToServer(); } else { ENetAddress serverAddr; serverAddr.host = ENET_HOST_ANY; serverAddr.port = port; m_server = enet_host_create(&serverAddr, 10, 3, 0, 0); if (m_server != nullptr) m_server->intercept = ENetUtil::InterceptCallback; } if (m_server != nullptr) { is_connected = true; m_do_loop = true; m_thread = std::thread(&NetPlayServer::ThreadFunc, this); m_target_buffer_size = 5; #ifdef USE_UPNP if (forward_port) UPnP::TryPortmapping(port); #endif } }
// called from ---GUI--- thread NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlayUI* dialog, const std::string& name, bool traversal, const std::string& centralServer, u16 centralPort) : m_state(Failure) , m_dialog(dialog) , m_client(nullptr) , m_server(nullptr) , m_is_running(false) , m_do_loop(true) , m_target_buffer_size() , m_local_player(nullptr) , m_current_game(0) , m_is_recording(false) , m_pid(0) , m_connecting(false) , m_traversal_client(nullptr) { m_target_buffer_size = 20; ClearBuffers(); is_connected = false; m_player_name = name; if (!traversal) { //Direct Connection m_client = enet_host_create(nullptr, 1, 3, 0, 0); if (m_client == nullptr) { PanicAlertT("Couldn't Create Client"); } ENetAddress addr; enet_address_set_host(&addr, address.c_str()); addr.port = port; m_server = enet_host_connect(m_client, &addr, 3, 0); if (m_server == nullptr) { PanicAlertT("Couldn't create peer."); } ENetEvent netEvent; int net = enet_host_service(m_client, &netEvent, 5000); if (net > 0 && netEvent.type == ENET_EVENT_TYPE_CONNECT) { if (Connect()) { m_client->intercept = ENetUtil::InterceptCallback; m_thread = std::thread(&NetPlayClient::ThreadFunc, this); } } else { PanicAlertT("Failed to Connect!"); } } else { if (address.size() > NETPLAY_CODE_SIZE) { PanicAlertT("Host code size is to large.\nPlease recheck that you have the correct code"); return; } if (!EnsureTraversalClient(centralServer, centralPort)) return; m_client = g_MainNetHost.get(); m_traversal_client = g_TraversalClient.get(); // If we were disconnected in the background, reconnect. if (m_traversal_client->m_State == TraversalClient::Failure) m_traversal_client->ReconnectToServer(); m_traversal_client->m_Client = this; m_host_spec = address; m_state = WaitingForTraversalClientConnection; OnTraversalStateChanged(); m_connecting = true; Common::Timer connect_timer; connect_timer.Start(); while (m_connecting) { ENetEvent netEvent; if (m_traversal_client) m_traversal_client->HandleResends(); while (enet_host_service(m_client, &netEvent, 4) > 0) { sf::Packet rpac; switch (netEvent.type) { case ENET_EVENT_TYPE_CONNECT: m_server = netEvent.peer; if (Connect()) { m_state = Connected; m_thread = std::thread(&NetPlayClient::ThreadFunc, this); } return; default: break; } } if (connect_timer.GetTimeElapsed() > 5000) break; } PanicAlertT("Failed To Connect!"); } }