Skip to content

Commit c3cfd02

Browse files
author
skywind3000
committed
commit new rate.c
1 parent 3c33dc4 commit c3cfd02

File tree

4 files changed

+326
-3
lines changed

4 files changed

+326
-3
lines changed

src/common.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#define MSG_BUFSIZE 512
99
#define FILTER_BUFSIZE 1024
1010
#define NAME_SIZE 16
11-
#define MODULE_CNT 7
11+
#define MODULE_CNT 8
1212
#define ICON_UPDATE_MS 200
1313

1414
#define CONTROLS_HANDLE "__CONTROLS_HANDLE"
@@ -103,6 +103,7 @@ int uiSyncChance(Ihandle *ih);
103103
int uiSyncToggle(Ihandle *ih, int state);
104104
int uiSyncInteger(Ihandle *ih);
105105
int uiSyncFixed(Ihandle *ih);
106+
int uiSyncInt32(Ihandle *ih);
106107

107108

108109
// module
@@ -133,6 +134,7 @@ extern Module dupModule;
133134
extern Module tamperModule;
134135
extern Module resetModule;
135136
extern Module capModule;
137+
extern Module bandwidthModule;
136138
extern Module* modules[MODULE_CNT]; // all modules in a list
137139

138140
// status for sending packets,

src/main.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Module* modules[MODULE_CNT] = {
1616
&oodModule,
1717
&tamperModule,
1818
&resetModule,
19+
&bandwidthModule,
1920
//&capModule
2021
};
2122

@@ -509,4 +510,4 @@ int main(int argc, char* argv[]) {
509510
startup();
510511
cleanup();
511512
return 0;
512-
}
513+
}

src/rate.c

