Build fix: missing type traits on gcc < 5.0
[lttng-tools.git] / src / common / session-descriptor.cpp
1 /*
2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 */
6
7 #include <lttng/session-descriptor-internal.hpp>
8 #include <common/macros.hpp>
9 #include <common/uri.hpp>
10 #include <common/defaults.hpp>
11 #include <common/error.hpp>
12 #include <time.h>
13 #include <stdio.h>
14
15 struct lttng_session_descriptor_network_location {
16 struct lttng_uri *control;
17 struct lttng_uri *data;
18 };
19
20 struct 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
35 struct 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
43 struct lttng_session_descriptor_live {
44 struct lttng_session_descriptor base;
45 unsigned long long live_timer_us;
46 };
47
48 struct 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
59 struct 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
65 static
66 struct 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<lttng_uri>();
75 if (!new_uri) {
76 goto end;
77 }
78 memcpy(new_uri, uri, sizeof(*new_uri));
79 end:
80 return new_uri;
81 }
82
83 static
84 struct 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
109 end:
110 return uris;
111 error:
112 free(uris);
113 return NULL;
114 }
115
116 static
117 void 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. */
125 static
126 int 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;
154 end:
155 free(control);
156 free(data);
157 return ret;
158 }
159
160 static
161 int 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<lttng_uri>();
183 data_uri = zmalloc<lttng_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;
199 end:
200 free(parsed_uris);
201 free(control_uri);
202 free(data_uri);
203 return ret;
204 }
205
206 struct lttng_session_descriptor *
207 lttng_session_descriptor_create(const char *name)
208 {
209 struct lttng_session_descriptor *descriptor;
210
211 descriptor = zmalloc<lttng_session_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;
223 error:
224 lttng_session_descriptor_destroy(descriptor);
225 return NULL;
226 }
227
228 /* Ownership of uri is transferred. */
229 static
230 struct 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;
251 error:
252 free(uri);
253 lttng_session_descriptor_destroy(descriptor);
254 return NULL;
255 }
256
257 struct lttng_session_descriptor *
258 lttng_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;
271 error:
272 return NULL;
273 }
274
275 /* Assumes the ownership of both uris. */
276 static
277 struct 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;
300 error:
301 lttng_session_descriptor_destroy(descriptor);
302 free(control);
303 free(data);
304 return NULL;
305 }
306
307 struct lttng_session_descriptor *
308 lttng_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;
326 error:
327 lttng_session_descriptor_destroy(descriptor);
328 return NULL;
329 }
330
331 static
332 struct 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<lttng_session_descriptor_snapshot>();
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;
350 error:
351 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
352 return NULL;
353 }
354
355 /* Ownership of control and data is transferred. */
356 static
357 struct 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;
381 error:
382 free(control);
383 free(data);
384 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
385 return NULL;
386 }
387
388 struct lttng_session_descriptor *
389 lttng_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
397 struct lttng_session_descriptor *
398 lttng_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;
417 error:
418 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
419 return NULL;
420 }
421
422 /* Ownership of uri is transferred. */
423 static
424 struct 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;
444 error:
445 free(uri);
446 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
447 return NULL;
448 }
449
450 struct lttng_session_descriptor *
451 lttng_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;
466 error:
467 return NULL;
468 }
469
470 static
471 struct 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<lttng_session_descriptor_live>();
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;
495 error:
496 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
497 return NULL;
498 }
499
500 /* Ownership of control and data is transferred. */
501 static
502 struct 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);
513 if (!descriptor) {
514 goto error;
515 }
516
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;
530 error:
531 free(control);
532 free(data);
533 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
534 return NULL;
535 }
536
537 struct lttng_session_descriptor *
538 lttng_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);
545
546 return descriptor ? &descriptor->base : NULL;
547 }
548
549 struct lttng_session_descriptor *
550 lttng_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;
571 error:
572 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
573 return NULL;
574 }
575
576 void 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
600 ssize_t lttng_session_descriptor_create_from_buffer(
601 const struct lttng_buffer_view *payload,
602 struct lttng_session_descriptor **descriptor)
603 {
604 int i;
605 ssize_t offset = 0, ret;
606 struct lttng_buffer_view current_view;
607 const char *name = NULL;
608 const struct lttng_session_descriptor_comm *base_header;
609 size_t max_expected_uri_count;
610 uint64_t live_timer_us = 0;
611 struct lttng_uri *uris[2] = {};
612 enum lttng_session_descriptor_type type;
613 enum lttng_session_descriptor_output_type output_type;
614
615 current_view = lttng_buffer_view_from_view(payload, offset,
616 sizeof(*base_header));
617 if (!lttng_buffer_view_is_valid(&current_view)) {
618 ret = -1;
619 goto end;
620 }
621
622 base_header = (typeof(base_header)) current_view.data;
623 switch (base_header->type) {
624 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
625 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
626 break;
627 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
628 {
629 const struct lttng_session_descriptor_live_comm *live_header;
630
631 current_view = lttng_buffer_view_from_view(payload, offset,
632 sizeof(*live_header));
633 if (!lttng_buffer_view_is_valid(&current_view)) {
634 ret = -1;
635 goto end;
636 }
637
638 live_header = (typeof(live_header)) current_view.data;
639 live_timer_us = live_header->live_timer_us;
640 break;
641 }
642 default:
643 ret = -1;
644 goto end;
645 }
646 /* type has been validated. */
647 type = (lttng_session_descriptor_type) base_header->type;
648
649 switch (base_header->output_type) {
650 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
651 max_expected_uri_count = 0;
652 break;
653 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
654 max_expected_uri_count = 1;
655 break;
656 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
657 max_expected_uri_count = 2;
658 break;
659 default:
660 ret = -1;
661 goto end;
662 }
663 /* output_type has been validated. */
664 output_type = (lttng_session_descriptor_output_type) base_header->output_type;
665
666 /* Skip after header. */
667 offset += current_view.size;
668 if (!base_header->name_len) {
669 goto skip_name;
670 }
671
672 /* Map the name. */
673 current_view = lttng_buffer_view_from_view(payload, offset,
674 base_header->name_len);
675 if (!lttng_buffer_view_is_valid(&current_view)) {
676 ret = -1;
677 goto end;
678 }
679
680 name = current_view.data;
681 if (base_header->name_len == 1 ||
682 name[base_header->name_len - 1] ||
683 strlen(name) != base_header->name_len - 1) {
684 /*
685 * Check that the name is not NULL, is NULL-terminated, and
686 * does not contain a NULL before the last byte.
687 */
688 ret = -1;
689 goto end;
690 }
691
692 /* Skip after the name. */
693 offset += base_header->name_len;
694 skip_name:
695 if (base_header->uri_count > max_expected_uri_count) {
696 ret = -1;
697 goto end;
698 }
699
700 for (i = 0; i < base_header->uri_count; i++) {
701 struct lttng_uri *uri;
702
703 /* Map a URI. */
704 current_view = lttng_buffer_view_from_view(payload,
705 offset, sizeof(*uri));
706 if (!lttng_buffer_view_is_valid(&current_view)) {
707 ret = -1;
708 goto end;
709 }
710
711 uri = (typeof(uri)) current_view.data;
712 uris[i] = zmalloc<lttng_uri>();
713 if (!uris[i]) {
714 ret = -1;
715 goto end;
716 }
717 memcpy(uris[i], uri, sizeof(*uri));
718 offset += sizeof(*uri);
719 }
720
721 switch (type) {
722 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
723 switch (output_type) {
724 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
725 *descriptor = lttng_session_descriptor_create(name);
726 break;
727 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
728 *descriptor = _lttng_session_descriptor_local_create(
729 name, uris[0]);
730 break;
731 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
732 *descriptor = _lttng_session_descriptor_network_create(
733 name, uris[0], uris[1]);
734 break;
735 default:
736 /* Already checked. */
737 abort();
738 }
739 break;
740 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
741 {
742 struct lttng_session_descriptor_snapshot *snapshot;
743 switch (output_type) {
744 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
745 snapshot = _lttng_session_descriptor_snapshot_create(
746 name);
747 break;
748 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
749 snapshot = _lttng_session_descriptor_snapshot_local_create(
750 name, uris[0]);
751 break;
752 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
753 snapshot = _lttng_session_descriptor_snapshot_network_create(
754 name, uris[0], uris[1]);
755 break;
756 default:
757 /* Already checked. */
758 abort();
759 }
760 *descriptor = snapshot ? &snapshot->base : NULL;
761 break;
762 }
763 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
764 {
765 struct lttng_session_descriptor_live *live;
766
767 switch (output_type) {
768 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
769 live = _lttng_session_descriptor_live_create(
770 name, live_timer_us);
771 break;
772 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
773 live = _lttng_session_descriptor_live_network_create(
774 name, uris[0], uris[1],
775 live_timer_us);
776 break;
777 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
778 ret = -1;
779 goto end;
780 default:
781 /* Already checked. */
782 abort();
783 }
784 *descriptor = live ? &live->base : NULL;
785 break;
786 }
787 default:
788 /* Already checked. */
789 abort();
790 }
791 memset(uris, 0, sizeof(uris));
792 if (!*descriptor) {
793 ret = -1;
794 goto end;
795 }
796
797 ret = offset;
798 end:
799 free(uris[0]);
800 free(uris[1]);
801 return ret;
802 }
803
804 int lttng_session_descriptor_serialize(
805 const struct lttng_session_descriptor *descriptor,
806 struct lttng_dynamic_buffer *buffer)
807 {
808 int ret, i;
809 /* There are, at most, two URIs to serialize. */
810 struct lttng_uri *uris[2] = {};
811 size_t uri_count = 0;
812 /* The live header is a superset of all headers. */
813 struct lttng_session_descriptor_live_comm header = {
814 .base = {
815 .type = (uint8_t) descriptor->type,
816 .output_type = (uint8_t) descriptor->output_type,
817 .name_len = (uint32_t) (descriptor->name ?
818 strlen(descriptor->name) + 1 : 0),
819 .uri_count = 0,
820 },
821 .live_timer_us = 0,
822
823 };
824 const void *header_ptr = NULL;
825 size_t header_size;
826
827 switch (descriptor->output_type) {
828 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
829 break;
830 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
831 uris[0] = descriptor->output.local;
832 break;
833 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
834 uris[0] = descriptor->output.network.control;
835 uris[1] = descriptor->output.network.data;
836 break;
837 default:
838 ret = -1;
839 goto end;
840 }
841 uri_count += !!uris[0];
842 uri_count += !!uris[1];
843
844 header.base.uri_count = uri_count;
845 if (descriptor->type == LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE) {
846 const struct lttng_session_descriptor_live *live =
847 container_of(descriptor, typeof(*live),
848 base);
849
850 header.live_timer_us = live->live_timer_us;
851 header_ptr = &header;
852 header_size = sizeof(header);
853 } else {
854 header_ptr = &header.base;
855 header_size = sizeof(header.base);
856 }
857
858 ret = lttng_dynamic_buffer_append(buffer, header_ptr, header_size);
859 if (ret) {
860 goto end;
861 }
862 if (header.base.name_len) {
863 ret = lttng_dynamic_buffer_append(buffer, descriptor->name,
864 header.base.name_len);
865 if (ret) {
866 goto end;
867 }
868 }
869
870 for (i = 0; i < uri_count; i++) {
871 ret = lttng_dynamic_buffer_append(buffer, uris[i],
872 sizeof(struct lttng_uri));
873 if (ret) {
874 goto end;
875 }
876 }
877 end:
878 return ret;
879 }
880
881 enum lttng_session_descriptor_type
882 lttng_session_descriptor_get_type(
883 const struct lttng_session_descriptor *descriptor)
884 {
885 return descriptor->type;
886 }
887
888 enum lttng_session_descriptor_output_type
889 lttng_session_descriptor_get_output_type(
890 const struct lttng_session_descriptor *descriptor)
891 {
892 return descriptor->output_type;
893 }
894
895 void 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
902 void lttng_session_descriptor_get_network_output_uris(
903 const struct lttng_session_descriptor *descriptor,
904 struct lttng_uri *control,
905 struct lttng_uri *data)
906 {
907 memcpy(control, descriptor->output.network.control, sizeof(*control));
908 memcpy(data, descriptor->output.network.data, sizeof(*data));
909 }
910
911 unsigned long long
912 lttng_session_descriptor_live_get_timer_interval(
913 const struct lttng_session_descriptor *descriptor)
914 {
915 struct lttng_session_descriptor_live *live;
916
917 live = container_of(descriptor, typeof(*live), base);
918 return live->live_timer_us;
919 }
920
921 enum lttng_session_descriptor_status
922 lttng_session_descriptor_get_session_name(
923 const struct lttng_session_descriptor *descriptor,
924 const char **session_name)
925 {
926 enum lttng_session_descriptor_status status;
927
928 if (!descriptor || !session_name) {
929 status = LTTNG_SESSION_DESCRIPTOR_STATUS_INVALID;
930 goto end;
931 }
932
933 *session_name = descriptor->name;
934 status = descriptor->name ?
935 LTTNG_SESSION_DESCRIPTOR_STATUS_OK :
936 LTTNG_SESSION_DESCRIPTOR_STATUS_UNSET;
937 end:
938 return status;
939 }
940
941 int lttng_session_descriptor_set_session_name(
942 struct lttng_session_descriptor *descriptor,
943 const char *name)
944 {
945 int ret = 0;
946 char *new_name;
947
948 if (!name) {
949 goto end;
950 }
951 if (strlen(name) >= LTTNG_NAME_MAX) {
952 ret = -1;
953 goto end;
954 }
955 new_name = strdup(name);
956 if (!new_name) {
957 ret = -1;
958 goto end;
959 }
960 free(descriptor->name);
961 descriptor->name = new_name;
962 end:
963 return ret;
964 }
965
966 bool lttng_session_descriptor_is_output_destination_initialized(
967 const struct lttng_session_descriptor *descriptor)
968 {
969 switch (descriptor->output_type) {
970 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
971 return true;
972 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
973 return descriptor->output.local;
974 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
975 return descriptor->output.network.control;
976 default:
977 abort();
978 }
979 }
980
981 bool lttng_session_descriptor_has_output_directory(
982 const struct lttng_session_descriptor *descriptor)
983 {
984 switch (descriptor->output_type) {
985 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
986 break;
987 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
988 if (descriptor->output.local) {
989 return *descriptor->output.local->dst.path;
990 }
991 break;
992 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
993 if (descriptor->output.network.control) {
994 return *descriptor->output.network.control->subdir;
995 }
996 break;
997 default:
998 abort();
999 }
1000 return false;
1001 }
1002
1003 enum lttng_error_code lttng_session_descriptor_set_default_output(
1004 struct lttng_session_descriptor *descriptor,
1005 time_t *session_creation_time,
1006 const char *absolute_home_path)
1007 {
1008 enum lttng_error_code ret_code = LTTNG_OK;
1009 struct lttng_uri *uris = NULL;
1010
1011 switch (descriptor->output_type) {
1012 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1013 goto end;
1014 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1015 {
1016 int ret;
1017 ssize_t uri_ret;
1018 char local_uri[LTTNG_PATH_MAX];
1019 char creation_datetime_suffix[17] = {};
1020
1021 if (session_creation_time) {
1022 size_t strftime_ret;
1023 struct tm *timeinfo;
1024
1025 timeinfo = localtime(session_creation_time);
1026 if (!timeinfo) {
1027 ret_code = LTTNG_ERR_FATAL;
1028 goto end;
1029 }
1030 strftime_ret = strftime(creation_datetime_suffix,
1031 sizeof(creation_datetime_suffix),
1032 "-%Y%m%d-%H%M%S", timeinfo);
1033 if (strftime_ret == 0) {
1034 ERR("Failed to format session creation timestamp while setting default local output destination");
1035 ret_code = LTTNG_ERR_FATAL;
1036 goto end;
1037 }
1038 }
1039 LTTNG_ASSERT(descriptor->name);
1040 ret = snprintf(local_uri, sizeof(local_uri),
1041 "file://%s/%s/%s%s",
1042 absolute_home_path,
1043 DEFAULT_TRACE_DIR_NAME, descriptor->name,
1044 creation_datetime_suffix);
1045 if (ret >= sizeof(local_uri)) {
1046 ERR("Truncation occurred while setting default local output destination");
1047 ret_code = LTTNG_ERR_SET_URL;
1048 goto end;
1049 } else if (ret < 0) {
1050 PERROR("Failed to format default local output URI");
1051 ret_code = LTTNG_ERR_SET_URL;
1052 goto end;
1053 }
1054
1055 uri_ret = uri_parse(local_uri, &uris);
1056 if (uri_ret != 1) {
1057 ret_code = LTTNG_ERR_SET_URL;
1058 goto end;
1059 }
1060 free(descriptor->output.local);
1061 descriptor->output.local = &uris[0];
1062 uris = NULL;
1063 break;
1064 }
1065 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1066 {
1067 int ret;
1068 ssize_t uri_ret;
1069 struct lttng_uri *control = NULL, *data = NULL;
1070
1071 uri_ret = uri_parse_str_urls("net://127.0.0.1", NULL, &uris);
1072 if (uri_ret != 2) {
1073 ret_code = LTTNG_ERR_SET_URL;
1074 goto end;
1075 }
1076
1077 control = uri_copy(&uris[0]);
1078 data = uri_copy(&uris[1]);
1079 if (!control || !data) {
1080 free(control);
1081 free(data);
1082 ret_code = LTTNG_ERR_SET_URL;
1083 goto end;
1084 }
1085
1086 /* Ownership of uris is transferred. */
1087 ret = network_location_set_from_lttng_uris(
1088 &descriptor->output.network,
1089 control, data);
1090 if (ret) {
1091 abort();
1092 ret_code = LTTNG_ERR_SET_URL;
1093 goto end;
1094 }
1095 break;
1096 }
1097 default:
1098 abort();
1099 }
1100 end:
1101 free(uris);
1102 return ret_code;
1103 }
1104
1105 /*
1106 * Note that only properties that can be populated by the session daemon
1107 * (output destination and name) are assigned.
1108 */
1109 int lttng_session_descriptor_assign(
1110 struct lttng_session_descriptor *dst,
1111 const struct lttng_session_descriptor *src)
1112 {
1113 int ret = 0;
1114
1115 if (dst->type != src->type) {
1116 ret = -1;
1117 goto end;
1118 }
1119 if (dst->output_type != src->output_type) {
1120 ret = -1;
1121 goto end;
1122 }
1123 ret = lttng_session_descriptor_set_session_name(dst, src->name);
1124 if (ret) {
1125 goto end;
1126 }
1127 switch (dst->output_type) {
1128 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1129 free(dst->output.local);
1130 dst->output.local = uri_copy(src->output.local);
1131 if (!dst->output.local) {
1132 ret = -1;
1133 goto end;
1134 }
1135 break;
1136 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1137 {
1138 struct lttng_uri *control_copy = NULL, *data_copy = NULL;
1139
1140 control_copy = uri_copy(dst->output.network.control);
1141 if (!control_copy && dst->output.network.control) {
1142 ret = -1;
1143 goto end;
1144 }
1145 data_copy = uri_copy(dst->output.network.data);
1146 if (!data_copy && dst->output.network.data) {
1147 free(control_copy);
1148 ret = -1;
1149 goto end;
1150 }
1151 ret = network_location_set_from_lttng_uris(&dst->output.network,
1152 control_copy, data_copy);
1153 break;
1154 }
1155 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1156 goto end;
1157 }
1158 end:
1159 return ret;
1160 }
This page took 0.054557 seconds and 4 git commands to generate.