Basic serialization/deserialization for lttng_session
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Wed, 20 Apr 2022 21:03:52 +0000 (17:03 -0400)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 19 Aug 2022 14:30:22 +0000 (10:30 -0400)
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Change-Id: I38ec05059ade8ad2400c9e5a871928a4da96c52f

include/lttng/session-internal.hpp
src/bin/lttng-sessiond/client.cpp
src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/cmd.hpp
src/common/Makefile.am
src/common/session.cpp [new file with mode: 0644]
src/lib/lttng-ctl/lttng-ctl.cpp

index 7f73b9610dd3adf3c54539e90172f65a19e0bae5..b56ab214cb268c5042545b02512633d5baa49711 100644 (file)
@@ -8,14 +8,43 @@
 #ifndef LTTNG_SESSION_INTERNAL_H
 #define LTTNG_SESSION_INTERNAL_H
 
-#include <lttng/constant.h>
+#include <common/buffer-view.hpp>
 #include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/constant.h>
+#include <lttng/lttng-error.h>
+
+struct lttng_session;
+struct lttng_payload_view;
 
 struct lttng_session_extended {
-       struct {
-               uint64_t value;
-               uint8_t is_set;
-       } LTTNG_PACKED creation_time;
+       LTTNG_OPTIONAL(uint64_t) creation_time;
+};
+
+struct lttng_session_comm {
+       uint32_t name_len;
+       uint32_t path_len;
+       uint8_t enabled;
+       uint32_t snapshot_mode;
+       uint32_t live_timer_interval;
+       /* lttng_session_extended data */
+       LTTNG_OPTIONAL(uint64_t) LTTNG_PACKED creation_time;
+       /*
+        * Dynamic payload:
+        *   - name[name_len]
+        *   - path[path_len]
+        */
+       char payload[];
 } LTTNG_PACKED;
 
+int lttng_session_serialize(const struct lttng_session *session, struct lttng_payload *payload);
+
+ssize_t lttng_session_create_from_payload(
+               struct lttng_payload_view *view, struct lttng_session **out_session);
+
+enum lttng_error_code lttng_sessions_create_and_flatten_from_payload(
+               struct lttng_payload_view *view,
+               unsigned int count,
+               struct lttng_session **sessions);
+
 #endif /* LTTNG_SESSION_INTERNAL_H */
index 1f94bdad8954f94a7aa06c1576dec4668b6141e0..aafbd919ce07e73d0b071cac3ec3327996498201 100644 (file)
@@ -582,33 +582,6 @@ error_create:
        return ret;
 }
 
-/*
- * Count number of session permitted by uid/gid.
- */
-static unsigned int lttng_sessions_count(uid_t uid,
-               gid_t gid __attribute__((unused)))
-{
-       unsigned int i = 0;
-       struct ltt_session *session;
-       const struct ltt_session_list *session_list = session_get_list();
-
-       DBG("Counting number of available session for UID %d", uid);
-       cds_list_for_each_entry(session, &session_list->head, list) {
-               if (!session_get(session)) {
-                       continue;
-               }
-               session_lock(session);
-               /* Only count the sessions the user can control. */
-               if (session_access_ok(session, uid) &&
-                               !session->destroyed) {
-                       i++;
-               }
-               session_unlock(session);
-               session_put(session);
-       }
-       return i;
-}
-
 static enum lttng_error_code receive_lttng_trigger(struct command_ctx *cmd_ctx,
                int sock,
                int *sock_error,
@@ -1893,42 +1866,33 @@ skip_domain:
        }
        case LTTNG_LIST_SESSIONS:
        {
-               unsigned int nr_sessions;
-               lttng_session *sessions_payload = nullptr;
-               size_t payload_len = 0;
+               enum lttng_error_code ret_code;
+               size_t original_payload_size;
+               size_t payload_size;
+               const size_t command_header_size = sizeof(struct lttcomm_list_command_header);
+
+               ret = setup_empty_lttng_msg(cmd_ctx);
+               if (ret) {
+                       ret = LTTNG_ERR_NOMEM;
+                       goto setup_error;
+               }
+
+               original_payload_size = cmd_ctx->reply_payload.buffer.size;
 
                session_lock_list();
-               nr_sessions = lttng_sessions_count(
+               ret_code = cmd_list_lttng_sessions(&cmd_ctx->reply_payload,
                                LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
                                LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds));
-
-               if (nr_sessions > 0) {
-                       payload_len = (sizeof(struct lttng_session) *
-                                                     nr_sessions) +
-                                       (sizeof(struct lttng_session_extended) *
-                                                       nr_sessions);
-                       sessions_payload = zmalloc<lttng_session>(payload_len);
-                       if (!sessions_payload) {
-                               session_unlock_list();
-                               ret = -ENOMEM;
-                               goto setup_error;
-                       }
-
-                       cmd_list_lttng_sessions(sessions_payload, nr_sessions,
-                                       LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
-                                       LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds));
-               }
-
                session_unlock_list();
