7

I would like to make the following happen:

  • My application runs on a Windows machine (call it application A).
  • I can modify the source code of application A to introduce bandwidth throttling.
  • I would like to be able to reuse my bandwidth throttling code and drop it into any other applications that I have (in other words, I would like to try and throttle the bandwidth on an application domain level in order to not have to re-factor existing applications for bandwidth throttling).
  • I want to throttle A's cumulative upload and download speed separately. For example, if A has a maximum of 5 Kbps allotted to upload, then all of A's upload streams will be capped to a cumulative amount of 5 Kbps.

My requirements:

  • I cannot use a kernel-mode driver.
  • I need to add throttling on an application domain level.

I have tried to research into this, especially on Stack Overflow but could not find anything useful for my case:

  • I have seen this example of using a ThrottledStream class wrapper around a Stream object that will introduce throttling when used, but I need this to be at a domain level; taking this approach is problematic because it would require me to refactor a lot of existing code in other applications.
  • I have seen this question who's answer speaks about using the Windows Filtering Platform API. Unfortunately, a requirement I have is that I absolutely can't use a kernel-mode driver to accomplish this, and my understanding is that the WFP API requires one.

Does anyone know a way to implement my specific bandwidth throttling requirements in order to throttle applications on an application domain level?

Community
  • 1
  • 1
Alexandru
  • 10,808
  • 12
  • 98
  • 183
  • I'm not sure how this one is different from http://stackoverflow.com/questions/27512920/what-apis-can-i-use-for-my-specific-bandwidth-throttling-requirements, but you claim they are... On other hand both look like "search for tools/libraries", so likely get closed separately. – Alexei Levenkov Dec 16 '14 at 21:40
  • Note that there is no such API built into .Net Framework so you are really into search for libraries. – Alexei Levenkov Dec 16 '14 at 21:41
  • @AlexeiLevenkov That other one did not have access to the source code of the application A so it could never introduce throttling on an application domain level. My requirements have changed since I wrote it, though, thankfully! – Alexandru Dec 16 '14 at 21:45
  • @AlexeiLevenkov What about the QoS API? I know that policy-based QoS can do this (http://technet.microsoft.com/en-us/library/dd919203%28v=ws.10%29.aspx) and that QoS has its own API. Can that API do the same as policies? I guess if not, can still code something to create such policies. – Alexandru Dec 16 '14 at 22:12
  • PeakBandwidth (http://msdn.microsoft.com/en-us/library/windows/desktop/aa373702(v=vs.85).aspx) should be what I need. It is *the upper limit on time-based transmission permission for a given flow, in bytes per second.* This FLOWSPEC is passed in through a QOS structure (http://msdn.microsoft.com/en-us/library/windows/desktop/aa374024(v=vs.85).aspx) when calling WSCInstallQOSTemplate (http://msdn.microsoft.com/en-us/library/windows/desktop/aa374497(v=vs.85).aspx) – Alexandru Dec 16 '14 at 22:21
  • Bah, I spoke too soon - "[ This function is not supported as of Windows Vista.]" – Alexandru Dec 16 '14 at 22:41
  • However it has been updated since to a newer API (http://msdn.microsoft.com/en-us/library/windows/desktop/aa374469(v=vs.85).aspx) with new traffic control options. (http://msdn.microsoft.com/en-us/library/windows/desktop/aa374469(v=vs.85).aspx) – Alexandru Dec 16 '14 at 22:46
  • I can't for the life of me find any QoS API samples for the new version of the API... – Alexandru Dec 17 '14 at 14:11

1 Answers1

1

I think I have found a solution. With the QOS API, you need to get a handle to your target interface using TcOpenInterface (you can figure out which interface you want to target via a call to TcEnumerateInterfaces). With your interface handle, you need to call TcAddFlow along with a pointer to a TC_GEN_FLOW structure, which allows you to specify both a SendingFlowspec (FLOWSPEC structure) and a ReceivingFlowspec (FLOWSPEC structure) which contains a PeakBandwidth member. Then, to make your interface utilize this flow you've just added to it, you need to add a filter to your interface using a call to TcAddFilter, as MSDN says that the TcAddFilter function associates a new filter with an existing flow that allows packets matching the filter to be directed to the associated flow. I think that to make it application specific, calling TcRegisterClient may do the trick, which you will need to call anyways in order to get a client handle to use with TcEnumerateInterfaces and TcAddFlow from the looks of it (but this remains to be tested). I found this useful example as well (haven't tested it).

Taken from MSDN, the PeakBandwidth member is the upper limit on time-based transmission permission for a given flow, in bytes per second. The PeakBandwidth member restricts flows that may have accrued a significant amount of transmission credits, or tokens from overburdening network resources with one-time or cyclical data bursts, by enforcing a per-second data transmission ceiling. Some intermediate systems can take advantage of this information, resulting in more efficient resource allocation.

Alexandru
  • 10,808
  • 12
  • 98
  • 183
  • Thanks for the tips, did you found any sample code, or have you done some?! – dariush Aug 16 '15 at 12:14
  • @Dariush Haven't done any of this so far, sorry. Application requirements changed on me, but if you end up giving it a shot, maybe you can post a better answer with a programmatic solution that will help a few people. – Alexandru Aug 16 '15 at 13:47