@@ -8,6 +8,8 @@ use Protocol::WebSocket::URL;
88use Protocol::WebSocket::Handshake::Client;
99use Protocol::WebSocket::Frame;
1010
11+ use Encode ();
12+
1113sub new {
1214 my $class = shift ;
1315 $class = ref $class if ref $class ;
@@ -103,9 +105,15 @@ sub read {
103105 while (defined (my $bytes = $frame_buffer -> next)) {
104106 if ($frame_buffer -> is_close) {
105107 # Remote WebSocket close (TCP socket may stay open for a bit)
106- $self -> disconnect if ($self -> is_ready);
107- # TODO: see message in disconnect() about error code / reason
108- $self -> {on_eof }-> ($self ) if $self -> {on_eof };
108+ # Decode the error code and message, if it exists
109+ my $code = length $bytes > 1 ? unpack (' n' , substr ($bytes , 0, 2)) : undef ;
110+ my $message = length $bytes > 3 ? Encode::decode(' UTF-8' , substr ($bytes , 2)) : undef ;
111+
112+ # Spec says to send our own close frame (and echo the errno.)
113+ $self -> disconnect($code ) if ($self -> is_ready);
114+
115+ # Call user callback
116+ $self -> {on_eof }-> ($self , $code , $message ) if $self -> {on_eof };
109117 } elsif ($frame_buffer -> is_pong) {
110118 # Server responded to our ping.
111119 $self -> {on_pong }-> ($self , $bytes ) if $self -> {on_pong };
@@ -162,11 +170,13 @@ sub connect {
162170# also sets state to -1 when called
163171sub disconnect {
164172 my $self = shift ;
173+ my ($code , $message ) = @_ ;
174+
175+ my $buffer ;
176+ if (defined $code ) { $buffer = pack ' n' , $code }
177+ if (defined $message ) { $buffer .= Encode::encode(' UTF-8' , $message ) }
165178
166- # TODO: Spec states 'close' messages may contain a uint16 error code, and a utf-8 reason.
167- # Clients are supposed to echo back the error code when receiving close from server.
168- # For now, we just send an empty message.
169- $self -> write ( $self -> _build_frame(type => ' close' , masked => 1) );
179+ $self -> write ( $self -> _build_frame(type => ' close' , masked => 1, buffer => $buffer ) );
170180
171181 $self -> {state } = -1;
172182
0 commit comments