713731c3e222590d9a92085cd349d9fadc0264d4
[lttng-tools.git] / src / common / session-descriptor.c
1 /*
2 * Copyright (C) 2019 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
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.
7 *
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
11 * for more details.
12 *
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
16 */
17
18 #include <lttng/session-descriptor-internal.h>
19 #include <common/macros.h>
20 #include <common/uri.h>
21 #include <common/defaults.h>
22 #include <common/error.h>
23 #include <time.h>
24 #include <assert.h>
25 #include <stdio.h>
26
27 struct lttng_session_descriptor_network_location {
28 struct lttng_uri *control;
29 struct lttng_uri *data;
30 };
31
32 struct lttng_session_descriptor {
33 enum lttng_session_descriptor_type type;
34 /*
35 * If an output type that is not OUTPUT_TYPE_NONE is specified,
36 * it means that an output of that type must be generated at
37 * session-creation time.
38 */
39 enum lttng_session_descriptor_output_type output_type;
40 char *name;
41 union {
42 struct lttng_session_descriptor_network_location network;
43 struct lttng_uri *local;
44 } output;
45 };
46
47 struct lttng_session_descriptor_snapshot {
48 struct lttng_session_descriptor base;
49 /*
50 * Assumes at-most one snapshot output is supported. Uses
51 * the output field of the base class.
52 */
53 };
54
55 struct lttng_session_descriptor_live {
56 struct lttng_session_descriptor base;
57 unsigned long long live_timer_us;
58 };
59
60 struct lttng_session_descriptor_comm {
61 /* enum lttng_session_descriptor_type */
62 uint8_t type;
63 /* enum lttng_session_descriptor_output_type */
64 uint8_t output_type;
65 /* Includes trailing null. */
66 uint32_t name_len;
67 /* Name follows, followed by URIs */
68 uint8_t uri_count;
69 } LTTNG_PACKED;
70
71 struct lttng_session_descriptor_live_comm {
72 struct lttng_session_descriptor_comm base;
73 /* Live-specific parameters. */
74 uint64_t live_timer_us;
75 } LTTNG_PACKED;
76
77 static
78 struct lttng_uri *uri_copy(const struct lttng_uri *uri)
79 {
80 struct lttng_uri *new_uri = NULL;
81
82 if (!uri) {
83 goto end;
84 }
85
86 new_uri = zmalloc(sizeof(*new_uri));
87 if (!new_uri) {
88 goto end;
89 }
90 memcpy(new_uri, uri, sizeof(*new_uri));
91 end:
92 return new_uri;
93 }
94
95 static
96 struct lttng_uri *uri_from_path(const char *path)
97 {
98 struct lttng_uri *uris = NULL;
99 ssize_t uri_count;
100 char local_protocol_string[LTTNG_PATH_MAX + sizeof("file://")] =
101 "file://";
102
103 if (strlen(path) >= LTTNG_PATH_MAX) {
104 goto end;
105 }
106
107 if (path[0] != '/') {
108 /* Not an absolute path. */
109 goto end;
110 }
111
112 strncat(local_protocol_string, path, LTTNG_PATH_MAX);
113 uri_count = uri_parse(local_protocol_string, &uris);
114 if (uri_count != 1) {
115 goto error;
116 }
117 if (uris[0].dtype != LTTNG_DST_PATH) {
118 goto error;
119 }
120
121 end:
122 return uris;
123 error:
124 free(uris);
125 return NULL;
126 }
127
128 static
129 void network_location_fini(
130 struct lttng_session_descriptor_network_location *location)
131 {
132 free(location->control);
133 free(location->data);
134 }
135
136 /* Assumes ownership of control and data. */
137 static
138 int network_location_set_from_lttng_uris(
139 struct lttng_session_descriptor_network_location *location,
140 struct lttng_uri *control, struct lttng_uri *data)
141 {
142 int ret = 0;
143
144 if (!control && !data) {
145 goto end;
146 }
147
148 if (!(control && data)) {
149 /* None or both must be set. */
150 ret = -1;
151 goto end;
152 }
153
154 if (control->stype != LTTNG_STREAM_CONTROL ||
155 data->stype != LTTNG_STREAM_DATA) {
156 ret = -1;
157 goto end;
158 }
159
160 free(location->control);
161 free(location->data);
162 location->control = control;
163 location->data = data;
164 control = NULL;
165 data = NULL;
166 end:
167 free(control);
168 free(data);
169 return ret;
170 }
171
172 static
173 int network_location_set_from_uri_strings(
174 struct lttng_session_descriptor_network_location *location,
175 const char *control, const char *data)
176 {
177 int ret = 0;
178 ssize_t uri_count;
179 struct lttng_uri *parsed_uris = NULL;
180 struct lttng_uri *control_uri = NULL;
181 struct lttng_uri *data_uri = NULL;
182
183 uri_count = uri_parse_str_urls(control, data, &parsed_uris);
184 if (uri_count != 2 && uri_count != 0) {
185 ret = -1;
186 goto end;
187 }
188
189 /*
190 * uri_parse_str_urls returns a contiguous array of lttng_uris whereas
191 * session descriptors expect individually allocated lttng_uris.
192 */
193 if (uri_count == 2) {
194 control_uri = zmalloc(sizeof(*control_uri));
195 data_uri = zmalloc(sizeof(*data_uri));
196 if (!control_uri || !data_uri) {
197 ret = -1;
198 goto end;
199 }
200 memcpy(control_uri, &parsed_uris[0], sizeof(*control_uri));
201 memcpy(data_uri, &parsed_uris[1], sizeof(*data_uri));
202 }
203
204 /* Ownership of control and data uris is transferred. */
205 ret = network_location_set_from_lttng_uris(
206 location,
207 control_uri,
208 data_uri);
209 control_uri = NULL;
210 data_uri = NULL;
211 end:
212 free(parsed_uris);
213 free(control_uri);
214 free(data_uri);
215 return ret;
216 }
217
218 struct lttng_session_descriptor *
219 lttng_session_descriptor_create(const char *name)
220 {
221 struct lttng_session_descriptor *descriptor;
222
223 descriptor = zmalloc(sizeof(*descriptor));
224 if (!descriptor) {
225 goto error;
226 }
227
228 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
229 descriptor->output_type =
230 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
231 if (lttng_session_descriptor_set_session_name(descriptor, name)) {
232 goto error;
233 }
234 return descriptor;
235 error:
236 lttng_session_descriptor_destroy(descriptor);
237 return NULL;
238 }
239
240 /* Ownership of uri is transferred. */
241 static
242 struct lttng_session_descriptor *
243 _lttng_session_descriptor_local_create(const char *name,
244 struct lttng_uri *uri)
245 {
246 struct lttng_session_descriptor *descriptor;
247
248 descriptor = lttng_session_descriptor_create(name);
249 if (!descriptor) {
250 goto error;
251 }
252 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
253 descriptor->output_type =
254 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
255 if (uri) {
256 if (uri->dtype != LTTNG_DST_PATH) {
257 goto error;
258 }
259 descriptor->output.local = uri;
260 uri = NULL;
261 }
262 return descriptor;
263 error:
264 free(uri);
265 lttng_session_descriptor_destroy(descriptor);
266 return NULL;
267 }
268
269 struct lttng_session_descriptor *
270 lttng_session_descriptor_local_create(const char *name, const char *path)
271 {
272 struct lttng_uri *uri = NULL;
273 struct lttng_session_descriptor *descriptor;
274
275 if (path) {
276 uri = uri_from_path(path);
277 if (!uri) {
278 goto error;
279 }
280 }
281 descriptor = _lttng_session_descriptor_local_create(name, uri);
282 return descriptor;
283 error:
284 return NULL;
285 }
286
287 /* Assumes the ownership of both uris. */
288 static
289 struct lttng_session_descriptor *
290 _lttng_session_descriptor_network_create(const char *name,
291 struct lttng_uri *control, struct lttng_uri *data)
292 {
293 int ret;
294 struct lttng_session_descriptor *descriptor;
295
296 descriptor = lttng_session_descriptor_create(name);
297 if (!descriptor) {
298 goto error;
299 }
300
301 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
302 descriptor->output_type = LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
303 /* Assumes the ownership of both uris. */
304 ret = network_location_set_from_lttng_uris(&descriptor->output.network,
305 control, data);
306 control = NULL;
307 data = NULL;
308 if (ret) {
309 goto error;
310 }
311 return descriptor;
312 error:
313 lttng_session_descriptor_destroy(descriptor);
314 free(control);
315 free(data);
316 return NULL;
317 }
318
319 struct lttng_session_descriptor *
320 lttng_session_descriptor_network_create(const char *name,
321 const char *control_url, const char *data_url)
322 {
323 int ret;
324 struct lttng_session_descriptor *descriptor;
325
326 descriptor = _lttng_session_descriptor_network_create(name,
327 NULL, NULL);
328 if (!descriptor) {
329 goto error;
330 }
331
332 ret = network_location_set_from_uri_strings(&descriptor->output.network,
333 control_url, data_url);
334 if (ret) {
335 goto error;
336 }
337 return descriptor;
338 error:
339 lttng_session_descriptor_destroy(descriptor);
340 return NULL;
341 }
342
343 static
344 struct lttng_session_descriptor_snapshot *
345 _lttng_session_descriptor_snapshot_create(const char *name)
346 {
347 struct lttng_session_descriptor_snapshot *descriptor;
348
349 descriptor = zmalloc(sizeof(*descriptor));
350 if (!descriptor) {
351 goto error;
352 }
353
354 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT;
355 descriptor->base.output_type =
356 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
357 if (lttng_session_descriptor_set_session_name(&descriptor->base,
358 name)) {
359 goto error;
360 }
361 return descriptor;
362 error:
363 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
364 return NULL;
365 }
366
367 /* Ownership of control and data is transferred. */
368 static
369 struct lttng_session_descriptor_snapshot *
370 _lttng_session_descriptor_snapshot_network_create(const char *name,
371 struct lttng_uri *control, struct lttng_uri *data)
372 {
373 int ret;
374 struct lttng_session_descriptor_snapshot *descriptor;
375
376 descriptor = _lttng_session_descriptor_snapshot_create(name);
377 if (!descriptor) {
378 goto error;
379 }
380
381 descriptor->base.output_type =
382 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
383 /* Ownership of control and data is transferred. */
384 ret = network_location_set_from_lttng_uris(
385 &descriptor->base.output.network,
386 control, data);
387 control = NULL;
388 data = NULL;
389 if (ret) {
390 goto error;
391 }
392 return descriptor;
393 error:
394 free(control);
395 free(data);
396 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
397 return NULL;
398 }
399
400 struct lttng_session_descriptor *
401 lttng_session_descriptor_snapshot_create(const char *name)
402 {
403 struct lttng_session_descriptor_snapshot *descriptor;
404
405 descriptor = _lttng_session_descriptor_snapshot_create(name);
406 return descriptor ? &descriptor->base : NULL;
407 }
408
409 struct lttng_session_descriptor *
410 lttng_session_descriptor_snapshot_network_create(const char *name,
411 const char *control_url, const char *data_url)
412 {
413 int ret;
414 struct lttng_session_descriptor_snapshot *descriptor;
415
416 descriptor = _lttng_session_descriptor_snapshot_network_create(name,
417 NULL, NULL);
418 if (!descriptor) {
419 goto error;
420 }
421
422 ret = network_location_set_from_uri_strings(
423 &descriptor->base.output.network,
424 control_url, data_url);
425 if (ret) {
426 goto error;
427 }
428 return &descriptor->base;
429 error:
430 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
431 return NULL;
432 }
433
434 /* Ownership of uri is transferred. */
435 static
436 struct lttng_session_descriptor_snapshot *
437 _lttng_session_descriptor_snapshot_local_create(const char *name,
438 struct lttng_uri *uri)
439 {
440 struct lttng_session_descriptor_snapshot *descriptor;
441
442 descriptor = _lttng_session_descriptor_snapshot_create(name);
443 if (!descriptor) {
444 goto error;
445 }
446 descriptor->base.output_type =
447 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
448 if (uri) {
449 if (uri->dtype != LTTNG_DST_PATH) {
450 goto error;
451 }
452 descriptor->base.output.local = uri;
453 uri = NULL;
454 }
455 return descriptor;
456 error:
457 free(uri);
458 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
459 return NULL;
460 }
461
462 struct lttng_session_descriptor *
463 lttng_session_descriptor_snapshot_local_create(const char *name,
464 const char *path)
465 {
466 struct lttng_uri *path_uri = NULL;
467 struct lttng_session_descriptor_snapshot *descriptor;
468
469 if (path) {
470 path_uri = uri_from_path(path);
471 if (!path_uri) {
472 goto error;
473 }
474 }
475 descriptor = _lttng_session_descriptor_snapshot_local_create(name,
476 path_uri);
477 return descriptor ? &descriptor->base : NULL;
478 error:
479 return NULL;
480 }
481
482 static
483 struct lttng_session_descriptor_live *
484 _lttng_session_descriptor_live_create(const char *name,
485 unsigned long long live_timer_interval_us)
486 {
487 struct lttng_session_descriptor_live *descriptor = NULL;
488
489 if (live_timer_interval_us == 0) {
490 goto error;
491 }
492 descriptor = zmalloc(sizeof(*descriptor));
493 if (!descriptor) {
494 goto error;
495 }
496
497 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE;
498 descriptor->base.output_type =
499 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
500 descriptor->live_timer_us = live_timer_interval_us;
501 if (lttng_session_descriptor_set_session_name(&descriptor->base,
502 name)) {
503 goto error;
504 }
505
506 return descriptor;
507 error:
508 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
509 return NULL;
510 }
511
512 /* Ownership of control and data is transferred. */
513 static
514 struct lttng_session_descriptor_live *
515 _lttng_session_descriptor_live_network_create(
516 const char *name,
517 struct lttng_uri *control, struct lttng_uri *data,
518 unsigned long long live_timer_interval_us)
519 {
520 int ret;
521 struct lttng_session_descriptor_live *descriptor;
522
523 descriptor = _lttng_session_descriptor_live_create(name,
524 live_timer_interval_us);
525 descriptor->base.output_type =
526 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
527
528 /* Ownerwhip of control and data is transferred. */
529 ret = network_location_set_from_lttng_uris(
530 &descriptor->base.output.network,
531 control, data);
532 control = NULL;
533 data = NULL;
534 if (ret) {
535 goto error;
536 }
537 return descriptor;
538 error:
539 free(control);
540 free(data);
541 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
542 return NULL;
543 }
544
545 struct lttng_session_descriptor *
546 lttng_session_descriptor_live_create(
547 const char *name,
548 unsigned long long live_timer_us)
549 {
550 struct lttng_session_descriptor_live *descriptor;
551
552 descriptor = _lttng_session_descriptor_live_create(name, live_timer_us);
553
554 return descriptor ? &descriptor->base : NULL;
555 }
556
557 struct lttng_session_descriptor *
558 lttng_session_descriptor_live_network_create(
559 const char *name,
560 const char *control_url, const char *data_url,
561 unsigned long long live_timer_us)
562 {
563 int ret;
564 struct lttng_session_descriptor_live *descriptor;
565
566 descriptor = _lttng_session_descriptor_live_network_create(name,
567 NULL, NULL, live_timer_us);
568 if (!descriptor) {
569 goto error;
570 }
571
572 ret = network_location_set_from_uri_strings(
573 &descriptor->base.output.network,
574 control_url, data_url);
575 if (ret) {
576 goto error;
577 }
578 return &descriptor->base;
579 error:
580 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
581 return NULL;
582 }
583
584 void lttng_session_descriptor_destroy(
585 struct lttng_session_descriptor *descriptor)
586 {
587 if (!descriptor) {
588 return;
589 }
590
591 switch (descriptor->output_type) {
592 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
593 break;
594 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
595 free(descriptor->output.local);
596 break;
597 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
598 network_location_fini(&descriptor->output.network);
599 break;
600 default:
601 abort();
602 }
603
604 free(descriptor->name);
605 free(descriptor);
606 }
607
608 LTTNG_HIDDEN
609 ssize_t lttng_session_descriptor_create_from_buffer(
610 const struct lttng_buffer_view *payload,
611 struct lttng_session_descriptor **descriptor)
612 {
613 int i;
614 ssize_t offset = 0, ret;
615 struct lttng_buffer_view current_view;
616 const char *name = NULL;
617 const struct lttng_session_descriptor_comm *base_header;
618 size_t max_expected_uri_count;
619 uint64_t live_timer_us = 0;
620 struct lttng_uri *uris[2] = {};
621 enum lttng_session_descriptor_type type;
622 enum lttng_session_descriptor_output_type output_type;
623
624 current_view = lttng_buffer_view_from_view(payload, offset,
625 sizeof(*base_header));
626 base_header = (typeof(base_header)) current_view.data;
627 if (!base_header) {
628 ret = -1;
629 goto end;
630 }
631
632 switch (base_header->type) {
633 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
634 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
635 break;
636 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
637 {
638 const struct lttng_session_descriptor_live_comm *live_header;
639
640 current_view = lttng_buffer_view_from_view(payload, offset,
641 sizeof(*live_header));
642 live_header = (typeof(live_header)) current_view.data;
643 if (!live_header) {
644 ret = -1;
645 goto end;
646 }
647
648 live_timer_us = live_header->live_timer_us;
649 break;
650 }
651 default:
652 ret = -1;
653 goto end;
654 }
655 /* type has been validated. */
656 type = base_header->type;
657
658 switch (base_header->output_type) {
659 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
660 max_expected_uri_count = 0;
661 break;
662 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
663 max_expected_uri_count = 1;
664 break;
665 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
666 max_expected_uri_count = 2;
667 break;
668 default:
669 ret = -1;
670 goto end;
671 }
672 /* output_type has been validated. */
673 output_type = base_header->output_type;
674
675 /* Skip after header. */
676 offset += current_view.size;
677 if (!base_header->name_len) {
678 goto skip_name;
679 }
680
681 /* Map the name. */
682 current_view = lttng_buffer_view_from_view(payload, offset,
683 base_header->name_len);
684 name = current_view.data;
685 if (!name) {
686 ret = -1;
687 goto end;
688 }
689
690 if (base_header->name_len == 1 ||
691 name[base_header->name_len - 1] ||
692 strlen(name) != base_header->name_len - 1) {
693 /*
694 * Check that the name is not NULL, is NULL-terminated, and
695 * does not contain a NULL before the last byte.
696 */
697 ret = -1;
698 goto end;
699 }
700
701 /* Skip after the name. */
702 offset += base_header->name_len;
703 skip_name:
704 if (base_header->uri_count > max_expected_uri_count) {
705 ret = -1;
706 goto end;
707 }
708
709 for (i = 0; i < base_header->uri_count; i++) {
710 struct lttng_uri *uri;
711
712 /* Map a URI. */
713 current_view = lttng_buffer_view_from_view(payload,
714 offset, sizeof(*uri));
715 uri = (typeof(uri)) current_view.data;
716 if (!uri) {
717 ret = -1;
718 goto end;
719 }
720 uris[i] = zmalloc(sizeof(*uri));
721 if (!uris[i]) {
722 ret = -1;
723 goto end;
724 }
725 memcpy(uris[i], uri, sizeof(*uri));
726 offset += sizeof(*uri);
727 }
728
729 switch (type) {
730 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
731 switch (output_type) {
732 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
733 *descriptor = lttng_session_descriptor_create(name);
734 break;
735 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
736 *descriptor = _lttng_session_descriptor_local_create(
737 name, uris[0]);
738 break;
739 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
740 *descriptor = _lttng_session_descriptor_network_create(
741 name, uris[0], uris[1]);
742 break;
743 default:
744 /* Already checked. */
745 abort();
746 }
747 break;
748 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
749 {
750 struct lttng_session_descriptor_snapshot *snapshot;
751 switch (output_type) {
752 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
753 snapshot = _lttng_session_descriptor_snapshot_create(
754 name);
755 break;
756 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
757 snapshot = _lttng_session_descriptor_snapshot_local_create(
758 name, uris[0]);
759 break;
760 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
761 snapshot = _lttng_session_descriptor_snapshot_network_create(
762 name, uris[0], uris[1]);
763 break;
764 default:
765 /* Already checked. */
766 abort();
767 }
768 *descriptor = snapshot ? &snapshot->base : NULL;
769 break;
770 }
771 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
772 {
773 struct lttng_session_descriptor_live *live;
774
775 switch (output_type) {
776 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
777 live = _lttng_session_descriptor_live_create(
778 name, live_timer_us);
779 break;
780 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
781 live = _lttng_session_descriptor_live_network_create(
782 name, uris[0], uris[1],
783 live_timer_us);
784 break;
785 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
786 ret = -1;
787 goto end;
788 default:
789 /* Already checked. */
790 abort();
791 }
792 *descriptor = live ? &live->base : NULL;
793 break;
794 }
795 default:
796 /* Already checked. */
797 abort();
798 }
799 memset(uris, 0, sizeof(uris));
800 if (!*descriptor) {
801 ret = -1;
802 goto end;
803 }
804
805 ret = offset;
806 end:
807 free(uris[0]);
808 free(uris[1]);
809 return ret;
810 }
811
812 LTTNG_HIDDEN
813 int lttng_session_descriptor_serialize(
814 const struct lttng_session_descriptor *descriptor,
815 struct lttng_dynamic_buffer *buffer)
816 {
817 int ret, i;
818 /* There are, at most, two URIs to serialize. */
819 struct lttng_uri *uris[2] = {};
820 size_t uri_count = 0;
821 /* The live header is a superset of all headers. */
822 struct lttng_session_descriptor_live_comm header = {
823 .base.type = (uint8_t) descriptor->type,
824 .base.output_type = (uint8_t) descriptor->output_type,
825 .base.name_len = descriptor->name ?
826 strlen(descriptor->name) + 1 : 0,
827 };
828 const void *header_ptr = NULL;
829 size_t header_size;
830
831 switch (descriptor->output_type) {
832 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
833 break;
834 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
835 uris[0] = descriptor->output.local;
836 break;
837 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
838 uris[0] = descriptor->output.network.control;
839 uris[1] = descriptor->output.network.data;
840 break;
841 default:
842 ret = -1;
843 goto end;
844 }
845 uri_count += !!uris[0];
846 uri_count += !!uris[1];
847
848 header.base.uri_count = uri_count;
849 if (descriptor->type == LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE) {
850 const struct lttng_session_descriptor_live *live =
851 container_of(descriptor, typeof(*live),
852 base);
853
854 header.live_timer_us = live->live_timer_us;
855 header_ptr = &header;
856 header_size = sizeof(header);
857 } else {
858 header_ptr = &header.base;
859 header_size = sizeof(header.base);
860 }
861
862 ret = lttng_dynamic_buffer_append(buffer, header_ptr, header_size);
863 if (ret) {
864 goto end;
865 }
866 if (header.base.name_len) {
867 ret = lttng_dynamic_buffer_append(buffer, descriptor->name,
868 header.base.name_len);
869 if (ret) {
870 goto end;
871 }
872 }
873
874 for (i = 0; i < uri_count; i++) {
875 ret = lttng_dynamic_buffer_append(buffer, uris[i],
876 sizeof(struct lttng_uri));
877 if (ret) {
878 goto end;
879 }
880 }
881 end:
882 return ret;
883 }
884
885 LTTNG_HIDDEN
886 enum lttng_session_descriptor_type
887 lttng_session_descriptor_get_type(
888 const struct lttng_session_descriptor *descriptor)
889 {
890 return descriptor->type;
891 }
892
893 LTTNG_HIDDEN
894 enum lttng_session_descriptor_output_type
895 lttng_session_descriptor_get_output_type(
896 const struct lttng_session_descriptor *descriptor)
897 {
898 return descriptor->output_type;
899 }
900
901 LTTNG_HIDDEN
902 void lttng_session_descriptor_get_local_output_uri(
903 const struct lttng_session_descriptor *descriptor,
904 struct lttng_uri *local_uri)
905 {
906 memcpy(local_uri, descriptor->output.local, sizeof(*local_uri));
907 }
908
909 LTTNG_HIDDEN
910 void lttng_session_descriptor_get_network_output_uris(
911 const struct lttng_session_descriptor *descriptor,
912 struct lttng_uri *control,
913 struct lttng_uri *data)
914 {
915 memcpy(control, descriptor->output.network.control, sizeof(*control));
916 memcpy(data, descriptor->output.network.data, sizeof(*data));
917 }
918
919 LTTNG_HIDDEN
920 unsigned long long
921 lttng_session_descriptor_live_get_timer_interval(
922 const struct lttng_session_descriptor *descriptor)
923 {
924 struct lttng_session_descriptor_live *live;
925
926 live = container_of(descriptor, typeof(*live), base);
927 return live->live_timer_us;
928 }
929
930 enum lttng_session_descriptor_status
931 lttng_session_descriptor_get_session_name(
932 const struct lttng_session_descriptor *descriptor,
933 const char **session_name)
934 {
935 enum lttng_session_descriptor_status status;
936
937 if (!descriptor || !session_name) {
938 status = LTTNG_SESSION_DESCRIPTOR_STATUS_INVALID;
939 goto end;
940 }
941
942 *session_name = descriptor->name;
943 status = descriptor->name ?
944 LTTNG_SESSION_DESCRIPTOR_STATUS_OK :
945 LTTNG_SESSION_DESCRIPTOR_STATUS_UNSET;
946 end:
947 return status;
948 }
949
950 LTTNG_HIDDEN
951 int lttng_session_descriptor_set_session_name(
952 struct lttng_session_descriptor *descriptor,
953 const char *name)
954 {
955 int ret = 0;
956 char *new_name;
957
958 if (!name) {
959 goto end;
960 }
961 if (strlen(name) >= LTTNG_NAME_MAX) {
962 ret = -1;
963 goto end;
964 }
965 new_name = strdup(name);
966 if (!new_name) {
967 ret = -1;
968 goto end;
969 }
970 free(descriptor->name);
971 descriptor->name = new_name;
972 end:
973 return ret;
974 }
975
976 LTTNG_HIDDEN
977 bool lttng_session_descriptor_is_output_destination_initialized(
978 const struct lttng_session_descriptor *descriptor)
979 {
980 switch (descriptor->output_type) {
981 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
982 return true;
983 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
984 return descriptor->output.local;
985 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
986 return descriptor->output.network.control;
987 default:
988 abort();
989 }
990 }
991
992 LTTNG_HIDDEN
993 bool lttng_session_descriptor_has_output_directory(
994 const struct lttng_session_descriptor *descriptor)
995 {
996 switch (descriptor->output_type) {
997 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
998 break;
999 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1000 if (descriptor->output.local) {
1001 return *descriptor->output.local->dst.path;
1002 }
1003 break;
1004 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1005 if (descriptor->output.network.control) {
1006 return *descriptor->output.network.control->subdir;
1007 }
1008 break;
1009 default:
1010 abort();
1011 }
1012 return false;
1013 }
1014
1015 LTTNG_HIDDEN
1016 enum lttng_error_code lttng_session_descriptor_set_default_output(
1017 struct lttng_session_descriptor *descriptor,
1018 time_t *session_creation_time,
1019 const char *absolute_home_path)
1020 {
1021 enum lttng_error_code ret_code = LTTNG_OK;
1022 struct lttng_uri *uris = NULL;
1023
1024 switch (descriptor->output_type) {
1025 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1026 goto end;
1027 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1028 {
1029 int ret;
1030 ssize_t uri_ret;
1031 char local_uri[LTTNG_PATH_MAX];
1032 char creation_datetime_suffix[17] = {};
1033
1034 if (session_creation_time) {
1035 size_t strftime_ret;
1036 struct tm *timeinfo;
1037
1038 timeinfo = localtime(session_creation_time);
1039 if (!timeinfo) {
1040 ret_code = LTTNG_ERR_FATAL;
1041 goto end;
1042 }
1043 strftime_ret = strftime(creation_datetime_suffix,
1044 sizeof(creation_datetime_suffix),
1045 "-%Y%m%d-%H%M%S", timeinfo);
1046 if (strftime_ret == 0) {
1047 ERR("Failed to format session creation timestamp while setting default local output destination");
1048 ret_code = LTTNG_ERR_FATAL;
1049 goto end;
1050 }
1051 }
1052 assert(descriptor->name);
1053 ret = snprintf(local_uri, sizeof(local_uri),
1054 "file://%s/%s/%s%s",
1055 absolute_home_path,
1056 DEFAULT_TRACE_DIR_NAME, descriptor->name,
1057 creation_datetime_suffix);
1058 if (ret >= sizeof(local_uri)) {
1059 ERR("Truncation occurred while setting default local output destination");
1060 ret_code = LTTNG_ERR_SET_URL;
1061 goto end;
1062 } else if (ret < 0) {
1063 PERROR("Failed to format default local output URI");
1064 ret_code = LTTNG_ERR_SET_URL;
1065 goto end;
1066 }
1067
1068 uri_ret = uri_parse(local_uri, &uris);
1069 if (uri_ret != 1) {
1070 ret_code = LTTNG_ERR_SET_URL;
1071 goto end;
1072 }
1073 free(descriptor->output.local);
1074 descriptor->output.local = &uris[0];
1075 uris = NULL;
1076 break;
1077 }
1078 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1079 {
1080 int ret;
1081 ssize_t uri_ret;
1082 struct lttng_uri *control = NULL, *data = NULL;
1083
1084 uri_ret = uri_parse_str_urls("net://127.0.0.1", NULL, &uris);
1085 if (uri_ret != 2) {
1086 ret_code = LTTNG_ERR_SET_URL;
1087 goto end;
1088 }
1089
1090 control = uri_copy(&uris[0]);
1091 data = uri_copy(&uris[1]);
1092 if (!control || !data) {
1093 free(control);
1094 free(data);
1095 ret_code = LTTNG_ERR_SET_URL;
1096 goto end;
1097 }
1098
1099 /* Ownership of uris is transferred. */
1100 ret = network_location_set_from_lttng_uris(
1101 &descriptor->output.network,
1102 control, data);
1103 if (ret) {
1104 abort();
1105 ret_code = LTTNG_ERR_SET_URL;
1106 goto end;
1107 }
1108 break;
1109 }
1110 default:
1111 abort();
1112 }
1113 end:
1114 free(uris);
1115 return ret_code;
1116 }
1117
1118 /*
1119 * Note that only properties that can be populated by the session daemon
1120 * (output destination and name) are assigned.
1121 */
1122 LTTNG_HIDDEN
1123 int lttng_session_descriptor_assign(
1124 struct lttng_session_descriptor *dst,
1125 const struct lttng_session_descriptor *src)
1126 {
1127 int ret = 0;
1128
1129 if (dst->type != src->type) {
1130 ret = -1;
1131 goto end;
1132 }
1133 if (dst->output_type != src->output_type) {
1134 ret = -1;
1135 goto end;
1136 }
1137 ret = lttng_session_descriptor_set_session_name(dst, src->name);
1138 if (ret) {
1139 goto end;
1140 }
1141 switch (dst->output_type) {
1142 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1143 free(dst->output.local);
1144 dst->output.local = uri_copy(src->output.local);
1145 if (!dst->output.local) {
1146 ret = -1;
1147 goto end;
1148 }
1149 break;
1150 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1151 {
1152 struct lttng_uri *control_copy = NULL, *data_copy = NULL;
1153
1154 control_copy = uri_copy(dst->output.network.control);
1155 if (!control_copy && dst->output.network.control) {
1156 ret = -1;
1157 goto end;
1158 }
1159 data_copy = uri_copy(dst->output.network.data);
1160 if (!data_copy && dst->output.network.data) {
1161 free(control_copy);
1162 ret = -1;
1163 goto end;
1164 }
1165 ret = network_location_set_from_lttng_uris(&dst->output.network,
1166 control_copy, data_copy);
1167 break;
1168 }
1169 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1170 goto end;
1171 }
1172 end:
1173 return ret;
1174 }
1175
1176 LTTNG_HIDDEN
1177 int lttng_session_descriptor_get_base_path(struct lttng_session_descriptor *dst,
1178 const char **_base_path)
1179 {
1180 switch (dst->output_type) {
1181 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1182 {
1183 if (dst->output.network.control &&
1184 dst->output.network.control->subdir[0]) {
1185 *_base_path = dst->output.network.control->subdir;
1186 } else {
1187 *_base_path = NULL;
1188 }
1189 break;
1190 }
1191 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1192 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1193 *_base_path = NULL;
1194 break;
1195 }
1196 return 0;
1197 }
This page took 0.088178 seconds and 3 git commands to generate.