1 | #!/usr/bin/perl |
1 | #!/usr/bin/perl |
2 | |
2 | |
3 | # this is a relatively small web-server, using coroutines |
3 | # this is a relatively small web-server, using coroutines for connections. |
4 | # for connections. play around with it but do not use |
4 | # play around with it but do not use it in production without checking it |
5 | # it in production. ask myhttpd@plan9.de for a better |
5 | # works for you. ask myhttpd@plan9.de in case of problems, or if you are |
6 | # version that's more usable and bugfixed. |
6 | # interested in a newer version (more useless features). |
7 | |
7 | |
8 | use Coro; |
8 | use Coro; |
9 | use Coro::Semaphore; |
9 | use Coro::Semaphore; |
10 | use Coro::Event; |
10 | use Coro::Event; |
11 | use Coro::Socket; |
11 | use Coro::Socket; |
… | |
… | |
62 | schedule; |
62 | schedule; |
63 | } |
63 | } |
64 | } |
64 | } |
65 | } |
65 | } |
66 | |
66 | |
67 | async { |
67 | # move the event main loop into a coroutine |
|
|
68 | async { loop }; |
|
|
69 | |
68 | slog 1, "accepting connections"; |
70 | slog 1, "accepting connections"; |
69 | while () { |
71 | while () { |
70 | $connections->down; |
72 | $connections->down; |
71 | push @fh, $port->accept; |
73 | push @fh, $port->accept; |
72 | #slog 3, "accepted @$connections ".scalar(@pool); |
74 | #slog 3, "accepted @$connections ".scalar(@pool); |
73 | if (@pool) { |
75 | if (@pool) { |
74 | (pop @pool)->ready; |
76 | (pop @pool)->ready; |
75 | } else { |
77 | } else { |
76 | async \&handler; |
78 | async \&handler; |
77 | } |
|
|
78 | |
|
|
79 | } |
79 | } |
80 | }; |
|
|
81 | |
80 | |
82 | loop; |
81 | } |
83 | print "ende\n";#d# |
|
|
84 | |
82 | |
85 | package conn; |
83 | package conn; |
86 | |
84 | |
87 | use Socket; |
85 | use Socket; |
88 | use HTTP::Date; |
86 | use HTTP::Date; |
… | |
… | |
164 | my (%hdr, $h, $v); |
162 | my (%hdr, $h, $v); |
165 | |
163 | |
166 | $hdr{lc $1} .= ",$2" |
164 | $hdr{lc $1} .= ",$2" |
167 | while $req =~ /\G |
165 | while $req =~ /\G |
168 | ([^:\000-\040]+): |
166 | ([^:\000-\040]+): |
169 | [\010\040]* |
167 | [\011\040]* |
170 | ((?: [^\015\012]+ | \015\012[\010\040] )*) |
168 | ((?: [^\015\012]+ | \015\012[\011\040] )*) |
171 | \015\012 |
169 | \015\012 |
172 | /gxc; |
170 | /gxc; |
173 | |
171 | |
174 | $req =~ /\G\015\012$/ |
172 | $req =~ /\G\015\012$/ |
175 | or $self->err(400, "bad request"); |
173 | or $self->err(400, "bad request"); |
… | |
… | |
317 | ($l, $h) = ($1, ($2 ne "" || $2 >= $length) ? $2 : $length - 1); |
315 | ($l, $h) = ($1, ($2 ne "" || $2 >= $length) ? $2 : $length - 1); |
318 | } else { |
316 | } else { |
319 | ($l, $h) = (0, $length - 1); |
317 | ($l, $h) = (0, $length - 1); |
320 | goto ignore; |
318 | goto ignore; |
321 | } |
319 | } |
322 | goto satisfiable if $l >= 0 && $l < $length && $h >= 0 && $h > $l; |
320 | goto satisfiable if $l >= 0 && $l < $length && $h >= 0 && $h >= $l; |
323 | } |
321 | } |
324 | $hdr->{"Content-Range"} = "bytes */$length"; |
322 | $hdr->{"Content-Range"} = "bytes */$length"; |
325 | $self->err(416, "not satisfiable", $hdr); |
323 | $self->err(416, "not satisfiable", $hdr); |
326 | |
324 | |
327 | satisfiable: |
325 | satisfiable: |
… | |
… | |
344 | |
342 | |
345 | $self->print_response(@code, $hdr, ""); |
343 | $self->print_response(@code, $hdr, ""); |
346 | |
344 | |
347 | if ($self->{method} eq "GET") { |
345 | if ($self->{method} eq "GET") { |
348 | my ($fh, $buf); |
346 | my ($fh, $buf); |
349 | cpen $fh, "<", $self->{path} |
347 | open $fh, "<", $self->{path} |
350 | or die "$self->{path}: late open failure ($!)"; |
348 | or die "$self->{path}: late open failure ($!)"; |
351 | |
349 | |
352 | if ($l) { |
350 | if ($l) { |
353 | sysseek $fh, $l, 0 |
351 | sysseek $fh, $l, 0 |
354 | or die "$self->{path}: cannot seek to $l ($!)"; |
352 | or die "$self->{path}: cannot seek to $l ($!)"; |
… | |
… | |
363 | } |
361 | } |
364 | } |
362 | } |
365 | |
363 | |
366 | close $fh; |
364 | close $fh; |
367 | } |
365 | } |
|
|
366 | |