235 , m_server_no_context_takeover(
false)
236 , m_client_no_context_takeover(
false)
237 , m_server_max_window_bits(15)
238 , m_client_max_window_bits(15)
239 , m_server_max_window_bits_mode(mode::accept)
240 , m_client_max_window_bits_mode(mode::accept)
241 , m_initialized(
false)
242 , m_compress_buffer_size(8192)
243 , m_max_message_size(detail::max_message_size_or_default<
244 config, default_max_message_size>::get())
246 m_dstate.zalloc = Z_NULL;
247 m_dstate.zfree = Z_NULL;
248 m_dstate.opaque = Z_NULL;
250 m_istate.zalloc = Z_NULL;
251 m_istate.zfree = Z_NULL;
252 m_istate.opaque = Z_NULL;
253 m_istate.avail_in = 0;
254 m_istate.next_in = Z_NULL;
258 if (!m_initialized) {
262 int ret = deflateEnd(&m_dstate);
269 ret = inflateEnd(&m_istate);
279
280
281
282
283
284
285
286
287
288 lib::error_code
init(
bool is_server) {
289 uint8_t deflate_bits;
290 uint8_t inflate_bits;
293 deflate_bits = m_server_max_window_bits;
294 inflate_bits = m_client_max_window_bits;
296 deflate_bits = m_client_max_window_bits;
297 inflate_bits = m_server_max_window_bits;
300 int ret = deflateInit2(
302 Z_DEFAULT_COMPRESSION,
322 m_compress_buffer.reset(
new unsigned char[m_compress_buffer_size]);
323 m_decompress_buffer.reset(
new unsigned char[m_compress_buffer_size]);
324 if ((m_server_no_context_takeover && is_server) ||
325 (m_client_no_context_takeover && !is_server))
327 m_flush = Z_FULL_FLUSH;
329 m_flush = Z_SYNC_FLUSH;
331 m_initialized =
true;
332 return lib::error_code();
337
338
339
340
347
348
349
350
351
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
378 m_server_no_context_takeover =
true;
383
384
385
386
387
388
389
390
391
392
393
394
395
397 m_client_no_context_takeover =
true;
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
440 m_server_max_window_bits = bits;
441 m_server_max_window_bits_mode = mode;
443 return lib::error_code();
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
485 m_client_max_window_bits = bits;
486 m_client_max_window_bits_mode = mode;
488 return lib::error_code();
493
494
495
496
497
500 return "permessage-deflate; client_no_context_takeover; client_max_window_bits";
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
521 m_max_message_size = value;
526
527
528
529
530
531
533 return lib::error_code();
538
539
540
541
542
543
544
548 http::attribute_list::const_iterator it;
549 for (it = offer.begin(); it != offer.end(); ++it) {
550 if (it->first ==
"server_no_context_takeover") {
551 negotiate_server_no_context_takeover(it->second,ret.first);
552 }
else if (it->first ==
"client_no_context_takeover") {
553 negotiate_client_no_context_takeover(it->second,ret.first);
554 }
else if (it->first ==
"server_max_window_bits") {
555 negotiate_server_max_window_bits(it->second,ret.first);
556 }
else if (it->first ==
"client_max_window_bits") {
557 negotiate_client_max_window_bits(it->second,ret.first);
567 if (ret.first == lib::error_code()) {
569 ret.second = generate_response();
577
578
579
580
581 lib::error_code
compress(std::string
const & in, std::string & out) {
582 if (!m_initialized) {
589 uint8_t buf[6] = {0x02, 0x00, 0x00, 0x00, 0xff, 0xff};
590 out.append((
char *)(buf),6);
591 return lib::error_code();
596 size_t input_remaining = in.size();
597 m_dstate.avail_in = 0;
598 m_dstate.next_in = (
unsigned char *)(
const_cast<
char *>(in.data()));
601 if (m_dstate.avail_in == 0 && input_remaining > 0) {
602 size_t
const input = (std::min)(m_compress_buffer_size, input_remaining);
603 m_dstate.avail_in =
static_cast<uInt>(input);
604 input_remaining -= input;
608 m_dstate.avail_out =
static_cast<uInt>(m_compress_buffer_size);
609 m_dstate.next_out = m_compress_buffer.get();
611 deflate(&m_dstate, input_remaining == 0 ? m_flush : Z_NO_FLUSH);
613 output = m_compress_buffer_size - m_dstate.avail_out;
615 out.append((
char *)(m_compress_buffer.get()),output);
616 }
while (m_dstate.avail_out == 0 || (m_dstate.avail_in == 0 && input_remaining > 0));
618 return lib::error_code();
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641 lib::error_code
decompress(uint8_t
const * buf, size_t len, std::string &
644 if (!m_initialized) {
651 size_t input_remaining = len;
652 m_istate.avail_in = 0;
653 m_istate.next_in =
const_cast<
unsigned char *>(buf);
656 if (m_istate.avail_in == 0 && input_remaining > 0) {
657 size_t
const input = (std::min)(m_compress_buffer_size, input_remaining);
658 m_istate.avail_in =
static_cast<uInt>(input);
659 input_remaining -= input;
662 size_t
const remaining = out.size() < m_max_message_size
663 ? m_max_message_size - out.size()
667 size_t
const output_limit = (std::min)(m_compress_buffer_size, remaining + size_t(1));
669 m_istate.avail_out =
static_cast<uInt>(output_limit);
670 m_istate.next_out = m_decompress_buffer.get();
672 ret = inflate(&m_istate, Z_SYNC_FLUSH);
674 if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
678 size_t
const output = output_limit -
static_cast<size_t>(m_istate.avail_out);
680 if (output > remaining) {
683 reinterpret_cast<
char *>(m_decompress_buffer.get()),
692 reinterpret_cast<
char *>(m_decompress_buffer.get()),
695 }
while (m_istate.avail_out == 0 || (m_istate.avail_in == 0 && input_remaining > 0));
697 return lib::error_code();
700 static bool is_message_too_big(lib::error_code
const & ec) {
707
708
709 std::string generate_response() {
710 std::string ret =
"permessage-deflate";
712 if (m_server_no_context_takeover) {
713 ret +=
"; server_no_context_takeover";
716 if (m_client_no_context_takeover) {
717 ret +=
"; client_no_context_takeover";
722 s <<
int(m_server_max_window_bits);
723 ret +=
"; server_max_window_bits="+s.str();
728 s <<
int(m_client_max_window_bits);
729 ret +=
"; client_max_window_bits="+s.str();
737
738
739
740 void negotiate_server_no_context_takeover(std::string
const & value,
741 lib::error_code & ec)
743 if (!value.empty()) {
748 m_server_no_context_takeover =
true;
753
754
755
756 void negotiate_client_no_context_takeover(std::string
const & value,
757 lib::error_code & ec)
759 if (!value.empty()) {
764 m_client_no_context_takeover =
true;
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789 void negotiate_server_max_window_bits(std::string
const & value,
790 lib::error_code & ec)
792 uint8_t bits = uint8_t(atoi(value.c_str()));
800 switch (m_server_max_window_bits_mode) {
805 m_server_max_window_bits = bits;
808 m_server_max_window_bits = std::min(bits,m_server_max_window_bits);
819 if (m_server_max_window_bits == 8) {
820 m_server_max_window_bits = 9;
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845 void negotiate_client_max_window_bits(std::string
const & value,
846 lib::error_code & ec)
848 uint8_t bits = uint8_t(atoi(value.c_str()));
860 switch (m_client_max_window_bits_mode) {
865 m_client_max_window_bits = bits;
868 m_client_max_window_bits = std::min(bits,m_client_max_window_bits);
879 if (m_client_max_window_bits == 8) {
880 m_client_max_window_bits = 9;
885 bool m_server_no_context_takeover;
886 bool m_client_no_context_takeover;
887 uint8_t m_server_max_window_bits;
888 uint8_t m_client_max_window_bits;
889 mode::value m_server_max_window_bits_mode;
890 mode::value m_client_max_window_bits_mode;
894 size_t m_compress_buffer_size;
895 size_t m_max_message_size;
896 lib::unique_ptr_uchar_array m_compress_buffer;
897 lib::unique_ptr_uchar_array m_decompress_buffer;