Newer Older
664 lines | 15.864kb
copy gitweblite soruce code
root authored on 2012-11-23
1
package Mojo::Transaction::WebSocket;
2
use Mojo::Base 'Mojo::Transaction';
3

            
4
use Config;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
5
use Mojo::JSON;
copy gitweblite soruce code
root authored on 2012-11-23
6
use Mojo::Transaction::HTTP;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
7
use Mojo::Util qw(b64_encode decode encode sha1_bytes xor_encode);
copy gitweblite soruce code
root authored on 2012-11-23
8

            
9
use constant DEBUG => $ENV{MOJO_WEBSOCKET_DEBUG} || 0;
10

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
11
# Perl with support for quads
12
use constant MODERN =>
13
  ((defined $Config{use64bitint} ? $Config{use64bitint} : '') eq 'define' || $Config{longsize} >= 8);
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
14

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
15
# Unique value from RFC 6455
copy gitweblite soruce code
root authored on 2012-11-23
16
use constant GUID => '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
17

            
18
# Opcodes
19
use constant {
20
  CONTINUATION => 0,
21
  TEXT         => 1,
22
  BINARY       => 2,
23
  CLOSE        => 8,
24
  PING         => 9,
25
  PONG         => 10
26
};
27

            
28
has handshake => sub { Mojo::Transaction::HTTP->new };
29
has 'masked';
30
has max_websocket_size => sub { $ENV{MOJO_MAX_WEBSOCKET_SIZE} || 262144 };
31

            
32
sub new {
33
  my $self = shift->SUPER::new(@_);
34
  $self->on(frame => sub { shift->_message(@_) });
35
  return $self;
36
}
37

            
38
sub build_frame {
39
  my ($self, $fin, $rsv1, $rsv2, $rsv3, $op, $payload) = @_;
40
  warn "-- Building frame ($fin, $rsv1, $rsv2, $rsv3, $op)\n" if DEBUG;
41

            
42
  # Head
43
  my $frame = 0b00000000;
44
  vec($frame, 0, 8) = $op | 0b10000000 if $fin;
45
  vec($frame, 0, 8) |= 0b01000000 if $rsv1;
46
  vec($frame, 0, 8) |= 0b00100000 if $rsv2;
47
  vec($frame, 0, 8) |= 0b00010000 if $rsv3;
48

            
49
  # Small payload
50
  my $len    = length $payload;
51
  my $prefix = 0;
52
  my $masked = $self->masked;
53
  if ($len < 126) {
54
    warn "-- Small payload ($len)\n$payload\n" if DEBUG;
55
    vec($prefix, 0, 8) = $masked ? ($len | 0b10000000) : $len;
56
    $frame .= $prefix;
57
  }
58

            
59
  # Extended payload (16bit)
60
  elsif ($len < 65536) {
61
    warn "-- Extended 16bit payload ($len)\n$payload\n" if DEBUG;
62
    vec($prefix, 0, 8) = $masked ? (126 | 0b10000000) : 126;
63
    $frame .= $prefix;
64
    $frame .= pack 'n', $len;
65
  }
66

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
67
  # Extended payload (64bit with 32bit fallback)
copy gitweblite soruce code
root authored on 2012-11-23
68
  else {
69
    warn "-- Extended 64bit payload ($len)\n$payload\n" if DEBUG;
70
    vec($prefix, 0, 8) = $masked ? (127 | 0b10000000) : 127;
71
    $frame .= $prefix;
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
72
    $frame .= pack('NN', 0, $len & 0xffffffff);
copy gitweblite soruce code
root authored on 2012-11-23
73
  }
74

            
75
  # Mask payload
76
  if ($masked) {
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
77
    my $mask = pack 'N', int(rand 9 x 7);
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
78
    $payload = $mask . xor_encode($payload, $mask x 128);
copy gitweblite soruce code
root authored on 2012-11-23
79
  }
80

            
81
  return $frame . $payload;
82
}
83

            
84
sub client_challenge {
85
  my $self = shift;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
86
  return _challenge($self->req->headers->sec_websocket_key) eq
87
    $self->res->headers->sec_websocket_accept;
copy gitweblite soruce code
root authored on 2012-11-23
88
}
89

            
90
sub client_handshake {
91
  my $self = shift;
92

            
93
  my $headers = $self->req->headers;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
94
  $headers->upgrade('websocket')      unless $headers->upgrade;
95
  $headers->connection('Upgrade')     unless $headers->connection;
copy gitweblite soruce code
root authored on 2012-11-23
96
  $headers->sec_websocket_version(13) unless $headers->sec_websocket_version;
97

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
98
  # Generate 16 byte WebSocket challenge
99
  my $challenge = b64_encode sprintf('%16u', int(rand 9 x 16)), '';
100
  $headers->sec_websocket_key($challenge) unless $headers->sec_websocket_key;
copy gitweblite soruce code
root authored on 2012-11-23
101
}
102

            
103
sub client_read  { shift->server_read(@_) }
104
sub client_write { shift->server_write(@_) }
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
105

            
106
sub connection { shift->handshake->connection }
copy gitweblite soruce code
root authored on 2012-11-23
107

            
108
sub finish {
109
  my $self = shift;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
110

            
111
  my $close = $self->{close} = [@_];
112
  my $payload = $close->[0] ? pack('n', $close->[0]) : '';
113
  $payload .= encode 'UTF-8', $close->[1] if defined $close->[1];
114
  $close->[0] = defined $close->[0] ? $close->[0] : 1005;
115
  $self->send([1, 0, 0, 0, CLOSE, $payload])->{finished} = 1;
116

            
copy gitweblite soruce code
root authored on 2012-11-23
117
  return $self;
118
}
119

            
120
sub is_websocket {1}
121

            
122
sub kept_alive    { shift->handshake->kept_alive }
123
sub local_address { shift->handshake->local_address }
124
sub local_port    { shift->handshake->local_port }
125

            
126
sub parse_frame {
127
  my ($self, $buffer) = @_;
128

            
129
  # Head
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
130
  return undef unless length(my $clone = $$buffer) >= 2;
copy gitweblite soruce code
root authored on 2012-11-23
131
  my $head = substr $clone, 0, 2;
132

            
133
  # FIN
134
  my $fin = (vec($head, 0, 8) & 0b10000000) == 0b10000000 ? 1 : 0;
135

            
136
  # RSV1-3
137
  my $rsv1 = (vec($head, 0, 8) & 0b01000000) == 0b01000000 ? 1 : 0;
138
  my $rsv2 = (vec($head, 0, 8) & 0b00100000) == 0b00100000 ? 1 : 0;
139
  my $rsv3 = (vec($head, 0, 8) & 0b00010000) == 0b00010000 ? 1 : 0;
140

            
141
  # Opcode
142
  my $op = vec($head, 0, 8) & 0b00001111;
143
  warn "-- Parsing frame ($fin, $rsv1, $rsv2, $rsv3, $op)\n" if DEBUG;
144

            
145
  # Small payload
146
  my $len = vec($head, 1, 8) & 0b01111111;
147
  my $hlen = 2;
148
  if ($len < 126) { warn "-- Small payload ($len)\n" if DEBUG }
149

            
150
  # Extended payload (16bit)
151
  elsif ($len == 126) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
152
    return undef unless length $clone > 4;
copy gitweblite soruce code
root authored on 2012-11-23
153
    $hlen = 4;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
154
    $len = unpack 'n', substr($clone, 2, 2);
copy gitweblite soruce code
root authored on 2012-11-23
155
    warn "-- Extended 16bit payload ($len)\n" if DEBUG;
156
  }
