ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Coro/myhttpd/httpd.pl
(Generate patch)

Comparing cvsroot/Coro/myhttpd/httpd.pl (file contents):
Revision 1.82 by root, Sat Dec 2 03:31:42 2006 UTC vs.
Revision 1.89 by root, Sun Jan 24 20:44:34 2010 UTC

1use Coro; 1use Coro;
2use Coro::Semaphore; 2use Coro::Semaphore;
3use Coro::Event; 3use Coro::EV;
4use Coro::Socket; 4use Coro::Socket;
5use Coro::Signal; 5use Coro::Signal;
6use Coro::AIO (); 6use Coro::AIO ();
7 7
8use HTTP::Date; 8use HTTP::Date;
26our $HTTP_NOW; 26our $HTTP_NOW;
27 27
28our $ERROR_LOG; 28our $ERROR_LOG;
29our $ACCESS_LOG; 29our $ACCESS_LOG;
30 30
31Event->timer(interval => 1, hard => 1, cb => sub { 31our $update_time = EV::periodic 0, 1, undef, sub {
32 $NOW = time; 32 $NOW = time;
33 $HTTP_NOW = time2str $NOW; 33 $HTTP_NOW = time2str $NOW;
34})->now; 34};
35$update_time->invoke;
35 36
36if ($ERROR_LOG) { 37if ($ERROR_LOG) {
37 use IO::Handle; 38 use IO::Handle;
38 open $errorlog, ">>$ERROR_LOG" 39 open $errorlog, ">>$ERROR_LOG"
39 or die "$ERROR_LOG: $!"; 40 or die "$ERROR_LOG: $!";
74 $queue_file->force_wake_next; 75 $queue_file->force_wake_next;
75 slog 1, "forced filetransfer due to unused bandwidth"; 76 slog 1, "forced filetransfer due to unused bandwidth";
76 } 77 }
77} 78}
78 79
79my @newcons;
80my @pool;
81
82# one "execution thread"
83sub handler {
84 while () {
85 if (@newcons) {
86 eval {
87 conn->new (@{pop @newcons})->handle;
88 };
89 slog 1, "$@" if $@ && !ref $@;
90
91 $httpevent->broadcast; # only for testing, but doesn't matter much
92
93 $connections->up;
94 } else {
95 last if @pool >= $MAX_POOL;
96 push @pool, $Coro::current;
97 schedule;
98 }
99 }
100}
101
102sub listen_on { 80sub listen_on {
103 my $listen = $_[0]; 81 my $listen = $_[0];
104 82
105 push @listen_sockets, $listen; 83 push @listen_sockets, $listen;
106 84
107 # the "main thread" 85 # the "main thread"
108 async { 86 async {
109 slog 1, "accepting connections"; 87 slog 1, "accepting connections";
110 while () { 88 while () {
111 $connections->down; 89 $connections->down;
112 push @newcons, [$listen->accept]; 90 my @conn = $listen->accept;
113 #slog 3, "accepted @$connections ".scalar(@pool); 91 #slog 3, "accepted @$connections ".scalar(@pool);
114 if (@pool) { 92
115 (pop @pool)->ready; 93 async_pool {
116 } else { 94 eval {
117 async \&handler; 95 conn->new (@conn)->handle;
96 };
97 slog 1, "$@" if $@ && !ref $@;
98
99 $httpevent->broadcast; # only for testing, but doesn't matter much
100
101 $connections->up;
118 } 102 }
119 } 103 }
120 }; 104 };
121} 105}
122 106
150use Convert::Scalar 'weaken'; 134use Convert::Scalar 'weaken';
151use IO::AIO; 135use IO::AIO;
152 136
153IO::AIO::min_parallel $::AIO_PARALLEL; 137IO::AIO::min_parallel $::AIO_PARALLEL;
154 138
155Event->io (fd => IO::AIO::poll_fileno, 139our $AIO_WATCHER = EV::io IO::AIO::poll_fileno, EV::READ, \&IO::AIO::poll_cb;
156 poll => 'r', async => 1,
157 cb => \&IO::AIO::poll_cb);
158 140
159our %conn; # $conn{ip}{self} => connobj 141our %conn; # $conn{ip}{self} => connobj
160our %uri; # $uri{ip}{uri}{self} 142our %uri; # $uri{ip}{uri}{self}
161our %blocked; 143our %blocked;
162our %mimetype; 144our %mimetype;
197} 179}
198 180
199sub DESTROY { 181sub DESTROY {
200 my $self = shift; 182 my $self = shift;
201 183
202 close $self->{fh}; # workaround
203 --$::conns; 184 --$::conns;
204} 185}
205 186
206sub prune_cache { 187sub prune_cache {
207 my $hash = $_[0]; 188 my $hash = $_[0];
223 for (keys %blocked) { 204 for (keys %blocked) {
224 delete $blocked{$_} unless $blocked{$_}[0] > $::NOW; 205 delete $blocked{$_} unless $blocked{$_}[0] > $::NOW;
225 } 206 }
226} 207}
227 208
228Event->timer (interval => 60, cb => \&prune_caches); 209our $PRUNE_WATCHER = EV::timer 60, 60, \&prune_caches;
229 210
230sub slog { 211sub slog {
231 my $self = shift; 212 my $self = shift;
232 main::slog($_[0], "$self->{remote_id}> $_[1]"); 213 main::slog($_[0], "$self->{remote_id}> $_[1]");
233} 214}
426sub map_uri { 407sub map_uri {
427 my $self = shift; 408 my $self = shift;
428 my $host = $self->{server_name}; 409 my $host = $self->{server_name};
429 my $uri = $self->{uri}; 410 my $uri = $self->{uri};
430 411
412 $host =~ /[\/\\]/
413 and $self->err(400, "bad request");
414
431 # some massaging, also makes it more secure 415 # some massaging, also makes it more secure
432 $uri =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr hex $1/ge; 416 $uri =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr hex $1/ge;
433 $uri =~ s%//+%/%g; 417 $uri =~ s%//+%/%g;
434 $uri =~ s%/\.(?=/|$)%%g; 418 $uri =~ s%/\.(?=/|$)%%g;
435 1 while $uri =~ s%/[^/]+/\.\.(?=/|$)%%; 419 1 while $uri =~ s%/[^/]+/\.\.(?=/|$)%%;
482 } else { 466 } else {
483 $self->err (404, "not found"); 467 $self->err (404, "not found");
484 } 468 }
485 } else { 469 } else {
486 470
487 stat $path 471 Coro::AIO::aio_stat $path
488 or $self->err (404, "not found"); 472 and $self->err (404, "not found");
489 473
490 $self->{stat} = [stat _]; 474 $self->{stat} = [stat _];
491 475
492 # idiotic netscape sends idiotic headers AGAIN 476 # idiotic netscape sends idiotic headers AGAIN
493 my $ims = $self->{h}{"if-modified-since"} =~ /^([^;]+)/ 477 my $ims = $self->{h}{"if-modified-since"} =~ /^([^;]+)/
554 }; 538 };
555 539
556 my @code = (200, "ok"); 540 my @code = (200, "ok");
557 my ($l, $h); 541 my ($l, $h);
558 542
559 if ($self->{h}{range} =~ /^bytes=(.*)$/) { 543 if ($self->{h}{range} =~ /^bytes=(.*)$/i) {
560 for (split /,/, $1) { 544 for (split /,/, $1) {
561 if (/^-(\d+)$/) { 545 if (/^-(\d+)$/) {
562 ($l, $h) = ($length - $1, $length - 1); 546 ($l, $h) = ($length - $1, $length - 1);
563 } elsif (/^(\d+)-(\d*)$/) { 547 } elsif (/^(\d+)-(\d*)$/) {
564 ($l, $h) = ($1, ($2 ne "" || $2 >= $length) ? $2 : $length - 1); 548 ($l, $h) = ($1, ($2 ne "" || $2 >= $length) ? $2 : $length - 1);
630 614
631 Coro::AIO::aio_read $fh, $l, ($h > $bufsize ? $bufsize : $h), my $buf, 0 615 Coro::AIO::aio_read $fh, $l, ($h > $bufsize ? $bufsize : $h), my $buf, 0
632 or last; 616 or last;
633 617
634 $tbf->request (length $buf); 618 $tbf->request (length $buf);
635 my $w = syswrite $self->{fh}, $buf 619 my $w = $self->{fh}->syswrite ($buf)
636 or last; 620 or last;
637 $::written += $w; 621 $::written += $w;
638 $self->{written} += $w; 622 $self->{written} += $w;
639 $l += $w; 623 $l += $w;
640 } 624 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines