+static ssize_t cmd_list_channels(int domain, struct ltt_session *session,
+ struct lttng_channel **channels)
+{
+ int ret;
+ ssize_t nb_chan = 0;
+
+ switch (domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ if (session->kernel_session != NULL) {
+ nb_chan = session->kernel_session->channel_count;
+ }
+ DBG3("Number of kernel channels %zd", nb_chan);
+ break;
+ case LTTNG_DOMAIN_UST:
+ if (session->ust_session != NULL) {
+ nb_chan = lttng_ht_get_count(
+ session->ust_session->domain_global.channels);
+ }
+ DBG3("Number of UST global channels %zd", nb_chan);
+ break;
+ default:
+ *channels = NULL;
+ ret = -LTTCOMM_UND;
+ goto error;
+ }
+
+ if (nb_chan > 0) {
+ *channels = zmalloc(nb_chan * sizeof(struct lttng_channel));
+ if (*channels == NULL) {
+ ret = -LTTCOMM_FATAL;
+ goto error;
+ }
+
+ list_lttng_channels(domain, session, *channels);
+ } else {
+ *channels = NULL;
+ }
+
+ return nb_chan;
+
+error:
+ return ret;
+}
+
+/*
+ * Command LTTNG_LIST_EVENTS processed by the client thread.
+ */
+static ssize_t cmd_list_events(int domain, struct ltt_session *session,
+ char *channel_name, struct lttng_event **events)
+{
+ int ret = 0;
+ ssize_t nb_event = 0;
+
+ switch (domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ if (session->kernel_session != NULL) {
+ nb_event = list_lttng_kernel_events(channel_name,
+ session->kernel_session, events);
+ }
+ break;
+ case LTTNG_DOMAIN_UST:
+ {
+ if (session->ust_session != NULL) {
+ nb_event = list_lttng_ust_global_events(channel_name,
+ &session->ust_session->domain_global, events);
+ }
+ break;
+ }
+ default:
+ ret = -LTTCOMM_UND;
+ goto error;
+ }
+
+ ret = nb_event;
+
+error:
+ return ret;
+}
+
+/*
+ * Command LTTNG_SET_CONSUMER_URI processed by the client thread.
+ */
+static int cmd_set_consumer_uri(int domain, struct ltt_session *session,
+ struct lttng_uri *uri)
+{
+ int ret;
+ struct ltt_kernel_session *ksess = session->kernel_session;
+ struct ltt_ust_session *usess = session->ust_session;
+ struct consumer_output *consumer;
+
+ /* Can't enable consumer after session started. */
+ if (session->enabled) {
+ ret = LTTCOMM_TRACE_ALREADY_STARTED;
+ goto error;
+ }
+
+ switch (domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ /* Code flow error if we don't have a kernel session here. */
+ assert(ksess);
+
+ /* Create consumer output if none exists */
+ consumer = ksess->tmp_consumer;
+ if (consumer == NULL) {
+ consumer = consumer_copy_output(ksess->consumer);
+ if (consumer == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ /* Reassign new pointer */
+ ksess->tmp_consumer = consumer;
+ }
+
+ switch (uri->dtype) {
+ case LTTNG_DST_IPV4:
+ case LTTNG_DST_IPV6:
+ DBG2("Setting network URI for kernel session %s", session->name);
+
+ /* Set URI into consumer output object */
+ ret = consumer_set_network_uri(consumer, uri);
+ if (ret < 0) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ /* On a new subdir, reappend the default trace dir. */
+ if (strlen(uri->subdir) != 0) {
+ strncat(consumer->subdir, DEFAULT_KERNEL_TRACE_DIR,
+ sizeof(consumer->subdir));
+ }
+
+ ret = send_socket_relayd_consumer(domain, session, uri, consumer,
+ ksess->consumer_fd);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ break;
+ case LTTNG_DST_PATH:
+ DBG2("Setting trace directory path from URI to %s", uri->dst.path);
+ memset(consumer->dst.trace_path, 0,
+ sizeof(consumer->dst.trace_path));
+ strncpy(consumer->dst.trace_path, uri->dst.path,
+ sizeof(consumer->dst.trace_path));
+ /* Append default kernel trace dir */
+ strncat(consumer->dst.trace_path, DEFAULT_KERNEL_TRACE_DIR,
+ sizeof(consumer->dst.trace_path));
+ break;
+ }
+
+ /* All good! */
+ break;
+ case LTTNG_DOMAIN_UST:
+ /* Code flow error if we don't have a kernel session here. */
+ assert(usess);
+
+ /* Create consumer output if none exists */
+ consumer = usess->tmp_consumer;
+ if (consumer == NULL) {
+ consumer = consumer_copy_output(usess->consumer);
+ if (consumer == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ /* Reassign new pointer */
+ usess->tmp_consumer = consumer;
+ }
+
+ switch (uri->dtype) {
+ case LTTNG_DST_IPV4:
+ case LTTNG_DST_IPV6:
+ {
+ DBG2("Setting network URI for UST session %s", session->name);
+
+ /* Set URI into consumer object */
+ ret = consumer_set_network_uri(consumer, uri);
+ if (ret < 0) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ /* On a new subdir, reappend the default trace dir. */
+ if (strlen(uri->subdir) != 0) {
+ strncat(consumer->subdir, DEFAULT_UST_TRACE_DIR,
+ sizeof(consumer->subdir));
+ }
+
+ if (ust_consumerd64_fd >= 0) {
+ ret = send_socket_relayd_consumer(domain, session, uri,
+ consumer, ust_consumerd64_fd);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+
+ if (ust_consumerd32_fd >= 0) {
+ ret = send_socket_relayd_consumer(domain, session, uri,
+ consumer, ust_consumerd32_fd);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+
+ break;
+ }
+ case LTTNG_DST_PATH:
+ DBG2("Setting trace directory path from URI to %s", uri->dst.path);
+ memset(consumer->dst.trace_path, 0,
+ sizeof(consumer->dst.trace_path));
+ strncpy(consumer->dst.trace_path, uri->dst.path,
+ sizeof(consumer->dst.trace_path));
+ /* Append default UST trace dir */
+ strncat(consumer->dst.trace_path, DEFAULT_UST_TRACE_DIR,
+ sizeof(consumer->dst.trace_path));
+ break;
+ }
+ break;
+ }
+
+ /* All good! */
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Command LTTNG_DISABLE_CONSUMER processed by the client thread.
+ */
+static int cmd_disable_consumer(int domain, struct ltt_session *session)