File Coverage

blib/lib/Mojo/IRC/Server/Chinese.pm
Criterion Covered Total %
statement 39 432 9.0
branch 0 150 0.0
condition 0 22 0.0
subroutine 13 65 20.0
pod 1 21 4.7
total 53 690 7.6


line stmt bran cond sub pod time code
1             package Mojo::IRC::Server::Chinese;
2 1     1   13689 use strict;
  1         2  
  1         33  
3             $Mojo::IRC::Server::Chinese::VERSION = "1.8.0";
4 1     1   489 use Encode;
  1         7252  
  1         57  
5 1     1   420 use Encode::Locale;
  1         2237  
  1         35  
6 1     1   9 use Carp;
  1         1  
  1         38  
7 1     1   484 use Parse::IRC;
  1         1785  
  1         46  
8 1     1   453 use Mojo::IOLoop;
  1         133000  
  1         5  
9 1     1   36 use POSIX ();
  1         1  
  1         16  
10 1     1   3 use List::Util qw(first);
  1         1  
  1         42  
11 1     1   3 use Fcntl ':flock';
  1         1  
  1         75  
12 1     1   425 use Mojo::IRC::Server::Chinese::Base 'Mojo::EventEmitter';
  1         1  
  1         5  
13 1     1   408 use Mojo::IRC::Server::Chinese::User;
  1         2  
  1         8  
14 1     1   427 use Mojo::IRC::Server::Chinese::Channel;
  1         2  
  1         11  
