Files
2025-09-18 17:55:52 -04:00

228 lines
7.4 KiB
C++

//// 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"
#include "MeshPacketStatistics.h"
#include "MeshConnection.h"
#include "MeshEvents.h"
#include "MeshThread.h"
namespace Microsoft {
namespace Xbox {
namespace Samples {
namespace NetworkMesh {
static const int WSARECV_BUFFER_SIZE = 10000;
#define SKIPPED_PERCENT 5 // how much ahead do you want to skip to.
#define DEFAULT_HEARTBEAT_SIZE 0
struct MESH_PACKET_INFO
{
Windows::Xbox::Networking::SecureDeviceAssociation^ association;
std::vector<BYTE> packetBuffer;
};
struct MESH_PACKET_THAT_NEEDS_ACK
{
std::shared_ptr<MESH_PACKET_INFO> packetInfo;
uint16 messageId;
};
public ref class MeshPacketManager sealed
{
internal:
/// <summary>
/// To get MeshPacketManager, call MeshManger::GetMeshPacketManager()
/// </summary>
/// <param name="localConsoleId">Local console ID</param>
/// <param name="portNumberToBindTo">This is the sin6_port for the localSockAddress which is used to bind to the socket</param>
/// <param name="meshManager">Instance of the mesh manager</param>
MeshPacketManager(
uint8 localConsoleId,
unsigned short portNumberToBindTo,
MeshManager^ meshManager,
bool dropOutOfOrderPackets
);
public:
/// <summary>
/// Get local consoleId
/// </summary>
uint8 GetLocalConsoleId();
MeshPacketStatistics^ GetMeshPacketStatistics();
void UpdateDebugTimers( float timeDelta );
void SendChatMessage(
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
Windows::Storage::Streams::IBuffer^ buffer,
bool sendReliable
);
/// <summary>
/// gameDefinedMessageType is a 0 indexed number that the game can use to identify packet types
/// gameDefinedMessageType can be no greater than 192
/// </summary>
void SendCustomMessage(
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
uint8 gameDefinedMessageType,
Windows::Storage::Streams::IBuffer^ buffer,
bool sendReliable
);
/// <summary>
/// Resend packets until ack
/// </summary>
void SendReliablePacketsUntilACK();
float GetDebugTimeSincePacketReceive();
float GetDebugTimeSincePacketSend();
bool GetDebugInsideWSAReceive();
bool GetDebugInsideWSASend();
uint16 GetPreviousPacketMessageId();
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::MeshChatMessageReceivedEvent^>^ OnChatMessageReceived;
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::GameCustomMessageReceivedEvent^>^ OnGameCustomMessageReceived;
internal:
/// <summary>
/// The heartbeat is handled internally and shouldn't be called by the game
/// </summary>
void SendHeartbeatMessageAsync(
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
uint8 consoleId
);
/// <summary>
/// The hello handshake is handled internally and shouldn't be called by the game
/// </summary>
void SendHelloMessage(
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
Platform::String^ consoleName,
bool respondingToHello
);
/// <summary>
/// Sends an ACK for a message ID
/// </summary>
void SendAckMessage(
Windows::Xbox::Networking::SecureDeviceAssociation^ association,
uint16 messageIdToAck
);
void DeleteAllPendingAckMeshPackets();
void SetDropOutOfOrderPackets(bool val);
void SetHeartbeatSize(UINT size);
UINT GetHeartbeatSize();
UINT16 IncrementPacketMessageId();
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::MeshHeartbeatReceivedEvent^>^ OnHeartbeatReceived;
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::MeshHelloReceivedEvent^>^ OnHelloReceived;
event Windows::Foundation::EventHandler<Microsoft::Xbox::Samples::NetworkMesh::MeshAckReceivedEvent^>^ OnAckReceived;
internal:
/// <summary>
/// The MeshManager ripples the debug event to its own OnDebugMessage so the caller can see debug events in the MeshPacketManager
/// </summary>
event Windows::Foundation::EventHandler<DebugMessageEventArgs^>^ OnDebugMessage;
/// <summary>
/// Called by the MeshManager when shutting down
/// </summary>
void Shutdown();
private:
void GetPacketWithHeader(
size_t packetSize,
uint8 messageType,
std::vector<BYTE>& packetBuffer,
bool sendReliable
);
void QueuePacketToSend(
std::shared_ptr<MESH_PACKET_INFO> packetInfo
);
void ProcessPacket(
Microsoft::Xbox::Samples::NetworkMesh::MeshConnection^ meshConnection,
BYTE* packetBuffer
);
Platform::Array<BYTE>^ ConvertSenderSocketAddressToArray(
BYTE* buffer,
int bufferSize
);
void LogMeshPacketManagerComment(
Platform::String^ message
);
void LogMeshPacketManagerCommentWithError(
Platform::String^ message,
HRESULT hr
);
bool ShouldPacketBeDropped( Microsoft::Xbox::Samples::NetworkMesh::MeshPacketHeader& packet );
void RecordMessageIfSendingReliable(
std::shared_ptr<MESH_PACKET_INFO> packetInfo
);
MeshConnection^ GetMeshConnection( SOCKADDR_STORAGE senderSocketAddress );
void SendReliablePacketsToConsolesWhoHaveNotAcked();
std::vector< std::shared_ptr<MESH_PACKET_THAT_NEEDS_ACK> > GetMeshPacketsThatNeedAckCopy();
void DeleteMeshPacketWhenGotAck(uint16 messageId);
void SocketReceiveWorkerThreadDoWork( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args );
void SocketSendWorkerThreadDoWork( Microsoft::Xbox::Samples::NetworkMesh::ProcessThreadsEventArgs^ args );
void ProcessSendPacket( std::shared_ptr<MESH_PACKET_INFO> packetInfo );
void SetDebugTimeSincePacketReceive(float val);
void SetDebugTimeSincePacketSend(float val);
void SetDebugInsideWSAReceive(bool val);
void SetDebugInsideWSASend(bool val);
void SetPreviousPacketMessageId(uint16 val);
private:
SOCKET m_localSocket;
SOCKADDR_IN6 m_localSockAddress;
uint8 m_localConsoleId;
LONG m_packetMessageId;
uint16 m_previousPacketMessageId;
MeshPacketStatistics^ m_meshPacketStatistics;
Platform::WeakReference m_meshManager;
bool m_dropOutOfOrderPackets;
MeshThread^ m_socketReceiveThread;
BYTE m_bufferForWSARecv[WSARECV_BUFFER_SIZE];
MeshThread^ m_socketSendThread;
Concurrency::critical_section m_sendLock;
std::queue< std::shared_ptr<MESH_PACKET_INFO> > m_packetsToSend;
HANDLE m_sendWakeUpEventHandle;
Concurrency::critical_section m_debugStatsLock;
Concurrency::critical_section m_stateLock;
float m_debugTimeSincePacketReceive;
float m_debugTimeSincePacketSend;
bool m_debugInsideWSAReceive;
bool m_debugInsideWSASend;
UINT m_heartbeatMessageSize;
Concurrency::critical_section m_meshPacketsThatNeedAckLock;
std::vector< std::shared_ptr<MESH_PACKET_THAT_NEEDS_ACK> > m_meshPacketsThatNeedAck;
LARGE_INTEGER m_timerFrequency;
LARGE_INTEGER m_timerLastSendReliablePacketsUntilACK;
};
}}}}