-
-               ret = setup_lttng_msg_no_cmd_header(
-                               cmd_ctx, sessions_payload, payload_len);
-               free(sessions_payload);
-
-               if (ret < 0) {
-                       goto setup_error;
+               if (ret_code != LTTNG_OK) {
+                       ret = (int) ret_code;
+                       goto error;
                }
 
+               payload_size = cmd_ctx->reply_payload.buffer.size - command_header_size -
+                               original_payload_size;
+               update_lttng_msg(cmd_ctx, command_header_size, payload_size);
+
                ret = LTTNG_OK;
                break;
        }
index 0b74920556d59230a5bf2a87adcef42590dd1627..0db41e127367c75a9924c96730b3ada86b7a8cca 100644 (file)
@@ -3946,23 +3946,38 @@ end:
  * The session list lock MUST be acquired before calling this function. Use
  * session_lock_list() and session_unlock_list().
  */
-void cmd_list_lttng_sessions(struct lttng_session *sessions,
-               size_t session_count, uid_t uid, gid_t gid)
+enum lttng_error_code cmd_list_lttng_sessions(
+               struct lttng_payload *reply_payload, uid_t uid, gid_t gid)
 {
-       int ret;
-       unsigned int i = 0;
+       int buffer_resize_ret;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       struct lttcomm_list_command_header reply_command_header = {};
+       size_t reply_command_header_offset;
        struct ltt_session *session;
        struct ltt_session_list *list = session_get_list();
-       struct lttng_session_extended *extended =
-                       (typeof(extended)) (&sessions[session_count]);
+       int ret;
+       unsigned int i = 0;
+
+       assert(reply_payload);
+
+       /* Reserve space for command reply header. */
+       reply_command_header_offset = reply_payload->buffer.size;
+       buffer_resize_ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer,
+                       reply_command_header_offset + sizeof(struct lttcomm_list_command_header));
+       if (buffer_resize_ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto error;
+       }
 
        DBG("Getting all available session for UID %d GID %d",
                        uid, gid);
