mod_zlib.inl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* Experimental implementation for on-the-fly compression */
  2. #if !defined(USE_ZLIB)
  3. #error "This file must only be included, if USE_ZLIB is set"
  4. #endif
  5. #include "zconf.h"
  6. #include "zlib.h"
  7. #if !defined(MEM_LEVEL)
  8. #define MEM_LEVEL (8)
  9. #endif
  10. static void *
  11. zalloc(void *opaque, uInt items, uInt size)
  12. {
  13. struct mg_connection *conn = (struct mg_connection *)opaque;
  14. void *ret = mg_calloc_ctx(items, size, conn->phys_ctx);
  15. return ret;
  16. }
  17. static void
  18. zfree(void *opaque, void *address)
  19. {
  20. struct mg_connection *conn = (struct mg_connection *)opaque;
  21. (void)conn; /* not required */
  22. mg_free(address);
  23. }
  24. static void
  25. send_compressed_data(struct mg_connection *conn, struct mg_file *filep)
  26. {
  27. int zret;
  28. z_stream zstream;
  29. int do_flush;
  30. unsigned bytes_avail;
  31. unsigned char in_buf[MG_BUF_LEN];
  32. unsigned char out_buf[MG_BUF_LEN];
  33. FILE *in_file = filep->access.fp;
  34. /* Prepare state buffer. User server context memory allocation. */
  35. memset(&zstream, 0, sizeof(zstream));
  36. zstream.zalloc = zalloc;
  37. zstream.zfree = zfree;
  38. zstream.opaque = (void *)conn;
  39. /* Initialize for GZIP compression (MAX_WBITS | 16) */
  40. zret = deflateInit2(&zstream,
  41. Z_BEST_COMPRESSION,
  42. Z_DEFLATED,
  43. MAX_WBITS | 16,
  44. MEM_LEVEL,
  45. Z_DEFAULT_STRATEGY);
  46. if (zret != Z_OK) {
  47. mg_cry_internal(conn,
  48. "GZIP init failed (%i): %s",
  49. zret,
  50. (zstream.msg ? zstream.msg : "<no error message>"));
  51. deflateEnd(&zstream);
  52. return;
  53. }
  54. /* Read until end of file */
  55. do {
  56. zstream.avail_in = fread(in_buf, 1, MG_BUF_LEN, in_file);
  57. if (ferror(in_file)) {
  58. mg_cry_internal(conn, "fread failed: %s", strerror(ERRNO));
  59. (void)deflateEnd(&zstream);
  60. return;
  61. }
  62. do_flush = (feof(in_file) ? Z_FINISH : Z_NO_FLUSH);
  63. zstream.next_in = in_buf;
  64. /* run deflate() on input until output buffer not full, finish
  65. * compression if all of source has been read in */
  66. do {
  67. zstream.avail_out = MG_BUF_LEN;
  68. zstream.next_out = out_buf;
  69. zret = deflate(&zstream, do_flush);
  70. if (zret == Z_STREAM_ERROR) {
  71. /* deflate error */
  72. zret = -97;
  73. break;
  74. }
  75. bytes_avail = MG_BUF_LEN - zstream.avail_out;
  76. if (bytes_avail) {
  77. if (mg_send_chunk(conn, (char *)out_buf, bytes_avail) < 0) {
  78. zret = -98;
  79. break;
  80. }
  81. }
  82. } while (zstream.avail_out == 0);
  83. if (zret < -90) {
  84. /* Forward write error */
  85. break;
  86. }
  87. if (zstream.avail_in != 0) {
  88. /* all input will be used, otherwise GZIP is incomplete */
  89. zret = -99;
  90. break;
  91. }
  92. /* done when last data in file processed */
  93. } while (do_flush != Z_FINISH);
  94. if (zret != Z_STREAM_END) {
  95. /* Error: We did not compress everything. */
  96. mg_cry_internal(conn,
  97. "GZIP incomplete (%i): %s",
  98. zret,
  99. (zstream.msg ? zstream.msg : "<no error message>"));
  100. }
  101. deflateEnd(&zstream);
  102. /* Send "end of chunked data" marker */
  103. mg_write(conn, "0\r\n\r\n", 5);
  104. }