2026-03-01 12:16:08 +08:00
# include "stdafx.h"
# include "DQRNetworkManager.h"
# include "PartyController.h"
# include <collection.h>
# include <ppltasks.h>
# include <ws2tcpip.h>
# include "..\Minecraft.World\StringHelpers.h"
# include "base64.h"
# ifdef _DURANGO
# include "..\Minecraft.World\DurangoStats.h"
# endif
# include "ChatIntegrationLayer.h"
using namespace Concurrency ;
using namespace Windows : : Foundation : : Collections ;
DQRNetworkManagerEventHandlers : : DQRNetworkManagerEventHandlers ( DQRNetworkManager * pDQRNet )
{
m_pDQRNet = pDQRNet ;
}
void DQRNetworkManagerEventHandlers : : Setup ( WXNRs : : Session ^ session )
{
try
{
m_dataReceivedToken = session - > DataReceived + = ref new Windows : : Foundation : : EventHandler < WXNRs : : DataReceivedEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : DataReceivedHandler ) ;
m_sessionStatusToken = session - > SessionStatusUpdate + = ref new Windows : : Foundation : : EventHandler < WXNRs : : SessionStatusUpdateEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : SessionStatusUpdateHandler ) ;
m_sessionAddressToken = session - > SessionAddressDataChanged + = ref new Windows : : Foundation : : EventHandler < WXNRs : : SessionAddressDataChangedEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : SessionAddressDataChangedHandler ) ;
m_addedSessionToken = session - > AddedSessionAddress + = ref new Windows : : Foundation : : EventHandler < WXNRs : : AddedSessionAddressEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : AddedSessionAddressHandler ) ;
m_removedSessionToken = session - > RemovedSessionAddress + = ref new Windows : : Foundation : : EventHandler < WXNRs : : RemovedSessionAddressEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : RemovedSessionAddressHandler ) ;
m_globalDataToken = session - > GlobalSessionDataChanged + = ref new Windows : : Foundation : : EventHandler < WXNRs : : GlobalSessionDataChangedEventArgs ^ > ( this , & DQRNetworkManagerEventHandlers : : GlobalSessionDataChangedHandler ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
}
void DQRNetworkManagerEventHandlers : : Pulldown ( WXNRs : : Session ^ session )
{
try
{
session - > DataReceived - = m_dataReceivedToken ;
session - > SessionStatusUpdate - = m_sessionStatusToken ;
session - > SessionAddressDataChanged - = m_sessionAddressToken ;
session - > AddedSessionAddress - = m_addedSessionToken ;
session - > RemovedSessionAddress - = m_removedSessionToken ;
session - > GlobalSessionDataChanged - = m_globalDataToken ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
}
// This event handler is called directly by the realtime session layer, when data is received. We split this data into into data that is meant to be
// handled internally by the DQRNetworkManager, and that which is meant to be passed on to the game itself as communication between players.
void DQRNetworkManagerEventHandlers : : DataReceivedHandler ( Platform : : Object ^ session , WXNRs : : DataReceivedEventArgs ^ args )
{
// DQRNetworkManager::LogCommentFormat(L"DataReceivedHandler session addr: 0x%x (%d bytes)",args->SessionAddress,args->Data->Length);
if ( session = = m_pDQRNet - > m_XRNS_Session )
{
EnterCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
DQRNetworkManager : : RTS_Message rtsMessage ;
if ( args - > ChannelId = = WXNRs : : ChannelId : : DefaultChatReceive )
{
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_DATA_RECEIVED_CHAT ;
}
else
{
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_DATA_RECEIVED ;
}
rtsMessage . m_sessionAddress = args - > SessionAddress ;
rtsMessage . m_dataSize = args - > Data - > Length ;
2026-03-08 19:08:36 -04:00
rtsMessage . m_pucData = static_cast < unsigned char * > ( malloc ( rtsMessage . m_dataSize ) ) ;
2026-03-01 12:16:08 +08:00
memcpy ( rtsMessage . m_pucData , args - > Data - > Data , rtsMessage . m_dataSize ) ;
m_pDQRNet - > m_RTSMessageQueueIncoming . push ( rtsMessage ) ;
LeaveCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
}
}
// This event handler is called by the realtime session layer, when session address data is updated. We don't currently use session address data.
void DQRNetworkManagerEventHandlers : : SessionAddressDataChangedHandler ( Platform : : Object ^ session , WXNRs : : SessionAddressDataChangedEventArgs ^ args )
{
DQRNetworkManager : : LogComment ( L " SessionAddressDataChangedHandler " ) ;
}
// This event handler is called by the realtime session layer when a session changes status. We use this to determine that a connection has been made made to the host,
// and the case when a connection has been terminated.
void DQRNetworkManagerEventHandlers : : SessionStatusUpdateHandler ( Platform : : Object ^ session , WXNRs : : SessionStatusUpdateEventArgs ^ args )
{
DQRNetworkManager : : LogComment ( L " SessionStatusUpdateHandler " ) ;
if ( m_pDQRNet - > m_XRNS_Session = = session )
{
switch ( args - > NewStatus )
{
case WXNRs : : SessionStatus : : Active :
{
DQRNetworkManager : : LogComment ( L " Session active " ) ;
m_pDQRNet - > m_XRNS_LocalAddress = m_pDQRNet - > m_XRNS_Session - > LocalSessionAddress ;
m_pDQRNet - > m_XRNS_OldestAddress = m_pDQRNet - > m_XRNS_Session - > OldestSessionAddress ;
EnterCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
DQRNetworkManager : : RTS_Message rtsMessage ;
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_STATUS_ACTIVE ;
rtsMessage . m_sessionAddress = 0 ;
rtsMessage . m_dataSize = 0 ;
rtsMessage . m_pucData = 0 ;
m_pDQRNet - > m_RTSMessageQueueIncoming . push ( rtsMessage ) ;
LeaveCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
}
break ;
case WXNRs : : SessionStatus : : Terminated :
{
DQRNetworkManager : : LogComment ( L " Session terminated " ) ;
EnterCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
DQRNetworkManager : : RTS_Message rtsMessage ;
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_STATUS_TERMINATED ;
rtsMessage . m_sessionAddress = 0 ;
rtsMessage . m_dataSize = 0 ;
rtsMessage . m_pucData = 0 ;
m_pDQRNet - > m_RTSMessageQueueIncoming . push ( rtsMessage ) ;
LeaveCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
}
break ;
case WXNRs : : SessionStatus : : Activating :
DQRNetworkManager : : LogComment ( L " Session activating " ) ;
break ;
case WXNRs : : SessionStatus : : Terminating :
DQRNetworkManager : : LogComment ( L " Session terminating " ) ;
break ;
}
}
}
// This event is called from the realtime session layer to notify any clients that a new endpoint has been connected into the network mesh.
void DQRNetworkManagerEventHandlers : : AddedSessionAddressHandler ( Platform : : Object ^ session , WXNRs : : AddedSessionAddressEventArgs ^ args )
{
DQRNetworkManager : : LogCommentFormat ( L " AddedSessionAddressHandler session address 0x%x " , args - > SessionAddress ) ;
EnterCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
DQRNetworkManager : : RTS_Message rtsMessage ;
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_ADDED_SESSION_ADDRESS ;
rtsMessage . m_sessionAddress = args - > SessionAddress ;
rtsMessage . m_dataSize = 0 ;
rtsMessage . m_pucData = 0 ;
m_pDQRNet - > m_RTSMessageQueueIncoming . push ( rtsMessage ) ;
LeaveCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
}
// This event is called from the realtime session layer to notify any clients that an endpoint has been removed from the network mesh.
void DQRNetworkManagerEventHandlers : : RemovedSessionAddressHandler ( Platform : : Object ^ session , WXNRs : : RemovedSessionAddressEventArgs ^ args )
{
DQRNetworkManager : : LogCommentFormat ( L " RemovedSessionAddressHandler session address 0x%x " , args - > SessionAddress ) ;
EnterCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
DQRNetworkManager : : RTS_Message rtsMessage ;
rtsMessage . m_eType = DQRNetworkManager : : eRTSMessageType : : RTS_MESSAGE_REMOVED_SESSION_ADDRESS ;
rtsMessage . m_sessionAddress = args - > SessionAddress ;
rtsMessage . m_dataSize = 0 ;
rtsMessage . m_pucData = 0 ;
m_pDQRNet - > m_RTSMessageQueueIncoming . push ( rtsMessage ) ;
LeaveCriticalSection ( & m_pDQRNet - > m_csRTSMessageQueueIncoming ) ;
}
// This event is called from the realtime session layer when session global data has been updated. We don't currently use global session data.
void DQRNetworkManagerEventHandlers : : GlobalSessionDataChangedHandler ( Platform : : Object ^ session , WXNRs : : GlobalSessionDataChangedEventArgs ^ args )
{
DQRNetworkManager : : LogComment ( L " GlobalSessionDataChangedHandler " ) ;
}
void DQRNetworkManager : : UpdateRTSStats ( )
{
Platform : : Array < unsigned int > ^ sessionAddresses = nullptr ;
try
{
sessionAddresses = m_XRNS_Session - > GetAllRemoteSessionAddresses ( WXNRs : : RemoteSessionAddressStateOptions : : All , WXNRs : : RemoteSessionAddressConnectivityOptions : : All ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
if ( sessionAddresses )
{
unsigned int totalBytes = 0 ;
unsigned int totalSends = 0 ;
for ( unsigned int i = 0 ; i < sessionAddresses - > Length ; i + + )
{
try
{
totalBytes + = m_XRNS_Session - > GetSendChannelOutstandingBytes ( sessionAddresses - > get ( i ) , WXNRs : : ChannelId : : DefaultGameSend ) ;
totalSends + = m_XRNS_Session - > GetSendChannelOutstandingSends ( sessionAddresses - > get ( i ) , WXNRs : : ChannelId : : DefaultGameSend ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
}
m_RTS_Stat_totalBytes = totalBytes ;
m_RTS_Stat_totalSends = totalSends ;
}
else
{
m_RTS_Stat_totalBytes = 0 ;
m_RTS_Stat_totalSends = 0 ;
}
}
void DQRNetworkManager : : ProcessRTSMessagesIncoming ( )
{
EnterCriticalSection ( & m_csRTSMessageQueueIncoming ) ;
while ( m_RTSMessageQueueIncoming . size ( ) > 0 )
{
RTS_Message message = m_RTSMessageQueueIncoming . front ( ) ;
switch ( message . m_eType )
{
case eRTSMessageType : : RTS_MESSAGE_DATA_RECEIVED :
Process_RTS_MESSAGE_DATA_RECEIVED ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_DATA_RECEIVED_CHAT :
Process_RTS_MESSAGE_DATA_RECEIVED_CHAT ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_ADDED_SESSION_ADDRESS :
Process_RTS_MESSAGE_ADDED_SESSION_ADDRESS ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_REMOVED_SESSION_ADDRESS :
Process_RTS_MESSAGE_REMOVED_SESSION_ADDRESS ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_STATUS_ACTIVE :
Process_RTS_MESSAGE_STATUS_ACTIVE ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_STATUS_TERMINATED :
Process_RTS_MESSAGE_STATUS_TERMINATED ( message ) ;
break ;
default :
break ;
}
m_RTSMessageQueueIncoming . pop ( ) ;
}
LeaveCriticalSection ( & m_csRTSMessageQueueIncoming ) ;
} ;
void DQRNetworkManager : : Process_RTS_MESSAGE_DATA_RECEIVED ( RTS_Message & message )
{
DQRConnectionInfo * connectionInfo ;
if ( m_isHosting )
{
connectionInfo = m_sessionAddressToConnectionInfoMapHost [ message . m_sessionAddress ] ;
}
else
{
connectionInfo = & m_connectionInfoClient ;
}
// Handle any header data, and actual data, in our stream. Data is as follows:
// Byte 0 Byte 1
// fccsssss ssssssss
//
// Where: f is 0 if this is normal data send (to be passed up to the game), or is 1 if this is to be internally processed
// cc is the channel number that the data belongs to (0 to 3 representing actual player indices)
// sssssssssssss is the count of data bytes to follow (range 0 - 8191)
BYTE * pNextByte = message . m_pucData ;
BYTE * pEndByte = pNextByte + message . m_dataSize ;
do
{
BYTE byte = * pNextByte ;
switch ( connectionInfo - > m_state )
{
case DQRConnectionInfo : : ConnectionState_HeaderByte0 :
connectionInfo - > m_currentChannel = ( byte > > 5 ) & 3 ;
connectionInfo - > m_internalFlag = ( ( byte & 0x80 ) = = 0x80 ) ;
// Byte transfer mode. Bits 0-4 of this byte represent the upper 5 bits of our count of bytes to transfer... lower 8-bits will follow
connectionInfo - > m_bytesRemaining = ( ( int ) ( byte & 0x1f ) ) < < 8 ;
connectionInfo - > m_state = DQRConnectionInfo : : ConnectionState_HeaderByte1 ;
connectionInfo - > m_internalDataState = DQRConnectionInfo : : ConnectionState_InternalHeaderByte ;
pNextByte + + ;
break ;
case DQRConnectionInfo : : ConnectionState_HeaderByte1 :
// Add in the lower 8 bits of our byte count, the upper 5 were obtained from the first header byte.
connectionInfo - > m_bytesRemaining | = byte ;
// If there isn't any data following, then just go back to the initial state expecting another header byte.
if ( connectionInfo - > m_bytesRemaining = = 0 )
{
connectionInfo - > m_state = DQRConnectionInfo : : ConnectionState_HeaderByte0 ;
}
else
{
connectionInfo - > m_state = DQRConnectionInfo : : ConnectionState_ReadBytes ;
}
pNextByte + + ;
break ;
case DQRConnectionInfo : : ConnectionState_ReadBytes :
// At this stage we can send up to connectionInfo->m_bytesRemaining bytes, or the number of bytes that we have remaining in the data received, whichever is lowest.
2026-03-08 19:08:36 -04:00
int bytesInBuffer = static_cast < int > ( pEndByte - pNextByte ) ;
2026-03-01 12:16:08 +08:00
int bytesToReceive = ( ( connectionInfo - > m_bytesRemaining < bytesInBuffer ) ? connectionInfo - > m_bytesRemaining : bytesInBuffer ) ;
if ( connectionInfo - > m_internalFlag )
{
BytesReceivedInternal ( connectionInfo , message . m_sessionAddress , pNextByte , bytesToReceive ) ;
}
else
{
BytesReceived ( connectionInfo - > m_smallId [ connectionInfo - > m_currentChannel ] , pNextByte , bytesToReceive ) ;
}
// Adjust counts and pointers
pNextByte + = bytesToReceive ;
connectionInfo - > m_bytesRemaining - = bytesToReceive ;
// Set state back to expect a header if there is no more data bytes to receive
if ( connectionInfo - > m_bytesRemaining = = 0 )
{
connectionInfo - > m_state = DQRConnectionInfo : : ConnectionState_HeaderByte0 ;
}
break ;
}
} while ( pNextByte ! = pEndByte ) ;
free ( message . m_pucData ) ;
}
void DQRNetworkManager : : Process_RTS_MESSAGE_DATA_RECEIVED_CHAT ( RTS_Message & message )
{
if ( m_chat )
{
m_chat - > OnIncomingChatMessage ( message . m_sessionAddress , Platform : : ArrayReference < BYTE > ( message . m_pucData , message . m_dataSize ) ) ;
free ( message . m_pucData ) ;
}
}
void DQRNetworkManager : : Process_RTS_MESSAGE_ADDED_SESSION_ADDRESS ( RTS_Message & message )
{
if ( m_chat )
{
m_chat - > OnNewSessionAddressAdded ( message . m_sessionAddress ) ;
}
// New session address - add a mapping for it
if ( m_isHosting )
{
auto it = m_sessionAddressToConnectionInfoMapHost . find ( message . m_sessionAddress ) ;
DQRConnectionInfo * connectionInfo ;
if ( it = = m_sessionAddressToConnectionInfoMapHost . end ( ) )
{
connectionInfo = new DQRConnectionInfo ( ) ;
m_sessionAddressToConnectionInfoMapHost [ message . m_sessionAddress ] = connectionInfo ;
}
else
{
// This shouldn't happen as we should be removing mappings as session addresses are removed.
connectionInfo = it - > second ;
connectionInfo - > Reset ( ) ;
}
}
}
void DQRNetworkManager : : Process_RTS_MESSAGE_REMOVED_SESSION_ADDRESS ( RTS_Message & message )
{
if ( m_chat )
{
m_chat - > RemoveRemoteConsole ( message . m_sessionAddress ) ;
}
if ( m_isHosting )
{
auto it = m_sessionAddressToConnectionInfoMapHost . find ( message . m_sessionAddress ) ;
if ( it ! = m_sessionAddressToConnectionInfoMapHost . end ( ) )
{
delete it - > second ;
m_sessionAddressToConnectionInfoMapHost . erase ( it ) ;
RemoveRoomSyncPlayersWithSessionAddress ( message . m_sessionAddress ) ;
SendRoomSyncInfo ( ) ;
}
}
else
{
// As the client, if we are disonnected from the host, then it is all over. Proceed as if leaving the room.
if ( message . m_sessionAddress = = m_hostSessionAddress )
{
LeaveRoom ( ) ;
}
}
}
void DQRNetworkManager : : Process_RTS_MESSAGE_STATUS_ACTIVE ( RTS_Message & message )
{
// When we detect that the session has become active, we start sending unreliable packets, until we get some data back. This is because there is an issue with the
// realtime session layer where it is telling us that the connection is active a bit to early, and it will disconnect if it receives a packet that must be reliable in this
// state.
if ( ! m_isHosting )
{
m_firstUnreliableSendTime = 0 ;
m_hostSessionAddress = m_XRNS_OldestAddress ;
// Also initialise the status of this connection
m_connectionInfoClient . Reset ( ) ;
SetState ( DQRNetworkManager : : DNM_INT_STATE_JOINING_SENDING_UNRELIABLE ) ;
}
}
void DQRNetworkManager : : Process_RTS_MESSAGE_STATUS_TERMINATED ( RTS_Message & message )
{
if ( m_state = = DQRNetworkManager : : DNM_INT_STATE_JOINING_WAITING_FOR_ACTIVE_SESSION )
{
m_joinCreateSessionAttempts + + ;
if ( m_joinCreateSessionAttempts > DQRNetworkManager : : JOIN_CREATE_SESSION_MAX_ATTEMPTS )
{
SetState ( DQRNetworkManager : : DNM_INT_STATE_JOINING_FAILED ) ;
}
else
{
SetState ( DQRNetworkManager : : DNM_INT_STATE_JOINING_GET_SDA ) ;
}
}
}
int DQRNetworkManager : : _RTSDoWorkThread ( void * lpParameter )
{
2026-03-08 19:08:36 -04:00
DQRNetworkManager * pDQR = static_cast < DQRNetworkManager * > ( lpParameter ) ;
2026-03-01 12:16:08 +08:00
return pDQR - > RTSDoWorkThread ( ) ;
}
static const DWORD XRNS_TERMINATE_LOCAL_SESSION_FLAG_IMMEDIATE = 0x00000001 ;
int DQRNetworkManager : : RTSDoWorkThread ( )
{
do
{
if ( m_XRNS_Session )
{
try
{
m_XRNS_Session - > DoWork ( 20 ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
UpdateRTSStats ( ) ;
}
else
{
Sleep ( 20 ) ;
}
ProcessRTSMessagesOutgoing ( ) ;
} while ( true ) ;
}
void DQRNetworkManager : : ProcessRTSMessagesOutgoing ( )
{
EnterCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
while ( m_RTSMessageQueueOutgoing . size ( ) > 0 )
{
RTS_Message message = m_RTSMessageQueueOutgoing . front ( ) ;
switch ( message . m_eType )
{
case eRTSMessageType : : RTS_MESSAGE_START_CLIENT :
Process_RTS_MESSAGE_START_CLIENT ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_START_HOST :
Process_RTS_MESSAGE_START_HOST ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_TERMINATE :
Process_RTS_MESSAGE_TERMINATE ( message ) ;
break ;
case eRTSMessageType : : RTS_MESSAGE_SEND_DATA :
Process_RTS_MESSAGE_SEND_DATA ( message ) ;
break ;
default :
break ;
}
m_RTSMessageQueueOutgoing . pop ( ) ;
}
LeaveCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
} ;
void DQRNetworkManager : : Process_RTS_MESSAGE_START_CLIENT ( RTS_Message & message )
{
if ( m_XRNS_Session )
{
m_eventHandlers - > Pulldown ( m_XRNS_Session ) ;
// Close XRNS session
try
{
m_XRNS_Session - > TerminateLocalSession ( XRNS_TERMINATE_LOCAL_SESSION_FLAG_IMMEDIATE ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
m_XRNS_Session = nullptr ;
}
m_XRNS_Session = ref new WXNRs : : Session ( m_localSocketAddress , m_remoteSocketAddress , MAX_PLAYERS_IN_TEMPLATE , 0 ) ;
m_XRNS_Session - > MinSendRate = 512000 ;
LogCommentFormat ( L " connect retry period %d retries %d, data retry count %d, data retry timeout %d \n " , m_XRNS_Session - > ConnectRetryPeriod , m_XRNS_Session - > MaxConnectRetries , m_XRNS_Session - > MaxDataRetries , m_XRNS_Session - > MinDataRetryTimeout ) ;
m_XRNS_Session - > MaxConnectRetries = 50 ; // 50 at 100ms intervals = 5 seconds of attempting to connect
m_eventHandlers - > Setup ( m_XRNS_Session ) ;
}
void DQRNetworkManager : : Process_RTS_MESSAGE_START_HOST ( RTS_Message & message )
{
m_XRNS_Session = ref new WXNRs : : Session ( m_localSocketAddress , MAX_PLAYERS_IN_TEMPLATE , 0 ) ;
m_XRNS_Session - > MinSendRate = 512000 ;
m_XRNS_Session - > MaxConnectRetries = 50 ; // 50 at 100ms intervals = 5 seconds of attempting to connect
m_eventHandlers - > Setup ( m_XRNS_Session ) ;
}
void DQRNetworkManager : : Process_RTS_MESSAGE_TERMINATE ( RTS_Message & message )
{
if ( m_XRNS_Session )
{
m_eventHandlers - > Pulldown ( m_XRNS_Session ) ;
// Close XRNS session
try
{
m_XRNS_Session - > TerminateLocalSession ( XRNS_TERMINATE_LOCAL_SESSION_FLAG_IMMEDIATE ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
m_XRNS_Session = nullptr ;
}
}
void DQRNetworkManager : : Process_RTS_MESSAGE_SEND_DATA ( RTS_Message & message )
{
if ( m_XRNS_Session )
{
unsigned int sessionAddress = message . m_sessionAddress ;
try
{
if ( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_BROADCAST_MODE )
{
sessionAddress = m_XRNS_Session - > LocalSessionAddress ;
}
m_XRNS_Session - > Send ( ( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_GAME_CHANNEL ) ? WXNRs : : ChannelId : : DefaultGameSend : WXNRs : : ChannelId : : DefaultChatSend ,
( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_BROADCAST_MODE ) ? WXNRs : : SendExceptionType : : ExcludedAddresses : WXNRs : : SendExceptionType : : IncludedAddresses ,
Platform : : ArrayReference < unsigned int > ( & message . m_sessionAddress , 1 ) ,
Platform : : ArrayReference < BYTE > ( message . m_pucData , message . m_dataSize ) ,
0 ,
( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_RELIABLE ) ? WXNRs : : Send_Reliability : : Reliable : WXNRs : : Send_Reliability : : NonReliable ,
( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_SEQUENTIAL ) ? WXNRs : : Send_Sequence : : Sequential : WXNRs : : Send_Sequence : : NonSequential ,
WXNRs : : Send_Ack : : AckNormal ,
( message . m_flags & eRTSFlags : : RTS_MESSAGE_FLAG_COALESCE ) ? WXNRs : : Send_Coalesce : : CoalesceDelay : WXNRs : : Send_Coalesce : : CoalesceNever ,
WXNRs : : Send_MiscState : : NoMiscState ) ;
}
catch ( Platform : : COMException ^ ex )
{
// swallow exceptions
}
catch ( . . . )
{
// swallow exceptions
}
}
free ( message . m_pucData ) ;
}
void DQRNetworkManager : : RTS_StartCient ( )
{
EnterCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
RTS_Message message ;
message . m_eType = eRTSMessageType : : RTS_MESSAGE_START_CLIENT ;
2026-03-08 19:08:36 -04:00
message . m_pucData = nullptr ;
2026-03-01 12:16:08 +08:00
message . m_dataSize = 0 ;
m_RTSMessageQueueOutgoing . push ( message ) ;
LeaveCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
}
void DQRNetworkManager : : RTS_StartHost ( )
{
EnterCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
RTS_Message message ;
message . m_eType = eRTSMessageType : : RTS_MESSAGE_START_HOST ;
2026-03-08 19:08:36 -04:00
message . m_pucData = nullptr ;
2026-03-01 12:16:08 +08:00
message . m_dataSize = 0 ;
m_RTSMessageQueueOutgoing . push ( message ) ;
LeaveCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
}
void DQRNetworkManager : : RTS_Terminate ( )
{
EnterCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
RTS_Message message ;
message . m_eType = eRTSMessageType : : RTS_MESSAGE_TERMINATE ;
2026-03-08 19:08:36 -04:00
message . m_pucData = nullptr ;
2026-03-01 12:16:08 +08:00
message . m_dataSize = 0 ;
m_RTSMessageQueueOutgoing . push ( message ) ;
LeaveCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
}
void DQRNetworkManager : : RTS_SendData ( unsigned char * pucData , unsigned int dataSize , unsigned int sessionAddress , bool reliable , bool sequential , bool coalesce , bool broadcastMode , bool gameChannel )
{
EnterCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
RTS_Message message ;
message . m_eType = eRTSMessageType : : RTS_MESSAGE_SEND_DATA ;
2026-03-08 19:08:36 -04:00
message . m_pucData = static_cast < unsigned char * > ( malloc ( dataSize ) ) ;
2026-03-01 12:16:08 +08:00
memcpy ( message . m_pucData , pucData , dataSize ) ;
message . m_dataSize = dataSize ;
message . m_sessionAddress = sessionAddress ;
message . m_flags = 0 ;
if ( reliable ) message . m_flags | = eRTSFlags : : RTS_MESSAGE_FLAG_RELIABLE ;
if ( sequential ) message . m_flags | = eRTSFlags : : RTS_MESSAGE_FLAG_SEQUENTIAL ;
if ( coalesce ) message . m_flags | = eRTSFlags : : RTS_MESSAGE_FLAG_COALESCE ;
if ( broadcastMode ) message . m_flags | = eRTSFlags : : RTS_MESSAGE_FLAG_BROADCAST_MODE ;
if ( gameChannel ) message . m_flags | = eRTSFlags : : RTS_MESSAGE_FLAG_GAME_CHANNEL ;
m_RTSMessageQueueOutgoing . push ( message ) ;
LeaveCriticalSection ( & m_csRTSMessageQueueOutgoing ) ;
}