#!/usr/bin/perl
#Pear Core server version 0.05
use IO::Socket::INET;
use strict;
use Time::HiRes;
#No Go on windows :)
use vars qw(%filebase $socket);
$socket = IO::Socket::INET->new(Listen => 1,
LocalPort => 9876,
PeerAddr => "192.168.0.2",
#Change IP
Proto => "tcp",
ReuseAddr => 1,
Type => SOCK_STREAM,
);
if (!$socket) { die "No Socket"; }
$|++;
sub timer
{ for my $ip (keys %filebase)
{ $filebase{$ip}{timestamp}++;
if ($filebase{$ip}{timestamp} > 5)
{ logrequest("Deleted $ip -> $filebase{$ip}{timestamp}");
delete($filebase{$ip});
}
}
}
#Increase counter every 30 secs
#If above ceiling, remove host
$SIG{ALRM} = \&timer;
if ($^O ne "MSWin32")
{ Time::HiRes::ualarm(30_000_000,30_000_000); }
$socket->autoflush(1);
print "Accepting clients...\n";
#Complex Data Structure met files and IPs
while(my $client = $socket->accept())
{ my $line = <$client>;
chomp $line;
my $clientaddress = $client->peerhost;
$client->autoflush(1);
#Log it
if ($line eq "Pear Pear")
#Send file list
{ $line = <$client>;
chomp $line;
while($line)
{ push(@{$filebase{$clientaddress}{files}},{filename=>$line});
#Stick files in data struc based on IP
logrequest("$line located at $clientaddress");
$line = <$client>;
chomp $line;
}
close($client);
}
if ($line eq "Orange Orange")
#Send Time event
{ $filebase{$clientaddress}{timestamp} = 0;
logrequest("$clientaddress checked in...");
close($client);
}
if ($line eq "Apple Apple")
#Query file??
{ $line = <$client>;
chomp $line;
if ($line =~ /^Pluck ([^\s]*)$/)
#extract filename : Pluck filename
{ my $fruit = $1;
my @query = ();
for my $ip (keys %filebase)
{ for my $filerecord (@{$filebase{$ip}{files}})
{ my $filename = ${$filerecord}{filename};
if ($ip ne $clientaddress && $filename =~ /$fruit/i)
{ push(@query,"$ip;$filename"); }
#Check data struc for files
}
}
logrequest("$fruit queried by $clientaddress");
for(@query) { print $client $_,"\n"; }
#Send IP list to client
}
close($client);
}
}
close($socket);
sub logrequest
{ open(LOG,">>pear.log") || die $!;
my $hour = sprintf "%02d",(localtime(time))[2];
my $minute = sprintf "%02d",(localtime(time))[1];
my $second = sprintf "%02d",(localtime(time))[0];
my $day = sprintf "%02d",(localtime(time))[3];
my $month = sprintf "%02d",(localtime(time))[4]+1;
my $year = 1900+(localtime(time))[5];
#sprintf - Zero padding
my $datestring = "$hour:$minute:$second $day/$month/$year ";
print LOG $datestring,join(" - ",@_),"\n";
close(LOG);
#Log connections
}
# ------ Client
#!/usr/bin/perl
use IO::Socket;
use vars qw($pid $server $debug);
use Term::ReadLine;
use Time::HiRes;
use File::Find;
use strict;
$debug = 1;
#1 -> yes
#0 -> no
#Socket to Core
sub createsocket
{ $server = IO::Socket::INET->new(PeerPort => 9876,
PeerAddr => '192.168.0.2',
#Change Core IP
Proto => 'tcp',
ReuseAddr => 1,
Type => SOCK_STREAM,
);
$server->autoflush(1);
debuglog("Created Core Server Connection");
if (!$server) { return 0; } else { return 1; }
}
sub closesocket
{ close($server); debuglog("Closing Core Server Connection"); }
#Send timestamp
sub sendtime { createsocket(); print $server "Orange Orange\n"; closes
+ocket(); }
#Send file list
sub sendfiles
{ createsocket();
print $server "Pear Pear\n";
#Init file list
if ($^O ne "MSWin32")
{ File::Find::find({ wanted=> sub
{ my $filename = $File::Find::name;
$filename =~ s/^\.\/(.*)$/$1/;
print $server $filename,"\n" if !-d $File::Find::name;
}, follow=>1 }, ".");
} else
{ sub dodir
{ opendir(DIR,$_[0]);
my $dir = $_[0];
if ($dir !~ /\/$/) { $dir .= "/"; }
for my $file(readdir(DIR))
{ $file =~ s/^\.\/(.*)$/$1/;
if ($file =~ /^\.\.?$/)
{ next; }
my $fullpath = $dir.$file;
if (-d $fullpath) { dodir($fullpath); }
else { print $server $fullpath,"\n"; }
}
closedir(DIR);
}
dodir(".");
}
debuglog("Sending filelist to Core server");
closesocket();
}
#Query Core for files
sub queryfile
{ createsocket();
my $filename = shift;
print $server "Apple Apple\n";
print $server "Pluck $filename\n";
#Query filename
my @IP = ();
while(my $line = <$server>) { chomp $line; push(@IP,$line); }
debuglog("Querying files on Core server");
closesocket();
return \@IP;
}
sendtime();
sendfiles();
#Send sig every 60 secs
$SIG{ALRM} = \&sendtime;
if ($^O ne "MSWin32")
{ Time::HiRes::ualarm(60_000_000,60_000_000); }
die "can't fork: $!" unless defined($pid = fork());
if ($pid) # client
{ my $term = new Term::ReadLine 'Pear Client';
my $label = "Keyword : ";
my $keyword;
my @db;
my $file;
#Fancy input
while ( defined ($keyword = $term->readline($label)) )
{ if ($keyword =~ /^update$/i)
{ sendtime(); sendfiles(); }
if ($keyword =~ /^(quit|bye|exit)$/i)
{ kill 9,$pid; exit; }
if ($keyword =~ /^help$/i)
{ print "help:\t\t\tThis page\nupdate:\t\t\tUpdate filelist and ti
+me\nfind <filename>:\tFind filename\nget <number>:\t\tGet file from h
+ost indicated by number\n";
print "quit:\t\t\tQuit Pear\n";
}
if ($keyword =~ /^find ([^\s]*)$/i)
{ $file = $1;
#Find filename -> Core returns array
my @foo = @{queryfile($file)};
my $c = 0;
for(@foo)
{ my ($ip,$filename) = split(/;/,$_); push(@db,{IP=>$ip,Filename
+=>$filename}); }
for(@db) { print join("\t","[$c]",$_->{Filename},$_->{IP}."\n");
+ $c++ }
}
if ($keyword =~ /^get (\d*)$/i)
{ my $index = $1;
my $ip = $db[$index]->{IP};
#Displays list with index
my $socket = IO::Socket::INET->new(PeerPort => 6789,
PeerAddr => $ip,
Proto => "tcp",
ReuseAddr => 1,
Type => SOCK_STREAM,
);
if (!$socket) { debuglog("IP $ip is not online"); next; }
$socket->autoflush(1);
my $file = $db[$index]->{Filename};
debuglog("Fetching $file from $ip");
print $socket "Peach Peach $file\n";
my $filesize = <$socket>;
chomp $filesize;
if ($filesize eq "ERROR") { next; }
my $data;
my $buffersize = 4096;
my $returnsize;
my $readsize;
#Dump to file
if(open(OUTFILE,">$file"))
{ while($returnsize = read($socket,$data,$buffersize) && $readsi
+ze != $filesize)
{ print OUTFILE $data;
$readsize += $returnsize;
}
close(OUTFILE);
} else { debuglog("Error opening $file for writing ($ip)"); }
close($socket);
}
}
} else
{ my $socket = IO::Socket::INET->new(Listen => 1,
LocalPort => 6789,
PeerAddr => "192.168.0.2",
Proto => "tcp",
ReuseAddr => 1,
Type => SOCK_STREAM,
);
if (!$socket) { die "No Socket"; }
$|++;
$socket->autoflush(1);
print "Pear Server Accepting clients...\n";
while(my $client = $socket->accept())
{ $client->autoflush(1);
my $line = <$client>;
chomp $line;
if ($line =~ /^Peach Peach ([^\s]*)/)
{ my $filename = $1;
my $filesize = -s $filename;
print $client "$filesize\n";
if(open(FILE,"<$filename"))
{ print $client "$filesize\n";
my $data;
my $buffersize = 4096;
my $returnsize;
my $readsize;
while($returnsize = read(FILE,$data,$buffersize) && $readsize
+!= $filesize)
{ print $client $data;
$readsize += $returnsize;
}
close(FILE);
} else { print $client "ERROR\n"; debuglog("Error opening $filen
+ame for reading - ".$client->peerhost); }
close($client);
}
}
}
sub debuglog
{ if (!$debug) { return }
open(LOG,">>debug.log") || die $!;
my $hour = sprintf "%02d",(localtime(time))[2];
my $minute = sprintf "%02d",(localtime(time))[1];
my $second = sprintf "%02d",(localtime(time))[0];
my $day = sprintf "%02d",(localtime(time))[3];
my $month = sprintf "%02d",(localtime(time))[4]+1;
my $year = 1900+(localtime(time))[5];
my $datestring = "$hour:$minute:$second $day/$month/$year ";
print LOG $datestring,join(" - ",@_),"\n";
close(LOG);
#Log connections
}
|