2
This file was written by Loris Degioanni, and is part of Kismet
4
Kismet is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
Kismet is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with Kismet; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
#define HANDLE2FD_INTERNAL
29
#include "cygwin_utils.h"
32
// There are two main parameters that can be used to tune the WinPcap performance:
33
// mintocopy and the read event timeout.
35
// Mintocopy is the minimum amount of data in the kernel buffer that causes the read event to
36
// be set by the driver. A small mintocopy means good responisiveness but high CPU load. A big
37
// mintocopy forces bigger kernel buffering, at the cost of low responsiveness
39
// The read event timeout can be used to check the availability of data once in a while. When the
40
// timeout expires, the application will unblock and perform a read, even if the driver doesn't
41
// have mintocopy bytes in the buffer.
43
// Using the timeout prevents kismet from sitting forver before processing the packets when traffic
44
// is low, but can cause empty reads. Therefore, we set it to a large enough interval that the
45
// performace hit is neglibile.
47
#define THREAD_WAIT_INTERVAL 500
49
Handle2Fd::Handle2Fd() {
53
WaitThreadHandle = NULL;
55
InitializeCriticalSection(&PipeCs);
58
Handle2Fd::~Handle2Fd() {
59
// Kill the thread and wait until he's returned
61
SetEvent(WinHandles[0]);
62
WaitForSingleObject(WaitThreadHandle, INFINITE);
65
// Set the pipe fd so that it unblocks select
66
void Handle2Fd::SetPipe() {
69
EnterCriticalSection(&PipeCs);
72
write(PipeFds[1], &val, sizeof(val));
73
fdatasync(PipeFds[1]);
77
LeaveCriticalSection(&PipeCs);
80
// Reset the pipe fd so that it blocks select
81
void Handle2Fd::ResetPipe()
85
EnterCriticalSection(&PipeCs);
87
// First, write something to be sure the read will not block
88
write(PipeFds[1], &val, sizeof(val));
89
fdatasync(PipeFds[1]);
91
// Second, we drain the pipe
92
while(read(PipeFds[0], ResetBuf, sizeof(ResetBuf)) == sizeof(ResetBuf));
94
// Third, we clear the signalled flag
97
LeaveCriticalSection(&PipeCs);
100
// This thread handles asynchronously waiting on the Windows events.
101
// It signals the pipe if one or more events are set.
102
DWORD WINAPI Handle2Fd::WaitThread(LPVOID lpParameter) {
104
Handle2Fd* This = (Handle2Fd*)lpParameter;
106
while (This->ThreadAlive) {
107
WaitRes = WaitForMultipleObjects(This->NHandles,
110
THREAD_WAIT_INTERVAL);
112
// Event number 0 is the service event used to kill the thread
113
if (WaitRes != WAIT_OBJECT_0) {
114
ResetEvent(This->ReadEvent);
116
WaitForSingleObject(This->ReadEvent, INFINITE);
123
// Mark a signal as read
124
void Handle2Fd::Signalread() {
128
// Activate this instance of the Handle2Fd class.
129
// This involves creating the pipe, the service event and the support thread
130
int Handle2Fd::Activate() {
133
if (pipe(PipeFds) != 0) {
137
// The fd stars in non-signaled state
140
// Create the event for pipe control, and put it in our list
141
WinHandles[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
142
if (!WinHandles[0]) {
148
// Create the event that will syncronize us with the read loop
149
ReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
153
CloseHandle(WinHandles[0]);
157
// Start the thread that does the handle checking
158
if ((WaitThreadHandle = CreateThread(
161
Handle2Fd::WaitThread,
167
CloseHandle(WinHandles[0]);
168
CloseHandle(ReadEvent);
175
// The pipe exported by the Handle2Fd class requires manual reset.
176
void Handle2Fd::Reset() {
180
// Add a new handle to the class
181
int Handle2Fd::AddHandle(HANDLE h) {
182
// If the thread is running, we don't accept new handles. This reduces the syncronization requirements
183
if (!WaitThreadHandle) {
184
if (NHandles < sizeof(WinHandles) / sizeof(WinHandles[0]) - 1) {
185
WinHandles[NHandles++] = h;
193
// Get the pipe file descriptor.
194
int Handle2Fd::GetFd() {
198
// Kismet-like MergeSet function
199
unsigned int Handle2Fd::MergeSet(fd_set *set, unsigned int max) {
200
Reset(); // Manual reset
202
if (!FD_ISSET(GetFd(), set)) {
203
FD_SET(PipeFds[0], set);
213
// Nonzero if the HandleNumber event is set
214
int Handle2Fd::IsEventSet(unsigned int HandleNumber) {
215
if (WaitForSingleObject(WinHandles[HandleNumber + 1], 0) == WAIT_OBJECT_0) {