package Protocol::WebSocket::Handshake::Server; use strict; use warnings; use base 'Protocol::WebSocket::Handshake'; use Protocol::WebSocket::Request; use Protocol::WebSocket::Frame; sub new_from_psgi { my $class = shift; my $req = Protocol::WebSocket::Request->new_from_psgi(@_); my $self = $class->new(req => $req); return $self; } sub parse { my $self = shift; my $req = $self->req; my $res = $self->res; return 1 if $req->is_done; unless ($req->parse($_[0])) { $self->error($req->error); return; } if ($req->is_body || $req->is_done) { $res->version($req->version); $res->host($req->host); $res->secure($req->secure); $res->resource_name($req->resource_name); $res->origin($req->origin); } if ($req->version eq 'draft-ietf-hybi-00') { if ($self->is_done) { $res->checksum(undef); $res->number1($req->number1); $res->number2($req->number2); $res->challenge($req->challenge); } else { $res->checksum(''); } } elsif ($self->is_done && $req->version eq 'draft-ietf-hybi-10' || $req->version eq 'draft-ietf-hybi-17') { $res->key($req->key); } return 1; } sub is_body { shift->req->is_body } sub is_done { shift->req->is_done } sub to_string { my $self = shift; if ($self->is_body) { return $self->{partial} = $self->res->to_string; } elsif ($self->{partial}) { my $to_string = $self->res->to_string; $to_string =~ s/^\Q$self->{partial}\E//; return $to_string; } return $self->res->to_string; } sub build_frame { my $self = shift; return Protocol::WebSocket::Frame->new(version => $self->version, @_); } 1; __END__ =head1 NAME Protocol::WebSocket::Handshake::Server - WebSocket Server Handshake =head1 SYNOPSIS my $h = Protocol::WebSocket::Handshake::Server->new; # Parse client request $h->parse(<<"EOF"); WebSocket HTTP message EOF $h->error; # Check if there were any errors $h->is_done; # Returns 1 # Create response $h->to_string; =head1 DESCRIPTION Construct or parse a server WebSocket handshake. This module is written for convenience, since using request and response directly requires the same code again and again. =head1 METHODS =head2 C Create a new L instance. =head2 C my $env = { HTTP_HOST => 'example.com', HTTP_CONNECTION => 'Upgrade', ... }; my $handshake = Protocol::WebSocket::Handshake::Server->new_from_psgi($env); Create a new L instance from L environment. =head2 C $handshake->parse($buffer); $handshake->parse($handle); Parse a WebSocket client request. Returns C and sets C attribute on error. When buffer is passed it's modified (unless readonly). =head2 C $handshake->build_frame; Builds L with an appropriate version. =head2 C Construct a WebSocket server response. =head2 C Check whether handshake is in body state. =head2 C Check whether handshake is done. =cut