You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
473 lines
14 KiB
473 lines
14 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1999, 2000 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: fwdserver.cpp
|
|
* Content: Implements the forwarding server portion of the server class
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 11/01/2000 rodtoll Split out from dvsereng.cpp
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dxvoicepch.h"
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_CreatePlayer"
|
|
HRESULT CDirectVoiceServerEngine::Send_CreatePlayer( DVID dvidTarget, const CVoicePlayer *pPlayer )
|
|
{
|
|
PDVPROTOCOLMSG_PLAYERJOIN pdvPlayerJoin;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_PLAYERJOIN ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvPlayerJoin = (PDVPROTOCOLMSG_PLAYERJOIN) pBufferDesc->pBufferData;
|
|
|
|
pdvPlayerJoin->dwType = DVMSGID_CREATEVOICEPLAYER;
|
|
pdvPlayerJoin->dvidID = pPlayer->GetPlayerID();
|
|
pdvPlayerJoin->dwFlags = pPlayer->GetTransportFlags();
|
|
pdvPlayerJoin->dwHostOrderID = pPlayer->GetHostOrder();
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidTarget, 1, pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending create player to 0x%x hr=0x%x", dvidTarget, hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_ConnectRefuse"
|
|
HRESULT CDirectVoiceServerEngine::Send_ConnectRefuse( DVID dvidID, HRESULT hrReason )
|
|
{
|
|
PDVPROTOCOLMSG_CONNECTREFUSE pdvConnectRefuse;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_CONNECTREFUSE ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvConnectRefuse = (PDVPROTOCOLMSG_CONNECTREFUSE) pBufferDesc->pBufferData;
|
|
|
|
pdvConnectRefuse->dwType = DVMSGID_CONNECTREFUSE;
|
|
pdvConnectRefuse->hresResult = hrReason;
|
|
pdvConnectRefuse->ucVersionMajor = DVPROTOCOL_VERSION_MAJOR;
|
|
pdvConnectRefuse->ucVersionMinor = DVPROTOCOL_VERSION_MINOR;
|
|
pdvConnectRefuse->dwVersionBuild = DVPROTOCOL_VERSION_BUILD;
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidID, 1, pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending disconnect confirm migrated to all hr=0x%x", hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_DisconnectConfirm"
|
|
HRESULT CDirectVoiceServerEngine::Send_DisconnectConfirm( DVID dvidID, HRESULT hrReason )
|
|
{
|
|
PDVPROTOCOLMSG_DISCONNECT pdvDisconnectConfirm;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_DISCONNECT ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvDisconnectConfirm = (PDVPROTOCOLMSG_DISCONNECT) pBufferDesc->pBufferData;
|
|
|
|
pdvDisconnectConfirm->dwType = DVMSGID_DISCONNECTCONFIRM;
|
|
pdvDisconnectConfirm->hresDisconnect = hrReason;
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidID, 1, pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending disconnect confirm migrated to all hr=0x%x", hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_ConnectAccept"
|
|
HRESULT CDirectVoiceServerEngine::Send_ConnectAccept( DVID dvidID )
|
|
{
|
|
PDVPROTOCOLMSG_CONNECTACCEPT pdvConnectAccept;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_CONNECTACCEPT ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvConnectAccept = (PDVPROTOCOLMSG_CONNECTACCEPT) pBufferDesc->pBufferData;
|
|
|
|
pdvConnectAccept->dwType = DVMSGID_CONNECTACCEPT;
|
|
pdvConnectAccept->dwSessionFlags = m_dvSessionDesc.dwFlags;
|
|
pdvConnectAccept->dwSessionType = m_dvSessionDesc.dwSessionType;
|
|
pdvConnectAccept->ucVersionMajor = DVPROTOCOL_VERSION_MAJOR;
|
|
pdvConnectAccept->ucVersionMinor = DVPROTOCOL_VERSION_MINOR;
|
|
pdvConnectAccept->dwVersionBuild = DVPROTOCOL_VERSION_BUILD;
|
|
pdvConnectAccept->guidCT = m_dvSessionDesc.guidCT;
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidID, 1, pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending connect accept to player hr=0x%x", hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_DeletePlayer"
|
|
HRESULT CDirectVoiceServerEngine::Send_DeletePlayer( DVID dvidID )
|
|
{
|
|
PDVPROTOCOLMSG_PLAYERQUIT pdvPlayerQuit;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_PLAYERQUIT ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvPlayerQuit = (PDVPROTOCOLMSG_PLAYERQUIT) pBufferDesc->pBufferData;
|
|
|
|
pdvPlayerQuit->dwType = DVMSGID_DELETEVOICEPLAYER;
|
|
pdvPlayerQuit->dvidID = dvidID;
|
|
|
|
hr = m_lpSessionTransport->SendToAll( pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending delete player migrated to all hr=0x%x", hr );
|
|
ReturnTransmitBuffer( pvSendContext );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_SessionLost"
|
|
HRESULT CDirectVoiceServerEngine::Send_SessionLost( HRESULT hrReason )
|
|
{
|
|
PDVPROTOCOLMSG_SESSIONLOST pdvSessionLost;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_SESSIONLOST ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvSessionLost = (PDVPROTOCOLMSG_SESSIONLOST) pBufferDesc->pBufferData;
|
|
|
|
pdvSessionLost->dwType = DVMSGID_SESSIONLOST;
|
|
pdvSessionLost->hresReason = hrReason;
|
|
|
|
hr = m_lpSessionTransport->SendToAll( pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED | DVTRANSPORT_SEND_SYNC );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending session lost to all hr=0x%x", hr );
|
|
}
|
|
|
|
ReturnTransmitBuffer( pvSendContext );
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_HostMigrateLeave"
|
|
HRESULT CDirectVoiceServerEngine::Send_HostMigrateLeave( )
|
|
{
|
|
PDVPROTOCOLMSG_HOSTMIGRATELEAVE pdvHostMigrateLeave;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_HOSTMIGRATELEAVE ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvHostMigrateLeave = (PDVPROTOCOLMSG_HOSTMIGRATELEAVE) pBufferDesc->pBufferData;
|
|
|
|
pdvHostMigrateLeave->dwType = DVMSGID_HOSTMIGRATELEAVE;
|
|
|
|
// Send this message with sync. Sync messages do not generate callbacks
|
|
//
|
|
hr = m_lpSessionTransport->SendToAll( pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED | DVTRANSPORT_SEND_SYNC );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending host migrated to all hr=0x%x", hr );
|
|
}
|
|
|
|
ReturnTransmitBuffer( pvSendContext );
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::Send_HostMigrated"
|
|
HRESULT CDirectVoiceServerEngine::Send_HostMigrated()
|
|
{
|
|
PDVPROTOCOLMSG_HOSTMIGRATED pvMigrated;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PVOID pvSendContext;
|
|
HRESULT hr;
|
|
|
|
pBufferDesc = GetTransmitBuffer( sizeof( DVPROTOCOLMSG_HOSTMIGRATED ), &pvSendContext );
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc error" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pvMigrated = (PDVPROTOCOLMSG_HOSTMIGRATED) pBufferDesc->pBufferData;
|
|
|
|
pvMigrated->dwType = DVMSGID_HOSTMIGRATED;
|
|
|
|
hr = m_lpSessionTransport->SendToAll( pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error sending host migrated to all hr=0x%x", hr );
|
|
ReturnTransmitBuffer( pvSendContext );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL CDirectVoiceServerEngine::CheckProtocolCompatible( BYTE ucMajor, BYTE ucMinor, DWORD dwBuild )
|
|
{
|
|
/*
|
|
if( ucMajor != DVPROTOCOL_VERSION_MAJOR ||
|
|
ucMinor != DVPROTOCOL_VERSION_MINOR ||
|
|
dwBuild != DVPROTOCOL_VERSION_BUILD )
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}*/
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectVoiceServerEngine::SendPlayerList"
|
|
//
|
|
// SendPlayerList
|
|
//
|
|
// This function sends a bunch of DVMSGID_PLAYERLIST messages to the
|
|
// client containing the list of current players.
|
|
//
|
|
// This will send multiple structues if the number
|
|
//
|
|
HRESULT CDirectVoiceServerEngine::SendPlayerList( DVID dvidSource, DWORD dwHostOrderID )
|
|
{
|
|
BOOL bContinueEnum = FALSE;
|
|
CVoicePlayer *lpPlayer;
|
|
CBilink *pblSearch;
|
|
|
|
HRESULT hr = DV_OK;
|
|
|
|
BOOL fAtLeastOneSent = FALSE;
|
|
DWORD dwCurrentBufferLoc;
|
|
DWORD dwNumInCurrentPacket;
|
|
PDVTRANSPORT_BUFFERDESC pBufferDesc;
|
|
PDVPROTOCOLMSG_PLAYERLIST lpdvPlayerList;
|
|
DVPROTOCOLMSG_PLAYERLIST_ENTRY *pdvPlayerEntries;
|
|
PVOID pvSendContext;
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "Building player list" );
|
|
|
|
pBufferDesc = GetTransmitBuffer(DVPROTOCOL_PLAYERLIST_MAXSIZE, &pvSendContext);
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory!" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
lpdvPlayerList = (PDVPROTOCOLMSG_PLAYERLIST) pBufferDesc->pBufferData;
|
|
|
|
pdvPlayerEntries = (DVPROTOCOLMSG_PLAYERLIST_ENTRY *) &lpdvPlayerList[1];
|
|
|
|
lpdvPlayerList->dwType = DVMSGID_PLAYERLIST;
|
|
lpdvPlayerList->dwHostOrderID = dwHostOrderID;
|
|
|
|
dwNumInCurrentPacket = 0;
|
|
dwCurrentBufferLoc = sizeof(DVPROTOCOLMSG_PLAYERLIST);
|
|
|
|
DNEnterCriticalSection( &m_csPlayerActiveList );
|
|
|
|
pblSearch = m_blPlayerActiveList.GetNext();
|
|
|
|
while( pblSearch != &m_blPlayerActiveList )
|
|
{
|
|
lpPlayer = CONTAINING_RECORD( pblSearch, CVoicePlayer, m_blNotifyList );
|
|
|
|
// We need to split the packet, start a new packet, transmit this one.
|
|
if( (dwCurrentBufferLoc+sizeof(DVPROTOCOLMSG_PLAYERLIST_ENTRY)) > DVPROTOCOL_PLAYERLIST_MAXSIZE )
|
|
{
|
|
// Wrap up current packet and transmit
|
|
lpdvPlayerList->dwNumEntries = dwNumInCurrentPacket;
|
|
|
|
pBufferDesc->dwBufferSize = dwCurrentBufferLoc;
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidSource, 1,pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING )
|
|
{
|
|
hr = DV_OK;
|
|
}
|
|
else if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Error on internal send hr=0x%x (Didn't get playerlist)", hr );
|
|
return hr;
|
|
}
|
|
|
|
// Reset for further players
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "Transmitting playerlist chunk %d players", dwNumInCurrentPacket );
|
|
|
|
pBufferDesc = GetTransmitBuffer(DVPROTOCOL_PLAYERLIST_MAXSIZE, &pvSendContext);
|
|
|
|
if( pBufferDesc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory!" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
lpdvPlayerList = (PDVPROTOCOLMSG_PLAYERLIST) pBufferDesc->pBufferData;
|
|
pdvPlayerEntries = (DVPROTOCOLMSG_PLAYERLIST_ENTRY *) &lpdvPlayerList[1];
|
|
lpdvPlayerList->dwType = DVMSGID_PLAYERLIST;
|
|
lpdvPlayerList->dwHostOrderID = dwHostOrderID;
|
|
dwCurrentBufferLoc = sizeof(DVPROTOCOLMSG_PLAYERLIST);
|
|
dwNumInCurrentPacket = 0;
|
|
fAtLeastOneSent = TRUE;
|
|
}
|
|
|
|
pdvPlayerEntries[dwNumInCurrentPacket].dvidID = lpPlayer->GetPlayerID();
|
|
pdvPlayerEntries[dwNumInCurrentPacket].dwPlayerFlags = lpPlayer->GetTransportFlags();
|
|
pdvPlayerEntries[dwNumInCurrentPacket].dwHostOrderID = lpPlayer->GetHostOrder();
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "PlayerList: Adding player ID 0x%x", lpPlayer->GetPlayerID() );
|
|
|
|
dwNumInCurrentPacket++;
|
|
dwCurrentBufferLoc += sizeof(DVPROTOCOLMSG_PLAYERLIST_ENTRY);
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "PlayerList: Got next player" );
|
|
|
|
pblSearch = pblSearch->GetNext();
|
|
}
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "PlayerList: Build Complete" );
|
|
|
|
DNLeaveCriticalSection( &m_csPlayerActiveList );
|
|
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "PlayerList: Total of %d entries", dwNumInCurrentPacket );
|
|
|
|
// Remaining entries to be sent
|
|
//
|
|
// (Or empty packet just so user gets their ID)
|
|
//
|
|
if( !fAtLeastOneSent )
|
|
{
|
|
// Wrap up current packet and transmit
|
|
lpdvPlayerList->dwNumEntries = dwNumInCurrentPacket;
|
|
|
|
pBufferDesc->dwBufferSize = dwCurrentBufferLoc;
|
|
|
|
hr = m_lpSessionTransport->SendToIDS( &dvidSource, 1, pBufferDesc, pvSendContext, DVTRANSPORT_SEND_GUARANTEED );
|
|
|
|
if( hr == DVERR_PENDING || hr == DV_OK )
|
|
{
|
|
DPFX(DPFPREP, DVF_PLAYERMANAGE_DEBUG_LEVEL, "Playerlist sent" );
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error on internal send hr=0x%x (Didn't get playerlist)", hr );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|