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