Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish speed cap implementation #47

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 68 additions & 25 deletions src/cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,37 @@
#include "common.h"
#define NAME "cap"
#define CAP_MIN "0.1"
#define CAP_MAX "320.0" // TODO CAP_MAX actually can't be larger than 2**15...
#define CAP_MAX "2000000000.0"
#define KEEP_AT_MOST 5000
#define BUFFER_MAX_KB "100000"
#define BUFFER_MIN_KB "1"

static Ihandle *inboundCheckbox, *outboundCheckbox, *kpsInput;
#define ALLOW_SET_BUFFER_SIZE 0

static Ihandle *inboundCheckbox, *outboundCheckbox, *kpsInput, *kbBufSzInput;

static volatile short capEnabled = 0,
capInbound = 1, capOutbound = 1,
kps = (short)(32 / FIXED_EPSILON); // kb / second
capInbound = 1, capOutbound = 1;
static volatile long
kps = (long)(32 / FIXED_EPSILON),
kbBufSz = 200; // kb / second

static PacketNode capHeadNode = {0}, capTailNode = {0};
static PacketNode *bufHead = &capHeadNode, *bufTail = &capTailNode;
static int bufSize = 0;
static int bufSizeBytes = 0;
static DWORD capLastTick = 0;

static Ihandle* capSetupUI() {
Ihandle *capControlsBox = IupHbox(
inboundCheckbox = IupToggle("Inbound", NULL),
outboundCheckbox = IupToggle("Outbound", NULL),
IupLabel("Bandwidth Cap(kb/s):"),
IupLabel("Bandwidth Cap(kB/s):"),
kpsInput = IupText(NULL),
#if ALLOW_SET_BUFFER_SIZE
IupLabel("Buffer(kB):"),
kbBufSzInput = IupText(NULL),
#endif
NULL
);

Expand All @@ -34,11 +45,20 @@ static Ihandle* capSetupUI() {

IupSetAttribute(kpsInput, "VISIBLECOLUMNS", "4");
IupSetAttribute(kpsInput, "VALUE", "32.0");
IupSetCallback(kpsInput, "VALUECHANGED_CB", (Icallback)uiSyncFixed);
IupSetCallback(kpsInput, "VALUECHANGED_CB", (Icallback)uiSyncFixedInt);
IupSetAttribute(kpsInput, SYNCED_VALUE, (char*)&kps);
IupSetAttribute(kpsInput, FIXED_MAX, CAP_MAX);
IupSetAttribute(kpsInput, FIXED_MIN, CAP_MIN);

#if ALLOW_SET_BUFFER_SIZE
IupSetAttribute(kbBufSzInput, "VISIBLECOLUMNS", "4");
IupSetAttribute(kbBufSzInput, "VALUE", "200");
IupSetCallback(kbBufSzInput, "VALUECHANGED_CB", uiSyncInteger);
IupSetAttribute(kbBufSzInput, SYNCED_VALUE, (char*)&kbBufSz);
IupSetAttribute(kbBufSzInput, INTEGER_MAX, BUFFER_MAX_KB);
IupSetAttribute(kbBufSzInput, INTEGER_MIN, BUFFER_MIN_KB);
#endif

// enable by default to avoid confusing
IupSetAttribute(inboundCheckbox, "VALUE", "ON");
IupSetAttribute(outboundCheckbox, "VALUE", "ON");
Expand All @@ -47,6 +67,9 @@ static Ihandle* capSetupUI() {
setFromParameter(inboundCheckbox, "VALUE", NAME"-inbound");
setFromParameter(outboundCheckbox, "VALUE", NAME"-outbound");
setFromParameter(kpsInput, "VALUE", NAME"-kps");
#if ALLOW_SET_BUFFER_SIZE
setFromParameter(kbBufSzInput, "VALUE", NAME"-buf-sz-kb");
#endif
}

return capControlsBox;
Expand All @@ -73,6 +96,7 @@ static void capStartUp() {
bufHead->next = bufTail;
bufTail->prev = bufHead;
bufSize = 0;
bufSizeBytes = 0;
} else {
assert(isBufEmpty());
}
Expand All @@ -95,9 +119,14 @@ static short capProcess(PacketNode *head, PacketNode *tail) {
DWORD deltaTick = curTick - capLastTick;
int bytesCapped = (int)(deltaTick * 0.001 * kps * FIXED_EPSILON * 1024);
int totalBytes = 0;
LOG("kps val: %d, capped kps %.2f, capped at %d bytes", kps, kps * FIXED_EPSILON, bytesCapped);
capLastTick = curTick;
int capCnt = 0;
int droppedCnt = 0;

int maxBufSize = kps * 1024 / 4;

#if ALLOW_SET_BUFFER_SIZE
maxBufSize = kbBufSz * 1024;
#endif

// process buffered packets
oldLast = tail->prev;
Expand All @@ -106,16 +135,25 @@ static short capProcess(PacketNode *head, PacketNode *tail) {
// sends at least one from buffer or it would get stuck
pac = bufTail->prev;
totalBytes += pac->packetLen;
insertAfter(popNode(pac), oldLast);
--bufSize;

LOG("sending out packets of %d bytes", totalBytes);

if (totalBytes > bytesCapped) {
totalBytes -= pac->packetLen;
break;
}

insertAfter(popNode(pac), oldLast);
--bufSize;
bufSizeBytes -= pac->packetLen;

LOG("sending out packets of %d bytes", totalBytes);
}

if(tail->prev != oldLast || (tail->prev == head && isBufEmpty()))
{
LOG("kps delta: %d, val: %d, capped kps %.2f, capped at %d bytes", deltaTick, kps, kps * FIXED_EPSILON, bytesCapped);
capLastTick = curTick;
}

// process live packets
pac = oldLast;
while (pac != head) {
Expand All @@ -128,33 +166,38 @@ static short capProcess(PacketNode *head, PacketNode *tail) {
totalBytes += pac->packetLen;

if (totalBytes > bytesCapped) {
int capCnt = 0;
capped = TRUE;
// buffer from pac to head
while (bufSize < KEEP_AT_MOST && pac != head) {
if (bufSize < KEEP_AT_MOST && bufSizeBytes + pac->packetLen <= maxBufSize) {
pacTmp = pac->prev;
insertAfter(popNode(pac), bufHead);
++bufSize;
bufSizeBytes += pac->packetLen;
++capCnt;
pac = pacTmp;
}

if (pac != head) {
LOG("! hitting cap max, dropping all remaining");
while (pac != head) {
pacTmp = pac->prev;
freeNode(pac);
pac = pacTmp;
}
else
{
assert(pac != tail);
++capCnt;
++droppedCnt;
pacTmp = pac->prev;
popNode(pac);
freeNode(pac);
pac = pacTmp;
}
assert(pac == head);
LOG("capping %d packets", capCnt);
break;
} else {
pac = pac->prev;
}
}

if(capped)
{
assert(pac == head);
LOG("capping %d packets", capCnt);
LOG("dropped %d packets", droppedCnt);
}

return capped;
}

Expand Down
3 changes: 2 additions & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define MSG_BUFSIZE 512
#define FILTER_BUFSIZE 1024
#define NAME_SIZE 16
#define MODULE_CNT 7
#define MODULE_CNT 8
#define ICON_UPDATE_MS 200

#define CONTROLS_HANDLE "__CONTROLS_HANDLE"
Expand Down Expand Up @@ -103,6 +103,7 @@ int uiSyncChance(Ihandle *ih);
int uiSyncToggle(Ihandle *ih, int state);
int uiSyncInteger(Ihandle *ih);
int uiSyncFixed(Ihandle *ih);
int uiSyncFixedInt(Ihandle *ih);


// module
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Module* modules[MODULE_CNT] = {
&oodModule,
&tamperModule,
&resetModule,
//&capModule
&capModule
};

volatile short sendState = SEND_STATUS_NONE;
Expand Down
25 changes: 25 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,31 @@ int uiSyncFixed(Ihandle *ih) {
return IUP_DEFAULT;
}

int uiSyncFixedInt(Ihandle *ih) {
long *fixedPointer = (long*)IupGetAttribute(ih, SYNCED_VALUE);
const float maxFixedValue = IupGetFloat(ih, FIXED_MAX);
const float minFixedValue = IupGetFloat(ih, FIXED_MIN);
float value = IupGetFloat(ih, "VALUE");
float newValue = value;
long fixValue;
char valueBuf[8];
if (newValue > maxFixedValue) {
newValue = maxFixedValue;
} else if (newValue < minFixedValue) {
newValue = minFixedValue;
}

if (newValue != value && value != 0) {
sprintf(valueBuf, "%.2f", newValue);
IupStoreAttribute(ih, "VALUE", valueBuf);
// put caret at end to enable editing while normalizing
IupStoreAttribute(ih, "CARET", "10");
}
// sync back
fixValue = (long)(newValue / FIXED_EPSILON);
InterlockedExchange(fixedPointer, fixValue);
return IUP_DEFAULT;
}

// indicator icon, generated from scripts/im2carr.py
const unsigned char icon8x8[8*8] = {
Expand Down