72450d50c220770907b3f4b70cc3836f42268276
[lttng-tools.git] / src / bin / lttng-sessiond / consumer.c
1 /*
2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program 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 General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <assert.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include <common/common.h>
28 #include <common/defaults.h>
29 #include <common/uri.h>
30
31 #include "consumer.h"
32
33 /*
34 * Allocate and assign data to a consumer_output object.
35 *
36 * Return pointer to structure.
37 */
38 struct consumer_output *consumer_create_output(enum consumer_dst_type type)
39 {
40 struct consumer_output *output = NULL;
41
42 output = zmalloc(sizeof(struct consumer_output));
43 if (output == NULL) {
44 PERROR("zmalloc consumer_output");
45 goto error;
46 }
47
48 /* By default, consumer output is enabled */
49 output->enabled = 1;
50 output->type = type;
51 output->net_seq_index = -1;
52 /*
53 * Important to keep it to a negative value on creation since it was zeroed
54 * during allocation and the file descriptor 0 is a valid one.
55 */
56 output->sock = -1;
57
58 error:
59 return output;
60 }
61
62 /*
63 * Delete the consumer_output object from the list and free the ptr.
64 */
65 void consumer_destroy_output(struct consumer_output *obj)
66 {
67 if (obj == NULL) {
68 return;
69 }
70
71 if (obj->sock >= 0) {
72 (void) close(obj->sock);
73 }
74 free(obj);
75 }
76
77 /*
78 * Copy consumer output and returned the newly allocated copy.
79 */
80 struct consumer_output *consumer_copy_output(struct consumer_output *obj)
81 {
82 struct consumer_output *output;
83
84 assert(obj);
85
86 output = consumer_create_output(obj->type);
87 if (output == NULL) {
88 goto error;
89 }
90
91 memcpy(output, obj, sizeof(struct consumer_output));
92
93 error:
94 return output;
95 }
96
97 /*
98 * Set network URI to the consumer output object.
99 *
100 * Return 0 on success. Negative value on error.
101 */
102 int consumer_set_network_uri(struct consumer_output *obj,
103 struct lttng_uri *uri)
104 {
105 int ret;
106 char tmp_path[PATH_MAX];
107 char hostname[HOST_NAME_MAX];
108 struct lttng_uri *dst_uri = NULL;
109
110 /* Code flow error safety net. */
111 assert(obj);
112 assert(uri);
113
114 switch (uri->stype) {
115 case LTTNG_STREAM_CONTROL:
116 dst_uri = &obj->dst.net.control;
117 obj->dst.net.control_isset = 1;
118 if (uri->port == 0) {
119 /* Assign default port. */
120 uri->port = DEFAULT_NETWORK_CONTROL_PORT;
121 }
122 break;
123 case LTTNG_STREAM_DATA:
124 dst_uri = &obj->dst.net.data;
125 obj->dst.net.data_isset = 1;
126 if (uri->port == 0) {
127 /* Assign default port. */
128 uri->port = DEFAULT_NETWORK_DATA_PORT;
129 }
130 break;
131 default:
132 ERR("Set network uri type unknown %d", uri->stype);
133 goto error;
134 }
135
136 ret = uri_compare(dst_uri, uri);
137 if (!ret) {
138 /* Same URI, don't touch it and return success. */
139 DBG3("URI network compare are the same");
140 goto end;
141 }
142
143 /* URIs were not equal, replacing it. */
144 memset(dst_uri, 0, sizeof(struct lttng_uri));
145 memcpy(dst_uri, uri, sizeof(struct lttng_uri));
146 obj->type = CONSUMER_DST_NET;
147
148 /* Handle subdir and add hostname in front. */
149 if (dst_uri->stype == LTTNG_STREAM_CONTROL) {
150 /* Get hostname to append it in the pathname */
151 ret = gethostname(hostname, sizeof(hostname));
152 if (ret < 0) {
153 PERROR("gethostname. Fallback on default localhost");
154 strncpy(hostname, "localhost", sizeof(hostname));
155 }
156 hostname[sizeof(hostname) - 1] = '\0';
157
158 /* Setup consumer subdir if none present in the control URI */
159 if (strlen(dst_uri->subdir) == 0) {
160 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
161 hostname, obj->subdir);
162 } else {
163 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
164 hostname, dst_uri->subdir);
165 }
166 if (ret < 0) {
167 PERROR("snprintf set consumer uri subdir");
168 goto error;
169 }
170
171 strncpy(obj->subdir, tmp_path, sizeof(obj->subdir));
172 DBG3("Consumer set network uri subdir path %s", tmp_path);
173 }
174
175 end:
176 return 0;
177
178 error:
179 return -1;
180 }
181
182 /*
183 * Send file descriptor to consumer via sock.
184 */
185 int consumer_send_fds(int sock, int *fds, size_t nb_fd)
186 {
187 int ret;
188
189 assert(fds);
190 assert(nb_fd > 0);
191
192 ret = lttcomm_send_fds_unix_sock(sock, fds, nb_fd);
193 if (ret < 0) {
194 PERROR("send consumer fds");
195 goto error;
196 }
197
198 error:
199 return ret;
200 }
201
202 /*
203 * Consumer send channel communication message structure to consumer.
204 */
205 int consumer_send_channel(int sock, struct lttcomm_consumer_msg *msg)
206 {
207 int ret;
208
209 assert(msg);
210 assert(sock >= 0);
211
212 ret = lttcomm_send_unix_sock(sock, msg,
213 sizeof(struct lttcomm_consumer_msg));
214 if (ret < 0) {
215 PERROR("send consumer channel");
216 goto error;
217 }
218
219 error:
220 return ret;
221 }
222
223 /*
224 * Init channel communication message structure.
225 */
226 void consumer_init_channel_comm_msg(struct lttcomm_consumer_msg *msg,
227 enum lttng_consumer_command cmd,
228 int channel_key,
229 uint64_t max_sb_size,
230 uint64_t mmap_len,
231 const char *name)
232 {
233 assert(msg);
234
235 /* TODO: Args validation */
236
237 /* Zeroed structure */
238 memset(msg, 0, sizeof(struct lttcomm_consumer_msg));
239
240 /* Send channel */
241 msg->cmd_type = cmd;
242 msg->u.channel.channel_key = channel_key;
243 msg->u.channel.max_sb_size = max_sb_size;
244 msg->u.channel.mmap_len = mmap_len;
245 }
246
247 /*
248 * Init stream communication message structure.
249 */
250 void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg,
251 enum lttng_consumer_command cmd,
252 int channel_key,
253 int stream_key,
254 uint32_t state,
255 enum lttng_event_output output,
256 uint64_t mmap_len,
257 uid_t uid,
258 gid_t gid,
259 int net_index,
260 unsigned int metadata_flag,
261 const char *name,
262 const char *pathname)
263 {
264 assert(msg);
265
266 memset(msg, 0, sizeof(struct lttcomm_consumer_msg));
267
268 /* TODO: Args validation */
269
270 msg->cmd_type = cmd;
271 msg->u.stream.channel_key = channel_key;
272 msg->u.stream.stream_key = stream_key;
273 msg->u.stream.state = state;
274 msg->u.stream.output = output;
275 msg->u.stream.mmap_len = mmap_len;
276 msg->u.stream.uid = uid;
277 msg->u.stream.gid = gid;
278 msg->u.stream.net_index = net_index;
279 msg->u.stream.metadata_flag = metadata_flag;
280 strncpy(msg->u.stream.name, name, sizeof(msg->u.stream.name));
281 msg->u.stream.name[sizeof(msg->u.stream.name) - 1] = '\0';
282 strncpy(msg->u.stream.path_name, pathname,
283 sizeof(msg->u.stream.path_name));
284 msg->u.stream.path_name[sizeof(msg->u.stream.path_name) - 1] = '\0';
285 }
286
287 /*
288 * Send stream communication structure to the consumer.
289 */
290 int consumer_send_stream(int sock, struct consumer_output *dst,
291 struct lttcomm_consumer_msg *msg, int *fds, size_t nb_fd)
292 {
293 int ret;
294
295 assert(msg);
296 assert(dst);
297
298 switch (dst->type) {
299 case CONSUMER_DST_NET:
300 /* Consumer should send the stream on the network. */
301 msg->u.stream.net_index = dst->net_seq_index;
302 break;
303 case CONSUMER_DST_LOCAL:
304 /* Add stream file name to stream path */
305 strncat(msg->u.stream.path_name, "/", sizeof(msg->u.stream.path_name));
306 strncat(msg->u.stream.path_name, msg->u.stream.name,
307 sizeof(msg->u.stream.path_name));
308 msg->u.stream.path_name[sizeof(msg->u.stream.path_name) - 1] = '\0';
309 /* Indicate that the stream is NOT network */
310 msg->u.stream.net_index = -1;
311 break;
312 default:
313 ERR("Consumer unknown output type (%d)", dst->type);
314 ret = -1;
315 goto error;
316 }
317
318 /* Send on socket */
319 ret = lttcomm_send_unix_sock(sock, msg,
320 sizeof(struct lttcomm_consumer_msg));
321 if (ret < 0) {
322 PERROR("send consumer stream");
323 goto error;
324 }
325
326 ret = consumer_send_fds(sock, fds, nb_fd);
327 if (ret < 0) {
328 goto error;
329 }
330
331 error:
332 return ret;
333 }
334
335 /*
336 * Send relayd socket to consumer associated with a session name.
337 *
338 * On success return positive value. On error, negative value.
339 */
340 int consumer_send_relayd_socket(int consumer_sock,
341 struct lttcomm_sock *sock, struct consumer_output *consumer,
342 enum lttng_stream_type type)
343 {
344 int ret;
345 struct lttcomm_consumer_msg msg;
346
347 /* Code flow error. Safety net. */
348 assert(sock);
349 assert(consumer);
350
351 /* Bail out if consumer is disabled */
352 if (!consumer->enabled) {
353 ret = LTTCOMM_OK;
354 goto error;
355 }
356
357 msg.cmd_type = LTTNG_CONSUMER_ADD_RELAYD_SOCKET;
358 /*
359 * Assign network consumer output index using the temporary consumer since
360 * this call should only be made from within a set_consumer_uri() function
361 * call in the session daemon.
362 */
363 msg.u.relayd_sock.net_index = consumer->net_seq_index;
364 msg.u.relayd_sock.type = type;
365 memcpy(&msg.u.relayd_sock.sock, sock, sizeof(msg.u.relayd_sock.sock));
366
367 DBG3("Sending relayd sock info to consumer");
368 ret = lttcomm_send_unix_sock(consumer_sock, &msg, sizeof(msg));
369 if (ret < 0) {
370 PERROR("send consumer relayd socket info");
371 goto error;
372 }
373
374 DBG3("Sending relayd socket file descriptor to consumer");
375 ret = consumer_send_fds(consumer_sock, &sock->fd, 1);
376 if (ret < 0) {
377 goto error;
378 }
379
380 DBG2("Consumer relayd socket sent");
381
382 error:
383 return ret;
384 }
This page took 0.035654 seconds and 3 git commands to generate.