15              
16             has host => "0.0.0.0";
17             has port => 6667;
18             has listen => undef;
19             has network => "Chinese IRC NetWork";
20             has ioloop => sub { Mojo::IOLoop->singleton };
21             has parser => sub { Parse::IRC->new };
22             has servername => "chinese-irc-server";
23             has clienthost => undef,
24             has create_time => sub{POSIX::strftime( '%Y/%m/%d %H:%M:%S', localtime() )};
25             has log_level => "info";
26             has log_path => undef;
27             has auth=>undef;
28              
29             has version => sub{$Mojo::IRC::Server::Chinese::VERSION};
30             has start_time => sub{time};
31              
32             has user => sub {[]};
33             has channel => sub {[]};
34              
35             has log => sub{
36             require Mojo::Log;
37 1     1   192 no warnings 'redefine';
  1         1  
  1         4367  
38             *Mojo::Log::append = sub{
39             my ($self, $msg) = @_;
40             return unless my $handle = $self->handle;
41             flock $handle, LOCK_EX;
42             $handle->print(encode("console_out", decode("utf8",$msg))) or $_[0]->die("Can't write to log: $!");
43             flock $handle, LOCK_UN;
44             };
45             Mojo::Log->new(path=>$_[0]->log_path,level=>$_[0]->log_level,format=>sub{
46             my ($time, $level, @lines) = @_;
47             my $title="";
48             if(ref $lines[0] eq "HASH"){
49             my $opt = shift @lines;
50             $time = $opt->{"time"} if defined $opt->{"time"};
51             $title = (defined $opt->{"title"})?$opt->{title} . " ":"";
52             $level = $opt->{level} if defined $opt->{"level"};
53             }
54             @lines = split /\n/,join "",@lines;
55             my $return = "";
56             $time = POSIX::strftime('[%y/%m/%d %H:%M:%S]',localtime($time));
57             for(@lines){
58             $return .=
59             $time
60             . " "
61             . "[$level]"
62             . " "
63             . $title
64             . $_
65             . "\n";
66             }
67             return $return;
68             });
69             };
70              
71             sub new_user{
72 0     0 0   my $s = shift;
73 0           my $user = $s->add_user(Mojo::IRC::Server::Chinese::User->new(@_,_server=>$s));
74 0 0         return $user if $user->is_virtual;
75             $user->io->on(read=>sub{
76 0     0     my($stream,$bytes) = @_;
77 0           $bytes = $user->buffer . $bytes;
78 0           my $pos = rindex($bytes,"\r\n");
79 0 0         if($pos != -1){#\r\n
80 0           my $lines = substr($bytes,0,$pos);
81 0           my $remains = substr($bytes,$pos+2);
82 0           $user->buffer($remains);
83 0           $stream->emit(line=>$_) for split /\r?\n/,$lines;
84             }
85             else{
86 0           $pos = rindex($bytes,"\n");
87 0 0         if($pos != -1){
88 0           my $lines = substr($bytes,0,$pos);
89 0           my $remains = substr($bytes,$pos+1);
90 0           $user->buffer($remains);
91 0           $stream->emit(line=>$_) for split /\r?\n/,$lines;
92             }
93             else{
94 0           $user->buffer($bytes);
95             }
96             }
97 0           });
98             $user->io->on(line=>sub{
99 0     0     my($stream,$line) = @_;
100 0           my $msg = $s->parser->parse($line);
101 0           $user->last_active_time(time());
102 0           $s->emit(user_msg=>$user,$msg);
103 0 0         if($msg->{command} eq "CAP"){$user->emit(cap=>$msg)}
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
104 0           elsif($msg->{command} eq "PASS"){$user->emit(pass=>$msg)}
105 0           elsif($msg->{command} eq "NICK"){$user->emit(nick=>$msg);$s->emit(nick=>$user,$msg);}
  0            
106 0           elsif($msg->{command} eq "USER"){$user->emit(user=>$msg);$s->emit(user=>$user,$msg);}
  0            
107 0           elsif($msg->{command} eq "JOIN"){$user->emit(join=>$msg);$s->emit(join=>$user,$msg);}
  0            
108 0           elsif($msg->{command} eq "PART"){$user->emit(part=>$msg);$s->emit(part=>$user,$msg);}
  0            
109 0           elsif($msg->{command} eq "PING"){$user->emit(ping=>$msg);$s->emit(ping=>$user,$msg);}
  0            
110 0           elsif($msg->{command} eq "PONG"){$user->emit(pong=>$msg);$s->emit(pong=>$user,$msg);}
  0            
111 0           elsif($msg->{command} eq "MODE"){$user->emit(mode=>$msg);$s->emit(mode=>$user,$msg);}
  0            
112 0           elsif($msg->{command} eq "PRIVMSG"){$user->emit(privmsg=>$msg);$s->emit(privmsg=>$user,$msg);}
  0            
113 0           elsif($msg->{command} eq "QUIT"){$user->is_quit(1);$user->emit(quit=>$msg);$s->emit(quit=>$user,$msg);}
  0            
  0            
114 0           elsif($msg->{command} eq "WHO"){$user->emit(who=>$msg);$s->emit(who=>$user,$msg);}
  0            
115 0           elsif($msg->{command} eq "WHOIS"){$user->emit(whois=>$msg);$s->emit(whois=>$user,$msg);}
  0            
116 0           elsif($msg->{command} eq "LIST"){$user->emit(list=>$msg);$s->emit(list=>$user,$msg);}
  0            
117 0           elsif($msg->{command} eq "TOPIC"){$user->emit(topic=>$msg);$s->emit(topic=>$user,$msg);}
  0            
118 0           elsif($msg->{command} eq "AWAY"){$user->emit(away=>$msg);$s->emit(away=>$user,$msg);}
  0            
119 0           else{$user->send($user->serverident,"421",$user->nick,$msg->{command},"Unknown command");}
120 0           });
121              
122             $user->io->on(error=>sub{
123 0     0     my ($stream, $err) = @_;
124 0           $user->emit("close",$err);
125 0           $s->emit(close_user=>$user,$err);
126 0           $s->debug("C[" .$user->name."] 连接错误: $err");
127 0           });
128             $user->io->on(close=>sub{
129 0     0     my ($stream, $err) = @_;
130 0           $user->emit("close",$err);
131 0           $s->emit(close_user=>$user,$err);
132 0           });
133             $user->on(close=>sub{
134 0     0     my ($user,$err) = @_;
135 0 0         return if $user->is_quit;
136 0 0         my $quit_reason = defined $user->close_reason? $user->close_reason:
    0          
137             defined $err ? $err :
138             "remote host closed connection";
139 0           $user->forward($user->ident,"QUIT",$quit_reason);
140 0           $user->is_quit(1);
141 0           $user->info("[" . $user->name . "] 已退出($quit_reason)");
142 0           $user->{_server}->remove_user($user);
143 0           });
144 0     0     $user->on(pass=>sub{my($user,$msg) = @_;my $pass = $msg->{params}[0]; $user->pass($pass);});
  0            
  0            
  0            
145 0     0     $user->on(nick=>sub{my($user,$msg) = @_;my $nick = $msg->{params}[0];$user->set_nick($nick)});
  0            
  0            
  0            
146 0     0     $user->on(user=>sub{my($user,$msg) = @_;
147 0 0         if(defined $user->search_user(user=>$msg->{params}[0])){
148 0           $user->send($user->serverident,"446",$user->nick,"该帐号已被使用");
149 0           $user->io->close_gracefully();
150 0           $user->{_server}->remove_user($user);
151 0           return;
152             }
153 0           $user->user($msg->{params}[0]);
154             #$user->mode($msg->{params}[1]);
155 0           $user->realname($msg->{params}[3]);
156 0 0 0       if(!$user->is_registered and $user->nick ne "*" and $user->user ne "*"){
      0        
157 0           $user->is_registered(1);
158             }
159 0           });
160 0     0     $user->on(join=>sub{my($user,$msg) = @_;
161 0           my $channels = $msg->{params}[0];
162 0           for my $channel_name (split /,/,$channels){
163 0           my $channel = $user->search_channel(name=>$channel_name);
164 0 0         if(defined $channel){
165 0           $user->join_channel($channel);
166             }
167             else{
168 0           $channel = $user->new_channel(name=>$channel_name,id=>lc($channel_name));
169 0           $user->join_channel($channel);
170             }
171             }
172 0           });
173 0     0     $user->on(part=>sub{my($user,$msg) = @_;
174 0           my $channel_name = $msg->{params}[0];
175 0           my $part_info = $msg->{params}[1];
176 0           my $channel = $user->search_channel(name=>$channel_name);
177 0 0         return if not defined $channel;
178 0           $user->part_channel($channel,$part_info);
179 0           });
180 0     0     $user->on(ping=>sub{my($user,$msg) = @_;
181 0           my $servername = $msg->{params}[0];
182 0           $user->send($user->serverident,"PONG",$user->servername,$servername);
183 0           });
184             $user->on(pong=>sub{
185 0     0     my($user,$msg) = @_;
186 0           my $current_ping_count = $user->ping_count;
187 0           $user->ping_count(--$current_ping_count);
188 0           });
189 0     0     $user->on(quit=>sub{my($user,$msg) = @_;
190 0           my $quit_reason = $msg->{params}[0];
191 0           $user->quit($quit_reason);
192 0           });
193 0     0     $user->on(privmsg=>sub{my($user,$msg) = @_;
194 0           $user->last_speak_time(time());
195 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
196 0           my $channel_name = $msg->{params}[0];
197 0           my $content = $msg->{params}[1];
198 0           my $channel = $user->search_channel(name=>$channel_name);
199 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
200 0           $channel->forward($user,$user->ident,"PRIVMSG",$channel_name,$content);
201 0           $s->info({level=>"IRC频道消息",title=>$user->nick ."|" .$channel->name.":"},$content);
202             }
203             else{
204 0           my $nick = $msg->{params}[0];
205 0           my $content = $msg->{params}[1];
206 0           my $u = $user->search_user(nick=>$nick);
207 0 0         if(defined $u){
208 0           $u->send($user->ident,"PRIVMSG",$nick,$content);
209 0 0         $user->send($user->serverident,"301",$user->nick,$u->nick,$u->away_info) if $u->is_away;
210 0           $s->info({level=>"IRC私信消息",title=>"[".$user->nick."]->[$nick] :"},$content);
211             }
212             else{
213 0           $user->send($user->serverident,"401",$user->nick,$nick,"No such nick");
214             }
215             }
216 0           });
217 0     0     $user->on(mode=>sub{my($user,$msg) = @_;
218 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
219 0           my $channel_name = $msg->{params}[0];
220 0           my $channel_mode = $msg->{params}[1];
221 0           my $channel = $user->search_channel(name=>$channel_name);
222 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
223 0 0 0       if(defined $channel_mode and $channel_mode eq "b"){
    0 0        
224 0           $user->send($user->serverident,"368",$user->nick,$channel_name,"End of channel ban list");
225             }
226             elsif(defined $channel_mode and $channel_mode ne "b") {
227 0           $channel->set_mode($user,$channel_mode);
228             }
229             else{
230 0           $user->send($user->serverident,"324",$user->nick,$channel_name,'+'.$channel->mode);
231 0           $user->send($user->serverident,"329",$user->nick,$channel_name,$channel->ctime);
232             }
233             }
234             else{
235 0           my $nick = $msg->{params}[0];
236 0           my $mode = $msg->{params}[1];
237 0 0         if(defined $mode){$user->set_mode($mode)}
  0            
238 0           else{$user->send($user->serverident,"221",$user->nick,'+'.$user->mode)}
239             }
240 0           });
241 0     0     $user->on(who=>sub{my($user,$msg) = @_;
242 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
243 0           my $channel_name = $msg->{params}[0];
244 0           my $channel = $user->search_channel(name=>$channel_name);
245 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
246 0           for($channel->users){
247 0           $user->send($user->serverident,"352",$user->nick,$channel_name,$_->user,$_->host,$_->servername,$_->nick,"H","0 " . $_->realname);
248             }
249 0           $user->send($user->serverident,"315",$user->nick,$channel_name,"End of WHO list");
250             }
251             else{
252 0           my $nick = $msg->{params}[0];
253 0           my $u = $user->search_user(nick=>$nick);
254 0 0         if(defined $u){
255 0           my $channel_name = "*";
256 0 0         if($u->is_join_channel()){
257 0           my $last_channel = (grep {$_->mode !~ /s/} $u->channels)[-1];
  0            
258 0 0         $channel_name = $last_channel->name if defined $last_channel;
259             }
260 0           $user->send($user->serverident,"352",$user->nick,$channel_name,$u->user,$u->host,$u->servername,$u->nick,"H","0 " . $u->realname);
261 0           $user->send($user->serverident,"315",$user->nick,$nick,"End of WHO list");
262             }
263             else{
264 0           $user->send($user->serverident,"401",$user->nick,$nick,"No such nick");
265             }
266            
267             }
268 0           });
269 0     0     $user->on(whois=>sub{my($user,$msg) = @_;});
  0            
