1#!/usr/bin/perl -w
2
3use blib;
4use IO::KQueue;
5use IO::Socket;
6
7my $server = IO::Socket::INET->new(
8    LocalAddr => "127.0.0.1:3069",
9    Listen => 10,
10    Blocking => 0,
11    Reuse => 1,
12    );
13
14IO::Handle::blocking($server, 0);
15
16my $kq = IO::KQueue->new();
17
18$kq->EV_SET(fileno($server), EVFILT_READ, EV_ADD, 0, 5);
19
20my %users;
21while (1) {
22    my @ret = $kq->kevent();
23    if (!@ret) {
24        die "No kevents: $!";
25    }
26
27    foreach my $kevent (@ret) {
28        my $fd = $kevent->[KQ_IDENT];
29
30        if ($fd == fileno($server)) {
31            my $client = $server->accept();
32            IO::Handle::blocking($client, 0);
33            if (!$client) {
34                warn("accept() failed: $!");
35                next;
36            }
37
38            $kq->EV_SET(fileno($client), EVFILT_READ, EV_ADD);
39
40            $users{fileno($client)} = $client;
41        }
42        else {
43            my $client = $users{$fd} || die "Unknown fd: $fd";
44            my $buf;
45            my $blen = $client->read($buf, 8096);
46
47            if (!$blen) {
48                # eof
49                delete $users{$fd};
50                $client->close;
51            }
52            elsif ($blen == -1) {
53                # error
54                die "read error on $fd: $!";
55            }
56            else {
57                foreach my $f (keys %users) {
58                    next if $f == $fd;
59                    $users{$f}->print($buf);
60                }
61            }
62        }
63    }
64}