[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