get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/69023/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 69023,
    "url": "http://patches.dpdk.org/api/patches/69023/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200421123949.38270-13-ciara.power@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200421123949.38270-13-ciara.power@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200421123949.38270-13-ciara.power@intel.com",
    "date": "2020-04-21T12:39:44",
    "name": "[v3,12/17] telemetry: introduce telemetry backward compatibility",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "232e48baad023b3f71517e3025aeec40c968e68e",
    "submitter": {
        "id": 978,
        "url": "http://patches.dpdk.org/api/people/978/?format=api",
        "name": "Power, Ciara",
        "email": "ciara.power@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200421123949.38270-13-ciara.power@intel.com/mbox/",
    "series": [
        {
            "id": 9543,
            "url": "http://patches.dpdk.org/api/series/9543/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=9543",
            "date": "2020-04-21T12:39:32",
            "name": "update and simplify telemetry library.",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/9543/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/69023/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/69023/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 0723BA0597;\n\tTue, 21 Apr 2020 15:02:31 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 908FC1D61D;\n\tTue, 21 Apr 2020 14:59:55 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by dpdk.org (Postfix) with ESMTP id B38121D61D\n for <dev@dpdk.org>; Tue, 21 Apr 2020 14:59:53 +0200 (CEST)",
            "from fmsmga004.fm.intel.com ([10.253.24.48])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 21 Apr 2020 05:59:53 -0700",
            "from silpixa00399953.ir.intel.com (HELO\n silpixa00399953.ger.corp.intel.com) ([10.237.222.53])\n by fmsmga004.fm.intel.com with ESMTP; 21 Apr 2020 05:59:51 -0700"
        ],
        "IronPort-SDR": [
            "\n FFLOD1DsQ34yp54Xied66CecHkx3vZz3AFUB3TIUq3go00eIvJ7XhluLFvYjSj2aD8txBSLjto\n 3Oh6im3Ia/CQ==",
            "\n JPIbVAQVGr2/SH+WDvGBC0ZO++2hVMJRcsvjjn327JiNQZrpGLq3G1t+BB7nGOAmnH+1OiaJGb\n imYqrru85mxg=="
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.72,410,1580803200\"; d=\"scan'208\";a=\"279629180\"",
        "From": "Ciara Power <ciara.power@intel.com>",
        "To": "dev@dpdk.org,\n\tkevin.laatz@intel.com",
        "Cc": "reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com,\n keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net,\n Ciara Power <ciara.power@intel.com>",
        "Date": "Tue, 21 Apr 2020 13:39:44 +0100",
        "Message-Id": "<20200421123949.38270-13-ciara.power@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200421123949.38270-1-ciara.power@intel.com>",
        "References": "<20200319171907.60891-1-ciara.power@intel.com>\n <20200421123949.38270-1-ciara.power@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 12/17] telemetry: introduce telemetry backward\n\tcompatibility",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "The new telemetry will now open a socket using the old telemetry path,\nto ensure backward compatibility. This is not yet initialised, as it\nwould clash with the existing telemetry, to be removed in a later patch.\nThis means that both old and new telemetry socket interfaces are\nhandled in a common way.\n\nSigned-off-by: Ciara Power <ciara.power@intel.com>\n---\n lib/librte_metrics/rte_metrics_telemetry.c    | 113 +++++++++\n lib/librte_telemetry/Makefile                 |   1 +\n lib/librte_telemetry/meson.build              |   4 +-\n lib/librte_telemetry/rte_telemetry_legacy.h   |  65 +++++\n .../rte_telemetry_version.map                 |   2 +\n lib/librte_telemetry/telemetry.c              |  31 +++\n lib/librte_telemetry/telemetry_legacy.c       | 226 ++++++++++++++++++\n 7 files changed, 440 insertions(+), 2 deletions(-)\n create mode 100644 lib/librte_telemetry/rte_telemetry_legacy.h\n create mode 100644 lib/librte_telemetry/telemetry_legacy.c",
    "diff": "diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c\nindex 31d505551b..49de9d74b5 100644\n--- a/lib/librte_metrics/rte_metrics_telemetry.c\n+++ b/lib/librte_metrics/rte_metrics_telemetry.c\n@@ -8,6 +8,7 @@\n #include <rte_string_fns.h>\n #ifdef RTE_LIBRTE_TELEMETRY\n #include <rte_telemetry_internal.h>\n+#include <rte_telemetry_legacy.h>\n #endif\n \n #include \"rte_metrics.h\"\n@@ -417,6 +418,112 @@ rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data)\n \treturn 0;\n }\n \n+static int\n+rte_metrics_tel_initial_metrics_setup(void)\n+{\n+\tint ret;\n+\trte_metrics_init(rte_socket_id());\n+\n+\tif (!tel_met_data.metrics_register_done) {\n+\t\tret = rte_metrics_tel_reg_all_ethdev(\n+\t\t\t&tel_met_data.metrics_register_done,\n+\t\t\ttel_met_data.reg_index);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+handle_ports_all_stats_values(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tstruct telemetry_encode_param ep;\n+\tint ret, used = 0;\n+\tchar *json_buffer = NULL;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tmemset(&ep, 0, sizeof(ep));\n+\tret = rte_metrics_tel_get_port_stats_ids(&ep);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = rte_metrics_tel_get_ports_stats_json(&ep, tel_met_data.reg_index,\n+\t\t\t&json_buffer);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n+static int\n+handle_global_stats_values(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tchar *json_buffer = NULL;\n+\tstruct telemetry_encode_param ep = { .type = GLOBAL_STATS };\n+\tint ret, used = 0;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = rte_metrics_tel_encode_json_format(&ep, &json_buffer);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"JSON encode function failed\");\n+\t\treturn ret;\n+\t}\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n+static int\n+handle_ports_stats_values_by_name(const char *cmd __rte_unused,\n+\t\tconst char *params,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tchar *json_buffer = NULL;\n+\tstruct telemetry_encode_param ep;\n+\tint ret, used = 0;\n+\tjson_t *data;\n+\tjson_error_t error;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tdata = json_loads(params, 0, &error);\n+\tif (!data) {\n+\t\tMETRICS_LOG_WARN(\"Could not load JSON object from data passed in : %s\",\n+\t\t\t\terror.text);\n+\t\treturn -EPERM;\n+\t} else if (!json_is_object(data)) {\n+\t\tMETRICS_LOG_WARN(\"JSON Request data is not a JSON object\");\n+\t\tjson_decref(data);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = rte_metrics_tel_extract_data(&ep, data);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"Extract data function failed\");\n+\t\treturn ret;\n+\t}\n+\n+\tret = rte_metrics_tel_encode_json_format(&ep, &json_buffer);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"JSON encode function failed\");\n+\t\treturn ret;\n+\t}\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n RTE_INIT(metrics_ctor)\n {\n #ifdef RTE_LIBRTE_TELEMETRY\n@@ -428,6 +535,12 @@ RTE_INIT(metrics_ctor)\n \t\t.extract_data = rte_metrics_tel_extract_data\n \t};\n \trte_telemetry_set_metrics_fns(&fns); /* assign them to telemetry lib */\n+\trte_telemetry_legacy_register(\"ports_all_stat_values\", DATA_NOT_REQ,\n+\t\t\thandle_ports_all_stats_values);\n+\trte_telemetry_legacy_register(\"global_stat_values\", DATA_NOT_REQ,\n+\t\t\thandle_global_stats_values);\n+\trte_telemetry_legacy_register(\"ports_stats_values_by_name\", DATA_REQ,\n+\t\t\thandle_ports_stats_values_by_name);\n #endif\n \tmetrics_log_level = rte_log_register(\"lib.metrics\");\n \tif (metrics_log_level >= 0)\ndiff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile\nindex dbf16f4bec..6080257c40 100644\n--- a/lib/librte_telemetry/Makefile\n+++ b/lib/librte_telemetry/Makefile\n@@ -24,6 +24,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) := rte_telemetry.c\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser.c\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser_test.c\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c\n+SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry_legacy.c\n \n # export include files\n SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h\ndiff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build\nindex c8e2fdd0b2..5558e7d5c8 100644\n--- a/lib/librte_telemetry/meson.build\n+++ b/lib/librte_telemetry/meson.build\n@@ -3,8 +3,8 @@\n \n includes = [global_inc]\n \n-sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',\n-\t'telemetry.c')\n+sources = files('rte_telemetry.c','rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',\n+\t'telemetry.c', 'telemetry_legacy.c')\n headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h', 'rte_telemetry_json.h')\n includes += include_directories('../librte_metrics')\n \ndiff --git a/lib/librte_telemetry/rte_telemetry_legacy.h b/lib/librte_telemetry/rte_telemetry_legacy.h\nnew file mode 100644\nindex 0000000000..8ffd893aaf\n--- /dev/null\n+++ b/lib/librte_telemetry/rte_telemetry_legacy.h\n@@ -0,0 +1,65 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _RTE_TELEMETRY_LEGACY_H_\n+#define _RTE_TELEMETRY_LEGACY_H_\n+\n+#include <rte_compat.h>\n+#include \"rte_telemetry.h\"\n+\n+/**\n+ * @internal\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+\n+ * @file\n+ * RTE Telemetry Legacy\n+ *\n+ ***/\n+\n+/**\n+ * @internal\n+ * Value representing if data is required for the command\n+ */\n+enum rte_telemetry_legacy_data_req {\n+\tDATA_NOT_REQ = 0,\n+\tDATA_REQ\n+};\n+\n+/**\n+ * @internal\n+ * Counter for the number of registered legacy callbacks\n+ */\n+extern int num_legacy_callbacks;\n+\n+/**\n+ * @internal\n+ * Used for handling data received over the legacy telemetry socket.\n+ *\n+ * @return\n+ * Void.\n+ */\n+void *\n+legacy_client_handler(void *sock_id);\n+\n+/**\n+ * @internal\n+ *\n+ * Used when registering a command and callback function with\n+ * telemetry legacy support.\n+ *\n+ * @return\n+ *  0 on success.\n+ * @return\n+ *  -EINVAL for invalid parameters failure.\n+ *  @return\n+ *  -ENOENT if max callbacks limit has been reached.\n+ */\n+__rte_experimental\n+int\n+rte_telemetry_legacy_register(const char *cmd,\n+\t\tenum rte_telemetry_legacy_data_req data_req,\n+\t\ttelemetry_cb fn);\n+\n+#endif\ndiff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map\nindex 831bbd59ad..2db0a5a443 100644\n--- a/lib/librte_telemetry/rte_telemetry_version.map\n+++ b/lib/librte_telemetry/rte_telemetry_version.map\n@@ -8,6 +8,8 @@ EXPERIMENTAL {\n \trte_telemetry_set_metrics_fns;\n \trte_telemetry_new_init;\n \trte_telemetry_register_cmd;\n+\trte_telemetry_legacy_init;\n+\trte_telemetry_legacy_register;\n \n \tlocal: *;\n };\ndiff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c\nindex ed450df501..ad305cc8d4 100644\n--- a/lib/librte_telemetry/telemetry.c\n+++ b/lib/librte_telemetry/telemetry.c\n@@ -16,6 +16,7 @@\n #include <rte_version.h>\n \n #include \"rte_telemetry.h\"\n+#include \"rte_telemetry_legacy.h\"\n \n #define MAX_CMD_LEN 56\n #define MAX_OUTPUT_LEN (1024 * 16)\n@@ -42,6 +43,7 @@ struct socket {\n \thandler fn;\n };\n static struct socket v2_socket; /* socket for v2 telemetry */\n+static struct socket v1_socket; /* socket for v1 telemetry */\n static char telemetry_log_error[1024]; /* Will contain error on init failure */\n /* list of command callbacks, with one command registered by default */\n static struct cmd_callback callbacks[TELEMETRY_MAX_CALLBACKS];\n@@ -202,6 +204,8 @@ unlink_sockets(void)\n {\n \tif (v2_socket.path[0])\n \t\tunlink(v2_socket.path);\n+\tif (v1_socket.path[0])\n+\t\tunlink(v1_socket.path);\n }\n \n static int\n@@ -241,6 +245,33 @@ create_socket(char *path)\n \treturn -1;\n }\n \n+static int __rte_unused /* will be used in future commit */\n+telemetry_legacy_init(const char *runtime_dir)\n+{\n+\tpthread_t t_old;\n+\n+\tif (num_legacy_callbacks == 1) {\n+\t\tsnprintf(telemetry_log_error, sizeof(telemetry_log_error),\n+\t\t\t \"No legacy callbacks, legacy socket not created\");\n+\t\treturn -1;\n+\t}\n+\n+\tv1_socket.fn = legacy_client_handler;\n+\tif ((size_t) snprintf(v1_socket.path, sizeof(v1_socket.path),\n+\t\t\t\"%s/telemetry\", runtime_dir)\n+\t\t\t>= sizeof(v1_socket.path)) {\n+\t\tsnprintf(telemetry_log_error, sizeof(telemetry_log_error),\n+\t\t\t\t\"Error with socket binding, path too long\");\n+\t\treturn -1;\n+\t}\n+\tv1_socket.sock = create_socket(v1_socket.path);\n+\tif (v1_socket.sock < 0)\n+\t\treturn -1;\n+\tpthread_create(&t_old, NULL, socket_listener, &v1_socket);\n+\n+\treturn 0;\n+}\n+\n static int\n telemetry_v2_init(const char *runtime_dir)\n {\ndiff --git a/lib/librte_telemetry/telemetry_legacy.c b/lib/librte_telemetry/telemetry_legacy.c\nnew file mode 100644\nindex 0000000000..e7c01525b4\n--- /dev/null\n+++ b/lib/librte_telemetry/telemetry_legacy.c\n@@ -0,0 +1,226 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <unistd.h>\n+#include <sys/socket.h>\n+#include <sys/un.h>\n+#include <pthread.h>\n+\n+/* we won't link against libbsd, so just always use DPDKs-specific strlcpy */\n+#undef RTE_USE_LIBBSD\n+#include <rte_string_fns.h>\n+#include <rte_common.h>\n+#include <rte_spinlock.h>\n+\n+#include \"rte_telemetry_legacy.h\"\n+\n+#define MAX_LEN 128\n+#define BUF_SIZE 1024\n+#define CLIENTS_UNREG_ACTION \"\\\"action\\\":2\"\n+#define CLIENTS_CMD \"\\\"command\\\":\\\"clients\\\"\"\n+#define CLIENTS_DATA \"\\\"data\\\":{\\\"client_path\\\":\\\"\"\n+#define STATS_ACTION \"\\\"action\\\":0\"\n+#define DATA_REQ_LABEL \"\\\"data\\\":\"\n+#define TELEMETRY_LEGACY_MAX_CALLBACKS 4\n+\n+\n+static int\n+register_client(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len);\n+\n+struct json_command {\n+\tchar action[MAX_LEN];\n+\tchar cmd[MAX_LEN];\n+\tchar data[MAX_LEN];\n+\ttelemetry_cb fn;\n+\n+};\n+\n+struct json_command callbacks[TELEMETRY_LEGACY_MAX_CALLBACKS] = {\n+\t\t{\n+\t\t\t.action = \"\\\"action\\\":1\",\n+\t\t\t.cmd = CLIENTS_CMD,\n+\t\t\t.data = CLIENTS_DATA,\n+\t\t\t.fn = register_client\n+\t\t}\n+};\n+int num_legacy_callbacks = 1;\n+static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER;\n+\n+int\n+rte_telemetry_legacy_register(const char *cmd, enum\n+\t\trte_telemetry_legacy_data_req data_req, telemetry_cb fn)\n+{\n+\tif (fn == NULL)\n+\t\treturn -EINVAL;\n+\tif (num_legacy_callbacks >= (int) RTE_DIM(callbacks))\n+\t\treturn -ENOENT;\n+\n+\trte_spinlock_lock(&callback_sl);\n+\tstrlcpy(callbacks[num_legacy_callbacks].action, STATS_ACTION, MAX_LEN);\n+\tsnprintf(callbacks[num_legacy_callbacks].cmd, MAX_LEN,\n+\t\t\t\"\\\"command\\\":\\\"%s\\\"\", cmd);\n+\tsnprintf(callbacks[num_legacy_callbacks].data, MAX_LEN,\n+\t\t\tdata_req ? \"%s{\\\"\" : \"%snull\",\n+\t\t\tDATA_REQ_LABEL);\n+\tcallbacks[num_legacy_callbacks].fn = fn;\n+\tnum_legacy_callbacks++;\n+\trte_spinlock_unlock(&callback_sl);\n+\n+\treturn 0;\n+}\n+\n+static int\n+register_client(const char *cmd __rte_unused, const char *params,\n+\t\tchar *buffer __rte_unused, int buf_len __rte_unused)\n+{\n+\tpthread_t th;\n+\tchar data[BUF_SIZE];\n+\tint fd;\n+\tstruct sockaddr_un addrs;\n+\n+\tstrlcpy(data, strchr(params, ':'), sizeof(data));\n+\tmemcpy(data, &data[strlen(\":\\\"\")], strlen(data));\n+\t*strchr(data, '\\\"') = 0;\n+\n+\tfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\taddrs.sun_family = AF_UNIX;\n+\tstrlcpy(addrs.sun_path, data, sizeof(addrs.sun_path));\n+\n+\tif (connect(fd, (struct sockaddr *)&addrs, sizeof(addrs)) == -1) {\n+\t\tperror(\"\\nClient connection error\\n\");\n+\t\treturn -1;\n+\t}\n+\tpthread_create(&th, NULL, &legacy_client_handler,\n+\t\t\t(void *)(uintptr_t)fd);\n+\treturn 0;\n+}\n+\n+static int\n+send_error_response(int s, int err)\n+{\n+\tconst char *desc;\n+\tchar out_buf[100000];\n+\n+\tswitch (err) {\n+\tcase -ENOMEM:\n+\t\tdesc = \"Memory Allocation Error\";\n+\t\tbreak;\n+\tcase -EINVAL:\n+\t\tdesc = \"Invalid Argument 404\";\n+\t\tbreak;\n+\tcase -EPERM:\n+\t\tdesc = \"Unknown\";\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Default case keeps behaviour of Telemetry library */\n+\t\tprintf(\"\\nInvalid error type: %d\\n\", err);\n+\t\treturn -EINVAL;\n+\t}\n+\tint used = snprintf(out_buf, sizeof(out_buf), \"{\\\"status_code\\\": \"\n+\t\t\t\"\\\"Status Error: %s\\\", \\\"data\\\": null}\", desc);\n+\tif (write(s, out_buf, used) < 0) {\n+\t\tperror(\"Error writing to socket\");\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static void\n+perform_command(telemetry_cb fn, const char *param, int s)\n+{\n+\tchar out_buf[100000];\n+\tint ret, used = 0;\n+\n+\tret = fn(\"\", param, out_buf, sizeof(out_buf));\n+\tif (ret < 0) {\n+\t\tret = send_error_response(s, ret);\n+\t\tif (ret < 0)\n+\t\t\tprintf(\"\\nCould not send error response\\n\");\n+\t\treturn;\n+\t}\n+\tused += ret;\n+\tif (write(s, out_buf, used) < 0)\n+\t\tperror(\"Error writing to socket\");\n+}\n+\n+static int\n+parse_client_request(char *buffer, int buf_len, int s)\n+{\n+\tint i;\n+\tchar *data = buffer + buf_len;\n+\ttelemetry_cb fn = NULL;\n+\tconst char *valid_sep = \",}\";\n+\tif (buffer[0] != '{' || buffer[buf_len - 1] != '}')\n+\t\treturn -EPERM;\n+\n+\tif (strstr(buffer, CLIENTS_UNREG_ACTION) && strstr(buffer, CLIENTS_CMD)\n+\t\t\t&& strstr(buffer, CLIENTS_DATA))\n+\t\treturn 0;\n+\n+\tfor (i = 0; i < num_legacy_callbacks; i++) {\n+\t\tchar *action_ptr = strstr(buffer, callbacks[i].action);\n+\t\tchar *cmd_ptr = strstr(buffer, callbacks[i].cmd);\n+\t\tchar *data_ptr = strstr(buffer, callbacks[i].data);\n+\t\tif (!action_ptr || !cmd_ptr || !data_ptr)\n+\t\t\tcontinue;\n+\n+\t\tchar action_sep = action_ptr[strlen(callbacks[i].action)];\n+\t\tchar cmd_sep = cmd_ptr[strlen(callbacks[i].cmd)];\n+\t\tif (!(strchr(valid_sep, action_sep) && strchr(valid_sep,\n+\t\t\t\tcmd_sep)))\n+\t\t\treturn -EPERM;\n+\t\tchar data_sep;\n+\n+\t\tif (!strchr(data_ptr, '{'))\n+\t\t\tdata_sep = data_ptr[strlen(callbacks[i].data)];\n+\t\telse {\n+\t\t\tchar *data_end = strchr(data_ptr, '}');\n+\t\t\tdata = data_ptr + strlen(DATA_REQ_LABEL);\n+\t\t\tdata_sep = data_end[1];\n+\t\t\tdata_end[1] = 0;\n+\t\t}\n+\t\tif (!strchr(valid_sep, data_sep))\n+\t\t\treturn -EPERM;\n+\t\tfn = callbacks[i].fn;\n+\t\tbreak;\n+\t}\n+\n+\tif (!fn)\n+\t\treturn -EINVAL;\n+\tperform_command(fn, data, s);\n+\treturn 0;\n+}\n+\n+void *\n+legacy_client_handler(void *sock_id)\n+{\n+\tint s = (int)(uintptr_t)sock_id;\n+\tint ret;\n+\tchar buffer_recv[BUF_SIZE];\n+\t/* receive data is not null terminated */\n+\tint bytes = read(s, buffer_recv, sizeof(buffer_recv));\n+\tbuffer_recv[bytes] = 0;\n+\n+\twhile (bytes > 0) {\n+\t\tint i, j;\n+\t\tchar buffer[BUF_SIZE];\n+\t\tfor (i = 0, j = 0; buffer_recv[i] != '\\0'; i++) {\n+\t\t\tbuffer[j] = buffer_recv[i];\n+\t\t\tj += !isspace(buffer_recv[i]);\n+\t\t}\n+\t\tbuffer[j] = 0;\n+\t\tret = parse_client_request(buffer, j, s);\n+\t\tif (ret < 0) {\n+\t\t\tret = send_error_response(s, ret);\n+\t\t\tif (ret < 0)\n+\t\t\t\tprintf(\"\\nCould not send error response\\n\");\n+\t\t}\n+\t\tbytes = read(s, buffer_recv, sizeof(buffer_recv));\n+\t\tbuffer_recv[bytes] = 0;\n+\t}\n+\tclose(s);\n+\treturn NULL;\n+}\n",
    "prefixes": [
        "v3",
        "12/17"
    ]
}