#!/usr/bin/perl

use Win32::Pipe;
use Sys::Hostname;
my $PipeName = "My Named Pipe";

$| = 1; # Set output buffering to AUTO_FLUSH

print "Spawning server and client\n" ;

 SPAWN: {
     my $pid;
     print "Preparing to fork\n" ;
     
     if($pid=fork()) {
	 print "Spawning server\n" if defined ($DEBUG);
	 
	 np_server() ;

     } elsif (defined($pid)) {
	 print "Spawning client\n" if defined ($DEBUG);
	 
	 np_client() ;

     } elsif ($! =~ /No more process/) {
	 sleep 5;
	 print "Respawning\n" ;
	 redo SPAWN;
     } else {
	 die "Can't fork: $!\n";
     }
 }

sub np_server {

    my $Pipe_Error ;
    my $Client_Disconnected;
    my $Pipe_Connect_Status;
    my $Test_Done ; 
    my $In;

    print "NP Server: Creating pipe \"$PipeName\".\n";
    

    if( ($Pipe = new Win32::Pipe( $PipeName, NMPWAIT_WAIT_FOREVER, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT))  )
    {
	print "NP Server: Done creating pipe.\n";
		
	$User =  getlogin() ;
	print "NP Server: Pipe opened by $User.\n";
	$Pipe_Error = 0;
	$Test_Done = 0;
	while(!$Pipe_Error && !$Test_Done) {
	    $Client_Disconnected = 0;
	    print "NP Server: Waiting for client to connect\n";

	    while(( $Pipe->Connect()) && !$Pipe_Error && !$Client_Disconnected && !$Test_Done) {
		print "NP Server: Client connected\n";
		my $Data = "Pipe writen by $User. Time on " . hostname() . " is: " . localtime() . "\n";
		    
		if (!$Pipe->Write( $Data )) {
		    print "NP Server: Error writing pipe\n";
		    $Pipe_Error = 1;
		    next ;
		}
		if (!($In=$Pipe->Read())) {
		    print "NP Server: Error reading pipe\n";
		    $Pipe_Error = 1;
		    next ;
		}
		$Client_Disconnected = 1 if ($In eq "DONE") ;
		$Test_Done = 1 if ($In eq "FINIS") ;
		print "NP Server: Test Done\n" if ($In eq "FINIS") ;

		print "NP Server: Disconnecting...\n";
		$Pipe->Disconnect();
		$Pipe->Close() if ($Test_Done);
 
	    }

	    print "NP Server: Client Disconnected\n" if ($Client_Disconnected);;	    print "NP Server: Pipe Error -- $|\n" if ($Pipe_Error);
	    print "NP Server: Test Done\n" if ($Test_Done);
	    sleep 1;
	}
   }
    else
    {
	print "\nNP Server: Could not create pipe Error: " . Win32::Pipe::Error . "\n";
    }
}

sub np_client {
    
    my $FQNPipeName = "\\\\.\\pipe\\" . $PipeName;
    print "NP Client: Connecting to $FQNPipeName via Win32::Pipe\n";
    
    if( $Pipe = new Win32::Pipe( $FQNPipeName ) )
    {
	print "NP Client: Pipe has been opened, read data from it...\n";
	my $In = $Pipe->Read();
	print "NP Client: Server sent the client -- $In\n";
	print "NP Client: Closing the pipe\n";
	$Pipe->Write("DONE");
	$Pipe->Close();
    }
    else
    {
	print "NP Client: Error connecting: " .  $Win32::Pipe::Error  . "\n";
    }
    print "NP Client: Connecting to $FQNPipeName via open()\n";
    
    sleep 1;
    if( open(PIPE, "+<", $FQNPipeName ) )
    {
	my $In;
	print "NP Client: Pipe has been opened, reading data from it...\n";
	
	read PIPE,  $In, 70 ;
	print "NP Client: Server sent the client -- $In\n";
	print PIPE  "DONE", 4;

	close(PIPE);
    }
    else
    {
	print "NP Client: Error connecting via open(): $!\n";
    }
    print "NP Client: Finishing the test\n";

    if( $Pipe = new Win32::Pipe( $FQNPipeName ) )
    {
    print "NP Client: Finishing the test\n";

    $Pipe->Write("FINIS");
    $Pipe->Close();
    }
    else
    {
	print "NP Client: Error connecting: " .  $Win32::Pipe::Error . "\n";
    }
    print "NP Client: Test Done\n";

}

