1extern crate slog_term;
3
4#[macro_use]
5extern crate slog;
6#[macro_use]
7extern crate twist;
8
9use slog::Logger;
10use std::io;
11use twist::{BaseFrame, FromHeader, IntoResponse, OpCode, PerMessage};
12
13const RSV1: u8 = 4;
15const SWE: &'static str = "Sec-WebSocket-Extensions: ";
17const PMD: &'static str = "permessage-deflate";
19
20fn other(desc: &str) -> io::Error {
22 io::Error::new(io::ErrorKind::Other, desc)
23}
24
25pub struct Deflate {
27 enabled: bool,
29 _server_no_context_takeover: bool,
34 _client_no_context_takeover: bool,
43 server_max_window_bits: u8,
52 _client_max_window_bits: u8,
54 stdout: Option<Logger>,
56 stderr: Option<Logger>,
58}
59
60impl Deflate {
61 pub fn add_stdout(&mut self, stdout: Logger) -> &mut Deflate {
63 let ps_stdout = stdout.new(o!("extension" => "permessage-deflate"));
64 self.stdout = Some(ps_stdout);
65 self
66 }
67
68 pub fn add_stderr(&mut self, stderr: Logger) -> &mut Deflate {
70 let ps_stderr = stderr.new(o!("extension" => "permessage-deflate"));
71 self.stderr = Some(ps_stderr);
72 self
73 }
74}
75
76impl Default for Deflate {
77 fn default() -> Deflate {
78 Deflate {
79 enabled: false,
80 _server_no_context_takeover: false,
81 _client_no_context_takeover: true,
82 server_max_window_bits: 15,
83 _client_max_window_bits: 15,
84 stdout: None,
85 stderr: None,
86 }
87 }
88}
89
90impl FromHeader for Deflate {
91 fn init(&mut self, request: &str) {
92 try_trace!(self.stdout, "init Deflate with header '{}'", request);
93
94 if request.contains(PMD) {
95 self.enabled = true;
96 try_trace!(self.stdout, "permessage deflate is enabled");
97
98 let blah: Vec<&str> =
99 request.split(',').take_while(|s| s.starts_with("permessage-deflate")).collect();
100 for pmd in blah {
101 try_trace!(self.stdout, "{}", pmd);
102 }
103 self.server_max_window_bits = 8;
104 } else {
105 try_trace!(self.stdout, "permessage deflate is disabled");
106 }
107 }
108}
109
110impl IntoResponse for Deflate {
111 fn response(&self) -> String {
112 let mut resp = String::new();
113 if self.enabled {
114 resp.push_str(SWE);
115 resp.push_str(PMD);
116 }
117 resp
118 }
119}
120
121impl PerMessage for Deflate {
122 fn reserve_rsv(&self, current_rsv: u8) -> Result<u8, io::Error> {
123 if self.enabled {
124 if current_rsv & RSV1 == 0 {
125 Ok(current_rsv | RSV1)
126 } else {
127 Err(other("rsv1 bit already reserved"))
128 }
129 } else {
130 Ok(0)
131 }
132 }
133
134 fn uses_extension_data(&self) -> bool {
135 false
136 }
137
138 fn decode(&self, message: &mut BaseFrame) -> Result<(), io::Error> {
139 if self.enabled {
140 let opcode = message.opcode();
141 if (opcode == OpCode::Text || opcode == OpCode::Binary) && message.fin() {
142 try_trace!(self.stdout, "Decompressing Frame");
143 }
144 }
145 Ok(())
146 }
147
148 fn encode(&self, message: &mut BaseFrame) -> Result<(), io::Error> {
149 if self.enabled {
150 let opcode = message.opcode();
151 if (opcode == OpCode::Text || opcode == OpCode::Binary) && message.fin() {
152 try_trace!(self.stdout, "Compressing Frame");
153 }
154 }
155 Ok(())
156 }
157}
158
159
160#[test]
161fn it_works() {}