/* Copyright (C) 2014 * swift project community / contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, * including this file, may be copied, modified, propagated, or distributed except according to the terms * contained in the LICENSE file. */ #define _CRT_SECURE_NO_WARNINGS #include "blackcore/application.h" #include "blackmisc/logmessage.h" #include "directplayerror.h" #include "directplayutils.h" #include "fs9host.h" #include "multiplayerpacketparser.h" #include "multiplayerpackets.h" #include #include using namespace BlackMisc; namespace BlackSimPlugin { namespace Fs9 { CFs9Host::CFs9Host(QObject *owner) : CDirectPlayPeer(owner, sApp->swiftVersionString()) {} QString CFs9Host::getHostAddress() { QString address; if (m_hostStatus == Hosting) { DWORD dwNumAddresses = 0; HRESULT hr; QVector addresses(dwNumAddresses); m_directPlayPeer->GetLocalHostAddresses(addresses.data(), &dwNumAddresses, 0); addresses.resize(dwNumAddresses); ZeroMemory( addresses.data(), dwNumAddresses * sizeof(LPDIRECTPLAY8ADDRESS) ); if (FAILED (hr = m_directPlayPeer->GetLocalHostAddresses(addresses.data(), &dwNumAddresses, 0))) { logDirectPlayError(hr); return address; } char url[250]; DWORD size = 250; addresses[0]->GetURLA(url, &size); address = QString(url); for (uint ii = 0; ii < dwNumAddresses; ++ii) { LPDIRECTPLAY8ADDRESS pAddress = addresses[ii]; SafeRelease(pAddress); } } return address; } void CFs9Host::sendTextMessage(const QString &textMessage) { MPChatText mpChatText; mpChatText.chat_data = textMessage; QByteArray message; MultiPlayerPacketParser::writeType(message, CFs9Sdk::MPCHAT_PACKET_ID_CHAT_TEXT_SEND); MultiPlayerPacketParser::writeSize(message, mpChatText.chat_data.size() + 1); message = MultiPlayerPacketParser::writeMessage(message, mpChatText); qDebug() << "Message:" << textMessage; sendMessage(message); } void CFs9Host::initialize() { initDirectPlay(); createHostAddress(); startHosting(sApp->swiftVersionString(), m_callsign.toQString()); } void CFs9Host::cleanup() { stopHosting(); } HRESULT CFs9Host::startHosting(const QString &session, const QString &callsign) { HRESULT hr = S_OK; if (m_hostStatus == Hosting) { return hr; } if (!m_directPlayPeer) { return S_FALSE; } DPN_APPLICATION_DESC dpAppDesc; QScopedArrayPointer wszSession(new wchar_t[session.size() + 1]); QScopedArrayPointer wszPlayername(new wchar_t[callsign.size() + 1]); session.toWCharArray(wszSession.data()); wszSession[session.size()] = 0; callsign.toWCharArray(wszPlayername.data()); wszPlayername[callsign.size()] = 0; PLAYER_INFO_STRUCT playerInfo; ZeroMemory(&playerInfo, sizeof(PLAYER_INFO_STRUCT)); strcpy(playerInfo.szAircraft, "Boeing 737-400"); playerInfo.dwFlags = PLAYER_INFO_STRUCT::PARAMS_RECV | PLAYER_INFO_STRUCT::PARAMS_SEND; // Prepare and set the player information structure. DPN_PLAYER_INFO player; ZeroMemory(&player, sizeof(DPN_PLAYER_INFO)); player.dwSize = sizeof(DPN_PLAYER_INFO); player.pvData = &playerInfo; player.dwDataSize = sizeof(PLAYER_INFO_STRUCT); player.dwInfoFlags = DPNINFO_NAME | DPNINFO_DATA; player.pwszName = wszPlayername.data(); if (FAILED(hr = m_directPlayPeer->SetPeerInfo(&player, nullptr, nullptr, DPNSETPEERINFO_SYNC))) { logDirectPlayError(hr); return hr; } // Now set up the Application Description ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC)); dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC); dpAppDesc.guidApplication = CFs9Sdk::guid(); dpAppDesc.pwszSessionName = wszSession.data(); // We are now ready to host the app if (FAILED(hr = m_directPlayPeer->Host(&dpAppDesc, // AppDesc &m_deviceAddress, 1, // Device Address nullptr, nullptr, // Reserved nullptr, // Player Context 0))) // dwFlags { logDirectPlayError(hr); return hr; } else { CLogMessage(this).info("Hosting successfully started"); m_hostStatus = Hosting; } // Enumerate the number of stalled DirectPlay peers DWORD dwNumPlayers = 0; hr = m_directPlayPeer->EnumPlayersAndGroups( nullptr, &dwNumPlayers, DPNENUM_PLAYERS ); if(hr == DPNERR_BUFFERTOOSMALL) { QScopedArrayPointer stalledPeers(new DPNID[dwNumPlayers]); hr = m_directPlayPeer->EnumPlayersAndGroups( stalledPeers.data(), &dwNumPlayers, DPNENUM_PLAYERS ); // Destroy all stalled peers for (DWORD i = 0; i < dwNumPlayers; ++i) { m_directPlayPeer->DestroyPeer(stalledPeers[i], nullptr, 0, 0); } } emit statusChanged(m_hostStatus); return hr; } HRESULT CFs9Host::stopHosting() { HRESULT hr = S_OK; if (m_hostStatus == Terminated) return hr; CLogMessage(this).info("Hosting terminated!"); if (FAILED(hr = m_directPlayPeer->TerminateSession(nullptr, 0, 0))) { return logDirectPlayError(hr); } if (FAILED(hr = m_directPlayPeer->Close(0))) { return logDirectPlayError(hr); } m_hostStatus = Terminated; // Enumerate the number of stalled DirectPlay peers DWORD dwNumPlayers = 0; hr = m_directPlayPeer->EnumPlayersAndGroups( nullptr, &dwNumPlayers, DPNENUM_PLAYERS ); if(hr == DPNERR_BUFFERTOOSMALL) { QScopedArrayPointer stalledPeers(new DPNID[dwNumPlayers]); hr = m_directPlayPeer->EnumPlayersAndGroups( stalledPeers.data(), &dwNumPlayers, DPNENUM_PLAYERS ); // Destroy all stalled peers for (DWORD i = 0; i < dwNumPlayers; ++i) { m_directPlayPeer->DestroyPeer(stalledPeers[i], nullptr, 0, 0); } } emit statusChanged(m_hostStatus); return hr; } } }