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

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.



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

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



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

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.



52
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
# File 'lib/protocol/websocket/extension/compression.rb', line 52

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.



16
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
# File 'lib/protocol/websocket/extension/compression.rb', line 16

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



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

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