157

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
158
  # Extended payload (64bit with 32bit fallback)
copy gitweblite soruce code
root authored on 2012-11-23
159
  elsif ($len == 127) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
160
    return undef unless length $clone > 10;
copy gitweblite soruce code
root authored on 2012-11-23
161
    $hlen = 10;
162
    my $ext = substr $clone, 2, 8;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
163
    $len = unpack('N', substr($ext, 4, 4));
copy gitweblite soruce code
root authored on 2012-11-23
164
    warn "-- Extended 64bit payload ($len)\n" if DEBUG;
165
  }
166

            
167
  # Check message size
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
168
  $self->finish(1009) and return undef if $len > $self->max_websocket_size;
copy gitweblite soruce code
root authored on 2012-11-23
169

            
170
  # Check if whole packet has arrived
171
  my $masked = vec($head, 1, 8) & 0b10000000;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
172
  return undef if length $clone < ($len + $hlen + ($masked ? 4 : 0));
copy gitweblite soruce code
root authored on 2012-11-23
173
  substr $clone, 0, $hlen, '';
174

            
175
  # Payload
176
  $len += 4 if $masked;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
177
  return undef if length $clone < $len;
copy gitweblite soruce code
root authored on 2012-11-23
178
  my $payload = $len ? substr($clone, 0, $len, '') : '';
