summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rwxr-xr-xusr.sbin/pkg_add/OpenBSD/PackageRepository/HTTP.pm207
1 files changed, 204 insertions, 3 deletions
diff --git a/usr.sbin/pkg_add/OpenBSD/PackageRepository/HTTP.pm b/usr.sbin/pkg_add/OpenBSD/PackageRepository/HTTP.pm
index 8f01ce95f6f..d4abcda0d6f 100755
--- a/usr.sbin/pkg_add/OpenBSD/PackageRepository/HTTP.pm
+++ b/usr.sbin/pkg_add/OpenBSD/PackageRepository/HTTP.pm
@@ -1,6 +1,6 @@
#! /usr/bin/perl
# ex:ts=8 sw=4:
-# $OpenBSD: HTTP.pm,v 1.1 2011/07/06 13:05:52 espie Exp $
+# $OpenBSD: HTTP.pm,v 1.2 2011/07/12 10:29:20 espie Exp $
#
# Copyright (c) 2011 Marc Espie <espie@openbsd.org>
#
@@ -19,5 +19,206 @@
use strict;
use warnings;
-# to be done
-1;
+package OpenBSD::Repository::HTTP;
+sub urlscheme
+{
+ return 'http';
+}
+
+sub initiate
+{
+ my $self = shift;
+ my ($rdfh, $wrfh);
+ pipe($self->{getfh}, $h1);
+ pipe($h2, $self->{cmdfh});
+ my $pid = fork();
+ if ($pid == 0) {
+ close($self->{getfh});
+ close($self->{cmdfh});
+ close(STDOUT);
+ close(STDIN);
+ open(STDOUT, '>&', $wrfh);
+ open(STDIN, '<&', $rdfh);
+ _Proxy::main($self);
+ } else {
+ close($rdfh);
+ close($wrfh);
+ $self->{controller} = $pid;
+ }
+}
+
+package _Proxy::connection;
+sub new
+{
+ my ($class, $host, $port) = @_;
+ require IO::Socket::INET;
+ my $o = IO::Socket::INET->new(
+ PeerHost => $host,
+ PeerPort => $port);
+ bless {fh => $o, buffer => ''}, $class;
+}
+
+sub getline
+{
+ my $self = shift;
+ while (1) {
+ if ($self->{buffer} =~ s/^(.*?)\015\012//) {
+ return $1;
+ }
+ my $buffer;
+ $self->{fh}->recv($buffer, 1024);
+ $self->{buffer}.=$buffer;
+ }
+}
+
+sub retrieve
+{
+ my ($self, $sz) = @_;
+ while(length($self->{buffer}) < $sz) {
+ my $buffer;
+ $self->{fh}->recv($buffer, $sz - length($self->{buffer}));
+ $self->{buffer}.=$buffer;
+ }
+ my $result= substr($self->{buffer}, 0, $sz);
+ $self->{buffer} = substr($self->{buffer}, $sz);
+ return $result;
+}
+
+sub print
+{
+ my ($self, @l) = @_;
+ print {$self->{fh}} @l;
+}
+
+package _Proxy;
+
+my $pid;
+my $token = 0;
+
+sub batch(&)
+{
+ my $code = shift;
+ if (defined $pid) {
+ waitpid($pid, 0);
+ undef $pid;
+ }
+ $token++;
+ $pid = fork();
+ if (!defined $pid) {
+ print "ERROR: fork failed: $!\n";
+ }
+ if ($pid == 0) {
+ &$code();
+ exit(0);
+ }
+}
+
+sub abort_batch()
+{
+ if (defined $pid) {
+ kill 1, $pid;
+ waitpid($pid, 0);
+ undef $pid;
+ }
+ print "\nABORTED $token\n";
+}
+
+sub main
+{
+ my $self = shift;
+ my $o = _Proxy::Connection->new($self->{host}, "www");
+ while (<STDIN>) {
+ chomp;
+ if (m/^LIST\s+(.*)$/o) {
+ my $dname = $1;
+ batch(sub {
+ my $d;
+ if (opendir($d, $dname)) {
+ print "SUCCESS: directory $dname\n";
+ } else {
+ print "ERROR: bad directory $dname $!\n";
+ }
+ while (my $e = readdir($d)) {
+ next if $e eq '.' or $e eq '..';
+ next unless $e =~ m/(.+)\.tgz$/;
+ next unless -f "$dname/$e";
+ print "$1\n";
+ }
+ print "\n";
+ closedir($d);
+ });
+ } elsif (m/^GET\s+(.*)$/o) {
+ my $fname = $1;
+ batch(sub {
+ if (open(my $fh, '<', $fname)) {
+ my $size = (stat $fh)[7];
+ print "TRANSFER: $size\n";
+ my $buffer = '';
+ while (read($fh, $buffer, 1024 * 1024) > 0) {
+ print $buffer;
+ }
+ close($fh);
+ } else {
+ print "ERROR: bad file $fname $!\n";
+ }
+ });
+ } elsif (m/^BYE$/o) {
+ exit(0);
+ } elsif (m/^ABORT$/o) {
+ abort_batch();
+ } else {
+ print "ERROR: Unknown command\n";
+ }
+ }
+}
+
+
+sub get_file
+{
+ my ($o, $file) = @_;
+ my $crlf="\015\012";
+ open my $fh, '>', $file;
+
+ my $start = 0;
+ my $end = 4000;
+ my $total_size = 0;
+
+ do {
+ $end *= 2;
+ $o->print("GET /pub/OpenBSD/snapshots/packages/amd64/$file HTTP/1.1$crlf",
+ "Host: www.w3.org$crlf",
+ "Range: bytes=",$start, "-", $end-1, $crlf, $crlf);
+
+ # get header
+
+ my $_ = $o->getline;
+ if (m,^HTTP/1\.1\s+(\d\d\d),) {
+ my $code = $1;
+ print "Code: $code\n";
+ } else {
+ print $_, "\n";
+ }
+ my $h = {};
+ while ($_ = $o->getline) {
+ last if m/^$/;
+ if (m/^([\w\-]+)\:\s*(.*)$/) {
+ print "$1 => $2\n";
+ $h->{$1} = $2;
+ } else {
+ print "unknown line: $_\n";
+ }
+ }
+
+ if (defined $h->{'Content-Range'} && $h->{'Content-Range'} =~
+ m/^bytes\s+\d+\-\d+\/(\d+)/) {
+ $total_size = $1;
+ }
+ print "END OF HEADER\n";
+
+ if (defined $h->{'Content-Length'}) {
+ my $v = $o->retrieve($h->{'Content-Length'});
+ print $fh $v;
+ }
+ $start = $end;
+ } while ($end < $total_size);
+}