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/error.h>
23 #include <common/dynamic-buffer.h>
24 #include <common/utils.h>
25 #include <common/defaults.h>
27 #include "lttng-ctl-helper.h"
29 struct lttng_notification_channel
*lttng_notification_channel_create(
30 struct lttng_endpoint
*endpoint
)
33 bool is_in_tracing_group
= false, is_root
= false;
34 char *sock_path
= NULL
;
35 struct lttng_notification_channel
*channel
= NULL
;
38 endpoint
!= lttng_session_daemon_notification_endpoint
) {
42 sock_path
= zmalloc(LTTNG_PATH_MAX
);
47 channel
= zmalloc(sizeof(struct lttng_notification_channel
));
53 is_root
= (getuid() == 0);
55 is_in_tracing_group
= lttng_check_tracing_group();
58 if (is_root
|| is_in_tracing_group
) {
59 lttng_ctl_copy_string(sock_path
,
60 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK
,
62 ret
= lttcomm_connect_unix_sock(sock_path
);
69 /* Fallback to local session daemon. */
70 ret
= snprintf(sock_path
, LTTNG_PATH_MAX
,
71 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK
,
72 utils_get_home_dir());
73 if (ret
< 0 || ret
>= LTTNG_PATH_MAX
) {
77 ret
= lttcomm_connect_unix_sock(sock_path
);
86 /* FIXME send creds */
91 lttng_notification_channel_destroy(channel
);
96 enum lttng_notification_channel_status
97 lttng_notification_channel_get_next_notification(
98 struct lttng_notification_channel
*channel
,
99 struct lttng_notification
**_notification
)
102 struct lttng_notification_comm comm
;
103 struct lttng_notification
*notification
= NULL
;
104 struct lttng_dynamic_buffer reception_buffer
;
105 struct lttng_notification_channel_message msg
;
106 enum lttng_notification_channel_status status
=
107 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
109 lttng_dynamic_buffer_init(&reception_buffer
);
111 if (!channel
|| !_notification
) {
112 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
116 ret
= lttcomm_recv_unix_sock(channel
->socket
, &msg
, sizeof(msg
));
118 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
121 if (msg
.type
!= LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION
) {
122 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
126 ret
= lttcomm_recv_unix_sock(channel
->socket
, &comm
, sizeof(comm
));
127 if (ret
< sizeof(comm
)) {
128 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
132 ret
= lttng_dynamic_buffer_set_size(&reception_buffer
,
133 comm
.length
+ sizeof(comm
));
135 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
139 memcpy(reception_buffer
.data
, &comm
, sizeof(comm
));
140 ret
= lttcomm_recv_unix_sock(channel
->socket
,
141 reception_buffer
.data
+ sizeof(comm
),
143 if (ret
< (ssize_t
) comm
.length
) {
144 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
148 ret
= lttng_notification_create_from_buffer(reception_buffer
.data
,
150 if (ret
!= (sizeof(comm
) + (ssize_t
) comm
.length
)) {
151 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
154 *_notification
= notification
;
156 lttng_dynamic_buffer_reset(&reception_buffer
);
159 lttng_notification_destroy(notification
);
164 enum lttng_notification_channel_status
send_command(
165 struct lttng_notification_channel
*channel
,
166 enum lttng_notification_channel_message_type type
,
167 struct lttng_condition
*condition
)
170 ssize_t command_size
, ret
;
172 enum lttng_notification_channel_status status
=
173 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
174 char *command_buffer
= NULL
;
175 struct lttng_notification_channel_message cmd_message
= {
178 struct lttng_notification_channel_message reply_message
;
179 struct lttng_notification_channel_command_reply reply
;
182 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
186 socket
= channel
->socket
;
187 if (!lttng_condition_validate(condition
)) {
188 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
192 ret
= lttng_condition_serialize(condition
, NULL
);
194 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
197 assert(ret
< UINT32_MAX
);
198 cmd_message
.size
= (uint32_t) ret
;
199 command_size
= ret
+ sizeof(
200 struct lttng_notification_channel_message
);
201 command_buffer
= zmalloc(command_size
);
202 if (!command_buffer
) {
206 memcpy(command_buffer
, &cmd_message
, sizeof(cmd_message
));
207 ret
= lttng_condition_serialize(condition
,
208 command_buffer
+ sizeof(cmd_message
));
213 ret
= lttcomm_send_unix_sock(socket
, command_buffer
, command_size
);
215 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
219 /* Receive command reply header. */
221 ret
= lttcomm_recv_unix_sock(socket
,
222 ((char *) &reply_message
) + received
,
223 sizeof(reply_message
) - received
);
225 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
229 } while (received
< sizeof(reply_message
));
230 if (reply_message
.type
!=
231 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY
||
232 reply_message
.size
!= sizeof(reply
)) {
233 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
237 /* Receive command reply payload. */
240 ret
= lttcomm_recv_unix_sock(socket
,
241 ((char *) &reply
) + received
,
242 sizeof(reply
) - received
);
244 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
248 } while (received
< sizeof(reply
));
249 status
= (enum lttng_notification_channel_status
) reply
.status
;
251 free(command_buffer
);
255 enum lttng_notification_channel_status
lttng_notification_channel_subscribe(
256 struct lttng_notification_channel
*channel
,
257 struct lttng_condition
*condition
)
259 return send_command(channel
,
260 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE
,
264 enum lttng_notification_channel_status
lttng_notification_channel_unsubscribe(
265 struct lttng_notification_channel
*channel
,
266 struct lttng_condition
*condition
)
268 return send_command(channel
,
269 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE
,
273 void lttng_notification_channel_destroy(
274 struct lttng_notification_channel
*channel
)
280 if (channel
->socket
>= 0) {
281 (void) lttcomm_close_unix_sock(channel
->socket
);