179

            
180
  # Unmask payload
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
181
  $payload = xor_encode($payload, substr($payload, 0, 4, '') x 128) if $masked;
copy gitweblite soruce code
root authored on 2012-11-23
182
  warn "$payload\n" if DEBUG;
183
  $$buffer = $clone;
184

            
185
  return [$fin, $rsv1, $rsv2, $rsv3, $op, $payload];
186
}
187

            
188
sub remote_address { shift->handshake->remote_address }
189
sub remote_port    { shift->handshake->remote_port }
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
190
sub req            { shift->handshake->req }
191
sub res            { shift->handshake->res }
copy gitweblite soruce code
root authored on 2012-11-23
192

            
193
sub resume {
194
  my $self = shift;
195
  $self->handshake->resume;
196
  return $self;
197
}
198

            
199
sub send {
200
  my ($self, $frame, $cb) = @_;
201

            
202
  if (ref $frame eq 'HASH') {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
203

            
204
    # JSON
205
    $frame->{text} = Mojo::JSON->new->encode($frame->{json}) if $frame->{json};
206

            
207
    # Binary or raw text
copy gitweblite soruce code
root authored on 2012-11-23
208
    $frame
209
      = exists $frame->{text}
210
      ? [1, 0, 0, 0, TEXT, $frame->{text}]
211
      : [1, 0, 0, 0, BINARY, $frame->{binary}];
212
  }
213

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
214
  # Text
215
  $frame = [1, 0, 0, 0, TEXT, encode('UTF-8', $frame)]
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
216
    if ref $frame ne 'ARRAY';
copy gitweblite soruce code
root authored on 2012-11-23
217

            
218
  $self->once(drain => $cb) if $cb;
219
  $self->{write} .= $self->build_frame(@$frame);
220
  $self->{state} = 'write';
221

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
222
  return $self->emit('resume');
copy gitweblite soruce code
root authored on 2012-11-23
223
}
224

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
225
sub server_close {
226
  my $self = shift;
227
  $self->{state} = 'finished';
228
  return $self->emit(finish => $self->{close} ? (@{$self->{close}}) : 1006);
229
}
230

            
copy gitweblite soruce code
root authored on 2012-11-23
231
sub server_handshake {
232
  my $self = shift;
233

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
234
  my $res_headers = $self->res->code(101)->headers;
235
  $res_headers->upgrade('websocket')->connection('Upgrade');
copy gitweblite soruce code
root authored on 2012-11-23
236
  my $req_headers = $self->req->headers;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
237
  (defined $req_headers->sec_websocket_protocol ? $req_headers->sec_websocket_protocol : '') =~ /^\s*([^,]+)/
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
238
    and $res_headers->sec_websocket_protocol($1);
copy gitweblite soruce code
root authored on 2012-11-23
239
  $res_headers->sec_websocket_accept(
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
240
    _challenge($req_headers->sec_websocket_key));
copy gitweblite soruce code
root authored on 2012-11-23
241
}
242

            
243
sub server_read {
244
  my ($self, $chunk) = @_;
245

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
246
  $self->{read} .= defined $chunk ? $chunk : '';
copy gitweblite soruce code
root authored on 2012-11-23
247
  while (my $frame = $self->parse_frame(\$self->{read})) {
248
    $self->emit(frame => $frame);
249
  }
250

            
251
  $self->emit('resume');
252
}
253

            
254
sub server_write {
255
  my $self = shift;
256

            
257
  unless (length(defined $self->{write} ? $self->{write} : '')) {
258
    $self->{state} = $self->{finished} ? 'finished' : 'read';
259
    $self->emit('drain');
260
  }
261

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
262
  return do { my $tmp = delete $self->{write}; defined $tmp ? $tmp : '' };
copy gitweblite soruce code
root authored on 2012-11-23
263
}
264

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
265
sub _challenge { b64_encode(sha1_bytes(($_[0] || '') . GUID), '') }
copy gitweblite soruce code
root authored on 2012-11-23
266

            
267
sub _message {
268
  my ($self, $frame) = @_;
269

            
270
  # Assume continuation
271
  my $op = $frame->[4] || CONTINUATION;
272

            
273
  # Ping/Pong
274
  return $self->send([1, 0, 0, 0, PONG, $frame->[5]]) if $op == PING;
275
  return if $op == PONG;
276

            
277
  # Close
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
278
  if ($op == CLOSE) {
279
    return $self->finish unless length $frame->[5] >= 2;
280
    return $self->finish(unpack('n', substr($frame->[5], 0, 2, '')),
281
      decode('UTF-8', $frame->[5]));
282
  }
copy gitweblite soruce code
root authored on 2012-11-23
283

            
284
  # Append chunk and check message size
285
  $self->{op} = $op unless exists $self->{op};
286
  $self->{message} .= $frame->[5];
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
287
  return $self->finish(1009)
copy gitweblite soruce code
root authored on 2012-11-23
288
    if length $self->{message} > $self->max_websocket_size;
289

            
290
  # No FIN bit (Continuation)
291
  return unless $frame->[0];
292

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
293
  # Whole message
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
294
  my $msg = delete $self->{message};
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
295
  $self->emit(json => Mojo::JSON->new->decode($msg))
296
    if $self->has_subscribers('json');
297
  $op = delete $self->{op};
298
  $self->emit($op == TEXT ? 'text' : 'binary' => $msg);
299
  $self->emit(message => $op == TEXT ? decode('UTF-8', $msg) : $msg)
300
    if $self->has_subscribers('message');
copy gitweblite soruce code
root authored on 2012-11-23
301
}
302

            
303
1;
304

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
305
=encoding utf8
306

            
copy gitweblite soruce code
root authored on 2012-11-23
307
=head1 NAME
308

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
309
Mojo::Transaction::WebSocket - WebSocket transaction
copy gitweblite soruce code
root authored on 2012-11-23
310

            
311
=head1 SYNOPSIS
312

            
313
  use Mojo::Transaction::WebSocket;
