Module: Protocol::WebSocket::Extension::Compression

Defined in:
lib/protocol/websocket/extension/compression.rb,
lib/protocol/websocket/extension/compression/deflate.rb,
lib/protocol/websocket/extension/compression/inflate.rb,
lib/protocol/websocket/extension/compression/constants.rb

Overview

Provides support for the permessage-deflate extension.

Defined Under Namespace

Classes: Deflate, Inflate

Constant Summary collapse

NAME =
"permessage-deflate"
MINIMUM_WINDOW_BITS =

Zlib is not capable of handling < 9 window bits.

9

Class Method Summary collapse

Class Method Details

.accept(arguments, **options) ⇒ Object

Accept on the client, the negotiated server response.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/protocol/websocket/extension/compression.rb', line 94

def self.accept(arguments, **options)
  arguments.each do |key, value|
    case key
    when "server_no_context_takeover"
      options[:server_no_context_takeover] = true
    when "client_no_context_takeover"
      options[:client_no_context_takeover] = true
    when "server_max_window_bits"
      options[:server_max_window_bits] = Integer(value || 15)
    when "client_max_window_bits"
      options[:client_max_window_bits] = Integer(value || 15)
    else
      raise ArgumentError, "Unknown option: #{key}!"
    end
  end
  
  return options
end

.client(connection, **options) ⇒ Object



114
115
116
117
118
119
# File 'lib/protocol/websocket/extension/compression.rb', line 114

def self.client(connection, **options)
  connection.reserve!(Frame::RSV1)
  
  connection.reader = Inflate.client(connection.reader, **options)
  connection.writer = Deflate.client(connection.writer, **options)
end

.negotiate(arguments, **options) ⇒ Object

Negotiate on the server a response to client based on the incoming client offer.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/protocol/websocket/extension/compression.rb', line 53

def self.negotiate(arguments, **options)
  header = [NAME]
  
  arguments.each do |key, value|
    case key
    when "server_no_context_takeover"
      options[:server_no_context_takeover] = true
      header << key
    when "client_no_context_takeover"
      options[:client_no_context_takeover] = true
      header << key
    when "server_max_window_bits"
      value = Integer(value || 15)
      value = MINIMUM_WINDOW_BITS if value < MINIMUM_WINDOW_BITS
      options[:server_max_window_bits] = value
      header << "server_max_window_bits=#{value}"
    when "client_max_window_bits"
      value = Integer(value || 15)
      value = MINIMUM_WINDOW_BITS if value < MINIMUM_WINDOW_BITS
      options[:client_max_window_bits] = value
      header << "client_max_window_bits=#{value}"
    else
      raise ArgumentError, "Unknown option: #{key}!"
    end
  end
  
  # The header which represents the final accepted/negotiated configuration.
  return header, options
end

.offer(client_max_window_bits: true, server_max_window_bits: true, client_no_context_takeover: false, server_no_context_takeover: false) ⇒ Object

Client offer to server, construct a list of requested compression parameters suitable for the ‘Sec-WebSocket-Extensions` header.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/protocol/websocket/extension/compression.rb', line 17

def self.offer(client_max_window_bits: true, server_max_window_bits: true, client_no_context_takeover: false, server_no_context_takeover: false)
  
  header = [NAME]
  
  case client_max_window_bits
  when 8..15
    header << "client_max_window_bits=#{client_max_window_bits}"
  when true
    header << "client_max_window_bits"
  else
    raise ArgumentError, "Invalid local maximum window bits!"
  end
  
  if client_no_context_takeover
    header << "client_no_context_takeover"
  end
  
  case server_max_window_bits
  when 8..15
    header << "server_max_window_bits=#{server_max_window_bits}"
  when true
    # Default (unspecified) to the server maximum window bits.
  else
    raise ArgumentError, "Invalid remote maximum window bits!"
  end
  
  if server_no_context_takeover
    header << "server_no_context_takeover"
  end
  
  return header
end

.server(connection, **options) ⇒ Object



84
85
86
87
88
89
# File 'lib/protocol/websocket/extension/compression.rb', line 84

def self.server(connection, **options)
  connection.reserve!(Frame::RSV1)
  
  connection.reader = Inflate.server(connection.reader, **options)
  connection.writer = Deflate.server(connection.writer, **options)
end