/
coro-chat
executable file
·69 lines (56 loc) · 1.61 KB
/
coro-chat
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
#!/usr/bin/perl
use AnyEvent;
use AnyEvent::Socket;
use Coro;
use Coro::AnyEvent;
use Coro::Handle;
use Guard;
my %clients;
my $client_counter = 0;
# OK, cheat and use AnyEvent for the main server
my $shutdown = AnyEvent->condvar;
my $server = tcp_server undef, 4554, unblock_sub(\&client);
$shutdown->recv;
sub client {
my ($fh, $host, $port) = @_;
my $client_id = ++$client_counter;
my $h = unblock $fh;
my $cleanup = guard {
delete $clients{$client_id};
$h->close(); # XXX cede
print "$client_id done.\n";
};
# prompt for name
$h->print("Name? "); # XXX cede
my $name = $h->readline(); # XXX cede
return unless $name;
chomp $name;
# client is now available to receive messages
$clients{$client_id} = $h;
$h->print("Hi $name, Enter text to chat.\n".
"A '.' by itself will disconnect you\n");
while (1) {
my $chat_msg = $h->readline(); # XXX cede
return unless defined $chat_msg;
chomp $chat_msg;
next unless length $chat_msg;
# disconnect
return if ($chat_msg eq '.');
# disconnect *everybody*
if ($chat_msg =~ /get back to work/) {
$shutdown->send;
return;
}
# broadcast the message
my $msg = $name.": ".$chat_msg."\n";
async {
# Capture list of client ids since list may change between print()
# calls.
my @cids = keys %clients;
for my $cid (@cids) {
my $c = $clients{$cid};
$c->print($msg) if $c; # XXX cede
}
};
}
}