314

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
315
  # Send and receive WebSocket messages
copy gitweblite soruce code
root authored on 2012-11-23
316
  my $ws = Mojo::Transaction::WebSocket->new;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
317
  $ws->send('Hello World!');
318
  $ws->on(message => sub {
319
    my ($ws, $msg) = @_;
320
    say "Message: $msg";
321
  });
322
  $ws->on(finish => sub {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
323
    my ($ws, $code, $reason) = @_;
324
    say "WebSocket closed with status $code.";
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
325
  });
copy gitweblite soruce code
root authored on 2012-11-23
326

            
327
=head1 DESCRIPTION
328

            
329
L<Mojo::Transaction::WebSocket> is a container for WebSocket transactions as
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
330
described in RFC 6455. Note that 64bit frames require a Perl with support for
331
quads or they are limited to 32bit.
copy gitweblite soruce code
root authored on 2012-11-23
332

            
333
=head1 EVENTS
334

            
335
L<Mojo::Transaction::WebSocket> inherits all events from L<Mojo::Transaction>
336
and can emit the following new ones.
337

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
338
=head2 binary
339

            
340
  $ws->on(binary => sub {
341
    my ($ws, $bytes) = @_;
342
    ...
343
  });
344

            
345
Emitted when a complete WebSocket binary message has been received.
346

            
347
  $ws->on(binary => sub {
348
    my ($ws, $bytes) = @_;
349
    say "Binary: $bytes";
350
  });
351

            
352
=head2 drain
copy gitweblite soruce code
root authored on 2012-11-23
353

            
354
  $ws->on(drain => sub {
355
    my $ws = shift;
356
    ...
357
  });
358

            
359
Emitted once all data has been sent.
360

            
361
  $ws->on(drain => sub {
362
    my $ws = shift;
363
    $ws->send(time);
364
  });
365

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
366
=head2 finish
367

            
368
  $ws->on(finish => sub {
369
    my ($ws, $code, $reason) = @_;
370
    ...
371
  });
