00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "nnratelimiter.h"
00021 #include "platform.h"
00022 #include "util.h"
00023
00024 #include <vector>
00025 #include <queue>
00026 #include <algorithm>
00027 #include <iostream>
00028
00029
00030 #define MAX_HISTORY 5
00031
00032 #ifndef DOXYGEN_UNDOCUMENTED
00033 typedef std::pair<struct timeval, ssize_t> RateData;
00034 struct NewNet::RateLimiter::Data
00035 {
00036 std::vector<RateData> rateData;
00037 };
00038 #endif // DOXYGEN_UNDOCUMENTED
00039
00040 NewNet::RateLimiter::RateLimiter()
00041 {
00042 m_Limit = -1;
00043 m_Data = new NewNet::RateLimiter::Data;
00044 }
00045
00046 #ifndef DOXYGEN_UNDOCUMENTED
00047 NewNet::RateLimiter::~RateLimiter()
00048 {
00049 delete m_Data;
00050 }
00051 #endif // DOXYGEN_UNDOCUMENTED
00052
00053 void
00054 NewNet::RateLimiter::transferred(ssize_t n)
00055 {
00056 struct timeval now;
00057 gettimeofday(&now, 0);
00058 m_Data->rateData.push_back(RateData(now, n));
00059 }
00060
00061 #ifndef timercmp
00062 #define timercmp(tvp, uvp, cmp)\
00063 ((tvp)->tv_sec cmp (uvp)->tv_sec ||\
00064 (tvp)->tv_sec == (uvp)->tv_sec &&\
00065 (tvp)->tv_usec cmp (uvp)->tv_usec)
00066 #endif
00067
00068 void
00069 NewNet::RateLimiter::flush()
00070 {
00071
00072 struct timeval tv;
00073 gettimeofday(&tv, 0);
00074 tv.tv_sec -= MAX_HISTORY;
00075 while((! m_Data->rateData.empty()) && timercmp(&tv, &m_Data->rateData.front().first, >))
00076 m_Data->rateData.erase(m_Data->rateData.begin());
00077 }
00078
00079 long
00080 NewNet::RateLimiter::nextWindow()
00081 {
00082 flush();
00083
00084 if(m_Limit == -1)
00085 return 0;
00086 else if(m_Limit == 0)
00087 return 60000;
00088
00089 ssize_t total = 0;
00090 std::vector<RateData>::reverse_iterator it, end = m_Data->rateData.rend();
00091 for(it = m_Data->rateData.rbegin(); it != end; ++it)
00092 {
00093 total += (*it).second;
00094 if(total >= m_Limit)
00095 {
00096
00097
00098 struct timeval now;
00099 gettimeofday(&now, 0);
00100
00101 struct timeval tv((*it).first);
00102 tv.tv_sec += 1;
00103
00104 long d = difftime(tv, now);
00105 if(d <= 0)
00106 return 0;
00107 else
00108 return d + 50;
00109 }
00110 }
00111
00112 return 0;
00113 }