[Winpcap-users] Using threads.
Ramiro Polla
ramiro86 at hotmail.com
Wed Mar 15 18:02:54 GMT 2006
Hello,
I have tried to do a threaded version of a program using winpcap, by
starting a thread for every capture interface found. I have even released a
version, but the program turned out to take too many resources on loaded
networks, much more than I expected.
The program reads data with "ip and (tcp or udp)" on all interfaces, spawing
a thread for every interface found (and every libpcap file added). The full
source can be found at http://ml20rc.msnfanatic.com/ml20gui-1.1-src.zip ,
but I'll write here the most important parts.
being tdev kind of a wrapper for the descriptors' info, this is the part
that spawns threads (on live interfaces) for all interfaces (for every
tdev):
DWORD dwThreadId;
tdev->name = calloc( 1, strlen(d->name) + 1 + 8 );
tdev->description = calloc( 1, strlen(d->description) + 1 );
sprintf( tdev->name, "rpcap://%s", d->name );
strcpy( tdev->description, d->description );
if( (tdev->pd = pcap_open_live( d->name, SNAPLEN, 1, 1, error )) != NULL )
{
tdev->hdrsz = find_hdrsize( tdev->pd );
if( pcap_compile(tdev->pd, &tdev->fcode, expression, 1, 0) >= 0 )
if( pcap_setfilter(tdev->pd, &decive->fcode) >= 0 )
SET_BIT( tdev->flags, INT_CAP );
}
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) CaptureThread, (LPVOID)
tdev, 0, &dwThreadId );
This is the CaptureThread spawned for every tdev:
DWORD WINAPI CaptureThread( LPARAM lparam )
{
struct pcap_pkthdr *h;
unsigned char *p;
device_t *tdev = (device_t*) lparam;
stream_t *live;
if( IS_SET( tdev->flags, NO_CAP ) )
return 0;
while( 1 )
{
switch( pcap_next_ex( tdev->pd, &h, &p ) )
{
case 1: //OK
if( IS_SET( tdev->flags, INT_CAP ) )
{
tdev->bytes += h->caplen;
if( live = process_ip( p + tdev->hdrsz, h->caplen - tdev->hdrsz ) )
{
< if process_ip found something, sends some messages to the gui thread to
update the information>
}
}
break;
case -2: //EOF
case -1: //ERROR
SET_BIT( tdev->flags, NO_CAP );
return 0;
}
}
// should never be reached.
return 0;
}
process_ip looks for patterns through all bytes of the tcp or udp data (for
i = 0 ; i < data_length ; i++), which I think shouldn't be the problem.
This cksum function is called within process_ip to check the ip header
checksum:
/* taken from TCP/IP Illustrated Vol. 2(1995) by Gary R. Wright and W.
Richard Stevens. Page 236 */
unsigned short cksum(struct ip *ip, int len)
{
long sum = 0; /* assume 32 bit long, 16 bit short */
while(len > 1)
{
sum += *((unsigned short*) ip)++;
if(sum & 0x80000000) /* if high order bit set, fold */
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if(len) /* take care of left over byte */
sum += (unsigned short) *(unsigned char *)ip;
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
return (unsigned short) ~sum;
}
I want to know if the CaptureThread function is ok, and if not, what
could/should be done to it (I'm particularly bugged by the while(1) thing I
did).
What are the differences by compiling (in msvc++ 2003) with the
single-threaded and multi-threaded library? I compiled the program on
dev-c++ (because I didn't have a profiler for msvc), but I'm not sure the
gprof profiler is working properly on the threaded version, it says 100% of
the program is spent calculating the ip header checksum (even if I do heavy
processing on other parts of the program).
Well, I think that's it...
Bye,
Ramiro Polla
More information about the Winpcap-users
mailing list