372

            
373
Emitted when transaction is finished.
374

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
375
=head2 frame
copy gitweblite soruce code
root authored on 2012-11-23
376

            
377
  $ws->on(frame => sub {
378
    my ($ws, $frame) = @_;
379
    ...
380
  });
381

            
382
Emitted when a WebSocket frame has been received.
383

            
384
  $ws->unsubscribe('frame');
385
  $ws->on(frame => sub {
386
    my ($ws, $frame) = @_;
387
    say "FIN: $frame->[0]";
388
    say "RSV1: $frame->[1]";
389
    say "RSV2: $frame->[2]";
390
    say "RSV3: $frame->[3]";
391
    say "Opcode: $frame->[4]";
392
    say "Payload: $frame->[5]";
393
  });
394

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
395
=head2 json
396

            
397
  $ws->on(json => sub {
398
    my ($ws, $json) = @_;
399
    ...
400
  });
401

            
402
Emitted when a complete WebSocket message has been received, all text and
403
binary messages will be automatically JSON decoded. Note that this event only
404
gets emitted when it has at least one subscriber.
405

            
406
  $ws->on(json => sub {
407
    my ($ws, $hash) = @_;
408
    say "Message: $hash->{msg}";
409
  });
410

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
411
=head2 message
copy gitweblite soruce code
root authored on 2012-11-23
412

            
413
  $ws->on(message => sub {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
414
    my ($ws, $msg) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
415
    ...
416
  });
417

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
418
Emitted when a complete WebSocket message has been received, text messages
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
419
will be automatically decoded. Note that this event only gets emitted when it
420
has at least one subscriber.
copy gitweblite soruce code
root authored on 2012-11-23
421

            
422
  $ws->on(message => sub {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
423
    my ($ws, $msg) = @_;
424
    say "Message: $msg";
copy gitweblite soruce code
root authored on 2012-11-23
425
  });
426

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
427
=head2 text
428

            
429
  $ws->on(text => sub {
430
    my ($ws, $bytes) = @_;
431
    ...
432
  });
433

            
434
Emitted when a complete WebSocket text message has been received.
435

            
436
  $ws->on(text => sub {
437
    my ($ws, $bytes) = @_;
438
    say "Text: $bytes";
439
  });
440

            
copy gitweblite soruce code
root authored on 2012-11-23
441
=head1 ATTRIBUTES
442

            
443
L<Mojo::Transaction::WebSocket> inherits all attributes from
444
L<Mojo::Transaction> and implements the following new ones.
445

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
446
=head2 handshake
copy gitweblite soruce code
root authored on 2012-11-23
447

            
448
  my $handshake = $ws->handshake;
449
  $ws           = $ws->handshake(Mojo::Transaction::HTTP->new);
450

            
451
The original handshake transaction, defaults to a L<Mojo::Transaction::HTTP>
452
object.
453

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
454
=head2 masked
copy gitweblite soruce code
root authored on 2012-11-23
455

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
456
  my $bool = $ws->masked;
457
  $ws      = $ws->masked($bool);
copy gitweblite soruce code
root authored on 2012-11-23
458

            
459
Mask outgoing frames with XOR cipher and a random 32bit key.
460

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
461
=head2 max_websocket_size
copy gitweblite soruce code
root authored on 2012-11-23
462

            
463
  my $size = $ws->max_websocket_size;
464
  $ws      = $ws->max_websocket_size(1024);
465

            
466
Maximum WebSocket message size in bytes, defaults to the value of the
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
467
MOJO_MAX_WEBSOCKET_SIZE environment variable or C<262144>.
copy gitweblite soruce code
root authored on 2012-11-23
468

            
469
=head1 METHODS
470

            
471
L<Mojo::Transaction::WebSocket> inherits all methods from
472
L<Mojo::Transaction> and implements the following new ones.
473

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
474
=head2 new
copy gitweblite soruce code
root authored on 2012-11-23
475

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
476
  my $ws = Mojo::Transaction::WebSocket->new;
