#include "unix-std.h"
#include "http_parser.h"
#include "libutil/regexp.h"
+#include "contrib/zstd/zstd.h"
#ifdef WITH_HYPERSCAN
#include "hs.h"
goto err;
}
- msg_info_map ("read map data from %s (%z bytes)", cbd->data->host,
- dlen);
- map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
+ if (cbd->bk->is_compressed) {
+ ZSTD_DStream *zstream;
+ ZSTD_inBuffer zin;
+ ZSTD_outBuffer zout;
+ guchar *out;
+ gsize outlen, r;
+
+ zstream = ZSTD_createDStream ();
+ ZSTD_initDStream (zstream);
+
+ zin.pos = 0;
+ zin.src = in;
+ zin.size = dlen;
+
+ if ((outlen = ZSTD_getDecompressedSize (zin.src, zin.size)) == 0) {
+ outlen = ZSTD_DStreamOutSize ();
+ }
+
+ out = g_malloc (outlen);
+
+ zout.dst = out;
+ zout.pos = 0;
+ zout.size = outlen;
+
+ while (zin.pos < zin.size) {
+ r = ZSTD_decompressStream (zstream, &zout, &zin);
+
+ if (ZSTD_isError (r)) {
+ msg_err_map ("cannot decompress data: %s",
+ ZSTD_getErrorName (r));
+ ZSTD_freeDStream (zstream);
+ g_free (out);
+ goto err;
+ }
+
+ if (zout.pos == zout.size) {
+ /* We need to extend output buffer */
+ zout.size = zout.size * 1.5 + 1.0;
+ out = g_realloc (zout.dst, zout.size);
+ zout.dst = out;
+ }
+ }
+
+ ZSTD_freeDStream (zstream);
+ msg_info_map ("read map data from %s (%z bytes compressed, "
+ "%z uncompressed)", cbd->data->host,
+ dlen, zout.pos);
+ map->read_callback (out, zout.pos, &cbd->periodic->cbdata, TRUE);
+ g_free (out);
+ }
+ else {
+ msg_info_map ("read map data from %s (%z bytes)", cbd->data->host,
+ dlen);
+ map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
+ }
/*
* We know that a map is in the locked state
}
if (len > 0) {
- map->read_callback (bytes, len, &periodic->cbdata, TRUE);
+ if (bk->is_compressed) {
+ ZSTD_DStream *zstream;
+ ZSTD_inBuffer zin;
+ ZSTD_outBuffer zout;
+ guchar *out;
+ gsize outlen, r;
+
+ zstream = ZSTD_createDStream ();
+ ZSTD_initDStream (zstream);
+
+ zin.pos = 0;
+ zin.src = bytes;
+ zin.size = len;
+
+ if ((outlen = ZSTD_getDecompressedSize (zin.src, zin.size)) == 0) {
+ outlen = ZSTD_DStreamOutSize ();
+ }
+
+ out = g_malloc (outlen);
+
+ zout.dst = out;
+ zout.pos = 0;
+ zout.size = outlen;
+
+ while (zin.pos < zin.size) {
+ r = ZSTD_decompressStream (zstream, &zout, &zin);
+
+ if (ZSTD_isError (r)) {
+ msg_err_map ("cannot decompress data: %s",
+ ZSTD_getErrorName (r));
+ ZSTD_freeDStream (zstream);
+ g_free (out);
+ munmap (bytes, len);
+ return FALSE;
+ }
+
+ if (zout.pos == zout.size) {
+ /* We need to extend output buffer */
+ zout.size = zout.size * 1.5 + 1.0;
+ out = g_realloc (zout.dst, zout.size);
+ zout.dst = out;
+ }
+ }
+
+ ZSTD_freeDStream (zstream);
+ msg_info_map ("read map data from %s (%z bytes compressed, "
+ "%z uncompressed)", data->filename,
+ len, zout.pos);
+ map->read_callback (out, zout.pos, &periodic->cbdata, TRUE);
+ g_free (out);
+ }
+ else {
+ msg_info_map ("read map data from %s (%z bytes)", data->filename,
+ len);
+ map->read_callback (bytes, len, &periodic->cbdata, TRUE);
+ }
}
munmap (bytes, len);
}
static gboolean
-rspamd_map_read_cached (struct rspamd_map *map,
+rspamd_map_read_cached (struct rspamd_map *map, struct rspamd_map_backend *bk,
struct map_periodic_cbdata *periodic, const gchar *host)
{
gsize len;
return FALSE;
}
- map->read_callback (in, map->cache->len, &periodic->cbdata, TRUE);
- msg_info_map ("read map data from %s (cached) (%z bytes)", host, len);
+ if (bk->is_compressed) {
+ ZSTD_DStream *zstream;
+ ZSTD_inBuffer zin;
+ ZSTD_outBuffer zout;
+ guchar *out;
+ gsize outlen, r;
+
+ zstream = ZSTD_createDStream ();
+ ZSTD_initDStream (zstream);
+
+ zin.pos = 0;
+ zin.src = in;
+ zin.size = len;
+
+ if ((outlen = ZSTD_getDecompressedSize (zin.src, zin.size)) == 0) {
+ outlen = ZSTD_DStreamOutSize ();
+ }
+
+ out = g_malloc (outlen);
+
+ zout.dst = out;
+ zout.pos = 0;
+ zout.size = outlen;
+
+ while (zin.pos < zin.size) {
+ r = ZSTD_decompressStream (zstream, &zout, &zin);
+
+ if (ZSTD_isError (r)) {
+ msg_err_map ("cannot decompress data: %s",
+ ZSTD_getErrorName (r));
+ ZSTD_freeDStream (zstream);
+ g_free (out);
+ munmap (in, len);
+ return FALSE;
+ }
+
+ if (zout.pos == zout.size) {
+ /* We need to extend output buffer */
+ zout.size = zout.size * 1.5 + 1.0;
+ out = g_realloc (zout.dst, zout.size);
+ zout.dst = out;
+ }
+ }
+
+ ZSTD_freeDStream (zstream);
+ msg_info_map ("read map data from %s (cached) (%z bytes compressed, "
+ "%z uncompressed)", host,
+ len, zout.pos);
+ map->read_callback (out, zout.pos, &periodic->cbdata, TRUE);
+ g_free (out);
+ }
+ else {
+ msg_info_map ("read map data from %s (cached) (%z bytes)", host,
+ len);
+ map->read_callback (in, len, &periodic->cbdata, TRUE);
+ }
+
munmap (in, len);
return TRUE;
return;
}
- else if (rspamd_map_read_cached (map, periodic, data->host)) {
+ else if (rspamd_map_read_cached (map, bk, periodic, data->host)) {
/* Switch to the next backend */
periodic->cur_backend ++;
data->last_checked = map->cache->last_checked;
struct file_map_data *fdata = NULL;
struct http_map_data *hdata = NULL;
struct http_parser_url up;
+ const gchar *end, *p;
rspamd_ftok_t tok;
bk = g_slice_alloc0 (sizeof (*bk));
goto err;
}
+ end = map_line + strlen (map_line);
+ if (end - map_line > 5) {
+ p = end - 5;
+ if (g_ascii_strcasecmp (p, ".zstd") == 0) {
+ bk->is_compressed = TRUE;
+ }
+ }
+
/* Now check for each proto separately */
if (bk->protocol == MAP_PROTO_FILE) {
fdata = g_slice_alloc0 (sizeof (struct file_map_data));