mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-08 06:17:48 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
#include "pch.h"
|
||||
#include "MeshConnection.h"
|
||||
#include "MeshManager.h"
|
||||
|
||||
using namespace Microsoft::Xbox::Samples::NetworkMesh;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
MeshConnection::MeshConnection( Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress, MeshManager^ manager ) :
|
||||
m_secureDeviceAddress(secureDeviceAddress),
|
||||
m_customProperty(nullptr),
|
||||
m_assocationFoundInTemplate(false),
|
||||
m_isInComingAssociation(false),
|
||||
m_isConnectionDestroying(false),
|
||||
m_isConnectionInProgress(false),
|
||||
m_retryAttempts(0),
|
||||
m_timerSinceLastAttempt(0.0f),
|
||||
m_connectionStatus(ConnectionStatus::Disconnected),
|
||||
m_consoleId(0xFF),
|
||||
m_heartTimer(0.0f)
|
||||
{
|
||||
m_meshManager = Platform::WeakReference(manager);
|
||||
m_userIdsToUserData = std::map<Platform::String^, UserMeshConnectionPropertyBag^>();
|
||||
|
||||
if(secureDeviceAddress == nullptr || manager == nullptr)
|
||||
{
|
||||
throw ref new Platform::InvalidArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
MeshConnection::~MeshConnection()
|
||||
{
|
||||
if (m_association != nullptr)
|
||||
{
|
||||
m_association->StateChanged -= m_associationStateChangeToken;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 MeshConnection::GetConsoleId()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_consoleId;
|
||||
}
|
||||
|
||||
void MeshConnection::SetConsoleId(uint8 consoleId)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_consoleId = consoleId;
|
||||
}
|
||||
|
||||
Platform::String^ MeshConnection::GetConsoleName()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
|
||||
Platform::String^ consoleName = L"n/a";
|
||||
if( !m_consoleName->IsEmpty() )
|
||||
{
|
||||
consoleName = m_consoleName;
|
||||
}
|
||||
|
||||
return consoleName;
|
||||
}
|
||||
|
||||
void MeshConnection::SetConsoleName(Platform::String^ consoleName)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_consoleName = consoleName;
|
||||
}
|
||||
|
||||
Platform::Object^ MeshConnection::GetCustomProperty()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_customProperty;
|
||||
}
|
||||
|
||||
void MeshConnection::SetCustomProperty(Platform::Object^ object)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_customProperty = object;
|
||||
}
|
||||
|
||||
int MeshConnection::GetNumberOfRetryAttempts()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_retryAttempts;
|
||||
}
|
||||
|
||||
void MeshConnection::SetNumberOfRetryAttempts(int retryAttempt)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_retryAttempts = retryAttempt;
|
||||
}
|
||||
|
||||
ConnectionStatus MeshConnection::GetConnectionStatus()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_connectionStatus;
|
||||
}
|
||||
|
||||
void MeshConnection::SetConnectionStatus(ConnectionStatus status)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_connectionStatus = status;
|
||||
}
|
||||
|
||||
bool MeshConnection::GetAssocationFoundInTemplate()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_assocationFoundInTemplate;
|
||||
}
|
||||
|
||||
void MeshConnection::SetAssocationFoundInTemplate(bool val)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_assocationFoundInTemplate = val;
|
||||
}
|
||||
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ MeshConnection::GetAssociation()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_association;
|
||||
}
|
||||
|
||||
void MeshConnection::SetAssociation( Windows::Xbox::Networking::SecureDeviceAssociation^ association )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
|
||||
if (m_association != nullptr)
|
||||
{
|
||||
m_association->StateChanged -= m_associationStateChangeToken;
|
||||
}
|
||||
|
||||
m_association = association;
|
||||
|
||||
if(association != nullptr)
|
||||
{
|
||||
// This is needed to know if the association is ever dropped.
|
||||
TypedEventHandler<Windows::Xbox::Networking::SecureDeviceAssociation^, Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^>^ stateChangeEvent =
|
||||
ref new TypedEventHandler<Windows::Xbox::Networking::SecureDeviceAssociation^, Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^>(
|
||||
[this] (Windows::Xbox::Networking::SecureDeviceAssociation^ association, Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^ args)
|
||||
{
|
||||
HandleAssociationChangedEvent(association, args);
|
||||
});
|
||||
|
||||
m_associationStateChangeToken = association->StateChanged += stateChangeEvent;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshConnection::HandleAssociationChangedEvent(
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^ args)
|
||||
{
|
||||
MeshManager^ meshManager = m_meshManager.Resolve<MeshManager>();
|
||||
//if (meshManager)
|
||||
meshManager->OnAssociationChange(args, association);
|
||||
}
|
||||
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ MeshConnection::GetSecureDeviceAddress()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_secureDeviceAddress;
|
||||
}
|
||||
|
||||
bool MeshConnection::IsInComingAssociation()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_isInComingAssociation;
|
||||
}
|
||||
|
||||
void MeshConnection::SetInComingAssociation(bool val)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_isInComingAssociation = val;
|
||||
}
|
||||
|
||||
bool MeshConnection::IsConnectionDestroying()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_isConnectionDestroying;
|
||||
}
|
||||
|
||||
void MeshConnection::SetConnectionDestroying( bool val )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_isConnectionDestroying = val;
|
||||
}
|
||||
|
||||
bool MeshConnection::IsConnectionInProgress()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_isConnectionInProgress;
|
||||
}
|
||||
|
||||
void MeshConnection::SetConnectionInProgress( bool val )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_isConnectionInProgress = val;
|
||||
}
|
||||
|
||||
void MeshConnection::SetHeartTimer( float timer )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_heartTimer = timer;
|
||||
}
|
||||
|
||||
float MeshConnection::GetHeartTimer()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_heartTimer;
|
||||
}
|
||||
|
||||
|
||||
UserMeshConnectionPropertyBag^ MeshConnection::GetUserPropertyBag( Platform::String^ xboxUserId )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_userIdsToUserData[xboxUserId];
|
||||
}
|
||||
|
||||
UserMeshConnectionPropertyBag^ MeshConnection::AddUserPropertyBag( Platform::String^ xboxUserId )
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
UserMeshConnectionPropertyBag^ userMeshConnectionPropertyBag = ref new UserMeshConnectionPropertyBag(xboxUserId);
|
||||
m_userIdsToUserData[xboxUserId] = userMeshConnectionPropertyBag;
|
||||
return userMeshConnectionPropertyBag;
|
||||
}
|
||||
|
||||
}}}}
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "UserMeshConnectionPropertyBag.h"
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
ref class MeshManager;
|
||||
|
||||
public enum class ConnectionStatus
|
||||
{
|
||||
Disconnected,
|
||||
Pending,
|
||||
Connected,
|
||||
PostHandshake
|
||||
};
|
||||
|
||||
public ref class MeshConnection sealed
|
||||
{
|
||||
internal:
|
||||
MeshConnection(Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress, MeshManager^ manager);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
virtual ~MeshConnection();
|
||||
|
||||
uint8 GetConsoleId();
|
||||
void SetConsoleId(uint8 consoleId);
|
||||
|
||||
Platform::String^ GetConsoleName();
|
||||
void SetConsoleName(Platform::String^ consoleName);
|
||||
|
||||
Platform::Object^ GetCustomProperty();
|
||||
void SetCustomProperty(Platform::Object^ object);
|
||||
|
||||
int GetNumberOfRetryAttempts();
|
||||
void SetNumberOfRetryAttempts(int retryAttempt);
|
||||
|
||||
ConnectionStatus GetConnectionStatus();
|
||||
void SetConnectionStatus(ConnectionStatus status);
|
||||
|
||||
bool GetAssocationFoundInTemplate();
|
||||
void SetAssocationFoundInTemplate(bool bFound);
|
||||
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ GetAssociation();
|
||||
void SetAssociation(Windows::Xbox::Networking::SecureDeviceAssociation^ association);
|
||||
|
||||
bool IsInComingAssociation();
|
||||
void SetInComingAssociation(bool val);
|
||||
|
||||
bool IsConnectionDestroying();
|
||||
void SetConnectionDestroying(bool val);
|
||||
|
||||
bool IsConnectionInProgress();
|
||||
void SetConnectionInProgress(bool val);
|
||||
|
||||
void SetHeartTimer( float timer );
|
||||
float GetHeartTimer();
|
||||
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ MeshConnection::GetSecureDeviceAddress();
|
||||
|
||||
UserMeshConnectionPropertyBag^ GetUserPropertyBag(Platform::String^ xboxUserId);
|
||||
|
||||
UserMeshConnectionPropertyBag^ AddUserPropertyBag(Platform::String^ xboxUserId);
|
||||
|
||||
private:
|
||||
Concurrency::critical_section m_stateLock;
|
||||
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ m_secureDeviceAddress;
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ m_association;
|
||||
Windows::Foundation::EventRegistrationToken m_associationStateChangeToken;
|
||||
|
||||
Platform::WeakReference m_meshManager; // weak ref to MeshManager^
|
||||
std::map<Platform::String^, UserMeshConnectionPropertyBag^> m_userIdsToUserData;
|
||||
|
||||
uint8 m_consoleId;
|
||||
Platform::String^ m_consoleName;
|
||||
Platform::Object^ m_customProperty;
|
||||
ConnectionStatus m_connectionStatus;
|
||||
bool m_isInComingAssociation;
|
||||
bool m_isConnectionInProgress;
|
||||
bool m_isConnectionDestroying;
|
||||
bool m_assocationFoundInTemplate;
|
||||
int m_retryAttempts;
|
||||
float m_timerSinceLastAttempt;
|
||||
float m_heartTimer;
|
||||
|
||||
void HandleAssociationChangedEvent(
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^ args
|
||||
);
|
||||
};
|
||||
|
||||
}}}}
|
||||
@@ -0,0 +1,207 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
//
|
||||
// Represents the base message that comes across
|
||||
//
|
||||
public ref class MeshHeartbeatReceivedEvent sealed
|
||||
{
|
||||
public:
|
||||
property MeshConnection^ Sender { MeshConnection^ get() { return m_sender; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 ConsoleId { uint8 get() { return m_consoleId; } }
|
||||
|
||||
internal:
|
||||
MeshHeartbeatReceivedEvent(
|
||||
uint8 consoleId,
|
||||
MeshConnection^ sender
|
||||
) :
|
||||
m_consoleId(consoleId),
|
||||
m_sender(sender) {}
|
||||
|
||||
private:
|
||||
uint8 m_consoleId;
|
||||
MeshConnection^ m_sender;
|
||||
};
|
||||
|
||||
//
|
||||
// Received when a console connects
|
||||
//
|
||||
public ref class MeshHelloReceivedEvent sealed
|
||||
{
|
||||
public:
|
||||
property MeshConnection^ Sender { MeshConnection^ get() { return m_sender; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 ConsoleId { uint8 get() { return m_consoleId; } }
|
||||
|
||||
// The console's debug name
|
||||
property Platform::String^ ConsoleName { Platform::String^ get() { return m_consoleName; } }
|
||||
|
||||
property bool RespondingToHello { bool get() { return m_respondingToHello; } }
|
||||
internal:
|
||||
MeshHelloReceivedEvent(
|
||||
uint8 consoleId,
|
||||
MeshConnection^ sender,
|
||||
Platform::String^ consoleName,
|
||||
bool respondingToHello ) :
|
||||
m_consoleId(consoleId),
|
||||
m_sender(sender),
|
||||
m_consoleName(consoleName),
|
||||
m_respondingToHello(respondingToHello)
|
||||
{}
|
||||
|
||||
private:
|
||||
uint8 m_consoleId;
|
||||
Platform::String^ m_consoleName;
|
||||
MeshConnection^ m_sender;
|
||||
bool m_respondingToHello;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Received when a console connects
|
||||
//
|
||||
public ref class MeshAckReceivedEvent sealed
|
||||
{
|
||||
public:
|
||||
property MeshConnection^ Sender { MeshConnection^ get() { return m_sender; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 ConsoleId { uint8 get() { return m_consoleId; } }
|
||||
|
||||
// The ID of the packet which was ACK'd
|
||||
property uint16 MessageId { uint16 get() { return m_messageId; } }
|
||||
|
||||
internal:
|
||||
MeshAckReceivedEvent(
|
||||
uint8 consoleId,
|
||||
MeshConnection^ sender,
|
||||
uint16 messageId
|
||||
) :
|
||||
m_consoleId(consoleId),
|
||||
m_sender(sender),
|
||||
m_messageId(messageId)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 m_consoleId;
|
||||
uint16 m_messageId;
|
||||
MeshConnection^ m_sender;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Received when a audio chat packet has been received
|
||||
//
|
||||
public ref class MeshChatMessageReceivedEvent sealed
|
||||
{
|
||||
public:
|
||||
property MeshConnection^ Sender { MeshConnection^ get() { return m_sender; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 ConsoleId { uint8 get() { return m_consoleId; } }
|
||||
|
||||
// Buffer containing chat voice data
|
||||
property Windows::Storage::Streams::IBuffer^ Buffer { Windows::Storage::Streams::IBuffer^ get() { return m_buffer; } }
|
||||
|
||||
internal:
|
||||
MeshChatMessageReceivedEvent(
|
||||
uint8 consoleId,
|
||||
MeshConnection^ sender,
|
||||
Windows::Storage::Streams::IBuffer^ buffer
|
||||
) :
|
||||
m_consoleId(consoleId),
|
||||
m_sender(sender),
|
||||
m_buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 m_consoleId;
|
||||
Windows::Storage::Streams::IBuffer^ m_buffer;
|
||||
MeshConnection^ m_sender;
|
||||
};
|
||||
|
||||
//
|
||||
// Received when a game custom data packet has been received
|
||||
//
|
||||
public ref class GameCustomMessageReceivedEvent sealed
|
||||
{
|
||||
public:
|
||||
property MeshConnection^ Sender { MeshConnection^ get() { return m_sender; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 MessageType { uint8 get() { return m_messageType; } }
|
||||
|
||||
// Mesh unique identifier for the console
|
||||
property uint8 ConsoleId { uint8 get() { return m_consoleId; } }
|
||||
|
||||
// Buffer containing chat voice data
|
||||
property Windows::Storage::Streams::IBuffer^ Buffer { Windows::Storage::Streams::IBuffer^ get() { return m_buffer; } }
|
||||
|
||||
internal:
|
||||
GameCustomMessageReceivedEvent(
|
||||
uint8 consoleId,
|
||||
MeshConnection^ sender,
|
||||
uint8 messageType,
|
||||
Windows::Storage::Streams::IBuffer^ buffer
|
||||
) :
|
||||
m_consoleId(consoleId),
|
||||
m_sender(sender),
|
||||
m_messageType(messageType),
|
||||
m_buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 m_messageType;
|
||||
uint8 m_consoleId;
|
||||
Windows::Storage::Streams::IBuffer^ m_buffer;
|
||||
MeshConnection^ m_sender;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Event for the Mesh Controller to report diagnostic and error message information
|
||||
//
|
||||
public ref class DebugMessageEventArgs sealed
|
||||
{
|
||||
public:
|
||||
property Platform::String^ Message { Platform::String^ get() { return m_message; } }
|
||||
property int HResult { int get() { return m_hresult; } }
|
||||
|
||||
internal:
|
||||
DebugMessageEventArgs(Platform::String^ message, int hr)
|
||||
{
|
||||
m_message = message;
|
||||
m_hresult = hr;
|
||||
}
|
||||
|
||||
private:
|
||||
Platform::String^ m_message;
|
||||
int m_hresult;
|
||||
};
|
||||
|
||||
|
||||
}}}}
|
||||
@@ -0,0 +1,765 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#include "pch.h"
|
||||
#include "MeshManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace Concurrency;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Xbox::Networking;
|
||||
using namespace Microsoft::Xbox::Samples::NetworkMesh;
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
MeshManager::MeshManager(
|
||||
uint8 localConsoleId,
|
||||
Platform::String^ secureDeviceAssociationTemplateName,
|
||||
Platform::String^ localConsoleName,
|
||||
bool dropOutOfOrderPackets ) :
|
||||
m_localConsoleName(localConsoleName),
|
||||
m_dropOutOfOrderPackets(dropOutOfOrderPackets)
|
||||
{
|
||||
// load template for Secure Device Association.
|
||||
m_associationTemplate = Windows::Xbox::Networking::SecureDeviceAssociationTemplate::GetTemplateByName( secureDeviceAssociationTemplateName );
|
||||
|
||||
Initialize(localConsoleId);
|
||||
RegisterMeshPacketEventHandlers();
|
||||
}
|
||||
|
||||
void MeshManager::Initialize(uint8 localConsoleId)
|
||||
{
|
||||
m_connections.clear();
|
||||
|
||||
if(m_associationTemplate != nullptr)
|
||||
{
|
||||
DestroyAllTemplateAssociations();
|
||||
|
||||
// Listen to AssociationIncoming event
|
||||
TypedEventHandler<Windows::Xbox::Networking::SecureDeviceAssociationTemplate^, Windows::Xbox::Networking::SecureDeviceAssociationIncomingEventArgs^>^ associationIncomingEvent =
|
||||
ref new TypedEventHandler<Windows::Xbox::Networking::SecureDeviceAssociationTemplate^, Windows::Xbox::Networking::SecureDeviceAssociationIncomingEventArgs^>(
|
||||
[this] (Windows::Xbox::Networking::SecureDeviceAssociationTemplate^ associationTemplate, Windows::Xbox::Networking::SecureDeviceAssociationIncomingEventArgs^ args)
|
||||
{
|
||||
OnAssociationIncoming( associationTemplate, args );
|
||||
});
|
||||
m_associationIncomingToken = m_associationTemplate->AssociationIncoming += associationIncomingEvent;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogComment("Association template is NULL!");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned short sin6_port = htons(m_associationTemplate->AcceptorSocketDescription->BoundPortRangeLower);
|
||||
|
||||
m_meshPacketManager = ref new MeshPacketManager(localConsoleId, sin6_port, this, m_dropOutOfOrderPackets);
|
||||
|
||||
// Try to connect to anything we need to every second
|
||||
int32 threadAffinityMask = ~0x04; // Means to this thread can run all everything except core 3 (which is reserved for graphics for example).
|
||||
m_autoConnectThread = ref new MeshThread(1000, threadAffinityMask, NORMAL_PRIORITY_CLASS);
|
||||
m_autoConnectThread->OnDoWork += ref new Windows::Foundation::EventHandler<ProcessThreadsEventArgs^>( [this]( Platform::Object^, ProcessThreadsEventArgs^ args )
|
||||
{
|
||||
OnAutoConnectWorkerThreadDoWork(args);
|
||||
});
|
||||
|
||||
// Send heartbeats and hellos every 2 seconds
|
||||
threadAffinityMask = ~0x04; // Means to this thread can run all everything except core 3 (which is reserved for graphics for example).
|
||||
m_heartbeatThread = ref new MeshThread(DEFAULT_HEARTBEAT_PERIOD_MILLISECONDS, threadAffinityMask, NORMAL_PRIORITY_CLASS);
|
||||
m_heartbeatThread->OnDoWork += ref new Windows::Foundation::EventHandler<ProcessThreadsEventArgs^>( [this]( Platform::Object^, ProcessThreadsEventArgs^ args )
|
||||
{
|
||||
OnHeartbeatWorkerThreadDoWork(args);
|
||||
});
|
||||
}
|
||||
|
||||
SecureDeviceAssociationTemplate^ MeshManager::GetSecureDeviceAssociationTemplate()
|
||||
{
|
||||
return m_associationTemplate;
|
||||
}
|
||||
|
||||
// This should only be called from ConnectTo or OnIncomingAssociation.
|
||||
MeshConnection^ MeshManager::AddConnection(
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ secureDeviceAssociation,
|
||||
bool inComingAssociation,
|
||||
ConnectionStatus connectionStatus
|
||||
)
|
||||
{
|
||||
if(secureDeviceAddress == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(GetConnectionFromSecureDeviceAddress(secureDeviceAddress) != nullptr)
|
||||
{
|
||||
// The secure device address already exists.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MeshConnection^ meshConnection = ref new MeshConnection(secureDeviceAddress, this);
|
||||
meshConnection->SetInComingAssociation(inComingAssociation);
|
||||
meshConnection->SetConnectionStatus(connectionStatus);
|
||||
meshConnection->SetAssociation(secureDeviceAssociation);
|
||||
|
||||
// Add him to the list of mesh connections.
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
m_connections.push_back(meshConnection);
|
||||
}
|
||||
|
||||
return meshConnection;
|
||||
}
|
||||
|
||||
void MeshManager::ConnectToAddress(
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress,
|
||||
Platform::String^ debugName
|
||||
)
|
||||
{
|
||||
if (secureDeviceAddress == nullptr)
|
||||
{
|
||||
LogComment(L"Cannot pass a nullptr for the address to MeshManager::ConnectTo");
|
||||
throw ref new InvalidArgumentException(L"Cannot pass a nullptr for the address to MeshManager::ConnectTo");
|
||||
}
|
||||
|
||||
if(AreSecureDeviceAddressesEqual(SecureDeviceAddress::GetLocal(), secureDeviceAddress))
|
||||
{
|
||||
// Don't try to connect to local console.
|
||||
return;
|
||||
}
|
||||
|
||||
LogComment( "ConnectToAddress: Attempting to connect to remote console: " + debugName);
|
||||
MeshConnection^ newMeshConnected = AddConnection(secureDeviceAddress, nullptr, false, ConnectionStatus::Disconnected);
|
||||
if( newMeshConnected != nullptr )
|
||||
{
|
||||
// If this connection was new, then set the console name to be debug name. It will change once the handshake is done
|
||||
newMeshConnected->SetConsoleName(debugName);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::OnAssociationIncoming(
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationTemplate^ associationTemplate,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationIncomingEventArgs^ args
|
||||
)
|
||||
{
|
||||
SecureDeviceAssociation^ association = args->Association;
|
||||
if(association != nullptr)
|
||||
{
|
||||
LogCommentFormat( L"OnAssociationIncoming: Incoming connection %s", Utils::PrintSecureDeviceAssociation(association, false, true)->Data() );
|
||||
MeshConnection^ newMeshConnected = AddConnection(association->RemoteSecureDeviceAddress, association, true, ConnectionStatus::Connected);
|
||||
if(newMeshConnected != nullptr)
|
||||
{
|
||||
RefreshConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::OnAutoConnectWorkerThreadDoWork( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args )
|
||||
{
|
||||
// Try to connect to every outgoing connection that we are disconnected from.
|
||||
SecureDeviceAssociationTemplate^ secureDeviceAssociationTemplate = GetSecureDeviceAssociationTemplate();
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allDisconnectedConnections = GetConnectionsByType(ConnectionStatus::Disconnected);
|
||||
for each (MeshConnection^ meshConnection in allDisconnectedConnections)
|
||||
{
|
||||
if(meshConnection->IsInComingAssociation())
|
||||
{
|
||||
// Don't bother connecting to someone who connected to you
|
||||
// because that would create bi-directional connection which cause failures.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore connections that have a CreateAssociationAsync in progress on them
|
||||
if(meshConnection->IsConnectionInProgress())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore anyone we have now a connection with. Just in case anything changed since we got the list of disconnected connections above
|
||||
if( meshConnection->GetAssociation() != nullptr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LogComment( Utils::GetThreadDescription(L"THREAD: Calling CreateAssociationAsync") );
|
||||
|
||||
meshConnection->SetConnectionInProgress(true);
|
||||
auto asyncOp = secureDeviceAssociationTemplate->CreateAssociationAsync(
|
||||
meshConnection->GetSecureDeviceAddress(),
|
||||
Windows::Xbox::Networking::CreateSecureDeviceAssociationBehavior::Default
|
||||
);
|
||||
|
||||
create_task( asyncOp )
|
||||
.then([this, meshConnection](task<SecureDeviceAssociation^> t)
|
||||
{
|
||||
LogComment( Utils::GetThreadDescription(L"THREAD: CreateAssociationAsync result") );
|
||||
|
||||
try
|
||||
{
|
||||
SecureDeviceAssociation^ association = t.get();
|
||||
LogCommentFormat( L"CreateAssociationAsync success: %s %s", meshConnection->GetConsoleName()->Data(), Utils::PrintSecureDeviceAssociation(association, false, true)->Data() );
|
||||
MeshConnection^ newMeshConnection = GetConnectionFromSecureDeviceAddress(association->RemoteSecureDeviceAddress);
|
||||
if(newMeshConnection != nullptr)
|
||||
{
|
||||
LogCommentFormat( L"Created new connection for %s", meshConnection->GetConsoleName()->Data() );
|
||||
newMeshConnection->SetAssociation(association);
|
||||
newMeshConnection->SetConnectionStatus(ConnectionStatus::Connected);
|
||||
}
|
||||
}
|
||||
catch(Platform::Exception^ ex)
|
||||
{
|
||||
//We will auto-retry this again on next update.
|
||||
LogCommentFormat(L"Connecting to remote machine failed %s. %s", meshConnection->GetConsoleName()->Data(), Utils::GetErrorString(ex->HResult)->Data() );
|
||||
}
|
||||
|
||||
meshConnection->SetConnectionInProgress(false);
|
||||
});
|
||||
|
||||
// This thread is waiting for CreateAssociationAsync to complete since this is happening
|
||||
// inside a worker thread that does nothing but try to connect to other consoles
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::OnHeartbeatWorkerThreadDoWork( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args )
|
||||
{
|
||||
// This function is called every so often (eg. every 2 sec) by the MeshThread class
|
||||
|
||||
// First, refresh the connection list
|
||||
RefreshConnections();
|
||||
|
||||
// Send hello to all connections that need it
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allconnected = GetConnectionsByType(ConnectionStatus::Connected);
|
||||
for each (MeshConnection^ meshConnection in allconnected)
|
||||
{
|
||||
//Send hello to retry handshake.
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ association = meshConnection->GetAssociation();
|
||||
if(association != nullptr)
|
||||
{
|
||||
bool isRespondingToHello = false;
|
||||
Platform::String^ remoteName = Utils::PrintSecureDeviceAssociation(association, false, true);
|
||||
LogCommentFormat( L"Sending hello to remote console: %s", remoteName->Data());
|
||||
m_meshPacketManager->SendHelloMessage(association, GetLocalConsoleDisplayName(), isRespondingToHello);
|
||||
}
|
||||
}
|
||||
|
||||
// Send heartbeat to all connections that we have completed handshake with
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ initializedConnections = GetConnectionsByType(ConnectionStatus::PostHandshake);
|
||||
for each (MeshConnection^ meshConnection in initializedConnections)
|
||||
{
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ association = meshConnection->GetAssociation();
|
||||
if( association != nullptr )
|
||||
{
|
||||
m_meshPacketManager->SendHeartbeatMessageAsync( association, meshConnection->GetConsoleId() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Platform::String^ MeshManager::GetLocalConsoleName()
|
||||
{
|
||||
Platform::String^ localConsoleName = L"Console";
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
localConsoleName = m_localConsoleName;
|
||||
}
|
||||
|
||||
return localConsoleName;
|
||||
}
|
||||
|
||||
void MeshManager::SetLocalConsoleName(Platform::String^ localConsoleName)
|
||||
{
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
m_localConsoleName = localConsoleName;
|
||||
}
|
||||
}
|
||||
|
||||
Platform::String^ MeshManager::GetLocalConsoleDisplayName()
|
||||
{
|
||||
return Utils::FormatString(L"%s [%d]", GetLocalConsoleName()->Data(), m_meshPacketManager->GetLocalConsoleId() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ MeshManager::GetConnections()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
auto v = ref new Platform::Collections::Vector<MeshConnection^>(m_connections);
|
||||
return v->GetView();
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ MeshManager::GetConnectionsByType(ConnectionStatus type)
|
||||
{
|
||||
auto associationsByType = ref new Platform::Collections::Vector<MeshConnection^>();
|
||||
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
if( meshConnection->GetConnectionStatus() == type )
|
||||
{
|
||||
associationsByType->Append(meshConnection);
|
||||
}
|
||||
}
|
||||
return associationsByType->GetView();
|
||||
}
|
||||
|
||||
void MeshManager::RefreshConnections()
|
||||
{
|
||||
// First, loop through all connections and mark all connections as not found in the template
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
meshConnection->SetAssocationFoundInTemplate(false);
|
||||
}
|
||||
|
||||
// Now, Loop thought template and find the each connection and mark the ones that we found
|
||||
// And take note of anything in the template that is not yet in our internal list of connections.
|
||||
Windows::Foundation::Collections::IVectorView<Windows::Xbox::Networking::SecureDeviceAssociation^>^ associations = GetSecureDeviceAssociationTemplate()->Associations;
|
||||
for each (Windows::Xbox::Networking::SecureDeviceAssociation^ associationInTemplate in associations)
|
||||
{
|
||||
MeshConnection^ meshConnection = GetConnectionFromSecureDeviceAddress(associationInTemplate->RemoteSecureDeviceAddress);
|
||||
if(meshConnection != nullptr)
|
||||
{
|
||||
meshConnection->SetAssocationFoundInTemplate(true);
|
||||
ConnectionStatus status = meshConnection->GetConnectionStatus();
|
||||
|
||||
// If the status is incorrect, then fix it log the error and fix it
|
||||
if( status != ConnectionStatus::Connected &&
|
||||
status != ConnectionStatus::PostHandshake )
|
||||
{
|
||||
LogCommentFormat( L"ERROR: Found association in template that we didn't CreateAssociationAsync or get an OnAssociationIncoming event for" );
|
||||
LogCommentFormat( L"ERROR: Address: %s", Utils::PrintSecureDeviceAssociation(associationInTemplate, false, true)->Data() );
|
||||
|
||||
meshConnection->SetConnectionStatus(ConnectionStatus::Connected);
|
||||
meshConnection->SetAssociation(associationInTemplate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogCommentFormat( L"ERROR: Mismatch occurred: Association in template not found in our internal list of connections" );
|
||||
}
|
||||
}
|
||||
|
||||
// First, loop through all connections again and for anything not found in the template, disconnect from it and tell the game.
|
||||
// Get the latest list again as connections could have been deleted.
|
||||
allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
if ( meshConnection != nullptr &&
|
||||
false == meshConnection->GetAssocationFoundInTemplate() &&
|
||||
meshConnection->GetConnectionStatus() != ConnectionStatus::Pending &&
|
||||
meshConnection->GetConnectionStatus() != ConnectionStatus::Disconnected
|
||||
)
|
||||
{
|
||||
// Do not delete him. We want the raise an event to the game and have the game call DestroyConnection explicitly.
|
||||
LogCommentFormat( L"Disconnecting remote console %s who was not in template", meshConnection->GetConsoleName()->Data() );
|
||||
LogCommentFormat( L"Address: %s", Utils::PrintSecureDeviceAssociation(meshConnection->GetAssociation(), false, true)->Data() );
|
||||
meshConnection->SetConnectionStatus(ConnectionStatus::Disconnected);
|
||||
OnDisconnected(this, meshConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshManager::DoesConnectionExistInList(Windows::Foundation::Collections::IVectorView<MeshConnection^>^ list, MeshConnection^ connection)
|
||||
{
|
||||
if(connection == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bfound = false;
|
||||
for (unsigned int i = 0; i < list->Size; i++ )
|
||||
{
|
||||
if (list->GetAt(i) == connection)
|
||||
{
|
||||
bfound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bfound;
|
||||
}
|
||||
|
||||
void MeshManager::OnAssociationChange( Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^ args, Windows::Xbox::Networking::SecureDeviceAssociation^ association )
|
||||
{
|
||||
// Update this mesh member with the latest information
|
||||
switch(args->NewState)
|
||||
{
|
||||
case Windows::Xbox::Networking::SecureDeviceAssociationState::DestroyingLocal:
|
||||
case Windows::Xbox::Networking::SecureDeviceAssociationState::DestroyingRemote:
|
||||
case Windows::Xbox::Networking::SecureDeviceAssociationState::Invalid:
|
||||
{
|
||||
bool bFound = false;
|
||||
{
|
||||
MeshConnection^ meshConnection = GetConnectionFromAssociation(association);
|
||||
if(meshConnection != nullptr)
|
||||
{
|
||||
bFound = true;
|
||||
// let the user know that this connection is being disconnected.
|
||||
LogCommentFormat( L"Remote console is disconnecting %s", meshConnection->GetConsoleName()->Data() );
|
||||
LogComment( Utils::GetThreadDescription(L"THREAD: Remote console disconnecting") );
|
||||
|
||||
meshConnection->SetConnectionDestroying(true);
|
||||
meshConnection->SetConnectionStatus(ConnectionStatus::Disconnected);
|
||||
OnDisconnected(this, meshConnection);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
LogComment(L"Association Change event fired for the wrong association.");
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MeshConnection^ MeshManager::GetConnectionFromAssociation(Windows::Xbox::Networking::SecureDeviceAssociation^ association)
|
||||
{
|
||||
if(association == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SecureDeviceAddress^ remoteSecureDeviceAddress = association->RemoteSecureDeviceAddress;
|
||||
return GetConnectionFromSecureDeviceAddress(remoteSecureDeviceAddress);
|
||||
}
|
||||
|
||||
MeshConnection^ MeshManager::GetConnectionFromSecureDeviceAddress(Windows::Xbox::Networking::SecureDeviceAddress^ address)
|
||||
{
|
||||
if(address == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
SecureDeviceAddress^ remoteSecureDeviceAddress = meshConnection->GetSecureDeviceAddress();
|
||||
if(AreSecureDeviceAddressesEqual(remoteSecureDeviceAddress, address))
|
||||
{
|
||||
return meshConnection;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MeshConnection^ MeshManager::GetConnectionFromConsoleId(uint8 consoleId)
|
||||
{
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
uint8 meshConsoleId = meshConnection->GetConsoleId();
|
||||
if( meshConsoleId == consoleId )
|
||||
{
|
||||
return meshConnection;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MeshManager::DeleteConnection(MeshConnection^ connection)
|
||||
{
|
||||
if (connection == nullptr)
|
||||
{
|
||||
LogComment(L"Cannot pass a nullptr for the member to DeleteConnection");
|
||||
throw ref new InvalidArgumentException(L"Cannot pass a nullptr for the member to DeleteConnection");
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
|
||||
auto iter = m_connections.begin();
|
||||
for( ; iter != m_connections.end(); iter++ )
|
||||
{
|
||||
if ((*iter) == connection)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
m_connections.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::DestroyConnection( MeshConnection^ connection )
|
||||
{
|
||||
if(connection == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SecureDeviceAssociation^ meshAssociation = connection->GetAssociation();
|
||||
if(meshAssociation != nullptr)
|
||||
{
|
||||
if(false == connection->IsConnectionDestroying())
|
||||
{
|
||||
connection->SetConnectionDestroying(true);
|
||||
IAsyncAction^ asyncOp = meshAssociation->DestroyAsync();
|
||||
create_task(asyncOp)
|
||||
.then([this] (task<void> t)
|
||||
{
|
||||
try
|
||||
{
|
||||
t.get(); // if t.get fails, it will throw.
|
||||
}
|
||||
catch (Platform::COMException^ ex)
|
||||
{
|
||||
LogCommentFormat( L"MeshManager::DestroyConnection - DestroyAsync failed %s", Utils::GetErrorString(ex->HResult)->Data());
|
||||
}
|
||||
}).wait();
|
||||
}
|
||||
connection->SetAssociation(nullptr);
|
||||
}
|
||||
|
||||
DeleteConnection(connection);
|
||||
}
|
||||
|
||||
void MeshManager::DisconectFromAddress( Windows::Xbox::Networking::SecureDeviceAddress^ address )
|
||||
{
|
||||
MeshConnection^ connection = GetConnectionFromSecureDeviceAddress(address);
|
||||
DestroyConnection(connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
void MeshManager::DestroyAndDisconnectAll()
|
||||
{
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ allConnections = GetConnections();
|
||||
for each (MeshConnection^ meshConnection in allConnections)
|
||||
{
|
||||
DestroyConnection(meshConnection);
|
||||
}
|
||||
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_connectionsLock);
|
||||
m_connections.clear();
|
||||
}
|
||||
|
||||
GetMeshPacketManager()->DeleteAllPendingAckMeshPackets();
|
||||
}
|
||||
|
||||
void MeshManager::DestroyAllTemplateAssociations()
|
||||
{
|
||||
if(GetSecureDeviceAssociationTemplate() != nullptr)
|
||||
{
|
||||
Windows::Foundation::Collections::IVectorView<Windows::Xbox::Networking::SecureDeviceAssociation^>^ associations = GetSecureDeviceAssociationTemplate()->Associations;
|
||||
if(associations == nullptr || associations->Size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogCommentFormat(L"We have %d associations on MeshManager::Initialize", associations->Size );
|
||||
for each (Windows::Xbox::Networking::SecureDeviceAssociation^ associationInTemplate in associations)
|
||||
{
|
||||
IAsyncAction^ asyncOp = associationInTemplate->DestroyAsync();
|
||||
create_task(asyncOp)
|
||||
.then([this] (task<void> t)
|
||||
{
|
||||
try
|
||||
{
|
||||
t.get(); // if t.get fails, it will throw.
|
||||
}
|
||||
catch (Platform::COMException^ ex)
|
||||
{
|
||||
LogCommentFormat( L"MeshManager::DestroyAllTemplateAssociations - DestroyAsync failed %s", Utils::GetErrorString(ex->HResult)->Data());
|
||||
}
|
||||
}).wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::Shutdown()
|
||||
{
|
||||
LogComment( L"MeshManager::Shutdown");
|
||||
|
||||
DestroyAndDisconnectAll();
|
||||
|
||||
if (m_autoConnectThread != nullptr)
|
||||
{
|
||||
m_autoConnectThread->Shutdown();
|
||||
m_autoConnectThread = nullptr;
|
||||
}
|
||||
|
||||
if (m_heartbeatThread != nullptr)
|
||||
{
|
||||
m_heartbeatThread->Shutdown();
|
||||
m_heartbeatThread = nullptr;
|
||||
}
|
||||
|
||||
if( m_associationTemplate != nullptr )
|
||||
{
|
||||
m_associationTemplate->AssociationIncoming -= m_associationIncomingToken;
|
||||
m_associationTemplate = nullptr;
|
||||
}
|
||||
|
||||
if( m_meshPacketManager != nullptr )
|
||||
{
|
||||
m_meshPacketManager->OnHelloReceived -= m_onHelloReceivedToken;
|
||||
m_meshPacketManager->OnHeartbeatReceived -= m_onHeartbeatReceivedToken;
|
||||
m_meshPacketManager->OnDebugMessage -= m_onDebugMessageReceivedToken;
|
||||
|
||||
m_meshPacketManager->Shutdown();
|
||||
m_meshPacketManager = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshManager::AreSecureDeviceAddressesEqual( Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress1, Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress2 )
|
||||
{
|
||||
if( secureDeviceAddress1 != nullptr &&
|
||||
secureDeviceAddress2 != nullptr &&
|
||||
secureDeviceAddress1->Compare(secureDeviceAddress2) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Microsoft::Xbox::Samples::NetworkMesh::MeshPacketManager^ MeshManager::GetMeshPacketManager()
|
||||
{
|
||||
return m_meshPacketManager;
|
||||
}
|
||||
|
||||
UINT MeshManager::GetHeartbeatPeriod()
|
||||
{
|
||||
if (m_heartbeatThread == nullptr)
|
||||
return 0;
|
||||
|
||||
return m_heartbeatThread->GetSendPeriod();
|
||||
}
|
||||
|
||||
void MeshManager::SetHeartbeatPeriod(UINT periodInMilliseconds)
|
||||
{
|
||||
if (m_heartbeatThread != nullptr)
|
||||
m_heartbeatThread->SetSendPeriod(periodInMilliseconds);
|
||||
}
|
||||
|
||||
void MeshManager::OnHeartbeatReceived( Microsoft::Xbox::Samples::NetworkMesh::MeshHeartbeatReceivedEvent^ args )
|
||||
{
|
||||
if(args != nullptr)
|
||||
{
|
||||
MeshConnection^ meshConnection = args->Sender;
|
||||
if(meshConnection != nullptr)
|
||||
{
|
||||
OnHeartbeat( this, args->Sender );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::OnHelloReceived( Microsoft::Xbox::Samples::NetworkMesh::MeshHelloReceivedEvent^ args )
|
||||
{
|
||||
if(args != nullptr)
|
||||
{
|
||||
LogCommentFormat( L"OnHelloReceived: Remote console: %s [%d]. RespondingToHello: %d", args->ConsoleName->Data(), args->ConsoleId, (int)args->RespondingToHello );
|
||||
|
||||
MeshConnection^ meshConnection = args->Sender;
|
||||
if(meshConnection != nullptr )
|
||||
{
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ secureDeviceAssociation = meshConnection->GetAssociation();
|
||||
if( secureDeviceAssociation == nullptr )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args->ConsoleId != 0)
|
||||
{
|
||||
meshConnection->SetConsoleId(args->ConsoleId);
|
||||
}
|
||||
|
||||
if (!args->ConsoleName->IsEmpty())
|
||||
{
|
||||
meshConnection->SetConsoleName(args->ConsoleName);
|
||||
}
|
||||
|
||||
// When the remote console sends us a Hello that wasn't a response from us, respond back with Hello
|
||||
if( args->RespondingToHello == false )
|
||||
{
|
||||
LogCommentFormat( L"OnHelloReceived: Responding to hello to %s", Utils::PrintSecureDeviceAssociation(secureDeviceAssociation, false, true)->Data() );
|
||||
m_meshPacketManager->SendHelloMessage( secureDeviceAssociation, GetLocalConsoleDisplayName(), true );
|
||||
}
|
||||
|
||||
// If the connection to them was not Initialized, mark it and fire OnPostHandshake
|
||||
ConnectionStatus connectionStatus = meshConnection->GetConnectionStatus();
|
||||
if( connectionStatus != ConnectionStatus::PostHandshake )
|
||||
{
|
||||
meshConnection->SetConnectionStatus(ConnectionStatus::PostHandshake);
|
||||
LogCommentFormat( L"Remote console %s", Utils::PrintSecureDeviceAssociation(secureDeviceAssociation, false, true)->Data() );
|
||||
LogCommentFormat( L"is now known as %s", meshConnection->GetConsoleName()->Data() );
|
||||
OnPostHandshake( this, meshConnection );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshManager::OnDebugMessageReceived( Microsoft::Xbox::Samples::NetworkMesh::DebugMessageEventArgs^ args )
|
||||
{
|
||||
DebugMessageEventArgs^ eventArgs = ref new DebugMessageEventArgs( args->Message, args->HResult);
|
||||
OnDebugMessage(this,eventArgs);
|
||||
}
|
||||
|
||||
void MeshManager::RegisterMeshPacketEventHandlers()
|
||||
{
|
||||
if(m_meshPacketManager == nullptr)
|
||||
{
|
||||
LogComment(L"Could not register for events as MeshPacketManager may have failed initializing.");
|
||||
return;
|
||||
}
|
||||
|
||||
EventHandler<MeshHelloReceivedEvent^>^ onHelloReceivedEvent = ref new EventHandler<MeshHelloReceivedEvent^>(
|
||||
[this] (Platform::Object^, MeshHelloReceivedEvent^ eventArgs)
|
||||
{
|
||||
OnHelloReceived(eventArgs);
|
||||
});
|
||||
m_onHelloReceivedToken = m_meshPacketManager->OnHelloReceived += onHelloReceivedEvent;
|
||||
|
||||
EventHandler<MeshHeartbeatReceivedEvent^>^ onHeartbeatReceivedEvent = ref new EventHandler<MeshHeartbeatReceivedEvent^>(
|
||||
[this] (Platform::Object^, MeshHeartbeatReceivedEvent^ eventArgs)
|
||||
{
|
||||
OnHeartbeatReceived(eventArgs);
|
||||
});
|
||||
m_onHeartbeatReceivedToken = m_meshPacketManager->OnHeartbeatReceived += onHeartbeatReceivedEvent;
|
||||
|
||||
EventHandler<DebugMessageEventArgs^>^ onDebugMessageEvent = ref new EventHandler<DebugMessageEventArgs^>(
|
||||
[this] (Platform::Object^, DebugMessageEventArgs^ eventArgs)
|
||||
{
|
||||
OnDebugMessageReceived(eventArgs);
|
||||
});
|
||||
m_onDebugMessageReceivedToken = m_meshPacketManager->OnDebugMessage += onDebugMessageEvent;
|
||||
}
|
||||
|
||||
void MeshManager::LogCommentFormat( LPCWSTR strMsg, ... )
|
||||
{
|
||||
WCHAR strBuffer[2048];
|
||||
|
||||
va_list args;
|
||||
va_start(args, strMsg);
|
||||
_vsnwprintf_s( strBuffer, 2048, _TRUNCATE, strMsg, args );
|
||||
strBuffer[2047] = L'\0';
|
||||
|
||||
va_end(args);
|
||||
|
||||
LogComment(ref new Platform::String(strBuffer));
|
||||
}
|
||||
|
||||
void MeshManager::LogComment( Platform::String^ strText )
|
||||
{
|
||||
DebugMessageEventArgs^ eventArgs = ref new DebugMessageEventArgs( strText, S_OK);
|
||||
OnDebugMessageReceived(eventArgs);
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include "XboxNetworkMeshDiagnosticsTraceLevel.h"
|
||||
#include "MeshThread.h"
|
||||
#include "MeshPacketManager.h"
|
||||
#include "MeshConnection.h"
|
||||
#include "MeshEvents.h"
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
ref class MeshPacketManager;
|
||||
|
||||
#define DEFAULT_HEARTBEAT_PERIOD_MILLISECONDS 2048
|
||||
|
||||
public ref class MeshManager sealed
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Pass in the template for the title's SDA and kick off the WSA initialization
|
||||
/// </summary>
|
||||
/// <param name="secureDeviceAssociationTemplateName"></param>
|
||||
MeshManager(
|
||||
uint8 localConsoleId,
|
||||
Platform::String^ secureDeviceAssociationTemplateName,
|
||||
Platform::String^ localConsoleName,
|
||||
bool dropOutOfOrderPackets
|
||||
);
|
||||
|
||||
Platform::String^ GetLocalConsoleDisplayName();
|
||||
Platform::String^ GetLocalConsoleName();
|
||||
void SetLocalConsoleName(Platform::String^ consoleName);
|
||||
|
||||
/// <summary>
|
||||
/// Return the template being used by local mesh manager
|
||||
/// </summary>
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationTemplate^ GetSecureDeviceAssociationTemplate();
|
||||
|
||||
/// <summary>
|
||||
/// Pass in the SDA you want to connect to.
|
||||
/// </summary>
|
||||
/// <param name="securedeviceAddress"></param>
|
||||
void ConnectToAddress(Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress, Platform::String^ debugName );
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ GetConnections();
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
Windows::Foundation::Collections::IVectorView<MeshConnection^>^ GetConnectionsByType(ConnectionStatus type);
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
MeshConnection^ GetConnectionFromAssociation(Windows::Xbox::Networking::SecureDeviceAssociation^ association);
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
MeshConnection^ GetConnectionFromSecureDeviceAddress(Windows::Xbox::Networking::SecureDeviceAddress^ address);
|
||||
|
||||
MeshConnection^ GetConnectionFromConsoleId(uint8 consoleId);
|
||||
|
||||
/// <summary>
|
||||
/// This will destroy the association and remove the connection from the list of all connections.
|
||||
/// </summary>
|
||||
void DestroyConnection( MeshConnection^ connection);
|
||||
|
||||
/// <summary>
|
||||
/// Given a secure device address, this will destroy the association
|
||||
/// and remove the connection from the list of all connections.
|
||||
/// </summary>
|
||||
void DisconectFromAddress( Windows::Xbox::Networking::SecureDeviceAddress^ address);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all connections and destroys all associations.
|
||||
/// </summary>
|
||||
void DestroyAndDisconnectAll();
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup winsock
|
||||
/// </summary>
|
||||
void Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
Microsoft::Xbox::Samples::NetworkMesh::MeshPacketManager^ GetMeshPacketManager();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Heartbeat period (in milliseconds)
|
||||
/// </summary>
|
||||
UINT GetHeartbeatPeriod();
|
||||
|
||||
/// <summary>
|
||||
/// sets the Heartbeat period (in milliseconds)
|
||||
/// </summary>
|
||||
void SetHeartbeatPeriod(UINT periodInMilliseconds);
|
||||
|
||||
/// <summary>
|
||||
/// // Warn the game that this connection is being disconnected. The game would have to then explicitly
|
||||
/// call DisconnectFromAddress or DisconnectFromConnection to remove him from the connection list, if needed.
|
||||
/// Otherwise, we will retry connecting to him.
|
||||
/// </summary>
|
||||
event Windows::Foundation::EventHandler<MeshConnection^>^ OnDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// This event is triggered when a proper handshake has been established between 2 connections.
|
||||
/// </summary>
|
||||
event Windows::Foundation::EventHandler<MeshConnection^>^ OnPostHandshake;
|
||||
|
||||
/// <summary>
|
||||
/// This event is triggered upon receiving heartbeats from remote connection.
|
||||
/// </summary>
|
||||
event Windows::Foundation::EventHandler<MeshConnection^>^ OnHeartbeat;
|
||||
|
||||
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::DebugMessageEventArgs^>^ OnDebugMessage;
|
||||
|
||||
internal:
|
||||
|
||||
void OnAssociationChange(
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationStateChangedEventArgs^ args,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ association );
|
||||
|
||||
/// <summary>
|
||||
/// Return the template being used by local mesh manager
|
||||
/// </summary>
|
||||
void RefreshConnections();
|
||||
|
||||
private:
|
||||
Concurrency::critical_section m_connectionsLock;
|
||||
|
||||
Microsoft::Xbox::Samples::NetworkMesh::MeshPacketManager^ m_meshPacketManager;
|
||||
Platform::String^ m_localConsoleName;
|
||||
|
||||
MeshThread^ m_autoConnectThread;
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationTemplate^ m_associationTemplate;
|
||||
std::vector<MeshConnection^> m_connections;
|
||||
bool m_dropOutOfOrderPackets;
|
||||
|
||||
MeshThread^ m_heartbeatThread;
|
||||
|
||||
void Initialize(uint8 localConsoleId);
|
||||
void RegisterMeshPacketEventHandlers();
|
||||
|
||||
MeshConnection^ AddConnection(
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociation^ secureDeviceAssociation,
|
||||
bool inComingAssociation,
|
||||
ConnectionStatus connectionStatus
|
||||
);
|
||||
|
||||
bool AreSecureDeviceAddressesEqual(
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress1,
|
||||
Windows::Xbox::Networking::SecureDeviceAddress^ secureDeviceAddress2
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the connection from the list of all connections.
|
||||
/// </summary>
|
||||
void DeleteConnection(MeshConnection^ connection);
|
||||
void DestroyAllTemplateAssociations();
|
||||
bool DoesConnectionExistInList(Windows::Foundation::Collections::IVectorView<MeshConnection^>^ list, MeshConnection^ connection);
|
||||
|
||||
///////////////////////
|
||||
// Events
|
||||
|
||||
Windows::Foundation::EventRegistrationToken m_associationIncomingToken;
|
||||
Windows::Foundation::EventRegistrationToken m_onHelloReceivedToken;
|
||||
Windows::Foundation::EventRegistrationToken m_onHeartbeatReceivedToken;
|
||||
Windows::Foundation::EventRegistrationToken m_onDebugMessageReceivedToken;
|
||||
|
||||
void OnHeartbeatReceived( Microsoft::Xbox::Samples::NetworkMesh::MeshHeartbeatReceivedEvent^ args );
|
||||
void OnHelloReceived( Microsoft::Xbox::Samples::NetworkMesh::MeshHelloReceivedEvent^ args );
|
||||
void OnDebugMessageReceived( Microsoft::Xbox::Samples::NetworkMesh::DebugMessageEventArgs^ args );
|
||||
|
||||
void OnAutoConnectWorkerThreadDoWork ( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args );
|
||||
void OnAssociationIncoming(
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationTemplate^ associationTemplate,
|
||||
Windows::Xbox::Networking::SecureDeviceAssociationIncomingEventArgs^ args
|
||||
);
|
||||
|
||||
void OnHeartbeatWorkerThreadDoWork( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args );
|
||||
|
||||
///////////////////////
|
||||
// Logging
|
||||
void LogComment( Platform::String^ strText );
|
||||
void LogCommentFormat( LPCWSTR strMsg, ... );
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "pch.h"
|
||||
#include "UserMeshConnectionPropertyBag.h"
|
||||
|
||||
using namespace Microsoft::Xbox::Samples::NetworkMesh;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
UserMeshConnectionPropertyBag::UserMeshConnectionPropertyBag(Platform::String^ xboxUserId) :
|
||||
m_xboxUserid(xboxUserId),
|
||||
m_isUserAckedReceived(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool UserMeshConnectionPropertyBag::IsUserAckedReceived()
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
return m_isUserAckedReceived;
|
||||
}
|
||||
void UserMeshConnectionPropertyBag::SetUserAckedReceived(bool val)
|
||||
{
|
||||
Concurrency::critical_section::scoped_lock lock(m_stateLock);
|
||||
m_isUserAckedReceived = val;
|
||||
}
|
||||
|
||||
}}}}
|
||||
@@ -0,0 +1,31 @@
|
||||
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
//// PARTICULAR PURPOSE.
|
||||
////
|
||||
//// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
#pragma once
|
||||
#include "MeshPacketStructs.h"
|
||||
|
||||
namespace Microsoft {
|
||||
namespace Xbox {
|
||||
namespace Samples {
|
||||
namespace NetworkMesh {
|
||||
|
||||
public ref class UserMeshConnectionPropertyBag sealed
|
||||
{
|
||||
internal:
|
||||
UserMeshConnectionPropertyBag(Platform::String^ xboxUserId);
|
||||
|
||||
public:
|
||||
bool IsUserAckedReceived();
|
||||
void SetUserAckedReceived(bool val);
|
||||
|
||||
private:
|
||||
Concurrency::critical_section m_stateLock;
|
||||
|
||||
Platform::String^ m_xboxUserid;
|
||||
volatile bool m_isUserAckedReceived;
|
||||
};
|
||||
|
||||
}}}}
|
||||
Reference in New Issue
Block a user