This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -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;
};
}}}}