#define MIN_SIZE_TO_DEFLATE 4
+#ifndef LWS_MAX_ZLIB_CONN_BUFFER
+#define LWS_MAX_ZLIB_CONN_BUFFER (64 * 1024)
+#endif
int lws_extension_callback_deflate_frame(
struct libwebsocket_context *context,
struct lws_tokens *eff_buf = (struct lws_tokens *)in;
size_t current_payload, remaining_payload, total_payload;
int n;
+ size_t len_so_far;
switch (reason) {
conn->zs_in.avail_in = total_payload + 4;
- conn->zs_in.next_out = conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
- conn->zs_in.avail_out = conn->buf_in_length;
-
- n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
- switch (n) {
- case Z_NEED_DICT:
- case Z_STREAM_ERROR:
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- /*
- * screwed.. close the connection... we will get a
- * destroy callback to take care of closing nicely
- */
- lwsl_ext("zlib error inflate %d: %s",
- n, conn->zs_in.msg);
- return -1;
- }
+ conn->zs_in.next_out = conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
+ conn->zs_in.avail_out = conn->buf_in_length;
+
+ while (1) {
+ n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
+ switch (n) {
+ case Z_NEED_DICT:
+ case Z_STREAM_ERROR:
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ /*
+ * screwed.. close the connection... we will get a
+ * destroy callback to take care of closing nicely
+ */
+ fprintf(stderr, "zlib error inflate %d: %s",
+ n, conn->zs_in.msg);
+ return -1;
+ }
+
+ if (conn->zs_in.avail_out)
+ break;
+
+ len_so_far = conn->zs_in.next_out -
+ (conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
+
+ conn->buf_in_length *= 2;
+ if (conn->buf_in_length > LWS_MAX_ZLIB_CONN_BUFFER) {
+ lwsl_ext("zlib in buffer tried to exceed "
+ "max allowed of %u\n",
+ LWS_MAX_ZLIB_CONN_BUFFER);
+ return -1;
+ }
+ conn->buf_in = (unsigned char *)realloc(conn->buf_in,
+ LWS_SEND_BUFFER_PRE_PADDING +
+ conn->buf_in_length +
+ LWS_SEND_BUFFER_POST_PADDING);
+ if (!conn->buf_in) {
+ lwsl_err("Out of memory\n");
+ return -1;
+ }
+ lwsl_debug(
+ "deflate-frame ext RX did realloc to %ld\n",
+ conn->buf_in_length);
+ conn->zs_in.next_out = conn->buf_in +
+ LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
+ conn->zs_in.avail_out =
+ conn->buf_in_length - len_so_far;
+ }
/* rewrite the buffer pointers and length */
eff_buf->token = (char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
return -1;
}
- /*
- * AG: uncertain about this log buffer expansion approach...
- * same approach in Rx led to memory runaway OOM
- */
- if (!conn->zs_out.avail_out) {
- size_t len_so_far = (conn->zs_out.next_out -
+ if (conn->zs_out.avail_out)
+ break;
+
+ len_so_far = (conn->zs_out.next_out -
(conn->buf_out +
LWS_SEND_BUFFER_PRE_PADDING));
- unsigned char *new_buf;
- conn->buf_out_length *= 2;
- new_buf = (unsigned char *)
- malloc(LWS_SEND_BUFFER_PRE_PADDING +
+ conn->buf_out_length *= 2;
+ if (conn->buf_out_length > LWS_MAX_ZLIB_CONN_BUFFER) {
+ lwsl_ext("zlib out buffer tried to exceed "
+ "max allowed of %u\n",
+ LWS_MAX_ZLIB_CONN_BUFFER);
+ return -1;
+ }
+ conn->buf_out = (unsigned char *)realloc(
+ conn->buf_out,
+ LWS_SEND_BUFFER_PRE_PADDING +
conn->buf_out_length +
LWS_SEND_BUFFER_POST_PADDING);
- if (!new_buf) {
- lwsl_err("Out of memory\n");
- return -1;
- }
- memcpy(new_buf + LWS_SEND_BUFFER_PRE_PADDING,
- conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING,
- len_so_far);
- free(conn->buf_out);
- conn->buf_out = new_buf;
- conn->zs_out.next_out = (new_buf +
+ if (!conn->buf_out) {
+ lwsl_err("Out of memory\n");
+ return -1;
+ }
+ lwsl_debug(
+ "deflate-frame ext TX did realloc to %ld\n",
+ conn->buf_in_length);
+
+ conn->zs_out.next_out = (conn->buf_out +
LWS_SEND_BUFFER_PRE_PADDING + len_so_far);
- conn->zs_out.avail_out =
+ conn->zs_out.avail_out =
(conn->buf_out_length - len_so_far);
- } else
- break;
}
conn->compressed_out = 1;