2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/notification/notification-internal.h>
19 #include <lttng/notification/channel-internal.h>
20 #include <lttng/condition/condition-internal.h>
21 #include <lttng/endpoint.h>
22 #include <common/defaults.h>
23 #include <common/error.h>
24 #include <common/dynamic-buffer.h>
25 #include <common/utils.h>
26 #include <common/defaults.h>
28 #include "lttng-ctl-helper.h"
29 #include <sys/select.h>
33 int handshake(struct lttng_notification_channel
*channel
);
36 * Populates the reception buffer with the next complete message.
37 * The caller must acquire the channel's lock.
40 int receive_message(struct lttng_notification_channel
*channel
)
43 struct lttng_notification_channel_message msg
;
45 if (lttng_dynamic_buffer_set_size(&channel
->reception_buffer
, 0)) {
50 ret
= lttcomm_recv_unix_sock(channel
->socket
, &msg
, sizeof(msg
));
56 if (msg
.size
> DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE
) {
61 /* Add message header at buffer's start. */
62 ret
= lttng_dynamic_buffer_append(&channel
->reception_buffer
, &msg
,
68 /* Reserve space for the payload. */
69 ret
= lttng_dynamic_buffer_set_size(&channel
->reception_buffer
,
70 channel
->reception_buffer
.size
+ msg
.size
);
75 /* Receive message payload. */
76 ret
= lttcomm_recv_unix_sock(channel
->socket
,
77 channel
->reception_buffer
.data
+ sizeof(msg
), msg
.size
);
78 if (ret
< (ssize_t
) msg
.size
) {
86 if (lttng_dynamic_buffer_set_size(&channel
->reception_buffer
, 0)) {
93 enum lttng_notification_channel_message_type
get_current_message_type(
94 struct lttng_notification_channel
*channel
)
96 struct lttng_notification_channel_message
*msg
;
98 assert(channel
->reception_buffer
.size
>= sizeof(*msg
));
100 msg
= (struct lttng_notification_channel_message
*)
101 channel
->reception_buffer
.data
;
102 return (enum lttng_notification_channel_message_type
) msg
->type
;
106 struct lttng_notification
*create_notification_from_current_message(
107 struct lttng_notification_channel
*channel
)
110 struct lttng_notification
*notification
= NULL
;
111 struct lttng_buffer_view view
;
113 if (channel
->reception_buffer
.size
<=
114 sizeof(struct lttng_notification_channel_message
)) {
118 view
= lttng_buffer_view_from_dynamic_buffer(&channel
->reception_buffer
,
119 sizeof(struct lttng_notification_channel_message
), -1);
121 ret
= lttng_notification_create_from_buffer(&view
, ¬ification
);
122 if (ret
!= channel
->reception_buffer
.size
-
123 sizeof(struct lttng_notification_channel_message
)) {
124 lttng_notification_destroy(notification
);
132 struct lttng_notification_channel
*lttng_notification_channel_create(
133 struct lttng_endpoint
*endpoint
)
136 bool is_in_tracing_group
= false, is_root
= false;
137 char *sock_path
= NULL
;
138 struct lttng_notification_channel
*channel
= NULL
;
141 endpoint
!= lttng_session_daemon_notification_endpoint
) {
145 sock_path
= zmalloc(LTTNG_PATH_MAX
);
150 channel
= zmalloc(sizeof(struct lttng_notification_channel
));
154 channel
->socket
= -1;
155 pthread_mutex_init(&channel
->lock
, NULL
);
156 lttng_dynamic_buffer_init(&channel
->reception_buffer
);
157 CDS_INIT_LIST_HEAD(&channel
->pending_notifications
.list
);
159 is_root
= (getuid() == 0);
161 is_in_tracing_group
= lttng_check_tracing_group();
164 if (is_root
|| is_in_tracing_group
) {
165 lttng_ctl_copy_string(sock_path
,
166 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK
,
168 ret
= lttcomm_connect_unix_sock(sock_path
);
175 /* Fallback to local session daemon. */
176 ret
= snprintf(sock_path
, LTTNG_PATH_MAX
,
177 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK
,
178 utils_get_home_dir());
179 if (ret
< 0 || ret
>= LTTNG_PATH_MAX
) {
183 ret
= lttcomm_connect_unix_sock(sock_path
);
190 channel
->socket
= fd
;
192 ret
= handshake(channel
);
200 lttng_notification_channel_destroy(channel
);
205 enum lttng_notification_channel_status
206 lttng_notification_channel_get_next_notification(
207 struct lttng_notification_channel
*channel
,
208 struct lttng_notification
**_notification
)
211 struct lttng_notification
*notification
= NULL
;
212 enum lttng_notification_channel_status status
=
213 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
216 if (!channel
|| !_notification
) {
217 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
221 pthread_mutex_lock(&channel
->lock
);
223 if (channel
->pending_notifications
.count
) {
224 struct pending_notification
*pending_notification
;
226 assert(!cds_list_empty(&channel
->pending_notifications
.list
));
228 /* Deliver one of the pending notifications. */
229 pending_notification
= cds_list_first_entry(
230 &channel
->pending_notifications
.list
,
231 struct pending_notification
,
233 notification
= pending_notification
->notification
;
235 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
;
237 cds_list_del(&pending_notification
->node
);
238 channel
->pending_notifications
.count
--;
239 free(pending_notification
);
244 * Block on select() instead of the message reception itself as the
245 * recvmsg() wrappers always restard on EINTR. We choose to wait
246 * using select() in order to:
247 * 1) Return if a signal occurs,
248 * 2) Not deal with partially received messages.
250 * The drawback to this approach is that we assume that messages
251 * are complete/well formed. If a message is shorter than its
252 * announced length, receive_message() will block on recvmsg()
253 * and never return (even if a signal is received).
256 FD_SET(channel
->socket
, &read_fds
);
257 ret
= select(channel
->socket
+ 1, &read_fds
, NULL
, NULL
, NULL
);
259 status
= errno
== EINTR
?
260 LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
261 LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
265 ret
= receive_message(channel
);
267 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
271 switch (get_current_message_type(channel
)) {
272 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION
:
273 notification
= create_notification_from_current_message(
276 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
280 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED
:
281 /* No payload to consume. */
282 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
;
285 /* Protocol error. */
286 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
291 pthread_mutex_unlock(&channel
->lock
);
294 *_notification
= notification
;
300 int enqueue_dropped_notification(
301 struct lttng_notification_channel
*channel
)
304 struct pending_notification
*pending_notification
;
305 struct cds_list_head
*last_element
=
306 channel
->pending_notifications
.list
.prev
;
308 pending_notification
= caa_container_of(last_element
,
309 struct pending_notification
, node
);
310 if (!pending_notification
->notification
) {
312 * The last enqueued notification indicates dropped
313 * notifications; there is nothing to do as we group
314 * dropped notifications together.
319 if (channel
->pending_notifications
.count
>=
320 DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT
&&
321 pending_notification
->notification
) {
323 * Discard the last enqueued notification to indicate
324 * that notifications were dropped at this point.
326 lttng_notification_destroy(
327 pending_notification
->notification
);
328 pending_notification
->notification
= NULL
;
332 pending_notification
= zmalloc(sizeof(*pending_notification
));
333 if (!pending_notification
) {
337 CDS_INIT_LIST_HEAD(&pending_notification
->node
);
338 cds_list_add(&pending_notification
->node
,
339 &channel
->pending_notifications
.list
);
340 channel
->pending_notifications
.count
++;
346 int enqueue_notification_from_current_message(
347 struct lttng_notification_channel
*channel
)
350 struct lttng_notification
*notification
;
351 struct pending_notification
*pending_notification
;
353 if (channel
->pending_notifications
.count
>=
354 DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT
) {
355 /* Drop the notification. */
356 ret
= enqueue_dropped_notification(channel
);
360 pending_notification
= zmalloc(sizeof(*pending_notification
));
361 if (!pending_notification
) {
365 CDS_INIT_LIST_HEAD(&pending_notification
->node
);
367 notification
= create_notification_from_current_message(channel
);
373 pending_notification
->notification
= notification
;
374 cds_list_add(&pending_notification
->node
,
375 &channel
->pending_notifications
.list
);
376 channel
->pending_notifications
.count
++;
380 free(pending_notification
);
384 enum lttng_notification_channel_status
385 lttng_notification_channel_has_pending_notification(
386 struct lttng_notification_channel
*channel
,
387 bool *_notification_pending
)
390 enum lttng_notification_channel_status status
=
391 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
393 struct timeval timeout
;
396 memset(&timeout
, 0, sizeof(timeout
));
398 if (!channel
|| !_notification_pending
) {
399 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
403 pthread_mutex_lock(&channel
->lock
);
405 if (channel
->pending_notifications
.count
) {
406 *_notification_pending
= true;
410 if (channel
->socket
< 0) {
411 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
;
416 * Check, without blocking, if data is available on the channel's
417 * socket. If there is data available, it is safe to read (blocking)
418 * on the socket for a message from the session daemon.
420 * Since all commands wait for the session daemon's reply before
421 * releasing the channel's lock, the protocol only allows for
422 * notifications and "notification dropped" messages to come
423 * through. If we receive a different message type, it is
424 * considered a protocol error.
426 * Note that this function is not guaranteed not to block. This
427 * will block until our peer (the session daemon) has sent a complete
428 * message if we see data available on the socket. If the peer does
429 * not respect the protocol, this may block indefinitely.
431 FD_SET(channel
->socket
, &read_fds
);
433 ret
= select(channel
->socket
+ 1, &read_fds
, NULL
, NULL
, &timeout
);
434 } while (ret
< 0 && errno
== EINTR
);
437 /* No data available. */
438 *_notification_pending
= false;
440 } else if (ret
< 0) {
441 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
445 /* Data available on socket. */
446 ret
= receive_message(channel
);
448 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
452 switch (get_current_message_type(channel
)) {
453 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION
:
454 ret
= enqueue_notification_from_current_message(channel
);
458 *_notification_pending
= true;
460 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED
:
461 ret
= enqueue_dropped_notification(channel
);
465 *_notification_pending
= true;
468 /* Protocol error. */
469 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
474 pthread_mutex_unlock(&channel
->lock
);
480 int receive_command_reply(struct lttng_notification_channel
*channel
,
481 enum lttng_notification_channel_status
*status
)
484 struct lttng_notification_channel_command_reply
*reply
;
487 enum lttng_notification_channel_message_type msg_type
;
489 ret
= receive_message(channel
);
494 msg_type
= get_current_message_type(channel
);
496 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY
:
498 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION
:
499 ret
= enqueue_notification_from_current_message(
505 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED
:
506 ret
= enqueue_dropped_notification(channel
);
511 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE
:
513 struct lttng_notification_channel_command_handshake
*handshake
;
515 handshake
= (struct lttng_notification_channel_command_handshake
*)
516 (channel
->reception_buffer
.data
+
517 sizeof(struct lttng_notification_channel_message
));
518 channel
->version
.major
= handshake
->major
;
519 channel
->version
.minor
= handshake
->minor
;
520 channel
->version
.set
= true;
530 if (channel
->reception_buffer
.size
<
531 (sizeof(struct lttng_notification_channel_message
) +
533 /* Invalid message received. */
538 reply
= (struct lttng_notification_channel_command_reply
*)
539 (channel
->reception_buffer
.data
+
540 sizeof(struct lttng_notification_channel_message
));
541 *status
= (enum lttng_notification_channel_status
) reply
->status
;
547 int handshake(struct lttng_notification_channel
*channel
)
550 enum lttng_notification_channel_status status
=
551 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
552 struct lttng_notification_channel_command_handshake handshake
= {
553 .major
= LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR
,
554 .minor
= LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR
,
556 struct lttng_notification_channel_message msg_header
= {
557 .type
= LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE
,
558 .size
= sizeof(handshake
),
560 char send_buffer
[sizeof(msg_header
) + sizeof(handshake
)];
562 memcpy(send_buffer
, &msg_header
, sizeof(msg_header
));
563 memcpy(send_buffer
+ sizeof(msg_header
), &handshake
, sizeof(handshake
));
565 pthread_mutex_lock(&channel
->lock
);
567 ret
= lttcomm_send_creds_unix_sock(channel
->socket
, send_buffer
,
568 sizeof(send_buffer
));
573 /* Receive handshake info from the sessiond. */
574 ret
= receive_command_reply(channel
, &status
);
579 if (!channel
->version
.set
) {
584 if (channel
->version
.major
!= LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR
) {
590 pthread_mutex_unlock(&channel
->lock
);
595 enum lttng_notification_channel_status
send_condition_command(
596 struct lttng_notification_channel
*channel
,
597 enum lttng_notification_channel_message_type type
,
598 const struct lttng_condition
*condition
)
602 enum lttng_notification_channel_status status
=
603 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
604 struct lttng_dynamic_buffer buffer
;
605 struct lttng_notification_channel_message cmd_header
= {
606 .type
= (int8_t) type
,
609 lttng_dynamic_buffer_init(&buffer
);
612 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
616 assert(type
== LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE
||
617 type
== LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE
);
619 pthread_mutex_lock(&channel
->lock
);
620 socket
= channel
->socket
;
621 if (!lttng_condition_validate(condition
)) {
622 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
626 ret
= lttng_dynamic_buffer_append(&buffer
, &cmd_header
,
629 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
633 ret
= lttng_condition_serialize(condition
, &buffer
);
635 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
639 /* Update payload length. */
640 ((struct lttng_notification_channel_message
*) buffer
.data
)->size
=
641 (uint32_t) (buffer
.size
- sizeof(cmd_header
));
643 ret
= lttcomm_send_unix_sock(socket
, buffer
.data
, buffer
.size
);
645 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
649 ret
= receive_command_reply(channel
, &status
);
651 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
655 pthread_mutex_unlock(&channel
->lock
);
657 lttng_dynamic_buffer_reset(&buffer
);
661 enum lttng_notification_channel_status
lttng_notification_channel_subscribe(
662 struct lttng_notification_channel
*channel
,
663 const struct lttng_condition
*condition
)
665 return send_condition_command(channel
,
666 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE
,
670 enum lttng_notification_channel_status
lttng_notification_channel_unsubscribe(
671 struct lttng_notification_channel
*channel
,
672 const struct lttng_condition
*condition
)
674 return send_condition_command(channel
,
675 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE
,
679 void lttng_notification_channel_destroy(
680 struct lttng_notification_channel
*channel
)
686 if (channel
->socket
>= 0) {
687 (void) lttcomm_close_unix_sock(channel
->socket
);
689 pthread_mutex_destroy(&channel
->lock
);
690 lttng_dynamic_buffer_reset(&channel
->reception_buffer
);