#!/usr/bin/perl -w # Copyright (c) 2008 Christian Laursen # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. use strict; use Net::TCP::Server; use POSIX; use MIME::Base64; my $flags = {}; my $file; if (@ARGV == 3 && $ARGV[0] eq '-s') { if ($ARGV[1] =~ /^\d+\.\d+\.\d+\.\d+$/) { $flags->{thishost} = $ARGV[1]; $file = $ARGV[2]; } else { die "$ARGV[1] is not a valid address"; } } elsif (@ARGV == 1) { $file = $ARGV[0]; } else { print STDERR "Usage: pls-proxy.pl [-s src_address] \n"; exit; } print STDERR "pls-proxy.pl 0.1\nCopyright (c) 2008 Christian Laursen \n\n"; # Pick playlist url my @urls = (); open (FILE, $file) or die "Couldn't open $file for reading: $!"; while (defined (my $line = )) { $line =~ s/\r?\n$//; if ($line =~ /^File\d+=(.*)$/) { push @urls, $1; } } close FILE; my $urlno = floor(rand(scalar(@urls))); my $url = $urls[$urlno]; print "Playlist contains ", scalar(@urls), " entries, picking number $urlno\n"; print "URL: $url\n\n"; my $auth; my $get; my $host; if ($url =~ m!^http://(([^:]+:[^@]+)\@)?([^:]+:\d+)(/.*)?$!) { ($auth, $host, $get) = ($2, $3, $4); $get = '/' unless defined $get; } else { die "Couldn't parse URL\n"; } $SIG{ALRM} = sub {print STDERR scalar(localtime), " Sorry, the world has ended\n"; exit 1;}; my $lh = 'Net::TCP::Server'->new(8020) or die "Couldn't listen on port 8020"; print STDERR "Waiting for client to connect on port 8020...\n"; if (my $sh = $lh->accept) { print STDERR "Client connected\n"; $sh->autoflush; my $header; my @headers = (); do { $header = <$sh>; $header =~ s/\r?\n//; $header =~ s/^(GET\s+)\S*(\s+HTTP\/\d+\.\d+)$/$1$get$2/; $header =~ s/^(Host:\s+).*$/$1$host/; push @headers, $header unless $header =~ /^$/ } while ($header !~ /^$/); if (defined $auth) { my $authheader = "Authorization: Basic " . encode_base64($auth); chomp $authheader; push @headers, $authheader; } if ($host =~ /^([^:]+):(\d+)$/) { my ($addr, $port) = ($1, $2); my $con = new Net::TCP($addr, $port, $flags) or die "Unable to connect: $!"; print STDERR "Connected to $host\n\n"; alarm 120; print "Headers:\n"; for $header (@headers) { print "$header\n"; print $con $header, "\r\n"; } print "\n"; print $con "\r\n"; my $buffer; my $total = 0; my $nextstatus = time + 10; while (my $r = read($con, $buffer, 8192)) { print $sh $buffer; $total += $r; if (time >= $nextstatus) { print scalar(localtime), " Bytes received: $total\n"; $nextstatus += 60; alarm 120; } } } else { die "Couldn't parse host\n"; } } else { print STDERR "Accept failed\n"; }