Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

stopwatch.pl - Limited lifetime network daemons

by #include (Curate)
on Feb 19, 2004 at 08:15 UTC ( [id://330169]=sourcecode: print w/replies, xml ) Need Help??
Category: Networking
Author/Contact Info #include
http://www.riotmod.com
Description: Ever needed to throw up a web or FTP server just so a friend could download something from you? You can use stopwatch.pl to throw up a FTP or HTTP server with any directory as its root, with a limited lifetime; you can specify how long the server will run for, and it will close down and exit and the end of its "life". This script uses POE, POE::Component::Server::FTP, POE::Component::HTTPServer, Filesys::Virtual, Proc::Simple, File::Basename, and Getopt::Mixed.

Usage:

% perl stopwatch.pl OPTIONS DIRECTORY

-v,--version Print version and exit.
-h,--help Prints this text.
-V,--verbose Displays more information while running.
-p,--port NUMBER Sets the server port (default 2020).
-s,--seconds NUMBER Sets the timelimit to NUMBER seconds.
-m,--minutes NUMBER Sets the timelimit to NUMBER minutes.
-g,--generate Generates index.html in the DIRECTORY.
-F,--ftp Sets the server type to FTP.
-H,--http Sets the server type to HTTP (the default).

EXAMPLE:
Say you want to share your home directory ("/home/me") on an FTP server so your friend can download some source code from you. You figure that it won't take him longer than 15 minutes to download the code from you, and decide to give him 20 minutes to get the file, and you want to run the server on port 12345. You open up a terminal and type this:

% perl stopwatch.pl --ftp --port 12345 --minutes 20 /home/me
or
% perl stopwatch.pl -Fp 12345 -m 20 /home/me
#!/usr/bin/perl
#
# stopwatch.pl
#
# Usage:
#
# % perl stopwatch.pl [ OPTIONS ] DIRECTORY
#
# -v,--version     Print version and exit.
# -h,--help        Prints this text.
# -V,--verbose     Displays more information while running.
# -p,--port NUMBER Sets the server port (default 2020).
# -s,--seconds NUMBER Sets the timelimit to NUMBER seconds.
# -m,--minutes NUMBER Sets the timelimit to NUMBER minutes.
# -g,--generate    Generates index.html in the DIRECTORY.
# -F,--ftp      Sets the server type to FTP.
# -H,--http     Sets the server type to HTTP (the default).
#
use strict;
use warnings;
use POE;
use POE::Component::Server::FTP;
use POE::Component::Server::HTTPServer;
use Filesys::Virtual;
use Proc::Simple;
use File::Basename;
use Getopt::Mixed "nextOption";
my $option;
my $value;

# FTP Settings
my $FTPD_DOMAIN    = 'localhost';
my $FTPD_VERSION   = "$0";
my $DOWNLOAD_LIMIT = 50;            # In kb/s
my $UPLOAD_LIMIT   = 100;
my $TIMEOUT        = 120;
my $ANONYMOUS      = 'allow';

# General Settings
my $VERSION        = "0.1";
my $APPNAME        = "Stopwatch";
my $SETTINGS_PORT  = 2020;
my $TIMELIMIT      = 300;
my $MODE           = 2;             # 1=FTP, 2=HTTP
my $VERBOSE        = 0;
my $GENERATE_INDEX = 0;

# ===========
# MAIN SCRIPT
# ===========

Getopt::Mixed::init(
"v version>v h help>h d p=i port>p s=i seconds>s m=i minutes>m F ftp>F
+ H http>H V verbose>V g generate>g"
);

while ( ( $option, $value ) = nextOption() ) {
    if ( $option =~ /v/ ) { print "$VERSION\n"; exit; }
    if ( $option =~ /p/ ) { $SETTINGS_PORT  = $value; }
    if ( $option =~ /s/ ) { $TIMELIMIT      = $value; }
    if ( $option =~ /m/ ) { $TIMELIMIT      = $value * 60; }
    if ( $option =~ /F/ ) { $MODE           = 1; }
    if ( $option =~ /H/ ) { $MODE           = 2; }
    if ( $option =~ /V/ ) { $VERBOSE        = 1; }
    if ( $option =~ /g/ ) { $GENERATE_INDEX = 1; }
    if ( $option =~ /h/ ) {
        Usage();
    }
}

Getopt::Mixed::cleanup();

if ( $#ARGV != 0 ) { print "ERROR: No directory named.\n"; exit; }

my $HOSTED_DIRECTORY = $ARGV[0];

if ( !( -e $HOSTED_DIRECTORY ) ) {
    print "ERROR: Directory doesn't exist.\n";
    exit;
}

if ( ( -f $HOSTED_DIRECTORY ) ) {
    print "ERROR: Directory expected, file found.\n";
    exit;
}

Print_Verbose("$APPNAME $VERSION\n");

if ( $MODE == 1 ) {    # FTP Mode
    Print_Verbose("Starting FTP daemon on port $SETTINGS_PORT...");
    my $ftpd_proc = Proc::Simple->new();
    $ftpd_proc->start( \&ftpd, $HOSTED_DIRECTORY, $SETTINGS_PORT );
    Print_Verbose("done!\nLifetime set to $TIMELIMIT seconds.\nRunning
+...");
    sleep $TIMELIMIT;
    Print_Verbose("done!\nShutting down daemon...");
    $ftpd_proc->kill();
    Print_Verbose("done!\n");
}
elsif ( $MODE == 2 ) {
    if ( $GENERATE_INDEX == 1 ) {
        Print_Verbose("Generating $HOSTED_DIRECTORY/index.html...");
        GenerateIndex($HOSTED_DIRECTORY);
        Print_Verbose("done!\n");
    }
    Print_Verbose("Starting HTTP daemon on port $SETTINGS_PORT...");
    my $httpd_proc = Proc::Simple->new();
    $httpd_proc->start( \&httpd, $HOSTED_DIRECTORY, $SETTINGS_PORT );
    Print_Verbose("done!\nLifetime set to $TIMELIMIT seconds.\nRunning
+...");
    sleep $TIMELIMIT;
    Print_Verbose("done!\nShutting down daemon...");
    $httpd_proc->kill();
    Print_Verbose("done!\n");
}

exit;

# ============
# SUPPORT SUBS
# ============

sub Usage {
    print "$0 [ OPTIONS ] DIRECTORY\n\n";
    print "-v,--version             Print version and exit.\n";
    print "-h,--help                Prints this text.\n";
    print "-V,--verbose             Displays more information while ru
+nning.\n";
    print "-p,--port NUMBER         Sets the server port (default 2020
+).\n";
    print "-s,--seconds NUMBER      Sets the timelimit to NUMBER secon
+ds.\n";
    print "-m,--minutes NUMBER      Sets the timelimit to NUMBER minut
+es.\n";
    print "-g,--generate            Generates index.html in the DIRECT
+ORY.\n";
    print "-F,--ftp                 Sets the server type to FTP.\n";
    print
      "-H,--http                Sets the server type to HTTP (the defa
+ult).\n";
    print "\n";
    print "The default timelimit is 5 minutes (300 seconds).\n";
    print "Generated index.html will OVERWRITE any index.html in\n";
    print "the target directory.\n";
    exit;
}

sub Print_Verbose {
    my ($text) = @_;
    if ( $VERBOSE == 1 ) { print $text; }
}

sub ftpd {
    my ( $directory, $port ) = @_;
    POE::Component::Server::FTP->spawn(
        Alias           => 'ftpd',
        ListenPort      => $port,
        Domain          => $FTPD_DOMAIN,
        Version         => $FTPD_VERSION,
        AnonymousLogin  => $ANONYMOUS,
        FilesystemClass => 'Filesys::Virtual::Plain',
        FilesystemArgs  => {
            'root_path' => $directory,
            'cwd'       => '/',
            'home_path' => '/',
        },

        # use 0 to disable these Limits
        DownloadLimit => ( $DOWNLOAD_LIMIT * 1024 ),
        UploadLimit   => ( $UPLOAD_LIMIT * 1024 ),
        LimitSceme    => 'ip',
        LogLevel => 1,          # 4=debug, 3=less info, 2=quiet, 1=rea
+lly quiet
        TimeOut  => $TIMEOUT,
    );

    $poe_kernel->run();
}

sub httpd {
    my ( $directory, $port ) = @_;
    my $server = POE::Component::Server::HTTPServer->new();
    $server->port($port);
    $server->handlers( [ '/' => new_handler( 'StaticHandler', $directo
+ry ), ] );
    my $svc = $server->create_server();
    $poe_kernel->run();
}

sub GenerateIndex {
    my ($directory) = @_;
    open( FILE, ">$directory/index.html" ) or die "Error creating inde
+x";
    print FILE BuildIndex($directory);
    close FILE;
}

sub BuildIndex {
    my ($directory) = @_;
    my @f           = GetFileList($directory);
    my $index       =
        "<html><head><title>HTTPD - $0 - "
      . basename($directory)
      . "</title></head><body>\n";
    $index .= "<h1>Contents of " . basename($directory) . "</h1>\n";
    $index .= "<ul>\n";
    foreach my $file (@f) {
        $index .= "<li><a href=\"$file\">$file</a></li>\n";
    }
    $index .= "</ul>\n";
    $index .= "<font size=\"1\">Created automatically by $0</font><br>
+\n";
    $index .= "</body></html>\n";
    return $index;
}

sub GetFileList {
    my ($directory_name) = @_;
    my @file_list = ();
    opendir( TDIR, "$directory_name" )
      or die "Error opening directory $directory_name.";
    my @tdir = grep { -f "$directory_name/$_" } readdir(TDIR);
    closedir(TDIR);
    foreach my $ent (@tdir) {
        if ( $ent =~ /index.html/ ) { }
        else {
            push( @file_list, "$ent" );
        }
    }
    return @file_list;
}
Replies are listed 'Best First'.
Re: stopwatch.pl - Limited lifetime network daemons
by Anonymous Monk on Aug 14, 2008 at 13:22 UTC
    Hi. I'm looking fore more complex usage of POE FTP Server component with authorization control and so on. Can't you point me on some code examples if any? Thx in advice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://330169]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-16 03:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found