ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/deliantra/server/ext/tcp.ext
Revision: 1.30
Committed: Fri Sep 19 12:06:30 2025 UTC (12 months, 1 week ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.29: +9 -5 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.17 #! perl # mandatory
2 root 1.1
3     # this listens for new tcp connections and hands them over to the server core
4    
5     use Socket;
6 root 1.12 use AnyEvent::Socket;
7 root 1.1
8 root 1.20 CONF BIND_ADDRESSES = [[undef, 13327]];
9 root 1.29 CONF DETECT_TIMEOUT = 300; # when to time-out connections
10 root 1.30 CONF LOG_CONNECTS = 1; # whether to even log connects
11 root 1.20
12 root 1.25 our $MAX_DETECT; # how many bytes to read to identify the protocol
13 root 1.21
14 root 1.15 our @LISTENERS;
15 root 1.25 our @DETECTORS;
16     our %DETECTORS;
17 root 1.12
18 root 1.25 sub _update_detectors {
19     $MAX_DETECT = List::Util::max map $_->[1], values %DETECTORS;
20 root 1.23 }
21    
22 root 1.25 sub register($$$$) {
23     my ($name, $max_detect, $detect, $serve) = @_;
24    
25 root 1.27 $DETECTORS{$name} = [$max_detect, $detect, $serve, $name];
26 root 1.25 _update_detectors;
27    
28     Guard::guard {
29     delete $DETECTORS{$name};
30 root 1.28 _update_detectors if defined &_update_detectors;
31 root 1.25 }
32     }
33    
34     our $deliantra_detector = ext::tcp::register deliantra => 10, sub {
35     /^..version /s
36     }, sub {
37     my $ns = cf::client::create fileno $_[1], $_[0];
38 root 1.26 $ns->run;
39 root 1.25 $ns->inbuf_append ($_[2]);
40     };
41    
42 root 1.20 for (@$BIND_ADDRESSES) {
43 root 1.12 my ($host, $port) = @$_;
44 root 1.16 cf::info "listening on ", (format_hostport $host, $port), "\n";
45 root 1.12
46 root 1.15 push @LISTENERS, tcp_server $host, $port, sub {
47 root 1.12 my ($fh, $host, $port) = @_
48     or return;
49    
50 root 1.18 my $lhost = AnyEvent::Socket::format_address
51     +(AnyEvent::Socket::unpack_sockaddr getsockname $fh)[1];
52    
53 root 1.21 my $id = format_hostport $host, $port;
54    
55 root 1.25 cf::info "$id: accepted connection.\n"
56 root 1.30 if $lhost ne $host and $LOG_CONNECTS; # do not log connections from the host, e.g. for watchdogs
57 root 1.12
58 root 1.29 my ($buf, $t, $r);
59    
60     $r = AE::io $fh, 0, sub {
61 root 1.21 my $len = sysread $fh, $buf, 512, length $buf;
62    
63     if ($len) {
64 root 1.25 for ($buf) {
65 root 1.27 for my $v (values %DETECTORS) {
66 root 1.25 if (my $cb = $v->[1]()) {
67 root 1.29 undef $r; undef $t;
68 root 1.30 cf::info "$id: detected protocol $v->[3].\n";
69 root 1.25 $v->[2]($id, $fh, $buf);
70     return;
71     }
72     }
73    
74     if (length >= $MAX_DETECT) { # unable to detect protocol
75 root 1.29 undef $r; undef $t;
76 root 1.30 cf::debug "$id: data received, but cannot detect protocol, closing.\n"
77     if $LOG_CONNECTS;
78 root 1.25 }
79 root 1.21 }
80     } else {
81 root 1.29 undef $r; undef $t;
82 root 1.30 cf::info "$id: read error during protocol detection ($!)\n"
83     if $LOG_CONNECTS;
84 root 1.21 }
85     };
86 root 1.29 $t = EV::timer $DETECT_TIMEOUT, 0, sub {
87 root 1.30 cf::info "$id: protocol detection tiomeout.\n"
88     if $LOG_CONNECTS;
89 root 1.29 shutdown $fh, 0;
90     };
91 root 1.12 };
92 root 1.1 }
93