typester (owner)

Revisions

  • 16d3cb Daisuke... Sun Sep 13 19:48:45 -0700 2009
  • 20a4d3 Daisuke... Sun Sep 13 18:57:44 -0700 2009
  • 441f23 typester Sun Sep 13 18:57:34 -0700 2009
  • 8f8b74 Daisuke... Sun Sep 13 18:57:24 -0700 2009
  • c2bc0b Daisuke... Sun Sep 13 18:01:49 -0700 2009
gist: 186434 Download_button fork
public
Public Clone URL: git://gist.github.com/186434.git
Embed All Files: show embed
ae_server.pl #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use strict;
use warnings;
 
use Getopt::Long;
use AnyEvent::Socket;
use AnyEvent::Handle;
 
use HTTP::Parser::XS qw(parse_http_request);
 
GetOptions(
    \my %option,
    qw/port=i/
);
$option{port} ||= 12345;
 
my $max_req_size = 131072;
 
sub handle_request {
    my ($handle, $env) = @_;
    if ($env->{REQUEST_METHOD} ne 'GET') {
        # todo return 403
        return;
    }
    my $content = "hello world!\n";
    my $keep_alive = ($env->{HTTP_CONNECTION} || '') =~ /keep-alive/i;
    my $res = join(
        "\r\n",
        'HTTP/1.0 200 OK',
        'Content-Type: text/plain',
        'Content-Length: ' . length($content),
        ($keep_alive ? 'Connection: keep-alive' : ()),
        '',
        $content,
    );
    $handle->push_write($res);
    $keep_alive;
}
 
tcp_server undef, $option{port}, sub {
    my ($fh) = @_ or die $!;
 
    my $handle; $handle = AnyEvent::Handle->new(
        fh => $fh,
        on_error => sub {
            undef $handle;
        },
    );
 
    $handle->on_read(sub {
        my ($h) = @_;
        my $reqlen = parse_http_request($h->{rbuf}, \my %env);
        if ($reqlen >= 0) {
            $h->{rbuf} = substr $h->{rbuf}, $reqlen;
            if (! handle_request($h, \%env)) {
                $h->destroy;
            }
        }
        elsif ($reqlen == -2) {
        }
        elsif ($reqlen == -1) {
            $h->destroy;
        }
    });
};
 
AnyEvent->condvar->recv;
 
danga_server.pl #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use strict;
use warnings;
 
use Getopt::Long;
 
use HTTP::Parser::XS qw(parse_http_request);
 
use Danga::Socket;
use Danga::Socket::Callback;
use IO::Handle;
use IO::Socket::INET;
use Socket qw/IPPROTO_TCP TCP_NODELAY/;
 
GetOptions(
    \my %option,
    qw/port=i/
);
$option{port} ||= 12345;
 
my $max_req_size = 131072;
 
sub handle_request {
    my ($socket, $env) = @_;
    if ($env->{REQUEST_METHOD} ne 'GET') {
        # todo return 403
        return;
    }
    my $content = "hello world!\n";
    my $keep_alive = ($env->{HTTP_CONNECTION} || '') =~ /keep-alive/i;
    my $res = join(
        "\r\n",
        'HTTP/1.0 200 OK',
        'Content-Type: text/plain',
        'Content-Length: ' . length($content),
        ($keep_alive ? 'Connection: keep-alive' : ()),
        '',
        $content,
    );
    $socket->write(\$res);
    $keep_alive;
}
 
my $ss = IO::Socket::INET->new(
    LocalPort => $option{port},
    Proto => 'tcp',
    Listen => SOMAXCONN,
    ReuseAddr => 1,
    Blocking => 0,
) or die $!;
IO::Handle::blocking($ss, 0);
 
Danga::Socket->AddOtherFds(
    fileno($ss) => sub {
        my $cs = $ss->accept or return;
 
        IO::Handle::blocking($cs, 0);
        setsockopt($cs, IPPROTO_TCP, TCP_NODELAY, pack('l', 1)) or die $!;
 
        my $rbuf = '';
        Danga::Socket::Callback->new(
            handle => $cs,
            on_read_ready => sub {
                my $socket = shift;
 
                my $bref = $socket->read($max_req_size);
 
                unless (defined $bref) {
                    $socket->close;
                    return;
                }
                $rbuf .= $$bref;
 
                my $reqlen = parse_http_request($rbuf, \my %env);
                if ($reqlen >= 0) {
                    $rbuf = substr $rbuf, $reqlen;
                    if (! handle_request($socket, \%env)) {
                        $socket->close;
                    }
                }
                elsif ($reqlen == -2) {
                    # request is incomplete
                }
                elsif ($reqlen == -1) {
                    # error, close conn (TODO send 400)
                    $socket->close;
                }
            },
        );
    },
);
 
Danga::Socket->AddTimer(0, sub {
    my $poll
        = $Danga::Socket::HaveKQueue ? 'kqueue'
        : $Danga::Socket::HaveEpoll ? 'epoll'
        : 'poll';
 
    print "Server started ($poll), http://localhost:$option{port}\n";
});
 
Danga::Socket->EventLoop;