-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathrate-limit.c
106 lines (96 loc) · 2.42 KB
/
rate-limit.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include "socklib.h"
#include "rate-limit.h"
#include "util.h"
#include "log.h"
#include "rateGovernor.h"
struct rate_limit {
long long date;
long long realDate;
int bitrate;
int queueSize;
};
#define MILLION 1000000
#define LLMILLION ((long long)1000000)
static unsigned long parseSpeed(const char *speedString) {
char *eptr;
unsigned long speed = strtoul(speedString, &eptr, 10);
if(eptr && *eptr) {
switch(*eptr) {
case 'm':
case 'M':
speed *= 1000000;
break;
case 'k':
case 'K':
speed *= 1000;
break;
case '\0':
break;
default:
udpc_fatal(1, "Unit %c unsupported\n", *eptr);
}
}
return speed;
}
static long long getLongLongDate(void) {
long long date;
struct timeval tv;
gettimeofday(&tv,0);
date = (long long) tv.tv_sec;
date *= LLMILLION;
date += (long long) tv.tv_usec;
return date;
}
static void *allocRateLimit(void) {
struct rate_limit *rateLimit = MALLOC(struct rate_limit);
if(rateLimit == NULL)
return NULL;
rateLimit->date = getLongLongDate();
rateLimit->bitrate = 0;
rateLimit->queueSize = 0;
return rateLimit;
}
static void setProp(void *data, const char *key, const char *bitrate) {
struct rate_limit *rateLimit = (struct rate_limit *) data;
if(rateLimit == NULL)
return;
if(!strcmp(MAX_BITRATE, key))
rateLimit->bitrate = parseSpeed(bitrate);
}
static void doRateLimit(void *data, int fd, in_addr_t ip, long size) {
struct rate_limit *rateLimit = (struct rate_limit *) data;
(void) fd;
(void) ip;
if(rateLimit) {
long long now = getLongLongDate();
long long elapsed = now - rateLimit->date;
long long bits = elapsed * ((long long)rateLimit->bitrate) / LLMILLION;
int sleepTime;
size += 28; /* IP header size */
if(bits >= rateLimit->queueSize * 8) {
rateLimit->queueSize = size;
rateLimit->date = now;
return;
}
rateLimit->queueSize -= bits / 8;
rateLimit->date += bits * LLMILLION / rateLimit->bitrate;
rateLimit->realDate = now;
sleepTime = rateLimit->queueSize * 8 * LLMILLION / rateLimit->bitrate;
if(sleepTime > 40000 || rateLimit->queueSize >= 100000) {
sleepTime -= 10000;
sleepTime -= sleepTime % 10000;
usleep(sleepTime);
}
rateLimit->queueSize += size;
}
}
rateGovernor_t maxBitrate = {
allocRateLimit,
setProp,
NULL,
doRateLimit,
NULL
};