-       /*
-        * Iterate over session list and append data after the control struct in
-        * the buffer.
-        */
+
        cds_list_for_each_entry(session, &list->head, list) {
+               struct lttng_session tmp_session = {};
+               struct lttng_session_extended tmp_extended = {};
+
+               tmp_session.extended.ptr = &tmp_extended;
+
                if (!session_get(session)) {
                        continue;
                }
@@ -3981,10 +3996,10 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions,
                if (session->consumer->type == CONSUMER_DST_NET ||
                                (ksess && ksess->consumer->type == CONSUMER_DST_NET) ||
                                (usess && usess->consumer->type == CONSUMER_DST_NET)) {
-                       ret = build_network_session_path(sessions[i].path,
-                                       sizeof(sessions[i].path), session);
+                       ret = build_network_session_path(
+                                       tmp_session.path, sizeof(tmp_session.path), session);
                } else {
-                       ret = snprintf(sessions[i].path, sizeof(sessions[i].path), "%s",
+                       ret = snprintf(tmp_session.path, sizeof(tmp_session.path), "%s",
                                        session->consumer->dst.session_root_path);
                }
                if (ret < 0) {
@@ -3993,16 +4008,33 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions,
                        continue;
                }
 
-               strncpy(sessions[i].name, session->name, NAME_MAX);
-               sessions[i].name[NAME_MAX - 1] = '\0';
-               sessions[i].enabled = session->active;
-               sessions[i].snapshot_mode = session->snapshot_mode;
-               sessions[i].live_timer_interval = session->live_timer;
-               extended[i].creation_time.value = (uint64_t) session->creation_time;
-               extended[i].creation_time.is_set = 1;
+               strncpy(tmp_session.name, session->name, NAME_MAX);
+               tmp_session.name[NAME_MAX - 1] = '\0';
+               tmp_session.enabled = session->active;
+               tmp_session.snapshot_mode = session->snapshot_mode;
+               tmp_session.live_timer_interval = session->live_timer;
+               LTTNG_OPTIONAL_SET(&tmp_extended.creation_time, (uint64_t) session->creation_time);
+               ret = lttng_session_serialize(&tmp_session, reply_payload);
+               if (ret) {
+                       ret_code = LTTNG_ERR_FATAL;
+                       goto error;
+               }
                i++;
                session_put(session);
        }
+
+       if (i > UINT32_MAX) {
+               ret_code = LTTNG_ERR_OVERFLOW;
+               goto error;
+       }
+
+       /* Update command reply header. */
+       reply_command_header.count = (uint32_t) i;
+       memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header,
+                       sizeof(reply_command_header));
+       ret_code = LTTNG_OK;
+error:
+       return ret_code;
 }
 
 /*
index 8727e741bca66a715237ed5e275c0000fc0d1a01..4dd877be7a3d3cc1a958c75eb1110d86073bb506 100644 (file)
@@ -117,8 +117,7 @@ enum lttng_error_code cmd_list_events(enum lttng_domain_type domain,
 enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain,
                struct ltt_session *session,
                struct lttng_payload *payload);
-void cmd_list_lttng_sessions(struct lttng_session *sessions,
-               size_t session_count, uid_t uid, gid_t gid);
+enum lttng_error_code cmd_list_lttng_sessions(struct lttng_payload *payload, uid_t uid, gid_t gid);
 enum lttng_error_code cmd_list_tracepoint_fields(enum lttng_domain_type domain,
                struct lttng_payload *reply);
 enum lttng_error_code cmd_list_tracepoints(enum lttng_domain_type domain,
index 66ab77d05d9cf825c61feb7c8edb49d77f85a6e1..a7d43b39c2ad36e63260ff18105784a373ee6b64 100644 (file)
@@ -99,6 +99,7 @@ libcommon_lgpl_la_SOURCES = \
        pthread-lock.hpp \
        readwrite.cpp readwrite.hpp \
        runas.cpp runas.hpp \
+       session.cpp \
        session-descriptor.cpp \
        snapshot.cpp snapshot.hpp \
        spawn-viewer.cpp spawn-viewer.hpp \
diff --git a/src/common/session.cpp b/src/common/session.cpp
new file mode 100644 (file)
index 0000000..0af62f7
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2022 Jonathan Rajotte<jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/uri.hpp>
+#include <lttng/session-internal.hpp>
+#include <lttng/session.h>
+#include <memory>
+#include <stdio.h>
+#include <time.h>
+
+struct session_list_element {
+       struct lttng_session *session;
+};
+
+static void session_list_destructor(void *ptr)
+{
+       struct session_list_element *element = (struct session_list_element *) ptr;
+
+       free(element->session);
+       free(element);
+}
+
+int lttng_session_serialize(const struct lttng_session *session, lttng_payload *payload)
+{
+       int ret;
+       size_t name_len, path_len;
+       struct lttng_session_comm session_comm = {};
+       struct lttng_session_extended *extended = (typeof(extended)) session->extended.ptr;
+
+       LTTNG_ASSERT(extended != nullptr);
+
+       name_len = lttng_strnlen(session->name, sizeof(session->name));
+       if (name_len == sizeof(session->name)) {
+               /* Session name is not NULL-terminated. */
+               ret = -1;
+               goto end;
+       }
+
+       /* Add null termination. */
+       name_len += 1;
+
+       path_len = lttng_strnlen(session->path, sizeof(session->path));
+       if (path_len == sizeof(session->path)) {
+               /* Session path is not NULL-terminated. */
+               ret = -1;
+               goto end;
+       }
+
+       /* Add null termination. */
+       path_len += 1;
+
+       session_comm.name_len = (uint32_t) name_len;
+       session_comm.path_len = (uint32_t) path_len;
+       session_comm.enabled = (uint8_t) session->enabled;
+       session_comm.snapshot_mode = session->snapshot_mode;
+       session_comm.live_timer_interval = session->live_timer_interval;
+       if (extended->creation_time.is_set) {
+               LTTNG_OPTIONAL_SET(&session_comm.creation_time,
+                               LTTNG_OPTIONAL_GET(extended->creation_time));
+       } else {
+               LTTNG_OPTIONAL_UNSET(&session_comm.creation_time);
+       }
+
+       /* Header */
+       ret = lttng_dynamic_buffer_append(&payload->buffer, &session_comm, sizeof(session_comm));
+       if (ret) {
+               goto end;
+       }
+
+       /* Session name */
+       ret = lttng_dynamic_buffer_append(&payload->buffer, session->name, name_len);
+       if (ret) {
+               goto end;
+       }
+
+       /* Session path */
+       ret = lttng_dynamic_buffer_append(&payload->buffer, session->path, path_len);
+       if (ret) {
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+ssize_t lttng_session_create_from_payload(
+               struct lttng_payload_view *view, struct lttng_session **out_session)
+{
+       ssize_t ret, offset = 0;
+       struct lttng_session *local_session = nullptr;
+       struct lttng_session_extended *local_extended = nullptr;
+       const struct lttng_session_comm *session_comm;
+
+       LTTNG_ASSERT(out_session);
+       LTTNG_ASSERT(view);
+
+       {
+               struct lttng_payload_view comm_view =
+                               lttng_payload_view_from_view(view, offset, sizeof(*session_comm));
+
+               if (!lttng_payload_view_is_valid(&comm_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               /* lttng_session_comm header */
+               session_comm = (typeof(session_comm)) comm_view.buffer.data;
+               offset += sizeof(*session_comm);
+       }
+
+       local_session = zmalloc<struct lttng_session>(
+                       sizeof(struct lttng_session) + sizeof(struct lttng_session_extended));
+       if (local_session == nullptr) {
+               ret = -1;
+               goto end;
+       }
+
+       local_extended = (struct lttng_session_extended *) ((char *) local_session +
+                       sizeof(lttng_session));
+       if (local_extended == nullptr) {
+               ret = -1;
+               goto end;
+       }
+
+       local_session->extended.ptr = local_extended;
+
+       local_session->enabled = session_comm->enabled;
+       local_session->live_timer_interval = session_comm->live_timer_interval;
+       local_session->snapshot_mode = session_comm->snapshot_mode;
+       if (session_comm->creation_time.is_set) {
+               LTTNG_OPTIONAL_SET(&local_extended->creation_time,
+                               LTTNG_OPTIONAL_GET(session_comm->creation_time));
+       }
+
+       {
+               const char *name;
+               const struct lttng_buffer_view name_view = lttng_buffer_view_from_view(
+                               &view->buffer, offset, session_comm->name_len);
+
+               if (!lttng_buffer_view_is_valid(&name_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               name = (const char *) name_view.data;
+
+               if (!lttng_buffer_view_contains_string(&name_view, name, session_comm->name_len)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = lttng_strncpy(local_session->name, name, sizeof(local_session->name));
+               if (ret) {
+                       ret = -1;
+                       goto end;
+               }
+
+               offset += session_comm->name_len;
+       }
+
+       {
+               const char *path;
+               const struct lttng_buffer_view path_view = lttng_buffer_view_from_view(
+                               &view->buffer, offset, session_comm->path_len);
+
+               if (!lttng_buffer_view_is_valid(&path_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               path = (const char *) path_view.data;
+
+               if (!lttng_buffer_view_contains_string(&path_view, path, session_comm->path_len)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = lttng_strncpy(local_session->path, path, sizeof(local_session->path));
+               if (ret) {
+                       ret = -1;
+                       goto end;
+               }
+
+               offset += session_comm->path_len;
+       }
+       /* Transfer ownership to the caller. */
+       *out_session = local_session;
+       local_session = nullptr;
+
+       ret = offset;
+end:
+       free(local_session);
+       return ret;
+}
+
+static enum lttng_error_code compute_flattened_size(
+               struct lttng_dynamic_pointer_array *sessions, size_t *size)
+{
+       enum lttng_error_code ret_code;
+       size_t storage_req, session_count;
+
+       assert(size);
+       assert(sessions);
+
+       session_count = lttng_dynamic_pointer_array_get_count(sessions);
+
+       /* The basic struct lttng_session */
+       storage_req = session_count * sizeof(struct lttng_session);
+
+       /* The struct lttng_session_extended */
+       storage_req += session_count * sizeof(struct lttng_session_extended);
+
+       *size = storage_req;
+       ret_code = LTTNG_OK;
+
+       return ret_code;
+}
+
+static enum lttng_error_code flatten_lttng_sessions(struct lttng_dynamic_pointer_array *sessions,
+               struct lttng_session **flattened_sessions)
+{
+       enum lttng_error_code ret_code;
+       int ret, i;
+       size_t storage_req;
+       struct lttng_dynamic_buffer local_flattened_sessions;
+       int nb_sessions;
+
+       assert(sessions);
+       assert(flattened_sessions);
+
+       lttng_dynamic_buffer_init(&local_flattened_sessions);
+       nb_sessions = lttng_dynamic_pointer_array_get_count(sessions);
+
+       ret_code = compute_flattened_size(sessions, &storage_req);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+
+       /*
+        * We must ensure that "local_flattened_sessions" is never resized so as
+        * to preserve the validity of the flattened objects.
+        */
+       ret = lttng_dynamic_buffer_set_capacity(&local_flattened_sessions, storage_req);
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       /* Start by laying the struct lttng_session */
+       for (i = 0; i < nb_sessions; i++) {
+               const struct session_list_element *element = (const struct session_list_element *)
+                               lttng_dynamic_pointer_array_get_pointer(sessions, i);
+
+               if (!element) {
+                       ret_code = LTTNG_ERR_FATAL;
+                       goto end;
+               }
+
+               ret = lttng_dynamic_buffer_append(&local_flattened_sessions, element->session,
+                               sizeof(struct lttng_session));
+               if (ret) {
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+       }
+
+       for (i = 0; i < nb_sessions; i++) {
+               const struct session_list_element *element = (const struct session_list_element *)
+                               lttng_dynamic_pointer_array_get_pointer(sessions, i);
+               struct lttng_session *session =
+                               (struct lttng_session *) (local_flattened_sessions.data +
+                                               (sizeof(struct lttng_session) * i));
+               struct lttng_session_extended *session_extended =
+                               (struct lttng_session_extended *) (local_flattened_sessions.data +
+                                               local_flattened_sessions.size);
+
+               assert(element);
+
+               /* Insert struct lttng_session_extended. */
+               ret = lttng_dynamic_buffer_set_size(&local_flattened_sessions,
+                               local_flattened_sessions.size + sizeof(*session_extended));
+               if (ret) {
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+               session->extended.ptr = session_extended;
+
+               memcpy(session_extended, element->session->extended.ptr,
+                               sizeof(struct lttng_session_extended));
+       }
+
+       /* Don't reset local_flattened_sessions buffer as we return its content. */
+       *flattened_sessions = (struct lttng_session *) local_flattened_sessions.data;
+       lttng_dynamic_buffer_init(&local_flattened_sessions);
+       ret_code = LTTNG_OK;
+end:
+       lttng_dynamic_buffer_reset(&local_flattened_sessions);
+       return ret_code;
+}
+
+static enum lttng_error_code session_list_create_from_payload(struct lttng_payload_view *view,
+               unsigned int count,
+               struct lttng_dynamic_pointer_array *session_list)
+{
+       enum lttng_error_code ret_code;
+       int ret;
+       unsigned int i;
+       int offset = 0;
+
+       assert(view);
+       assert(session_list);
+
+       for (i = 0; i < count; i++) {
+               ssize_t session_size;
+               struct lttng_payload_view session_view =
+                               lttng_payload_view_from_view(view, offset, -1);
+               struct session_list_element *element = zmalloc<session_list_element>();
+
+               if (!element) {
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+
+               /*
+                * Lifetime and management of the object is now bound to the
+                * array.
+                */
+               ret = lttng_dynamic_pointer_array_add_pointer(session_list, element);
+               if (ret) {
+                       session_list_destructor(element);
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+
+               session_size = lttng_session_create_from_payload(&session_view, &element->session);
+               if (session_size < 0) {
+                       ret_code = LTTNG_ERR_INVALID;
+                       goto end;
+               }
+
+               offset += session_size;
+       }
+
+       if (view->buffer.size != offset) {
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               goto end;
+       }
+
+       ret_code = LTTNG_OK;
+
+end:
+       return ret_code;
+}
+enum lttng_error_code lttng_sessions_create_and_flatten_from_payload(
+               struct lttng_payload_view *payload,
+               unsigned int count,
+               struct lttng_session **sessions)
+{
+       enum lttng_error_code ret = LTTNG_OK;
+       struct lttng_dynamic_pointer_array local_sessions;
+
+       lttng_dynamic_pointer_array_init(&local_sessions, session_list_destructor);
+
+       /* Deserialize the sessions. */
+       {
+               struct lttng_payload_view sessions_view =
+                               lttng_payload_view_from_view(payload, 0, -1);
+
+               ret = session_list_create_from_payload(&sessions_view, count, &local_sessions);
+               if (ret != LTTNG_OK) {
+                       goto end;
+               }
+       }
+
+       ret = flatten_lttng_sessions(&local_sessions, sessions);
+       if (ret != LTTNG_OK) {
+               goto end;
+       }
+
+end:
+       lttng_dynamic_pointer_array_reset(&local_sessions);
+       return ret;
+}
index 3d0c8b412cc7297914051a3417831d417857bf28..9dff22a2bca57e1b7c22cc612ef96d36aa40bb63 100644 (file)
@@ -2211,51 +2211,59 @@ int lttng_destroy_session_no_wait(const char *session_name)
 int lttng_list_sessions(struct lttng_session **out_sessions)
 {
        int ret;
-       struct lttcomm_session_msg lsm;
-       const size_t session_size = sizeof(struct lttng_session) +
-                       sizeof(struct lttng_session_extended);
-       size_t session_count, i;
-       struct lttng_session_extended *sessions_extended_begin;
-       struct lttng_session *sessions = NULL;
+       struct lttcomm_session_msg lsm = {};
+       struct lttng_payload reply;
+       struct lttng_payload_view lsm_view =
+                       lttng_payload_view_init_from_buffer((const char *) &lsm, 0, sizeof(lsm));
+       unsigned int nb_sessions = 0;
 
-       memset(&lsm, 0, sizeof(lsm));
+       lttng_payload_init(&reply);
+
+       /* Initialize command parameters. */
        lsm.cmd_type = LTTNG_LIST_SESSIONS;
-       /*
-        * Initialize out_sessions to NULL so it is initialized when
-        * lttng_list_sessions returns 0, thus allowing *out_sessions to
-        * be subsequently freed.
-        */
-       *out_sessions = NULL;
-       ret = lttng_ctl_ask_sessiond(&lsm, (void**) &sessions);
-       if (ret <= 0) {
-               goto end;
-       }
-       if (!sessions) {
-               ret = -LTTNG_ERR_FATAL;
+
+       /* Execute command against the session daemon. */
+       ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
+       if (ret < 0) {
                goto end;
        }
 
-       if (ret % session_size) {
-               ret = -LTTNG_ERR_UNK;
-               free(sessions);
-               goto end;
+       {
+               const struct lttcomm_list_command_header *cmd_reply_header = NULL;
+               const lttng_payload_view cmd_reply_header_view = lttng_payload_view_from_payload(
+                               &reply, 0, sizeof(*cmd_reply_header));
+
+               if (!lttng_payload_view_is_valid(&cmd_reply_header_view)) {
+                       ret = -LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+
+               cmd_reply_header = (const struct lttcomm_list_command_header *)
+                                                  cmd_reply_header_view.buffer.data;
+               if (cmd_reply_header->count > INT_MAX) {
+                       ret = -LTTNG_ERR_OVERFLOW;
+                       goto end;
+               }
+
+               nb_sessions = (unsigned int) cmd_reply_header->count;
        }
-       session_count = (size_t) ret / session_size;
-       sessions_extended_begin = (struct lttng_session_extended *)
-                       (&sessions[session_count]);
 
-       /* Set extended session info pointers. */
-       for (i = 0; i < session_count; i++) {
-               struct lttng_session *session = &sessions[i];
-               struct lttng_session_extended *extended =
-                               &(sessions_extended_begin[i]);
+       {
+               enum lttng_error_code ret_code;
+               lttng_payload_view cmd_reply_payload = lttng_payload_view_from_payload(
+                               &reply, sizeof(struct lttcomm_list_command_header), -1);
 
-               session->extended.ptr = extended;
+               ret_code = lttng_sessions_create_and_flatten_from_payload(
+                               &cmd_reply_payload, nb_sessions, out_sessions);
+               if (ret_code != LTTNG_OK) {
+                       ret = -((int) ret_code);
+                       goto end;
+               }
        }
 
-       ret = (int) session_count;
-       *out_sessions = sessions;
+       ret = (int) nb_sessions;
 end:
+       lttng_payload_reset(&reply);
        return ret;
 }
 
This page took 0.036147 seconds and 5 git commands to generate.