#ifndef NOTIFICATION_THREAD_INTERNAL_H
#define NOTIFICATION_THREAD_INTERNAL_H
+#include <common/compat/socket.h>
+#include <common/credentials.h>
+#include <common/payload.h>
+#include <lttng/notification/channel-internal.h>
#include <lttng/ref-internal.h>
-#include <urcu/rculfhash.h>
+#include <stdbool.h>
#include <unistd.h>
+#include <urcu/rculfhash.h>
+#include <urcu/ref.h>
+#include <urcu/call-rcu.h>
+#include "notification-thread.h"
+
+struct lttng_evaluation;
+struct notification_thread_handle;
struct channel_key {
uint64_t key;
struct rcu_head rcu_node;
};
+/*
+ * Facilities to carry the different notifications type in the action
+ * processing code path.
+ */
+struct lttng_event_notifier_notification {
+ uint64_t tracer_token;
+ enum lttng_domain_type type;
+ size_t capture_buf_size;
+ char *capture_buffer;
+};
+
+struct notification_client_list_element {
+ struct notification_client *client;
+ struct cds_list_head node;
+};
+
+/*
+ * Thread safety of notification_client and notification_client_list.
+ *
+ * The notification thread (main thread) and the action executor
+ * interact through client lists. Hence, when the action executor
+ * thread looks-up the list of clients subscribed to a given
+ * condition, it will acquire a reference to the list and lock it
+ * while attempting to communicate with the various clients.
+ *
+ * It is not necessary to reference-count clients as they are guaranteed
+ * to be 'alive' if they are present in a list and that list is locked. Indeed,
+ * removing references to the client from those subscription lists is part of
+ * the work performed on destruction of a client.
+ *
+ * No provision for other access scenarios are taken into account;
+ * this is the bare minimum to make these accesses safe and the
+ * notification thread's state is _not_ "thread-safe" in any general
+ * sense.
+ */
+struct notification_client_list {
+ pthread_mutex_t lock;
+ struct urcu_ref ref;
+ struct lttng_condition *condition;
+ /* List of triggers that have an identical condition than `condition`. */
+ struct cds_list_head triggers_list;
+ struct cds_list_head clients_list;
+ /* Weak reference to container. */
+ struct cds_lfht *notification_trigger_clients_ht;
+ struct cds_lfht_node notification_trigger_clients_ht_node;
+ /* call_rcu delayed reclaim. */
+ struct rcu_head rcu_node;
+};
+
+struct notification_client {
+ /*
+ * Nests within the notification_client_list lock.
+ *
+ * Protects the outbound communication and the active flag which
+ * is used by both the notification and action executor threads.
+ *
+ * The remaining fields of the object can be used without any
+ * synchronization as they are either immutable (id, creds, version) or
+ * only accessed by the notification thread.
+ */
+ pthread_mutex_t lock;
+ notification_client_id id;
+ int socket;
+ /* Client protocol version. */
+ uint8_t major, minor;
+ uid_t uid;
+ gid_t gid;
+ bool is_sessiond;
+ /*
+ * Indicates if the credentials and versions of the client have been
+ * checked.
+ */
+ bool validated;
+ /*
+ * Conditions to which the client's notification channel is subscribed.
+ * List of struct lttng_condition_list_node. The condition member is
+ * owned by the client.
+ */
+ struct cds_list_head condition_list;
+ struct cds_lfht_node client_socket_ht_node;
+ struct cds_lfht_node client_id_ht_node;
+ struct {
+ /*
+ * If a client's communication is inactive, it means that a
+ * fatal error has occurred (could be either a protocol error or
+ * the socket API returned a fatal error). No further
+ * communication should be attempted; the client is queued for
+ * clean-up.
+ */
+ bool active;
+ struct {
+ /*
+ * During the reception of a message, the reception
+ * buffers' "size" is set to contain the current
+ * message's complete payload.
+ */
+ struct lttng_payload payload;
+ /* Bytes left to receive for the current message. */
+ size_t bytes_to_receive;
+ /* FDs left to receive for the current message. */
+ int fds_to_receive;
+ /* Type of the message being received. */
+ enum lttng_notification_channel_message_type msg_type;
+ /*
+ * Indicates whether or not credentials are expected
+ * from the client.
+ */
+ bool expect_creds;
+ /*
+ * Indicates whether or not credentials were received
+ * from the client.
+ */
+ bool creds_received;
+ /* Only used during credentials reception. */
+ lttng_sock_cred creds;
+ } inbound;
+ struct {
+ /*
+ * Indicates whether or not a notification addressed to
+ * this client was dropped because a command reply was
+ * already buffered.
+ *
+ * A notification is dropped whenever the buffer is not
+ * empty.
+ */
+ bool dropped_notification;
+ /*
+ * Indicates whether or not a command reply is already
+ * buffered. In this case, it means that the client is
+ * not consuming command replies before emitting a new
+ * one. This could be caused by a protocol error or a
+ * misbehaving/malicious client.
+ */
+ bool queued_command_reply;
+ struct lttng_payload payload;
+ } outbound;
+ } communication;
+ /* call_rcu delayed reclaim. */
+ struct rcu_head rcu_node;
+};
+
+enum client_transmission_status {
+ CLIENT_TRANSMISSION_STATUS_COMPLETE,
+ CLIENT_TRANSMISSION_STATUS_QUEUED,
+ /* Communication failure. */
+ CLIENT_TRANSMISSION_STATUS_FAIL,
+ /* Fatal error. */
+ CLIENT_TRANSMISSION_STATUS_ERROR,
+};
+
+bool notification_client_list_get(struct notification_client_list *list);
+
+void notification_client_list_put(struct notification_client_list *list);
+
+/* Only returns a non-zero value if a fatal error occurred. */
+typedef int (*report_client_transmission_result_cb)(
+ struct notification_client *client,
+ enum client_transmission_status status,
+ void *user_data);
+
+int notification_client_list_send_evaluation(
+ struct notification_client_list *list,
+ const struct lttng_trigger *trigger,
+ const struct lttng_evaluation *evaluation,
+ const struct lttng_credentials *source_object_creds,
+ report_client_transmission_result_cb client_report,
+ void *user_data);
+
+int notification_thread_client_communication_update(
+ struct notification_thread_handle *handle,
+ notification_client_id id,
+ enum client_transmission_status transmission_status);
+
+/*
+ * Takes ownership of the payload if present.
+ */
+struct lttng_event_notifier_notification *lttng_event_notifier_notification_create(
+ uint64_t tracer_token,
+ enum lttng_domain_type domain,
+ char *payload,
+ size_t payload_size);
+
+void lttng_event_notifier_notification_destroy(
+ struct lttng_event_notifier_notification *event_notifier_notification);
+
#endif /* NOTIFICATION_THREAD_INTERNAL_H */