/*========================================================================== * * 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; }