#include "precomp.h" #include "fsdiag.h" DEBUG_FILEZONE(ZONE_T120_MSMCSTCP); #include #include #include #include /* T120qos.cpp * * Copyright (c) 1997 by Microsoft Corporation * * Abstract: * * Global Variables: * * g_pIQoS - Global interface pointer to QoS interface * g_dwLastQoSCB - timestamp of last QoS notification obtained via GetTickCount * g_dwSentSinceLastQoS - bytes sent since last QoS notification (or epoch) * */ // IQOS interface pointer and resources request LPIQOS g_pIQoS = NULL; T120RRQ g_aRRq; // Global last QoS notification time stamp DWORD g_dwLastQoSCB = 0; DWORD g_dwSentSinceLastQoS = 0; BOOL g_fResourcesRequested = FALSE; // NOTE: Since connections through this transport typically // consist of a single socket connection, followed by // disconnection, followed by multiple connections, the // following heuristic count is used to prevent on-off-on // initialization of QoS at the time the first call is started. // It represents the minimum number of socket connections that // must be initiated (without an intervening disconnect of all // connected sockets) before QoS initialization takes place. #define MIN_CONNECTION_COUNT (DEFAULT_NUMBER_OF_PRIORITIES - 1) WORD g_wConnectionCount = 0; // extern from transprt.cpp to detect no connections ///// QOS related stuff /////////////////////////////////// HRESULT CALLBACK QosNotifyDataCB ( LPRESOURCEREQUESTLIST lpResourceRequestList, DWORD_PTR dwThis) { HRESULT hr=NOERROR; LPRESOURCEREQUESTLIST prrl=lpResourceRequestList; int i; int iBWUsageId; for (i=0, iBWUsageId = -1L; i<(int)lpResourceRequestList->cRequests; i++) { if (lpResourceRequestList->aRequests[i].resourceID == RESOURCE_OUTGOING_BANDWIDTH) iBWUsageId = i; } if (iBWUsageId != -1L) { QoSLock(); // Calculate effective bits-per second rate: // // 1000 milliseconds per second // 8 bits per byte // int nEffRate = MulDiv ( g_dwSentSinceLastQoS, 1000 * 8, GetTickCount() - g_dwLastQoSCB ); // Report bandwidth usage to QoS: // // Are we using less than the available bandwidth? if ( ( nEffRate ) < lpResourceRequestList->aRequests[iBWUsageId].nUnitsMin ) { // Request our effective usage lpResourceRequestList->aRequests[iBWUsageId].nUnitsMin = nEffRate; } else { // Request everything by not modifying nUnitsMin ; } g_dwLastQoSCB = GetTickCount(); g_dwSentSinceLastQoS = 0; QoSUnlock(); } return hr; } VOID InitializeQoS( VOID ) { DWORD dwRes; HRESULT hRet; // Already initialized? if ( g_fResourcesRequested ) return; // If the number of connections has not reached the // trigger count, defer QoS initialization (see MIN_CONNECTION_COUNT // comment above) if ( g_wConnectionCount < MIN_CONNECTION_COUNT ) { g_wConnectionCount++; return; } // Initialize QoS. If it fails, that's Ok, we'll do without it. // No need to set the resource ourselves, this now done by the UI if (NULL == g_pIQoS) { if (0 != (hRet = CoCreateInstance( CLSID_QoS,NULL, CLSCTX_INPROC_SERVER, IID_IQoS, (void **) &g_pIQoS))) { WARNING_OUT (("Unable to initalize QoS: %x", hRet)); g_pIQoS = (LPIQOS)NULL; // Tolerate failure, operate w/o QoS return; } } // Initialize our request for bandwidth usage. g_aRRq.cResourceRequests = 1; g_aRRq.aResourceRequest[0].resourceID = RESOURCE_OUTGOING_BANDWIDTH; g_aRRq.aResourceRequest[0].nUnitsMin = 0; // Register with the QoS module. Even if this call fails, // that's Ok, we'll do without the QoS support dwRes = (HRESULT)g_pIQoS->RequestResources((GUID *)&MEDIA_TYPE_T120DATA, (LPRESOURCEREQUESTLIST)&g_aRRq, QosNotifyDataCB, NULL ); if ( 0 == dwRes ) { g_fResourcesRequested = TRUE; } } VOID DeInitializeQoS( VOID ) { if (NULL != g_pIQoS) { if ( g_fResourcesRequested ) { g_pIQoS->ReleaseResources((GUID *)&MEDIA_TYPE_T120DATA, (LPRESOURCEREQUESTLIST)&g_aRRq); g_fResourcesRequested = FALSE; } g_wConnectionCount = 0; g_pIQoS->Release(); g_pIQoS = NULL; } } VOID MaybeReleaseQoSResources( VOID ) { if (g_pSocketList->IsEmpty()) { if (NULL != g_pIQoS) { if ( g_fResourcesRequested ) { g_pIQoS->ReleaseResources((GUID *)&MEDIA_TYPE_T120DATA, (LPRESOURCEREQUESTLIST)&g_aRRq); g_fResourcesRequested = FALSE; } } g_wConnectionCount = 0; } }