copy gitweblite soruce code
root authored on 2012-11-23
477

            
478
Construct a new L<Mojo::Transaction::WebSocket> object and subscribe to
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
479
L</"frame"> event with default message parser, which also handles C<PING> and
copy gitweblite soruce code
root authored on 2012-11-23
480
C<CLOSE> frames automatically.
481

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
482
=head2 build_frame
copy gitweblite soruce code
root authored on 2012-11-23
483

            
484
  my $bytes = $ws->build_frame($fin, $rsv1, $rsv2, $rsv3, $op, $payload);
485

            
486
Build WebSocket frame.
487

            
488
  # Binary frame with FIN bit and payload
489
  say $ws->build_frame(1, 0, 0, 0, 2, 'Hello World!');
490

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
491
  # Text frame with payload but without FIN bit
492
  say $ws->build_frame(0, 0, 0, 0, 1, 'Hello ');
493

            
494
  # Continuation frame with FIN bit and payload
495
  say $ws->build_frame(1, 0, 0, 0, 0, 'World!');
496

            
copy gitweblite soruce code
root authored on 2012-11-23
497
  # Close frame with FIN bit and without payload
498
  say $ws->build_frame(1, 0, 0, 0, 8, '');
499

            
500
  # Ping frame with FIN bit and payload
501
  say $ws->build_frame(1, 0, 0, 0, 9, 'Test 123');
502

            
503
  # Pong frame with FIN bit and payload
504
  say $ws->build_frame(1, 0, 0, 0, 10, 'Test 123');
505

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
506
=head2 client_challenge
copy gitweblite soruce code
root authored on 2012-11-23
507

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
508
  my $bool = $ws->client_challenge;
copy gitweblite soruce code
root authored on 2012-11-23
509

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
510
Check WebSocket handshake challenge client-side, used to implement user
511
agents.
copy gitweblite soruce code
root authored on 2012-11-23
512

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
513
=head2 client_handshake
copy gitweblite soruce code
root authored on 2012-11-23
514

            
515
  $ws->client_handshake;
516

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
517
Perform WebSocket handshake client-side, used to implement user agents.
copy gitweblite soruce code
root authored on 2012-11-23
518

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
519
=head2 client_read
copy gitweblite soruce code
root authored on 2012-11-23
520

            
521
  $ws->client_read($data);
522

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
523
Read data client-side, used to implement user agents.
copy gitweblite soruce code
root authored on 2012-11-23
524

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
525
=head2 client_write
copy gitweblite soruce code
root authored on 2012-11-23
526

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
527
  my $bytes = $ws->client_write;
copy gitweblite soruce code
root authored on 2012-11-23
528

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
529
Write data client-side, used to implement user agents.
copy gitweblite soruce code
root authored on 2012-11-23
530

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
531
=head2 connection
copy gitweblite soruce code
root authored on 2012-11-23
532

            
533
  my $connection = $ws->connection;
534

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
535
Connection identifier or socket.
copy gitweblite soruce code
root authored on 2012-11-23
536

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
537
=head2 finish
copy gitweblite soruce code
root authored on 2012-11-23
538

            
539
  $ws = $ws->finish;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
540
  $ws = $ws->finish(1000);
541
  $ws = $ws->finish(1003 => 'Cannot accept data!');
copy gitweblite soruce code
root authored on 2012-11-23
542

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
543
Close WebSocket connection gracefully.
copy gitweblite soruce code
root authored on 2012-11-23
544

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
545
=head2 is_websocket
copy gitweblite soruce code
root authored on 2012-11-23
546

            
547
  my $true = $ws->is_websocket;
548

            
549
True.
550

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
551
=head2 kept_alive
copy gitweblite soruce code
root authored on 2012-11-23
552

            
553
  my $kept_alive = $ws->kept_alive;
554

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
555
Connection has been kept alive.
copy gitweblite soruce code
root authored on 2012-11-23
556

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
557
=head2 local_address
copy gitweblite soruce code
root authored on 2012-11-23
558

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
559
  my $address = $ws->local_address;
copy gitweblite soruce code
root authored on 2012-11-23
560

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
561
Local interface address.
copy gitweblite soruce code
root authored on 2012-11-23
562

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
563
=head2 local_port
copy gitweblite soruce code
root authored on 2012-11-23
564

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
565
  my $port = $ws->local_port;
copy gitweblite soruce code
root authored on 2012-11-23
566

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
567
Local interface port.
copy gitweblite soruce code
root authored on 2012-11-23
568

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
569
=head2 parse_frame
copy gitweblite soruce code
root authored on 2012-11-23
570

            
571
  my $frame = $ws->parse_frame(\$bytes);
