#!/usr/bin/perl -w use strict; my $PORT = 8018; my $BYTE_RATE = 1000; use HTTP::Daemon; use LWP::UserAgent; # Falls der Browser plötzlich abbricht $SIG{PIPE} = 'IGNORE'; # Reaper für terminierte Kindprozesse $SIG{CHLD} = sub { wait(); }; # Neuen Dämon erzeugen my $srv = HTTP::Daemon->new( LocalPort => $PORT, Reuse => 1 ); # Fehler aufgetreten? die "Can't start server ($@)" unless defined $srv; # Erfolgsmeldung print "Server listening at port $PORT\n"; my $ua = LWP::UserAgent->new(); $ua->agent("slowie/1.0"); while(my $conn = $srv->accept()) { # Parallelprozess abfeuern defined(my $pid = fork()) or die "Can't fork!"; # Vater kehrt zurück zum accept() next if $pid; # Kind bearbeitet Requests der Verbindung while (my $request = $conn->get_request) { my $resp = $ua->simple_request($request); if($resp->is_success()) { my $subref = get_slowsub($resp->content()); $resp->content($subref); } $conn->send_response($resp); } $conn->close; # Kind beendet sich exit(0); } ################################################## sub get_slowsub { ################################################## my ($content) = @_; my $start = time() - 1; my $followup = 0; # Closure erzeugen my $subref = sub { # Ende der Übertragung? if(0 == length($content)) { return undef; } sleep(1) if $followup++; # Maximal verfügbare Bytes my $max = (time() - $start) * $BYTE_RATE; # Timer zurücksetzen $start = time(); # Bereich aus $content ausschneiden # und zurückgeben my $chunk = substr($content, 0, $max, ""); return($chunk); }; return $subref; }