1 /*
2  * Copyright (C) 2009-2012 Jacek Sieka, arnetheduck on gmail point com
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #pragma once
20 
21 #include "Singleton.h"
22 #include "Socket.h"
23 #include "TimerManager.h"
24 #include "SettingsManager.h"
25 
26 namespace dcpp
27 {
28 /**
29  * Manager for throttling traffic flow.
30  * Inspired by Token Bucket algorithm: http://en.wikipedia.org/wiki/Token_bucket
31  */
32 class ThrottleManager :
33     public Singleton<ThrottleManager>, private TimerManagerListener
34 {
35 public:
36 
37     /*
38      * Throttles traffic and reads a packet from the network
39      */
40     int read(Socket* sock, void* buffer, size_t len);
41 
42     /*
43      * Throttles traffic and writes a packet to the network
44      * Handle this a little bit differently than downloads due to OpenSSL stupidity
45      */
46     int write(Socket* sock, void* buffer, size_t& len);
47 
48     static SettingsManager::IntSetting getCurSetting(SettingsManager::IntSetting setting);
49 
50     static int getUpLimit();
51     static int getDownLimit();
52 
53     static void setSetting(SettingsManager::IntSetting setting, int value);
54 
55     void shutdown();
56 private:
57     // stack up throttled read & write threads
58     CriticalSection stateCS;
59     CriticalSection waitCS[2];
60     long activeWaiter;
61 
62 #ifndef _WIN32 //*nix
63 
64     // shutdown wait
65     CriticalSection shutdownCS;
66     long n_lock, halt;
67 #endif
68     // download limiter
69     CriticalSection downCS;
70     int64_t         downTokens;
71 
72     // upload limiter
73     CriticalSection upCS;
74     int64_t         upTokens;
75 
76     friend class Singleton<ThrottleManager>;
77 
ThrottleManager(void)78     ThrottleManager(void) : activeWaiter(-1), downTokens(0), upTokens(0)
79     {
80 #ifndef _WIN32 //*nix
81         n_lock = halt = 0;
82 #endif
83         TimerManager::getInstance()->addListener(this);
84     }
85 
86     ~ThrottleManager(void);
87 
88     bool getCurThrottling();
89     void waitToken();
90 
91     // TimerManagerListener
92     void on(TimerManagerListener::Second, uint64_t /* aTick */) noexcept;
93 };
94 
95 }   // namespace dcpp
96