sub sockethandler($self, $ua) { ... { local $INPUT_RECORD_SEPARATOR = undef; my $socketclosed = 0; $ua->{realsocket}->blocking(0); binmode($ua->{realsocket}, ':bytes'); my $starttime = time + 10; while(!$socketclosed) { my $workCount = 0; # Read data from websocket my $buf; eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) local $SIG{ALRM} = sub{croak "alarm"}; alarm 0.5; my $status = sysread($ua->{realsocket}, $buf, $settings{chunk_size} * 2); if(!$ua->{realsocket}) { #if(0 && defined($status) && $status == 0) { if($self->{isDebugging}) { print STDERR "Websocket closed\n"; } $socketclosed = 1; last; } alarm 0; }; if(defined($buf) && length($buf)) { $frame->append($buf); $workCount++; } while (my $message = $frame->next_bytes) { $workCount++; my $realmsg; my $parseok = 0; eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) $realmsg = decode_json($message); $parseok = 1; }; if(!$parseok || !defined($realmsg) || !defined($realmsg->{type})) { # Broken message next; } if($frame->opcode == 8) { print STDERR "Connection closed by Browser\n"; $socketclosed = 1; last; } if($realmsg->{type} eq 'PING') { $timeout = time + $settings{client_disconnect_timeout}; my %msg = ( type => 'PING', ); if(!$self->wsprint(\%msg)) { print STDERR "Write to socket failed, closing connection!\n"; $socketclosed = 1; last; } next; } else { if(!$self->wshandlemessage($realmsg)) { $socketclosed = 1; last; } } } # This is OUTSIDE the $frame->next_bytes loop, because a close event never returns a full frame # from WSockFrame if($frame->is_close) { print STDERR "CLOSE FRAME RECIEVED!\n"; $socketclosed = 1; if(!webPrint($ua->{realsocket}, $frame->new(buffer => 'data', type => 'close')->to_bytes)) { print STDERR "Write to socket failed, failed to properly close connection!\n"; } } ... if(!$workCount) { sleep($self->{sleeptime}); } if($timeout < time) { print STDERR "CLIENT TIMEOUT\n"; $socketclosed = 1; } } } ... return 1; }