Skip to content

Commit c188d75

Browse files
committed
iiod-client: Add support for ZSTD-compressed metadata
If compiled WITH_ZSTD, use the ZPRINT command to receive a ZSTD-compressed payload that can be decompressed into the original XML string of the remote context. If the remote IIOD does not support ZPRINT, it will simply revert to using PRINT instead. This can dramatically speed up context creation when using a slow transport (e.g. serial), as the XML strings can be really big. For instance, the XML string of the ADALM-Pluto is close to 25 KiB. On a standard 57600 bps UART connection, this would take about ~3.4 seconds to transfer. The compressed payload amounts to only about 3.7 KiB, which would take about ~0.5 seconds to transfer. Signed-off-by: Paul Cercueil <[email protected]>
1 parent fbc2f1a commit c188d75

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

iiod-client.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88

99
#include "debug.h"
1010
#include "iiod-client.h"
11+
#include "iio-config.h"
1112
#include "iio-lock.h"
1213
#include "iio-private.h"
1314

1415
#include <errno.h>
1516
#include <inttypes.h>
1617
#include <string.h>
1718
#include <stdio.h>
19+
#if WITH_ZSTD
20+
#include <zstd.h>
21+
#endif
1822

1923
struct iiod_client {
2024
struct iio_context_pdata *pdata;
@@ -504,18 +508,29 @@ ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc,
504508
return ret;
505509
}
506510

507-
struct iio_context * iiod_client_create_context(
508-
struct iiod_client *client, void *desc)
511+
static struct iio_context *
512+
iiod_client_create_context_private(struct iiod_client *client,
513+
void *desc, bool zstd)
509514
{
515+
const char *cmd = zstd ? "ZPRINT\r\n" : "PRINT\r\n";
510516
struct iio_context *ctx = NULL;
511517
size_t xml_len;
512518
char *xml;
513519
int ret;
514520

515521
iio_mutex_lock(client->lock);
516-
ret = iiod_client_exec_command(client, desc, "PRINT\r\n");
517-
if (ret < 0)
522+
ret = iiod_client_exec_command(client, desc, cmd);
523+
if (ret < 0) {
524+
if (ret == -EINVAL && zstd) {
525+
/* If the ZPRINT command does not exist, try again
526+
* with the regular PRINT command. */
527+
iio_mutex_unlock(client->lock);
528+
529+
return iiod_client_create_context_private(client, desc, false);
530+
}
531+
518532
goto out_unlock;
533+
}
519534

520535
xml_len = (size_t) ret;
521536
xml = malloc(xml_len + 1);
@@ -529,6 +544,41 @@ struct iio_context * iiod_client_create_context(
529544
if (ret < 0)
530545
goto out_free_xml;
531546

547+
#if WITH_ZSTD
548+
if (zstd) {
549+
unsigned long long len;
550+
char *xml_zstd;
551+
552+
IIO_DEBUG("Received ZSTD-compressed XML string.\n");
553+
554+
len = ZSTD_getFrameContentSize(xml, xml_len);
555+
if (len == ZSTD_CONTENTSIZE_UNKNOWN ||
556+
len == ZSTD_CONTENTSIZE_ERROR) {
557+
ret = -EIO;
558+
goto out_free_xml;
559+
}
560+
561+
xml_zstd = malloc(len);
562+
if (!xml_zstd) {
563+
ret = -ENOMEM;
564+
goto out_free_xml;
565+
}
566+
567+
xml_len = ZSTD_decompress(xml_zstd, len, xml, xml_len);
568+
if (ZSTD_isError(xml_len)) {
569+
IIO_ERROR("Unable to decompress ZSTD data: %s\n",
570+
ZSTD_getErrorName(xml_len));
571+
ret = -EIO;
572+
free(xml_zstd);
573+
goto out_free_xml;
574+
}
575+
576+
/* Free compressed data, make "xml" point to uncompressed data */
577+
free(xml);
578+
xml = xml_zstd;
579+
}
580+
#endif
581+
532582
ctx = iio_create_xml_context_mem(xml, xml_len);
533583
if (!ctx)
534584
ret = -errno;
@@ -542,6 +592,11 @@ struct iio_context * iiod_client_create_context(
542592
return ctx;
543593
}
544594

595+
struct iio_context * iiod_client_create_context(struct iiod_client *client, void *desc)
596+
{
597+
return iiod_client_create_context_private(client, desc, WITH_ZSTD);
598+
}
599+
545600
int iiod_client_open_unlocked(struct iiod_client *client, void *desc,
546601
const struct iio_device *dev, size_t samples_count, bool cyclic)
547602
{

0 commit comments

Comments
 (0)