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:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user