270 0     0     $user->on(list=>sub{my($user,$msg) = @_;
271 0           for my $channel ($user->{_server}->channels){
272 0 0         next if $channel->mode =~ /s/;
273 0           $user->send($user->serverident,"322",$user->nick,$channel->name,$channel->count(),$channel->topic);
274             }
275 0           $user->send($user->serverident,"323",$user->nick,"End of LIST");
276 0           });
277 0     0     $user->on(topic=>sub{my($user,$msg) = @_;
278 0           my $channel_name = $msg->{params}[0];
279 0           my $channel = $user->search_channel(name=>$channel_name);
280 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
281 0 0         if(defined $msg->{params}[1]){
282 0           my $topic = $msg->{params}[1];
283 0           $channel->set_topic($user,$topic);
284             }
285             else{
286 0           $user->send($user->serverident,"332",$user->nick,$channel_name,$channel->topic);
287             }
288 0           });
289 0     0     $user->on(away=>sub{my($user,$msg) = @_;
290 0 0         if($msg->{params}[0]){
291 0           my $away_info = $msg->{params}[0];
292 0           $user->away($away_info);
293             }
294             else{
295 0           $user->back();
296             }
297 0           });
298              
299 0           $user;
300             }
301             sub new_channel{
302 0     0 0   my $s = shift;
303 0           my $channel = $s->add_channel(Mojo::IRC::Server::Chinese::Channel->new(@_,_server=>$s));
304 0           $s->emit(new_channel=>$channel);
305             }
306             sub add_channel{
307 0     0 0   my $s = shift;
308 0           my $channel = shift;
309 0           my $is_cover = shift;
310 0           my $channel_name = $channel->name;
311 0 0         $channel_name = "#" . $channel_name if substr($channel_name,0,1) ne "#";
312 0           $channel_name=~s/\s|,|&//g;
313 0           $channel->name($channel_name);
314 0           my $c = $s->search_channel(name=>$channel->name);
315 0 0         return $c if defined $c;
316 0           $c = $s->search_channel(id=>$channel->id);
317 0 0         if(defined $c){if($is_cover){$s->info("频道 " . $c->name. " 已更新");$c=$channel;};return $c;}
  0 0          
  0            
  0            
  0            
318 0           else{push @{$s->channel},$channel;$s->info("频道 ".$channel->name. " 已创建");return $channel;}
  0            
  0            
  0            
319              
320             }
321             sub add_user{
322 0     0 0   my $s = shift;
323 0           my $user = shift;
324 0           my $is_cover = shift;
325 0 0         if($user->is_virtual){
326 0           my $nick = $user->nick;
327 0 0         $nick =~s/\s|\@|!//g;$nick = '未知昵称' if not $nick;
  0            
328 0           $user->nick($nick);
329 0           my $u = $s->search_user(nick=>$user->nick,virtual=>1,id=>$user->id);
330 0 0         return $u if defined $u;
331 0           while(1){
332 0           my $u = $s->search_user(nick=>$user->nick);
333 0 0         if(defined $u){
334 0 0         if($u->nick =~/\((\d+)\)$/){
335 0           my $num = $1;$num++;$user->nick($nick . "($num)");
  0            
  0            
336             }
337 0           else{$user->nick($nick . "(1)")}
338             }
339 0           else{last};
340             }
341             }
342 0           my $u = $s->search_user(id=>$user->id);
343 0 0         if(defined $u){if($is_cover){$s->info("C[".$u->name. "]已更新");$u=$user;};return $u;}
  0 0          
  0            
  0            
  0            
344             else{
345 0           push @{$s->user},$user;$s->info("C[".$user->name. "]已加入");return $user;
  0            
  0            
  0            
346             }
347             }
348             sub remove_user{
349 0     0 0   my $s = shift;
350 0           my $user = shift;
351 0           for(my $i=0;$i<@{$s->user};$i++){
  0            
352 0 0         if($user->id eq $s->user->[$i]->id){
353 0           $_->remove_user($s->user->[$i]->id) for $s->user->[$i]->channels;
354 0           $user->channel([]);
355 0           splice @{$s->user},$i,1;
  0            
356 0 0         if($user->is_virtual){
357 0           $s->info("c[".$user->name."] 已被移除");
358             }
359             else{
360 0           $s->info("C[".$user->name."] 已离开");
361             }
362 0           last;
363             }
364             }
365             }
366              
367             sub remove_channel{
368 0     0 0   my $s = shift;
369 0           my $channel = shift;
370 0           for(my $i=0;$i<@{$s->channel};$i++){
  0            
371 0 0         if($channel->id eq $s->channel->[$i]->id){
372 0           splice @{$s->channel},$i,1;
  0            
373 0           $s->info("频道 ".$channel->name." 已删除");
374 0           last;
375             }
376             }
377             }
378             sub users {
379 0     0 0   my $s = shift;
380 0           return @{$s->user};
  0            
381             }
382             sub channels{
383 0     0 0   my $s = shift;
384 0           return @{$s->channel};
  0            
385             }
386              
387             sub search_user{
388 0     0 0   my $s = shift;
389 0           my %p = @_;
390 0 0         return if 0 == grep {defined $p{$_}} keys %p;
  0            
391 0 0         if(wantarray){
392 0 0   0     return grep {my $c = $_;(first {$p{$_} ne $c->$_} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->user};
  0            
  0            
  0            
  0            
  0            
393             }
394             else{
395 0 0   0     return first {my $c = $_;(first {$p{$_} ne $c->$_} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->user};
  0            
  0            
  0            
  0            
  0            
396             }
397              
398             }
399             sub search_channel{
400 0     0 0   my $s = shift;
401 0           my %p = @_;
402 0 0         return if 0 == grep {defined $p{$_}} keys %p;
  0            
403 0 0         if(wantarray){
404 0 0   0     return grep {my $c = $_;(first {$_ eq "name"?(lc($p{$_}) ne lc($c->$_)):($p{$_} ne $c->$_)} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->channel};
  0 0          
  0            
  0            
  0            
  0            
405             }
406             else{
407 0 0   0     return first {my $c = $_;(first {$_ eq "name"?(lc($p{$_}) ne lc($c->$_)):($p{$_} ne $c->$_)} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->channel};
  0 0          
  0            
  0            
  0            
  0            
408             }
409              
410             }
411             sub timer{
412 0     0 0   my $s = shift;
413 0           $s->ioloop->timer(@_);
414             }
415             sub interval{
416 0     0 0   my $s = shift;
417 0           $s->ioloop->recurring(@_);
418             }
419             sub ident {
420 0     0 0   return $_[0]->servername;
421             }
422             sub ready {
423 0     0 0   my $s = shift;
424 0           my @listen = ();
425 0 0 0       if(defined $s->listen and ref $s->listen eq "ARRAY"){
426 0   0       push @listen,{host=>$_->{host} || "0.0.0.0",port=>$_->{port}||"6667"} for @{$s->listen} ;
  0   0        
427             }
428             else{
429 0           @listen = ({host=>$s->host,port=>$s->port});
430             }
431 0           for my $listen (@listen){
432             $s->ioloop->server({address=>$listen->{host},port=>$listen->{port}}=>sub{
433 0     0     my ($loop, $stream) = @_;
434 0           $stream->timeout(0);
435 0           my $id = join ":",(
436             $stream->handle->sockhost,
437             $stream->handle->sockport,
438             $stream->handle->peerhost,
439             $stream->handle->peerport
440             );
441 0           my $user = $s->new_user(
442             id => $id,
443             name => join(":",($stream->handle->peerhost,$stream->handle->peerport)),
444             io => $stream,
445             );
446 0 0         $user->host($s->clienthost) if defined $s->clienthost;
447 0           $s->emit(new_user=>$user);
448 0           });
449             }
450            
451             $s->on(new_user=>sub{
452 0     0     my ($s,$user)=@_;
453 0           $s->debug("C[".$user->name. "]已连接");
454 0           });
455              
456             $s->on(user_registered=>sub{
457 0     0     my($s,$user) = @_;
458 0 0 0       if(defined $s->auth and ref $s->auth eq "CODE"){
459 0 0         if(! $s->auth->($user->nick,$user->user,$user->pass)){
460 0           $user->send($user->serverident,"464",$user->nick,"认证失败");
461 0           $user->io->close_gracefully();
462 0           $user->{_server}->remove_user($user);
463 0           return;
464             }
465             }
466 0           $user->send($user->serverident,"001",$user->nick,"Welcome to " . $s->network . " " . $user->ident);
467 0           $user->send($user->serverident,"002",$user->nick,"Your host is " . $s->servername. ", running version " . $s->version);
468 0           $user->send($user->serverident,"003",$user->nick,"This server was created " . POSIX::strftime('%a %b %d %y at %H:%M:%S %Z',localtime($s->start_time)));
469 0           $user->send($user->serverident,"004",$user->nick,$s->servername." " .$s->version . " DOQRSZaghilopswz Pbis");
470             #$user->send($user->serverident,"001",$user->nick,"欢迎来到 Chinese IRC Network " . $user->ident);
471             #$user->send($user->serverident,"396",$user->nick,$user->host,"您的主机地址已被隐藏");
472 0           });
473             $s->on(user_msg=>sub{
474 0     0     my ($s,$user,$msg)=@_;
475 0           $s->debug("C[".$user->name."] $msg->{raw_line}");
476 0           });
477              
478             $s->on(close_user=>sub{
479 0     0     my ($s,$user,$msg)=@_;
480 0           });
481              
482             $s->interval(60,sub{
483 0 0   0     for(grep {defined $_->last_active_time and time() - $_->last_active_time > 60 } grep {!$_->is_virtual} $s->users){
  0            
  0            
484 0 0         if($_->ping_count >=3 ){
485 0           $_->close_reason("PING timeout 180 seconds");
486 0           $_->io->close_gracefully();
487             }
488             else{
489 0           $_->send(undef,"PING",$_->servername);
490 0           my $current_ping_count = $_->ping_count;
491 0           $_->ping_count(++$current_ping_count);
492             }
493             }
494 0           });
495             }
496              
497             sub run{
498 0     0 0   my $s = shift;
499 0           $s->ready();
500 0 0         $s->ioloop->start unless $s->ioloop->is_running;
501             }
502             sub die{
503 0     0 0   my $s = shift;
504 0     0     local $SIG{__DIE__} = sub{$s->log->fatal(@_);exit -1};
  0            
  0            
505 0           Carp::confess(@_);
506             }
507             sub info{
508 0     0 0   my $s = shift;
509 0           $s->log->info(@_);
510 0           $s;
511             }
512             sub warn{
513 0     0 0   my $s = shift;
514 0           $s->log->warn(@_);
515 0           $s;
516             }
517             sub error{
518 0     0 1   my $s = shift;
519 0           $s->log->error(@_);
520 0           $s;
521             }
522             sub fatal{
523 0     0 0   my $s = shift;
524 0           $s->log->fatal(@_);
525 0           $s;
526             }
527             sub debug{
528 0     0 0   my $s = shift;
529 0           $s->log->debug(@_);
530 0           $s;
531             }
532              
533              
534             1;