+295
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
// bandwidthping packet module
2+
#include <stdlib.h>
3+
#include <Windows.h>
4+
#include <stdint.h>
5+
6+
#include "iup.h"
7+
#include "common.h"
8+
#define NAME "bandwidth"
9+
10+
#define BANDWIDTH_MIN "0"
11+
#define BANDWIDTH_MAX "99999"
12+
13+
14+
//---------------------------------------------------------------------
15+
// rate stats
16+
//---------------------------------------------------------------------
17+
typedef struct _CRateStats
18+
{
19+
int32_t initialized;
20+
uint32_t oldest_index;
21+
uint32_t oldest_ts;
22+
int64_t accumulated_count;
23+
int32_t sample_num;
24+
int window_size;
25+
float scale;
26+
uint32_t *array_sum;
27+
uint32_t *array_sample;
28+
} CRateStats;
29+
30+
31+
CRateStats* crate_stats_new(int window_size, float scale);
32+
33+
void crate_stats_delete(CRateStats *rate);
34+
35+
void crate_stats_reset(CRateStats *rate);
36+
37+
void crate_stats_update(CRateStats *rate, int32_t count, uint32_t now_ts);
38+
39+
int32_t crate_stats_calculate(CRateStats *rate, uint32_t now_ts);
40+
41+
42+
//---------------------------------------------------------------------
43+
// configuration
44+
//---------------------------------------------------------------------
45+
static Ihandle *inboundCheckbox, *outboundCheckbox, *bandwidthInput;
46+
47+
static volatile short bandwidthEnabled = 0,
48+
bandwidthInbound = 1, bandwidthOutbound = 1;
49+
50+
static volatile LONG bandwidthLimit = 0;
51+
static CRateStats *rateStats = NULL;
52+
53+
54+
static Ihandle* bandwidthSetupUI() {
55+
Ihandle *bandwidthControlsBox = IupHbox(
56+
inboundCheckbox = IupToggle("Inbound", NULL),
57+
outboundCheckbox = IupToggle("Outbound", NULL),
58+
IupLabel("Limit(KB/s):"),
59+
bandwidthInput = IupText(NULL),
60+
NULL
61+
);
62+
63+
IupSetAttribute(bandwidthInput, "VISIBLECOLUMNS", "4");
64+
IupSetAttribute(bandwidthInput, "VALUE", "0");
65+
IupSetCallback(bandwidthInput, "VALUECHANGED_CB", uiSyncInt32);
66+
IupSetAttribute(bandwidthInput, SYNCED_VALUE, (char*)&bandwidthLimit);
67+
IupSetAttribute(bandwidthInput, INTEGER_MAX, BANDWIDTH_MAX);
68+
IupSetAttribute(bandwidthInput, INTEGER_MIN, BANDWIDTH_MIN);
69+
IupSetCallback(inboundCheckbox, "ACTION", (Icallback)uiSyncToggle);
70+
IupSetAttribute(inboundCheckbox, SYNCED_VALUE, (char*)&bandwidthInbound);
71+
IupSetCallback(outboundCheckbox, "ACTION", (Icallback)uiSyncToggle);
72+
IupSetAttribute(outboundCheckbox, SYNCED_VALUE, (char*)&bandwidthOutbound);
73+
74+
// enable by default to avoid confusing
75+
IupSetAttribute(inboundCheckbox, "VALUE", "ON");
76+
IupSetAttribute(outboundCheckbox, "VALUE", "ON");
77+
78+
if (parameterized) {
79+
setFromParameter(inboundCheckbox, "VALUE", NAME"-inbound");
80+
setFromParameter(outboundCheckbox, "VALUE", NAME"-outbound");
81+
setFromParameter(bandwidthInput, "VALUE", NAME"-bandwidth");
82+
}
83+
84+
return bandwidthControlsBox;
85+
}
86+
87+
static void bandwidthStartUp() {
88+
if (rateStats) crate_stats_delete(rateStats);
89+
rateStats = crate_stats_new(1000, 1000);
90+
LOG("bandwidth enabled");
91+
}
92+
93+
static void bandwidthCloseDown(PacketNode *head, PacketNode *tail) {
94+
UNREFERENCED_PARAMETER(head);
95+
UNREFERENCED_PARAMETER(tail);
96+
if (rateStats) crate_stats_delete(rateStats);
97+
rateStats = NULL;
98+
LOG("bandwidth disabled");
99+
}
100+
101+
102+
//---------------------------------------------------------------------
103+
// process
104+
//---------------------------------------------------------------------
105+
static short bandwidthProcess(PacketNode *head, PacketNode* tail) {
106+
int dropped = 0;
107+
DWORD now_ts = timeGetTime();
108+
int limit = bandwidthLimit * 1024;
109+
if (limit <= 0 || rateStats == NULL)
110+
return 0;
111+
112+
while (head->next != tail) {
113+
PacketNode *pac = head->next;
114+
int discard = 0;
115+
// chance in range of [0, 10000]
116+
if (checkDirection(pac->addr.Direction, bandwidthInbound, bandwidthOutbound)) {
117+
int rate = crate_stats_calculate(rateStats, now_ts);
118+
int size = pac->packetLen;
119+
if (rate + size > limit) {
120+
LOG("dropped with bandwidth %dKB/s, direction %s",
121+
bandwidthLimit, BOUND_TEXT(pac->addr.Direction));
122+
discard = 1;
123+
}
124+
else {
125+
crate_stats_update(rateStats, size, now_ts);
126+
}
127+
}
128+
if (discard) {
129+
freeNode(popNode(pac));
130+
++dropped;
131+
} else {
132+
head = head->next;
133+
}
134+
}
135+
136+
return dropped > 0;
137+
}
138+
139+
140+
//---------------------------------------------------------------------
141+
// module
142+
//---------------------------------------------------------------------
143+
Module bandwidthModule = {
144+
"Bandwidth",
145+
NAME,
146+
(short*)&bandwidthEnabled,
147+
bandwidthSetupUI,
148+
bandwidthStartUp,
149+
bandwidthCloseDown,
150+
bandwidthProcess,
151+
// runtime fields
152+
0, 0, NULL
153+
};
154+
155+
156+
157+
//---------------------------------------------------------------------
158+
// create new CRateStat
159+
//---------------------------------------------------------------------
160+
CRateStats* crate_stats_new(int window_size, float scale)
161+
{
162+
CRateStats *rate = (CRateStats*)malloc(sizeof(CRateStats));
163+
assert(rate);
164+
rate->array_sum = (uint32_t*)malloc(sizeof(uint32_t) * window_size);
165+
assert(rate->array_sum);
166+
rate->array_sample = (uint32_t*)malloc(sizeof(uint32_t) * window_size);
167+
assert(rate->array_sample);
168+
rate->window_size = window_size;
169+
rate->scale = scale;
170+
crate_stats_reset(rate);
171+
return rate;
172+
}
173+
174+
175+
//---------------------------------------------------------------------
176+
// delete rate
177+
//---------------------------------------------------------------------
178+
void crate_stats_delete(CRateStats *rate)
179+
{
180+
if (rate) {
181+
rate->window_size = 0;
182+
if (rate->array_sum) free(rate->array_sum);
183+
if (rate->array_sample) free(rate->array_sample);
184+
rate->array_sum = NULL;
185+
rate->array_sample = NULL;
186+
rate->initialized = 0;
187+
free(rate);
188+
}
189+
}
190+
191+
192+
//---------------------------------------------------------------------
193+
// reset rate
194+
//---------------------------------------------------------------------
195+
void crate_stats_reset(CRateStats *rate)
196+
{
197+
int i;
198+
for (i = 0; i < rate->window_size; i++) {
199+
rate->array_sum[i] = 0;
200+
rate->array_sample[i] = 0;
201+
}
202+
rate->initialized = 0;
203+
rate->sample_num = 0;
204+
rate->accumulated_count = 0;
205+
rate->oldest_ts = 0;
206+
rate->oldest_index = 0;
207+
}
208+
209+
210+
//---------------------------------------------------------------------
211+
// evict oldest history
212+
//---------------------------------------------------------------------
213+
void crate_stats_evict(CRateStats *rate, uint32_t now_ts)
214+
{
215+
if (rate->initialized == 0)
216+
return;
217+
218+
uint32_t new_oldest_ts = now_ts - ((uint32_t)rate->window_size) + 1;
219+
220+
if (((int32_t)(new_oldest_ts - rate->oldest_ts)) < 0)
221+
return;
222+
223+
while (((int32_t)(rate->oldest_ts - new_oldest_ts)) < 0) {
224+
uint32_t index = rate->oldest_index;
225+
if (rate->sample_num == 0) break;
226+
rate->sample_num -= rate->array_sample[index];
227+
rate->accumulated_count -= rate->array_sum[index];
228+
rate->array_sample[index] = 0;
229+
rate->array_sum[index] = 0;
230+
rate->oldest_index++;
231+
if (rate->oldest_index >= (uint32_t)rate->window_size) {
232+
rate->oldest_index = 0;
233+
}
234+
rate->oldest_ts++;
235+
}
236+
assert(rate->sample_num >= 0);
237+
assert(rate->accumulated_count >= 0);
238+
rate->oldest_ts = new_oldest_ts;
239+
}
240+
241+
242+
//---------------------------------------------------------------------
243+
// update stats
244+
//---------------------------------------------------------------------
245+
void crate_stats_update(CRateStats *rate, int32_t count, uint32_t now_ts)
246+
{
247+
if (rate->initialized == 0) {
248+
rate->oldest_ts = now_ts;
249+
rate->oldest_index = 0;
250+
rate->accumulated_count = 0;
251+
rate->sample_num = 0;
252+
rate->initialized = 1;
253+
}
254+
255+
if (((int32_t)(now_ts - rate->oldest_ts)) < 0) {
256+
return;
257+
}
258+
259+
crate_stats_evict(rate, now_ts);
260+
261+
int32_t offset = (int32_t)(now_ts - rate->oldest_ts);
262+
int32_t index = (rate->oldest_index + offset) % rate->window_size;
263+
264+
rate->sample_num++;
265+
rate->accumulated_count += count;
266+
rate->array_sum[index] += count;
267+
rate->array_sample[index] += 1;
268+
}
269+
270+
271+
//---------------------------------------------------------------------
272+
// calculate
273+
//---------------------------------------------------------------------
274+
int32_t crate_stats_calculate(CRateStats *rate, uint32_t now_ts)
275+
{
276+
int32_t active_size = (int32_t)(now_ts - rate->oldest_ts + 1);
277+
float r;
278+
279+
crate_stats_evict(rate, now_ts);
280+
281+
if (rate->initialized == 0 ||
282+
rate->sample_num <= 0 ||
283+
active_size <= 1 ||
284+
active_size < rate->window_size) {
285+
return -1;
286+
}
287+
288+
r = ((((float)rate->accumulated_count) * rate->scale) /
289+
rate->window_size) + 0.5;
290+
291+
return (int32_t)r;
292+
}
293+
294+
295+

