26#if DETWS_ENABLE_SSH_ZLIB
32constexpr int MIN_MATCH = 3;
33constexpr int MAX_MATCH = 258;
34constexpr int HASH_MASK = SSH_ZLIB_HASH_SIZE - 1;
36constexpr int MAX_CHAIN = 128;
37constexpr uint16_t NONE = 0xFFFF;
40const short LEN_BASE[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
41 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
42const short LEN_EXTRA[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
45const short DIST_BASE[30] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129,
46 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
47const short DIST_EXTRA[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
48 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
51uint16_t reverse_bits(uint16_t code,
int len)
54 for (
int k = 0; k < len; k++)
56 r = (uint16_t)((r << 1) | (code & 1));
64void build_fixed(SshDeflate *z)
67 for (; sym < 144; sym++)
69 for (; sym < 256; sym++)
71 for (; sym < 280; sym++)
73 for (; sym < 288; sym++)
75 for (sym = 0; sym < 30; sym++)
78 uint16_t bl_count[16];
79 memset(bl_count, 0,
sizeof(bl_count));
80 for (sym = 0; sym < 288; sym++)
81 bl_count[z->ll_len[sym]]++;
82 uint16_t next_code[16];
85 for (
int b = 1; b <= 15; b++)
87 code = (uint16_t)((code + bl_count[b - 1]) << 1);
90 for (sym = 0; sym < 288; sym++)
92 int len = z->ll_len[sym];
93 z->ll_code[sym] = reverse_bits(next_code[len]++, len);
95 for (sym = 0; sym < 30; sym++)
96 z->d_code[sym] = reverse_bits((uint16_t)sym, 5);
110void put_bits(BitWriter *w, uint32_t bits,
int n)
112 w->acc |= bits << w->nbits;
114 while (w->nbits >= 8)
116 if (w->cnt >= w->cap)
121 w->out[w->cnt++] = (uint8_t)(w->acc & 0xFF);
128void align_byte(BitWriter *w)
132 if (w->cnt >= w->cap)
137 w->out[w->cnt++] = (uint8_t)(w->acc & 0xFF);
144void put_byte(BitWriter *w, uint8_t b)
146 if (w->cnt >= w->cap)
151 w->out[w->cnt++] = b;
155inline int hash3(
const uint8_t *p)
157 return (
int)(((uint32_t)p[0] << 10 ^ (uint32_t)p[1] << 5 ^ (uint32_t)p[2]) & HASH_MASK);
160void emit_literal(BitWriter *w,
const SshDeflate *z, uint8_t b)
162 put_bits(w, z->ll_code[b], z->ll_len[b]);
165void emit_match(BitWriter *w,
const SshDeflate *z,
int len,
int dist)
168 while (li < 28 && len >= LEN_BASE[li + 1])
171 put_bits(w, z->ll_code[lsym], z->ll_len[lsym]);
173 put_bits(w, (uint32_t)(len - LEN_BASE[li]), LEN_EXTRA[li]);
176 while (di < 29 && dist >= DIST_BASE[di + 1])
178 put_bits(w, z->d_code[di], z->d_len[di]);
180 put_bits(w, (uint32_t)(dist - DIST_BASE[di]), DIST_EXTRA[di]);
185void zlib_chain_match(
const SshDeflate *z,
const uint8_t *buf,
size_t i, uint16_t cand,
int chain,
size_t max_len,
186 int *best_len,
int *best_dist)
190 while (cand != NONE && chain > 0)
193 size_t dist = i - cand;
194 if (dist > (
size_t)WINDOW)
197 while (l < max_len && buf[cand + l] == buf[i + l])
199 if ((
int)l > *best_len)
202 *best_dist = (int)dist;
206 cand = z->prev[cand];
211void ssh_deflate_init(SshDeflate *z, uint8_t *work, uint16_t *head, uint16_t *prev, uint16_t *ll_code, uint8_t *ll_len,
212 uint16_t *d_code, uint8_t *d_len)
217 z->ll_code = ll_code;
222 z->header_sent =
false;
226int ssh_deflate_packet(SshDeflate *z,
const uint8_t *src,
size_t src_len, uint8_t *dst,
size_t dst_cap,
size_t *out_len)
232 size_t hist = z->hist;
233 if (hist + src_len > SSH_ZLIB_WORK_SIZE)
235 memcpy(z->work + hist, src, src_len);
236 size_t total = hist + src_len;
237 const uint8_t *buf = z->work;
240 for (
int b = 0; b < SSH_ZLIB_HASH_SIZE; b++)
242 for (
size_t p = 0; p + MIN_MATCH <= total && p < hist; p++)
244 int h = hash3(buf + p);
245 z->prev[p] = z->head[h];
246 z->head[h] = (uint16_t)p;
263 z->header_sent =
true;
276 if (i + MIN_MATCH <= total)
278 int h = hash3(buf + i);
279 uint16_t cand = z->head[h];
280 size_t max_len = total - i;
281 if (max_len > (
size_t)MAX_MATCH)
283 zlib_chain_match(z, buf, i, cand, MAX_CHAIN, max_len, &best_len, &best_dist);
287 if (best_len >= MIN_MATCH)
289 emit_match(&w, z, best_len, best_dist);
290 advance = (size_t)best_len;
294 emit_literal(&w, z, buf[i]);
300 size_t end = i + advance;
303 if (i + MIN_MATCH <= total)
305 int h = hash3(buf + i);
306 z->prev[i] = z->head[h];
307 z->head[h] = (uint16_t)i;
315 put_bits(&w, z->ll_code[256], z->ll_len[256]);
329 if (keep > (
size_t)WINDOW)
332 memmove(z->work, z->work + total - keep, keep);
#define DETWS_SSH_ZLIB_WINDOW
SSH s2c DEFLATE sliding-window size in bytes (max back-reference distance). Power of two,...
#define DETWS_SSH_ZLIB_MAX_IN
Largest uncompressed payload the s2c compressor accepts in one call (bytes). Outbound SSH payloads ar...
SSH server-to-client compression: a context-takeover DEFLATE stream (no heap).