Clean-up: sessiond comm relay: change spaces to tabs
[lttng-tools.git] / src / common / session-descriptor.c
1 /*
2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
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>
13 #include <assert.h>
14 #include <stdio.h>
15
16 struct lttng_session_descriptor_network_location {
17 struct lttng_uri *control;
18 struct lttng_uri *data;
19 };
20
21 struct lttng_session_descriptor {
22 enum lttng_session_descriptor_type type;
23 /*
24 * If an output type that is not OUTPUT_TYPE_NONE is specified,
25 * it means that an output of that type must be generated at
26 * session-creation time.
27 */
28 enum lttng_session_descriptor_output_type output_type;
29 char *name;
30 union {
31 struct lttng_session_descriptor_network_location network;
32 struct lttng_uri *local;
33 } output;
34 };
35
36 struct lttng_session_descriptor_snapshot {
37 struct lttng_session_descriptor base;
38 /*
39 * Assumes at-most one snapshot output is supported. Uses
40 * the output field of the base class.
41 */
42 };
43
44 struct lttng_session_descriptor_live {
45 struct lttng_session_descriptor base;
46 unsigned long long live_timer_us;
47 };
48
49 struct lttng_session_descriptor_comm {
50 /* enum lttng_session_descriptor_type */
51 uint8_t type;
52 /* enum lttng_session_descriptor_output_type */
53 uint8_t output_type;
54 /* Includes trailing null. */
55 uint32_t name_len;
56 /* Name follows, followed by URIs */
57 uint8_t uri_count;
58 } LTTNG_PACKED;
59
60 struct lttng_session_descriptor_live_comm {
61 struct lttng_session_descriptor_comm base;
62 /* Live-specific parameters. */
63 uint64_t live_timer_us;
64 } LTTNG_PACKED;
65
66 static
67 struct lttng_uri *uri_copy(const struct lttng_uri *uri)
68 {
69 struct lttng_uri *new_uri = NULL;
70
71 if (!uri) {
72 goto end;
73 }
74
75 new_uri = zmalloc(sizeof(*new_uri));
76 if (!new_uri) {
77 goto end;
78 }
79 memcpy(new_uri, uri, sizeof(*new_uri));
80 end:
81 return new_uri;
82 }
83
84 static
85 struct lttng_uri *uri_from_path(const char *path)
86 {
87 struct lttng_uri *uris = NULL;
88 ssize_t uri_count;
89 char local_protocol_string[LTTNG_PATH_MAX + sizeof("file://")] =
90 "file://";
91
92 if (strlen(path) >= LTTNG_PATH_MAX) {
93 goto end;
94 }
95
96 if (path[0] != '/') {
97 /* Not an absolute path. */
98 goto end;
99 }
100
101 strncat(local_protocol_string, path, LTTNG_PATH_MAX);
102 uri_count = uri_parse(local_protocol_string, &uris);
103 if (uri_count != 1) {
104 goto error;
105 }
106 if (uris[0].dtype != LTTNG_DST_PATH) {
107 goto error;
108 }
109
110 end:
111 return uris;
112 error:
113 free(uris);
114 return NULL;
115 }
116
117 static
118 void network_location_fini(
119 struct lttng_session_descriptor_network_location *location)
120 {
121 free(location->control);
122 free(location->data);
123 }
124
125 /* Assumes ownership of control and data. */
126 static
127 int network_location_set_from_lttng_uris(
128 struct lttng_session_descriptor_network_location *location,
129 struct lttng_uri *control, struct lttng_uri *data)
130 {
131 int ret = 0;
132
133 if (!control && !data) {
134 goto end;
135 }
136
137 if (!(control && data)) {
138 /* None or both must be set. */
139 ret = -1;
140 goto end;
141 }
142
143 if (control->stype != LTTNG_STREAM_CONTROL ||
144 data->stype != LTTNG_STREAM_DATA) {
145 ret = -1;
146 goto end;
147 }
148
149 free(location->control);
150 free(location->data);
151 location->control = control;
152 location->data = data;
153 control = NULL;
154 data = NULL;
155 end:
156 free(control);
157 free(data);
158 return ret;
159 }
160
161 static
162 int network_location_set_from_uri_strings(
163 struct lttng_session_descriptor_network_location *location,
164 const char *control, const char *data)
165 {
166 int ret = 0;
167 ssize_t uri_count;
168 struct lttng_uri *parsed_uris = NULL;
169 struct lttng_uri *control_uri = NULL;
170 struct lttng_uri *data_uri = NULL;
171
172 uri_count = uri_parse_str_urls(control, data, &parsed_uris);
173 if (uri_count != 2 && uri_count != 0) {
174 ret = -1;
175 goto end;
176 }
177
178 /*
179 * uri_parse_str_urls returns a contiguous array of lttng_uris whereas
180 * session descriptors expect individually allocated lttng_uris.
181 */
182 if (uri_count == 2) {
183 control_uri = zmalloc(sizeof(*control_uri));
184 data_uri = zmalloc(sizeof(*data_uri));
185 if (!control_uri || !data_uri) {
186 ret = -1;
187 goto end;
188 }
189 memcpy(control_uri, &parsed_uris[0], sizeof(*control_uri));
190 memcpy(data_uri, &parsed_uris[1], sizeof(*data_uri));
191 }
192
193 /* Ownership of control and data uris is transferred. */
194 ret = network_location_set_from_lttng_uris(
195 location,
196 control_uri,
197 data_uri);
198 control_uri = NULL;
199 data_uri = NULL;
200 end:
201 free(parsed_uris);
202 free(control_uri);
203 free(data_uri);
204 return ret;
205 }
206
207 struct lttng_session_descriptor *
208 lttng_session_descriptor_create(const char *name)
209 {
210 struct lttng_session_descriptor *descriptor;
211
212 descriptor = zmalloc(sizeof(*descriptor));
213 if (!descriptor) {
214 goto error;
215 }
216
217 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
218 descriptor->output_type =
219 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
220 if (lttng_session_descriptor_set_session_name(descriptor, name)) {
221 goto error;
222 }
223 return descriptor;
224 error:
225 lttng_session_descriptor_destroy(descriptor);
226 return NULL;
227 }
228
229 /* Ownership of uri is transferred. */
230 static
231 struct lttng_session_descriptor *
232 _lttng_session_descriptor_local_create(const char *name,
233 struct lttng_uri *uri)
234 {
235 struct lttng_session_descriptor *descriptor;
236
237 descriptor = lttng_session_descriptor_create(name);
238 if (!descriptor) {
239 goto error;
240 }
241 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
242 descriptor->output_type =
243 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
244 if (uri) {
245 if (uri->dtype != LTTNG_DST_PATH) {
246 goto error;
247 }
248 descriptor->output.local = uri;
249 uri = NULL;
250 }
251 return descriptor;
252 error:
253 free(uri);
254 lttng_session_descriptor_destroy(descriptor);
255 return NULL;
256 }
257
258 struct lttng_session_descriptor *
259 lttng_session_descriptor_local_create(const char *name, const char *path)
260 {
261 struct lttng_uri *uri = NULL;
262 struct lttng_session_descriptor *descriptor;
263
264 if (path) {
265 uri = uri_from_path(path);
266 if (!uri) {
267 goto error;
268 }
269 }
270 descriptor = _lttng_session_descriptor_local_create(name, uri);
271 return descriptor;
272 error:
273 return NULL;
274 }
275
276 /* Assumes the ownership of both uris. */
277 static
278 struct lttng_session_descriptor *
279 _lttng_session_descriptor_network_create(const char *name,
280 struct lttng_uri *control, struct lttng_uri *data)
281 {
282 int ret;
283 struct lttng_session_descriptor *descriptor;
284
285 descriptor = lttng_session_descriptor_create(name);
286 if (!descriptor) {
287 goto error;
288 }
289
290 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
291 descriptor->output_type = LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
292 /* Assumes the ownership of both uris. */
293 ret = network_location_set_from_lttng_uris(&descriptor->output.network,
294 control, data);
295 control = NULL;
296 data = NULL;
297 if (ret) {
298 goto error;
299 }
300 return descriptor;
301 error:
302 lttng_session_descriptor_destroy(descriptor);
303 free(control);
304 free(data);
305 return NULL;
306 }
307
308 struct lttng_session_descriptor *
309 lttng_session_descriptor_network_create(const char *name,
310 const char *control_url, const char *data_url)
311 {
312 int ret;
313 struct lttng_session_descriptor *descriptor;
314
315 descriptor = _lttng_session_descriptor_network_create(name,
316 NULL, NULL);
317 if (!descriptor) {
318 goto error;
319 }
320
321 ret = network_location_set_from_uri_strings(&descriptor->output.network,
322 control_url, data_url);
323 if (ret) {
324 goto error;
325 }
326 return descriptor;
327 error:
328 lttng_session_descriptor_destroy(descriptor);
329 return NULL;
330 }
331
332 static
333 struct lttng_session_descriptor_snapshot *
334 _lttng_session_descriptor_snapshot_create(const char *name)
335 {
336 struct lttng_session_descriptor_snapshot *descriptor;
337
338 descriptor = zmalloc(sizeof(*descriptor));
339 if (!descriptor) {
340 goto error;
341 }
342
343 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT;
344 descriptor->base.output_type =
345 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
346 if (lttng_session_descriptor_set_session_name(&descriptor->base,
347 name)) {
348 goto error;
349 }
350 return descriptor;
351 error:
352 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
353 return NULL;
354 }
355
356 /* Ownership of control and data is transferred. */
357 static
358 struct lttng_session_descriptor_snapshot *
359 _lttng_session_descriptor_snapshot_network_create(const char *name,
360 struct lttng_uri *control, struct lttng_uri *data)
361 {
362 int ret;
363 struct lttng_session_descriptor_snapshot *descriptor;
364
365 descriptor = _lttng_session_descriptor_snapshot_create(name);
366 if (!descriptor) {
367 goto error;
368 }
369
370 descriptor->base.output_type =
371 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
372 /* Ownership of control and data is transferred. */
373 ret = network_location_set_from_lttng_uris(
374 &descriptor->base.output.network,
375 control, data);
376 control = NULL;
377 data = NULL;
378 if (ret) {
379 goto error;
380 }
381 return descriptor;
382 error:
383 free(control);
384 free(data);
385 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
386 return NULL;
387 }
388
389 struct lttng_session_descriptor *
390 lttng_session_descriptor_snapshot_create(const char *name)
391 {
392 struct lttng_session_descriptor_snapshot *descriptor;
393
394 descriptor = _lttng_session_descriptor_snapshot_create(name);
395 return descriptor ? &descriptor->base : NULL;
396 }
397
398 struct lttng_session_descriptor *
399 lttng_session_descriptor_snapshot_network_create(const char *name,
400 const char *control_url, const char *data_url)
401 {
402 int ret;
403 struct lttng_session_descriptor_snapshot *descriptor;
404
405 descriptor = _lttng_session_descriptor_snapshot_network_create(name,
406 NULL, NULL);
407 if (!descriptor) {
408 goto error;
409 }
410
411 ret = network_location_set_from_uri_strings(
412 &descriptor->base.output.network,
413 control_url, data_url);
414 if (ret) {
415 goto error;
416 }
417 return &descriptor->base;
418 error:
419 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
420 return NULL;
421 }
422
423 /* Ownership of uri is transferred. */
424 static
425 struct lttng_session_descriptor_snapshot *
426 _lttng_session_descriptor_snapshot_local_create(const char *name,
427 struct lttng_uri *uri)
428 {
429 struct lttng_session_descriptor_snapshot *descriptor;
430
431 descriptor = _lttng_session_descriptor_snapshot_create(name);
432 if (!descriptor) {
433 goto error;
434 }
435 descriptor->base.output_type =
436 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
437 if (uri) {
438 if (uri->dtype != LTTNG_DST_PATH) {
439 goto error;
440 }
441 descriptor->base.output.local = uri;
442 uri = NULL;
443 }
444 return descriptor;
445 error:
446 free(uri);
447 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
448 return NULL;
449 }
450
451 struct lttng_session_descriptor *
452 lttng_session_descriptor_snapshot_local_create(const char *name,
453 const char *path)
454 {
455 struct lttng_uri *path_uri = NULL;
456 struct lttng_session_descriptor_snapshot *descriptor;
457
458 if (path) {
459 path_uri = uri_from_path(path);
460 if (!path_uri) {
461 goto error;
462 }
463 }
464 descriptor = _lttng_session_descriptor_snapshot_local_create(name,
465 path_uri);
466 return descriptor ? &descriptor->base : NULL;
467 error:
468 return NULL;
469 }
470
471 static
472 struct lttng_session_descriptor_live *
473 _lttng_session_descriptor_live_create(const char *name,
474 unsigned long long live_timer_interval_us)
475 {
476 struct lttng_session_descriptor_live *descriptor = NULL;
477
478 if (live_timer_interval_us == 0) {
479 goto error;
480 }
481 descriptor = zmalloc(sizeof(*descriptor));
482 if (!descriptor) {
483 goto error;
484 }
485
486 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE;
487 descriptor->base.output_type =
488 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
489 descriptor->live_timer_us = live_timer_interval_us;
490 if (lttng_session_descriptor_set_session_name(&descriptor->base,
491 name)) {
492 goto error;
493 }
494
495 return descriptor;
496 error:
497 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
498 return NULL;
499 }
500
501 /* Ownership of control and data is transferred. */
502 static
503 struct lttng_session_descriptor_live *
504 _lttng_session_descriptor_live_network_create(
505 const char *name,
506 struct lttng_uri *control, struct lttng_uri *data,
507 unsigned long long live_timer_interval_us)
508 {
509 int ret;
510 struct lttng_session_descriptor_live *descriptor;
511
512 descriptor = _lttng_session_descriptor_live_create(name,
513 live_timer_interval_us);
514 if (!descriptor) {
515 goto error;
516 }
517
518 descriptor->base.output_type =
519 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
520
521 /* Ownerwhip of control and data is transferred. */
522 ret = network_location_set_from_lttng_uris(
523 &descriptor->base.output.network,
524 control, data);
525 control = NULL;
526 data = NULL;
527 if (ret) {
528 goto error;
529 }
530 return descriptor;
531 error:
532 free(control);
533 free(data);
534 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
535 return NULL;
536 }
537
538 struct lttng_session_descriptor *
539 lttng_session_descriptor_live_create(
540 const char *name,
541 unsigned long long live_timer_us)
542 {
543 struct lttng_session_descriptor_live *descriptor;
544
545 descriptor = _lttng_session_descriptor_live_create(name, live_timer_us);
546
547 return descriptor ? &descriptor->base : NULL;
548 }
549
550 struct lttng_session_descriptor *
551 lttng_session_descriptor_live_network_create(
552 const char *name,
553 const char *control_url, const char *data_url,
554 unsigned long long live_timer_us)
555 {
556 int ret;
557 struct lttng_session_descriptor_live *descriptor;
558
559 descriptor = _lttng_session_descriptor_live_network_create(name,
560 NULL, NULL, live_timer_us);
561 if (!descriptor) {
562 goto error;
563 }
564
565 ret = network_location_set_from_uri_strings(
566 &descriptor->base.output.network,
567 control_url, data_url);
568 if (ret) {
569 goto error;
570 }
571 return &descriptor->base;
572 error:
573 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
574 return NULL;
575 }
576
577 void lttng_session_descriptor_destroy(
578 struct lttng_session_descriptor *descriptor)
579 {
580 if (!descriptor) {
581 return;
582 }
583
584 switch (descriptor->output_type) {
585 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
586 break;
587 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
588 free(descriptor->output.local);
589 break;
590 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
591 network_location_fini(&descriptor->output.network);
592 break;
593 default:
594 abort();
595 }
596
597 free(descriptor->name);
598 free(descriptor);
599 }
600
601 LTTNG_HIDDEN
602 ssize_t lttng_session_descriptor_create_from_buffer(
603 const struct lttng_buffer_view *payload,
604 struct lttng_session_descriptor **descriptor)
605 {
606 int i;
607 ssize_t offset = 0, ret;
608 struct lttng_buffer_view current_view;
609 const char *name = NULL;
610 const struct lttng_session_descriptor_comm *base_header;
611 size_t max_expected_uri_count;
612 uint64_t live_timer_us = 0;
613 struct lttng_uri *uris[2] = {};
614 enum lttng_session_descriptor_type type;
615 enum lttng_session_descriptor_output_type output_type;
616
617 current_view = lttng_buffer_view_from_view(payload, offset,
618 sizeof(*base_header));
619 base_header = (typeof(base_header)) current_view.data;
620 if (!base_header) {
621 ret = -1;
622 goto end;
623 }
624
625 switch (base_header->type) {
626 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
627 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
628 break;
629 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
630 {
631 const struct lttng_session_descriptor_live_comm *live_header;
632
633 current_view = lttng_buffer_view_from_view(payload, offset,
634 sizeof(*live_header));
635 live_header = (typeof(live_header)) current_view.data;
636 if (!live_header) {
637 ret = -1;
638 goto end;
639 }
640
641 live_timer_us = live_header->live_timer_us;
642 break;
643 }
644 default:
645 ret = -1;
646 goto end;
647 }
648 /* type has been validated. */
649 type = base_header->type;
650
651 switch (base_header->output_type) {
652 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
653 max_expected_uri_count = 0;
654 break;
655 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
656 max_expected_uri_count = 1;
657 break;
658 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
659 max_expected_uri_count = 2;
660 break;
661 default:
662 ret = -1;
663 goto end;
664 }
665 /* output_type has been validated. */
666 output_type = base_header->output_type;
667
668 /* Skip after header. */
669 offset += current_view.size;
670 if (!base_header->name_len) {
671 goto skip_name;
672 }
673
674 /* Map the name. */
675 current_view = lttng_buffer_view_from_view(payload, offset,
676 base_header->name_len);
677 name = current_view.data;
678 if (!name) {
679 ret = -1;
680 goto end;
681 }
682
683 if (base_header->name_len == 1 ||
684 name[base_header->name_len - 1] ||
685 strlen(name) != base_header->name_len - 1) {
686 /*
687 * Check that the name is not NULL, is NULL-terminated, and
688 * does not contain a NULL before the last byte.
689 */
690 ret = -1;
691 goto end;
692 }
693
694 /* Skip after the name. */
695 offset += base_header->name_len;
696 skip_name:
697 if (base_header->uri_count > max_expected_uri_count) {
698 ret = -1;
699 goto end;
700 }
701
702 for (i = 0; i < base_header->uri_count; i++) {
703 struct lttng_uri *uri;
704
705 /* Map a URI. */
706 current_view = lttng_buffer_view_from_view(payload,
707 offset, sizeof(*uri));
708 uri = (typeof(uri)) current_view.data;
709 if (!uri) {
710 ret = -1;
711 goto end;
712 }
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;
799 end:
800 free(uris[0]);
801 free(uris[1]);
802 return ret;
803 }
804
805 LTTNG_HIDDEN
806 int 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 }
874 end:
875 return ret;
876 }
877
878 LTTNG_HIDDEN
879 enum lttng_session_descriptor_type
880 lttng_session_descriptor_get_type(
881 const struct lttng_session_descriptor *descriptor)
882 {
883 return descriptor->type;
884 }
885
886 LTTNG_HIDDEN
887 enum lttng_session_descriptor_output_type
888 lttng_session_descriptor_get_output_type(
889 const struct lttng_session_descriptor *descriptor)
890 {
891 return descriptor->output_type;
892 }
893
894 LTTNG_HIDDEN
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 LTTNG_HIDDEN
903 void 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
912 LTTNG_HIDDEN
913 unsigned long long
914 lttng_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
923 enum lttng_session_descriptor_status
924 lttng_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;
939 end:
940 return status;
941 }
942
943 LTTNG_HIDDEN
944 int 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;
965 end:
966 return ret;
967 }
968
969 LTTNG_HIDDEN
970 bool 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
985 LTTNG_HIDDEN
986 bool 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
1008 LTTNG_HIDDEN
1009 enum 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 }
1045 assert(descriptor->name);
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 }
1106 end:
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 */
1115 LTTNG_HIDDEN
1116 int 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 }
1165 end:
1166 return ret;
1167 }
This page took 0.085442 seconds and 5 git commands to generate.