Add batched recv/send to WinDivert (#156).
This change allows multiple packets to be received/sent at once, reducing overheads. To exploit this feature, applications need to use the WinDivertRecvEx()/WinDivertSendEx() functions with the new addrLen parameter. The passthru example has been modified to use batching. The DEBUG flag has been retired since it conflicts with batching, and was not very useful anyway.
This commit is contained in:
@@ -47,7 +47,10 @@
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define MAXBUF 0xFFFF
|
||||
#define MAXBATCH 0xFF
|
||||
|
||||
static int batch = 1;
|
||||
|
||||
static DWORD passthru(LPVOID arg);
|
||||
|
||||
@@ -59,9 +62,10 @@ int __cdecl main(int argc, char **argv)
|
||||
int num_threads, priority = 0, i;
|
||||
HANDLE handle, thread;
|
||||
|
||||
if (argc != 3 && argc != 4)
|
||||
if (argc < 3 || argc > 5)
|
||||
{
|
||||
fprintf(stderr, "usage: %s filter num-threads [priority]\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s filter num-threads [batch] [priority]\n",
|
||||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
num_threads = atoi(argv[2]);
|
||||
@@ -70,9 +74,18 @@ int __cdecl main(int argc, char **argv)
|
||||
fprintf(stderr, "error: invalid number of threads\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (argc == 4)
|
||||
if (argc >= 4)
|
||||
{
|
||||
priority = atoi(argv[3]);
|
||||
batch = atoi(argv[3]);
|
||||
}
|
||||
if (batch <= 0 || batch > MAXBATCH)
|
||||
{
|
||||
fprintf(stderr, "error: invalid batch size\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (argc >= 5)
|
||||
{
|
||||
priority = atoi(argv[4]);
|
||||
}
|
||||
|
||||
// Divert traffic matching the filter:
|
||||
@@ -112,16 +125,18 @@ int __cdecl main(int argc, char **argv)
|
||||
// Passthru thread.
|
||||
static DWORD passthru(LPVOID arg)
|
||||
{
|
||||
unsigned char packet[MAXBUF];
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
UINT8 packet[MAXBUF];
|
||||
UINT packet_len, addr_len;
|
||||
WINDIVERT_ADDRESS addr[MAXBATCH];
|
||||
HANDLE handle = (HANDLE)arg;
|
||||
|
||||
// Main loop:
|
||||
while (TRUE)
|
||||
{
|
||||
// Read a matching packet.
|
||||
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), &packet_len, 0,
|
||||
addr, &addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -129,7 +144,8 @@ static DWORD passthru(LPVOID arg)
|
||||
}
|
||||
|
||||
// Re-inject the matching packet.
|
||||
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
|
||||
addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
GetLastError());
|
||||
|
||||
@@ -227,8 +227,8 @@ int __cdecl main(int argc, char **argv)
|
||||
memset(&overlapped, 0, sizeof(overlapped));
|
||||
ResetEvent(event);
|
||||
overlapped.hEvent = event;
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), 0, &addr,
|
||||
&packet_len, &overlapped))
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), &packet_len, 0,
|
||||
&addr, NULL, &overlapped))
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
@@ -299,8 +299,8 @@ read_failed:
|
||||
error("failed to allocate memory");
|
||||
}
|
||||
memset(poverlapped, 0, sizeof(OVERLAPPED));
|
||||
if (WinDivertSendEx(handle, packet, packet_len, 0, &addr, NULL,
|
||||
poverlapped))
|
||||
if (WinDivertSendEx(handle, packet, packet_len, NULL, 0, &addr,
|
||||
sizeof(WINDIVERT_ADDRESS), poverlapped))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -360,14 +360,9 @@ usage:
|
||||
printf("%sSEND_ONLY", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_DEBUG) != 0)
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_RECV_PARTIAL) != 0)
|
||||
{
|
||||
printf("%sDEBUG", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_PARTIAL) != 0)
|
||||
{
|
||||
printf("%sPARTIAL", (or? "|": ""));
|
||||
printf("%sRECV_PARTIAL", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_NO_INSTALL) != 0)
|
||||
|
||||
Reference in New Issue
Block a user