1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-06 01:33:12 +02:00

relay: add zstd compression in weechat protocol

Option relay.network.compression_level is renamed to relay.network.compression
and is now a percentage between 0 (no compression) to 100 (best compression,
slowest).

Compression is now disabled by default in weechat protocol and must be enabled
via the `handshake` command (option `compression` has been removed from `init`
command).
This commit is contained in:
Sébastien Helleu
2021-12-24 15:14:56 +01:00
parent d5c391b1ee
commit 498194f6fc
36 changed files with 441 additions and 870 deletions
+5 -2
View File
@@ -43,13 +43,16 @@ set_target_properties(relay PROPERTIES PREFIX "")
set(LINK_LIBS)
list(APPEND LINK_LIBS ${ZLIB_LIBRARY})
include_directories(${GNUTLS_INCLUDE_PATH})
list(APPEND LINK_LIBS ${GNUTLS_LIBRARY})
list(APPEND LINK_LIBS ${GCRYPT_LDFLAGS})
list(APPEND LINK_LIBS ${ZLIB_LIBRARY})
include_directories(${ZSTD_INCLUDE_DIRS})
list(APPEND LINK_LIBS ${LIBZSTD_LDFLAGS})
target_link_libraries(relay ${LINK_LIBS} coverage_config)
install(TARGETS relay LIBRARY DESTINATION ${WEECHAT_LIBDIR}/plugins)
+2 -2
View File
@@ -17,7 +17,7 @@
# along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
#
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(ZLIB_CFLAGS) $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS) $(ZLIB_CFLAGS) $(ZSTD_CFLAGS)
libdir = ${weechat_libdir}/plugins
@@ -61,6 +61,6 @@ relay_la_SOURCES = relay.c \
weechat/relay-weechat-protocol.h
relay_la_LDFLAGS = -module -no-undefined
relay_la_LIBADD = $(RELAY_LFLAGS) $(ZLIB_LFLAGS) $(GCRYPT_LFLAGS) $(GNUTLS_LFLAGS)
relay_la_LIBADD = $(RELAY_LFLAGS) $(GCRYPT_LFLAGS) $(GNUTLS_LFLAGS) $(ZLIB_LFLAGS) $(ZSTD_LFLAGS)
EXTRA_DIST = CMakeLists.txt
+10 -7
View File
@@ -63,7 +63,7 @@ struct t_config_option *relay_config_network_allowed_ips;
struct t_config_option *relay_config_network_auth_timeout;
struct t_config_option *relay_config_network_bind_address;
struct t_config_option *relay_config_network_clients_purge_delay;
struct t_config_option *relay_config_network_compression_level;
struct t_config_option *relay_config_network_compression;
struct t_config_option *relay_config_network_ipv6;
struct t_config_option *relay_config_network_max_clients;
struct t_config_option *relay_config_network_nonce_size;
@@ -1070,13 +1070,16 @@ relay_config_init ()
"clients immediately, -1 = never purge)"),
NULL, -1, 60 * 24 * 30, "0", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
relay_config_network_compression_level = weechat_config_new_option (
relay_config_network_compression = weechat_config_new_option (
relay_config_file, ptr_section,
"compression_level", "integer",
N_("compression level for packets sent to client with WeeChat protocol "
"(0 = disable compression, 1 = low compression ... 9 = best "
"compression)"),
NULL, 0, 9, "6", NULL, 0,
"compression", "integer",
N_("compression for packets sent to client with WeeChat "
"protocol: 0 = disable compression, 1 = low compression, fast "
"... 100 = best compression, slow; the value is a percentage "
"converted to 1-9 for zlib and 1-19 for zstd; "
"default value is 20 which is a sane default and offers good "
"compression and speed"),
NULL, 0, 100, "20", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
relay_config_network_ipv6 = weechat_config_new_option (
relay_config_file, ptr_section,
+1 -1
View File
@@ -42,7 +42,7 @@ extern struct t_config_option *relay_config_network_allowed_ips;
extern struct t_config_option *relay_config_network_auth_timeout;
extern struct t_config_option *relay_config_network_bind_address;
extern struct t_config_option *relay_config_network_clients_purge_delay;
extern struct t_config_option *relay_config_network_compression_level;
extern struct t_config_option *relay_config_network_compression;
extern struct t_config_option *relay_config_network_ipv6;
extern struct t_config_option *relay_config_network_max_clients;
extern struct t_config_option *relay_config_network_nonce_size;
+153 -43
View File
@@ -29,6 +29,7 @@
#include <errno.h>
#include <arpa/inet.h>
#include <zlib.h>
#include <zstd.h>
#include "../../weechat-plugin.h"
#include "../relay.h"
@@ -1026,6 +1027,150 @@ relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg,
relay_weechat_msg_set_bytes (msg, pos_count, &count32, 4);
}
/*
* Compresses the message with zlib.
*
* Returns:
* 1: OK, message compressed and sent
* 0: error, no message sent
*/
int
relay_weechat_msg_compress_zlib (struct t_relay_client *client,
struct t_relay_weechat_msg *msg)
{
char raw_message[1024];
uint32_t size32;
Bytef *dest;
uLongf dest_size;
struct timeval tv1, tv2;
long long time_diff;
int rc, rc_compress, compression, compression_level;
rc = 0;
dest = NULL;
dest_size = compressBound (msg->data_size - 5);
dest = malloc (dest_size + 5);
if (!dest)
goto error;
/* convert % to zlib compression level (1-9) */
compression = weechat_config_integer (relay_config_network_compression);
compression_level = (((compression - 1) * 9) / 100) + 1;
gettimeofday (&tv1, NULL);
rc_compress = compress2 (
dest + 5,
&dest_size,
(Bytef *)(msg->data + 5),
msg->data_size - 5,
compression_level);
gettimeofday (&tv2, NULL);
time_diff = weechat_util_timeval_diff (&tv1, &tv2);
if ((rc_compress != Z_OK) || ((int)dest_size + 5 >= msg->data_size))
goto error;
/* set size and compression flag */
size32 = htonl ((uint32_t)(dest_size + 5));
memcpy (dest, &size32, 4);
dest[4] = RELAY_WEECHAT_COMPRESSION_ZLIB;
/* display message in raw buffer */
snprintf (raw_message, sizeof (raw_message),
"obj: %d/%d bytes (zlib: %d%%, %.2fms), id: %s",
(int)dest_size + 5,
msg->data_size,
100 - ((((int)dest_size + 5) * 100) / msg->data_size),
((float)time_diff) / 1000,
msg->id);
/* send compressed data */
relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
(const char *)dest, dest_size + 5,
raw_message);
rc = 1;
error:
if (dest)
free (dest);
return rc;
}
/*
* Compresses the message with zstd.
*
* Returns:
* 1: OK, message compressed and sent
* 0: error, no message sent
*/
int
relay_weechat_msg_compress_zstd (struct t_relay_client *client,
struct t_relay_weechat_msg *msg)
{
char raw_message[1024];
uint32_t size32;
Bytef *dest;
size_t dest_size, comp_size;
struct timeval tv1, tv2;
long long time_diff;
int rc, compression, compression_level;
rc = 0;
dest = NULL;
dest_size = ZSTD_compressBound (msg->data_size - 5);
dest = malloc (dest_size + 5);
if (!dest)
goto error;
/* convert % to zstd compression level (1-19) */
compression = weechat_config_integer (relay_config_network_compression);
compression_level = (((compression - 1) * 19) / 100) + 1;
gettimeofday (&tv1, NULL);
comp_size = ZSTD_compress(
dest + 5,
dest_size,
(void *)(msg->data + 5),
msg->data_size - 5,
compression_level);
gettimeofday (&tv2, NULL);
time_diff = weechat_util_timeval_diff (&tv1, &tv2);
if ((comp_size == 0) || ((int)comp_size + 5 >= msg->data_size))
goto error;
/* set size and compression flag */
size32 = htonl ((uint32_t)(comp_size + 5));
memcpy (dest, &size32, 4);
dest[4] = RELAY_WEECHAT_COMPRESSION_ZSTD;
/* display message in raw buffer */
snprintf (raw_message, sizeof (raw_message),
"obj: %d/%d bytes (zstd: %d%%, %.2fms), id: %s",
(int)comp_size + 5,
msg->data_size,
100 - ((((int)comp_size + 5) * 100) / msg->data_size),
((float)time_diff) / 1000,
msg->id);
/* send compressed data */
relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
(const char *)dest, comp_size + 5,
raw_message);
rc = 1;
error:
if (dest)
free (dest);
return rc;
}
/*
* Sends a message.
*/
@@ -1034,55 +1179,20 @@ void
relay_weechat_msg_send (struct t_relay_client *client,
struct t_relay_weechat_msg *msg)
{
uint32_t size32;
char compression, raw_message[1024];
int rc;
Bytef *dest;
uLongf dest_size;
struct timeval tv1, tv2;
long long time_diff;
uint32_t size32;
if (weechat_config_integer (relay_config_network_compression_level) > 0)
if (weechat_config_integer (relay_config_network_compression) > 0)
{
switch (RELAY_WEECHAT_DATA(client, compression))
{
case RELAY_WEECHAT_COMPRESSION_ZLIB:
dest_size = compressBound (msg->data_size - 5);
dest = malloc (dest_size + 5);
if (dest)
{
gettimeofday (&tv1, NULL);
rc = compress2 (dest + 5, &dest_size,
(Bytef *)(msg->data + 5), msg->data_size - 5,
weechat_config_integer (relay_config_network_compression_level));
gettimeofday (&tv2, NULL);
time_diff = weechat_util_timeval_diff (&tv1, &tv2);
if ((rc == Z_OK) && ((int)dest_size + 5 < msg->data_size))
{
/* set size and compression flag */
size32 = htonl ((uint32_t)(dest_size + 5));
memcpy (dest, &size32, 4);
dest[4] = RELAY_WEECHAT_COMPRESSION_ZLIB;
/* display message in raw buffer */
snprintf (raw_message, sizeof (raw_message),
"obj: %d/%d bytes (%d%%, %.2fms), id: %s",
(int)dest_size + 5,
msg->data_size,
100 - ((((int)dest_size + 5) * 100) / msg->data_size),
((float)time_diff) / 1000,
msg->id);
/* send compressed data */
relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
(const char *)dest, dest_size + 5,
raw_message);
free (dest);
return;
}
free (dest);
}
if (relay_weechat_msg_compress_zlib (client, msg))
return;
break;
case RELAY_WEECHAT_COMPRESSION_ZSTD:
if (relay_weechat_msg_compress_zstd (client, msg))
return;
break;
default:
break;
@@ -229,7 +229,7 @@ relay_weechat_protocol_handshake_reply (struct t_relay_client *client,
RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake)
{
char **options, **auths, *pos;
char **options, **auths, **compressions, *pos;
int i, j, index_hash_algo, hash_algo_found, auth_allowed, compression;
int password_received, plain_text_password;
@@ -292,9 +292,28 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake)
}
else if (strcmp (options[i], "compression") == 0)
{
compression = relay_weechat_compression_search (pos);
if (compression >= 0)
RELAY_WEECHAT_DATA(client, compression) = compression;
compressions = weechat_string_split (
pos,
":",
NULL,
WEECHAT_STRING_SPLIT_STRIP_LEFT
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0,
NULL);
if (compressions)
{
for (j = 0; compressions[j]; j++)
{
compression = relay_weechat_compression_search (compressions[j]);
if (compression >= 0)
{
RELAY_WEECHAT_DATA(client, compression) = compression;
break;
}
}
weechat_string_free_split (compressions);
}
}
}
}
@@ -337,12 +356,9 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake)
* hash is given in hexadecimal
* totp time-based one time password used as secondary
* authentication factor
* compression zlib (default) or off
*
* Message looks like:
* init password=mypass
* init password=mypass,compression=zlib
* init password=mypass,compression=off
* init password_hash=sha256:71c480df93d6ae2f1efad1447c66c9…,totp=123456
* init password_hash=pbkdf2:sha256:414232…:100000:01757d53157c…,totp=123456
*/
@@ -350,7 +366,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake)
RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
{
char **options, *pos, *relay_password, *totp_secret, *info_totp_args, *info_totp;
int i, compression, length, password_received, totp_received;
int i, length, password_received, totp_received;
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
@@ -411,12 +427,6 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
}
}
}
else if (strcmp (options[i], "compression") == 0)
{
compression = relay_weechat_compression_search (pos);
if (compression >= 0)
RELAY_WEECHAT_DATA(client, compression) = compression;
}
}
}
weechat_string_free_split_command (options);
+2 -2
View File
@@ -41,7 +41,7 @@
char *relay_weechat_compression_string[] = /* strings for compression */
{ "off", "zlib" };
{ "off", "zlib", "zstd" };
/*
@@ -173,7 +173,7 @@ relay_weechat_alloc (struct t_relay_client *client)
RELAY_WEECHAT_DATA(client, handshake_done) = 0;
RELAY_WEECHAT_DATA(client, password_ok) = 0;
RELAY_WEECHAT_DATA(client, totp_ok) = 0;
RELAY_WEECHAT_DATA(client, compression) = RELAY_WEECHAT_COMPRESSION_ZLIB;
RELAY_WEECHAT_DATA(client, compression) = RELAY_WEECHAT_COMPRESSION_OFF;
RELAY_WEECHAT_DATA(client, buffers_sync) =
weechat_hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
@@ -34,6 +34,7 @@ enum t_relay_weechat_compression
{
RELAY_WEECHAT_COMPRESSION_OFF = 0, /* no compression of binary objects */
RELAY_WEECHAT_COMPRESSION_ZLIB, /* zlib compression */
RELAY_WEECHAT_COMPRESSION_ZSTD, /* Zstandard compression */
/* number of compressions */
RELAY_WEECHAT_NUM_COMPRESSIONS,
};