src/utils.c

+26-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,31 @@ int uiSyncChance(Ihandle *ih) {
4747
return IUP_DEFAULT;
4848
}
4949

50+
// shared callbacks
51+
int uiSyncInt32(Ihandle *ih) {
52+
LONG *integerPointer = (LONG*)IupGetAttribute(ih, SYNCED_VALUE);
53+
const int maxValue = IupGetInt(ih, INTEGER_MAX);
54+
const int minValue = IupGetInt(ih, INTEGER_MIN);
55+
// normalize input into [min, max]
56+
int value = IupGetInt(ih, "VALUE"), newValue = value;
57+
char valueBuf[8];
58+
if (newValue > maxValue) {
59+
newValue = maxValue;
60+
} else if (newValue < minValue) {
61+
newValue = minValue;
62+
}
63+
// test for 0 as for empty input
64+
if (newValue != value && value != 0) {
65+
sprintf(valueBuf, "%d", newValue);
66+
IupStoreAttribute(ih, "VALUE", valueBuf);
67+
// put caret at end to enable editing while normalizing
68+
IupStoreAttribute(ih, "CARET", "10");
69+
}
70+
// sync back
71+
InterlockedExchange(integerPointer, newValue);
72+
return IUP_DEFAULT;
73+
}
74+
5075
int uiSyncToggle(Ihandle *ih, int state) {
5176
short *togglePtr = (short*)IupGetAttribute(ih, SYNCED_VALUE);
5277
InterlockedExchange16(togglePtr, I2S(state));
@@ -170,4 +195,4 @@ BOOL parseArgs(int argc, char* argv[]) {
170195
}
171196

172197
return 1;
173-
}
198+
}

0 commit comments

Comments
 (0)