Advertisement
Guest User

Untitled

a guest
Jan 15th, 2020
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 2.43 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings qw(FATAL all);
  5. use threads;
  6. use threads::shared;
  7. use IO::Socket::INET;
  8. use Time::HiRes qw(usleep);
  9.  
  10. my $USAGE = "Usage $0 port [thread_count]\n";
  11. scalar @ARGV or die $USAGE;
  12. my ($port) = shift(@ARGV) =~ /(\d+)/ or die $USAGE;
  13.  
  14. my $thread_count = 2;
  15. if (scalar @ARGV) {
  16.     ($thread_count) = shift(@ARGV) =~ /(\d+)/ or die $USAGE;
  17. }
  18.  
  19. my $busy_i :shared = 0;
  20. my $client_i :shared = 1;
  21. my $id_i :shared = 2;
  22.  
  23. my @thread_pool :shared;
  24. for (my $i = 0; $i < $thread_count; $i++) {
  25.     my @server_thread :shared;
  26.     $server_thread[$busy_i] = 0;
  27.     $server_thread[$client_i] = -1;
  28.     $server_thread[$id_i] = $i;
  29.     $thread_pool[$i] = \@server_thread;
  30.  
  31.     threads->create(\&worker, $i)->detach();
  32. }
  33.  
  34. my $server = IO::Socket::INET->new(
  35.     LocalPort => $port, Proto => 'tcp', Listen => SOMAXCONN
  36. ) or die "Failed to start the server: $!\n";
  37.  
  38. print "Listening on $port\n";
  39.  
  40. while (1) {
  41.     if ((my $free_thread_id = get_free_thread()) != -1) {
  42.         my $clt = $server->accept();
  43.         $thread_pool[$free_thread_id]->[$client_i] = $clt;
  44.  
  45.     }
  46.     usleep(1000);
  47. }
  48.  
  49. sub get_free_thread {
  50.     for (my $i = 0; $i < $thread_count; $i++) {
  51.         if ($thread_pool[$i]->[$busy_i] == 0) {
  52.             $thread_pool[$i]->[$busy_i] = 1;
  53.             return $i;
  54.         }
  55.     }
  56.     return -1;
  57. }
  58.  
  59. sub worker {
  60.     my $id = shift @_;
  61.     my $meta = $thread_pool[$id];
  62.     while (1) {
  63.         while (1) {
  64.             if ($meta->[$busy_i] == 1 && $meta->[$client_i] != -1) {
  65.                 last;
  66.             }
  67.             usleep(5000);
  68.         }
  69.         my $clt = $meta->[$client_i];
  70.         my $clt_addr = $clt->peerhost;
  71.         my $clt_port = $clt->peerport;
  72.         print "Thread #$id: client connected: $clt_addr:$clt_port\n";
  73.  
  74.         my $request = "";
  75.         while (<$clt>) {
  76.             $request .= $_;
  77.             last if $request =~ /\r\n\r\n$/;
  78.         }
  79.  
  80.         my @dirs = split /\r\n/, $request;
  81.  
  82.         for my $dir (@dirs) {
  83.             if (opendir my $dirent, $dir) {
  84.                 my @files = readdir $dirent;
  85.                 closedir $dirent;
  86.  
  87.                 print $clt "Contents of $dir:\r\n" . join("\r\n", @files) . "\r\n\r\n";
  88.             }
  89.             else {
  90.                 print $clt "Failed to open $dir: $!\r\n\r\n";
  91.             }
  92.         }
  93.  
  94.         close $clt;
  95.         $meta->[$client_i] = -1;
  96.         $meta->[$busy_i] = 0;
  97.     }
  98. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement