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