572

            
573
Parse WebSocket frame.
574

            
575
  # Parse single frame and remove it from buffer
576
  my $frame = $ws->parse_frame(\$buffer);
577
  say "FIN: $frame->[0]";
578
  say "RSV1: $frame->[1]";
579
  say "RSV2: $frame->[2]";
580
  say "RSV3: $frame->[3]";
581
  say "Opcode: $frame->[4]";
582
  say "Payload: $frame->[5]";
583

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
584
=head2 remote_address
copy gitweblite soruce code
root authored on 2012-11-23
585

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
586
  my $address = $ws->remote_address;
copy gitweblite soruce code
root authored on 2012-11-23
587

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
588
Remote interface address.
copy gitweblite soruce code
root authored on 2012-11-23
589

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
590
=head2 remote_port
copy gitweblite soruce code
root authored on 2012-11-23
591

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
592
  my $port = $ws->remote_port;
copy gitweblite soruce code
root authored on 2012-11-23
593

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
594
Remote interface port.
copy gitweblite soruce code
root authored on 2012-11-23
595

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
596
=head2 req
copy gitweblite soruce code
root authored on 2012-11-23
597

            
598
  my $req = $ws->req;
599

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
600
Handshake request, usually a L<Mojo::Message::Request> object.
copy gitweblite soruce code
root authored on 2012-11-23
601

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
602
=head2 res
copy gitweblite soruce code
root authored on 2012-11-23
603

            
604
  my $res = $ws->res;
605

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
606
Handshake response, usually a L<Mojo::Message::Response> object.
copy gitweblite soruce code
root authored on 2012-11-23
607

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
608
=head2 resume
copy gitweblite soruce code
root authored on 2012-11-23
609

            
610
  $ws = $ws->resume;
611

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
612
Resume L</"handshake"> transaction.
copy gitweblite soruce code
root authored on 2012-11-23
613

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
614
=head2 send
copy gitweblite soruce code
root authored on 2012-11-23
615

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
616
  $ws = $ws->send({binary => $bytes});
617
  $ws = $ws->send({text   => $bytes});
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
618
  $ws = $ws->send({json   => {test => [1, 2, 3]}});
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
619
  $ws = $ws->send([$fin, $rsv1, $rsv2, $rsv3, $op, $bytes]);
620
  $ws = $ws->send($chars);
621
  $ws = $ws->send($chars => sub {...});
copy gitweblite soruce code
root authored on 2012-11-23
622

            
623
Send message or frame non-blocking via WebSocket, the optional drain callback
624
will be invoked once all data has been written.
625

            
626
  # Send "Ping" frame
627
  $ws->send([1, 0, 0, 0, 9, 'Hello World!']);
628

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
629
=head2 server_close
630

            
631
  $ws->server_close;
632

            
633
Transaction closed server-side, used to implement web servers.
634

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
635
=head2 server_handshake
copy gitweblite soruce code
root authored on 2012-11-23
636

            
637
  $ws->server_handshake;
638

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
639
Perform WebSocket handshake server-side, used to implement web servers.
copy gitweblite soruce code
root authored on 2012-11-23
640

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
641
=head2 server_read
copy gitweblite soruce code
root authored on 2012-11-23
642

            
643
  $ws->server_read($data);
644

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
645
Read data server-side, used to implement web servers.
copy gitweblite soruce code
root authored on 2012-11-23
646

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
647
=head2 server_write
copy gitweblite soruce code
root authored on 2012-11-23
648

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
649
  my $bytes = $ws->server_write;
copy gitweblite soruce code
root authored on 2012-11-23
650

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
651
Write data server-side, used to implement web servers.
copy gitweblite soruce code
root authored on 2012-11-23
652

            
653
=head1 DEBUGGING
654

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
655
You can set the MOJO_WEBSOCKET_DEBUG environment variable to get some advanced
656
diagnostics information printed to C<STDERR>.
copy gitweblite soruce code
root authored on 2012-11-23
657

            
658
  MOJO_WEBSOCKET_DEBUG=1
659

            
660
=head1 SEE ALSO
661

            
662
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
663

            
664
=cut