sharing objects

[email protected] (Christopher Fowler) Fri, 06 Oct 2006 15:23:14 -0400
Newsgroups perl.ithreads
Message-ID <[email protected]>
I'm trying to figure out the best way to share objects.  I've got a etst
program that has 2 threads.  

Thread 1:
  Look for SYN packets and create a Packet object
  Add that object to a list.

Thread 2:
  Look through list looking for any Packet objects
  Display to stdout the packet.


I am not getting the sharing part done write.  In order to share Packet
do I have to create the constructor like I did?  What is the best
practice for what I'm trying to do?


--- [ Cut Here ] ---------------------------------
use Net::PcapUtils;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use threads;
use threads::shared;
use Data::Dumper;
use strict;

{
	package Packet;

	sub new {
		shift;
		my ($v1, $v2 ) = @_;
		my $pkt;
		threads::shared::share($pkt);
		$pkt = &threads::shared::share({});
		bless $pkt, 'Packet';   # Tag object with pkg name
		$pkt->{'packet'} = $v1;
		$pkt->{'timestamp'} = $v2;

		return $pkt;                     # Return object
	}

	sub get_timestamp {
		my $self=shift;
		return $self->{'timestamp'};
	}

	sub get_packet {
		my $self= shift;
		return $self->{'packet'};
	}
}

$| = 1;
my @objs  : shared = ();
my $prog = "tcp[13] = 2 and src net not 192.168.2";

sub get_timestamp {
	my $ti = shift;
	$ti = time() unless $ti;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
		localtime($ti);

	my $text = sprintf("%02d-%02d %02d:%02d:%02d",
		($mon+1), $mday, $hour, $min, $sec);
	return $text;

}

sub usleep {
	my $time = shift;
	$time = $time * 0.000001;
	select(undef, undef, undef, $time);
	return;
}

sub now {
	return time();
}


sub redir {
	my $file = shift;
	return unless $file;
	open STDOUT, ">> $file" or return;
	open STDERR, ">&STDOUT";
	open STDIN, "</dev/null";
	return;
}

sub resolv {
	my $addr = shift;

	my $host = `host $addr`;
	chomp $host;

	return $addr if $host =~ m/not found/;
	return $addr unless $host =~ m/pointer\s(.+?)\.$/;

	$addr = $1;
	return $addr;

}

sub process_thread {

	while(1) {
		
		# We do not want to consume much CPU and
		# we do not want to sleep too long.  Just
		# sleep a bit then test again.
		while($#objs == -1 ) { usleep(250000); }

		# Get the packet off the list and unpack the time
		my %p = shift @objs;
		my $pkt = $p->get_packet();
		my $ti = $p->get_timestamp();
		
		#my ($ti, $pkt) = unpack "Ia*", $pkt;

		# get the source IP adrress
		my $src_ip = NetPacket::IP->decode(
			NetPacket::Ethernet::strip($pkt))->{src_ip};

		# I want incoming
		next if $src_ip =~ m/209\.168\.246\.233/;

		my $pt = NetPacket::TCP->decode(
			 NetPacket::IP::strip(
				 NetPacket::Ethernet::strip($pkt)));

		print get_timestamp($ti)." SYN ".resolv($src_ip)."($src_ip) -> $pt->{'dest_port'}\n";
	}
}

sub catch {
	my ($arg,$hdr,$pkt) = @_ ;
	#my $data = pack "Ia*", now(), $pkt;
	push @objs, Packet->new($pkt, now());
}

sub main {
	#my $pid = fork();
	#return 0 if $pid;
	
	# in Child
	#redir "/opt/SAM/logs/syn.log";
	my $pthr = threads->new(\&process_thread);
	Net::PcapUtils::loop(\&catch, FILTER=> $prog);
	return 0;

}

exit main;