compat: fix compilation with !BABELTRACE_HAVE_OPEN_MEMSTREAM
[babeltrace.git] / src / plugins / ctf / lttng-live / viewer-connection.c
CommitLineData
7cdc2bab 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
7cdc2bab 3 *
0235b0db
MJ
4 * Copyright 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
5 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7cdc2bab
MD
6 */
7
2ece7dd0 8#define BT_COMP_LOG_SELF_COMP (viewer_connection->self_comp)
c01594de 9#define BT_LOG_OUTPUT_LEVEL (viewer_connection->log_level)
350ad6c1 10#define BT_LOG_TAG "PLUGIN/SRC.CTF.LTTNG-LIVE/VIEWER"
d9c39b0a 11#include "logging/comp-logging.h"
020bc26f 12
3c22a242
FD
13#include <fcntl.h>
14#include <stdbool.h>
7cdc2bab 15#include <stdint.h>
3c22a242 16#include <stdio.h>
7cdc2bab 17#include <stdlib.h>
3c22a242 18#include <sys/types.h>
7cdc2bab 19#include <unistd.h>
3c22a242 20
7cdc2bab 21#include <glib.h>
7cdc2bab 22
578e048b
MJ
23#include "compat/socket.h"
24#include "compat/endian.h"
25#include "compat/compiler.h"
26#include "common/common.h"
3fadfbc0 27#include <babeltrace2/babeltrace.h>
7cdc2bab 28
14f28187 29#include "lttng-live.h"
7cdc2bab
MD
30#include "viewer-connection.h"
31#include "lttng-viewer-abi.h"
32#include "data-stream.h"
33#include "metadata.h"
34
f79c2d7a
FD
35#define viewer_handle_send_recv_status(_self_comp, _self_comp_class, \
36 _status, _action, _msg_str) \
37do { \
38 switch (_status) { \
39 case LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED: \
40 break; \
41 case LTTNG_LIVE_VIEWER_STATUS_ERROR: \
42 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(_self_comp, \
43 _self_comp_class, "Error " _action " " _msg_str); \
44 break; \
45 default: \
46 bt_common_abort(); \
47 } \
48} while (0)
49
50#define viewer_handle_send_status(_self_comp, _self_comp_class, _status, _msg_str) \
51 viewer_handle_send_recv_status(_self_comp, _self_comp_class, _status, \
52 "sending", _msg_str)
53
54#define viewer_handle_recv_status(_self_comp, _self_comp_class, _status, _msg_str) \
55 viewer_handle_send_recv_status(_self_comp, _self_comp_class, _status, \
56 "receiving", _msg_str)
57
58#define LTTNG_LIVE_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE_ERRNO(_self_comp, \
59 _self_comp_class, _msg, _fmt, ...) \
60 do { \
61 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(_self_comp, _self_comp_class, \
62 _msg ": %s" _fmt, bt_socket_errormsg(), ##__VA_ARGS__); \
63 } while (0)
64
f93afbf9
FD
65static
66const char *lttng_viewer_command_string(enum lttng_viewer_command cmd)
67{
68 switch (cmd){
69 case LTTNG_VIEWER_CONNECT:
70 return "CONNECT";
71 case LTTNG_VIEWER_LIST_SESSIONS:
72 return "LIST_SESSIONS";
73 case LTTNG_VIEWER_ATTACH_SESSION:
74 return "ATTACH_SESSION";
75 case LTTNG_VIEWER_GET_NEXT_INDEX:
76 return "GET_NEXT_INDEX";
77 case LTTNG_VIEWER_GET_PACKET:
78 return "GET_PACKET";
79 case LTTNG_VIEWER_GET_METADATA:
80 return "GET_METADATA";
81 case LTTNG_VIEWER_GET_NEW_STREAMS:
82 return "GET_NEW_STREAMS";
83 case LTTNG_VIEWER_CREATE_SESSION:
84 return "CREATE_SESSION";
85 case LTTNG_VIEWER_DETACH_SESSION:
86 return "DETACH_SESSION";
87 }
88
89 bt_common_abort();
90}
91
92static
93const char *lttng_viewer_next_index_return_code_string(
94 enum lttng_viewer_next_index_return_code code)
95{
96 switch (code) {
97 case LTTNG_VIEWER_INDEX_OK:
98 return "INDEX_OK";
99 case LTTNG_VIEWER_INDEX_RETRY:
100 return "INDEX_RETRY";
101 case LTTNG_VIEWER_INDEX_HUP:
102 return "INDEX_HUP";
103 case LTTNG_VIEWER_INDEX_ERR:
104 return "INDEX_ERR";
105 case LTTNG_VIEWER_INDEX_INACTIVE:
106 return "INDEX_INACTIVE";
107 case LTTNG_VIEWER_INDEX_EOF:
108 return "INDEX_EOF";
109 }
110
111 bt_common_abort();
112}
113
114static
115const char *lttng_viewer_get_packet_return_code_string(
116 enum lttng_viewer_get_packet_return_code code)
117{
118 switch (code) {
119 case LTTNG_VIEWER_GET_PACKET_OK:
120 return "GET_PACKET_OK";
121 case LTTNG_VIEWER_GET_PACKET_RETRY:
122 return "GET_PACKET_RETRY";
123 case LTTNG_VIEWER_GET_PACKET_ERR:
124 return "GET_PACKET_ERR";
125 case LTTNG_VIEWER_GET_PACKET_EOF:
126 return "GET_PACKET_EOF";
127 }
128
129 bt_common_abort();
130};
131
132static
133const char *lttng_viewer_seek_string(enum lttng_viewer_seek seek)
134{
135 switch (seek) {
136 case LTTNG_VIEWER_SEEK_BEGINNING:
137 return "SEEK_BEGINNING";
138 case LTTNG_VIEWER_SEEK_LAST:
139 return "SEEK_LAST";
140 }
141
142 bt_common_abort();
143}
144
f79c2d7a
FD
145static inline
146enum lttng_live_iterator_status viewer_status_to_live_iterator_status(
147 enum lttng_live_viewer_status viewer_status)
148{
149 switch (viewer_status) {
150 case LTTNG_LIVE_VIEWER_STATUS_OK:
151 return LTTNG_LIVE_ITERATOR_STATUS_OK;
152 case LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED:
153 return LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
154 case LTTNG_LIVE_VIEWER_STATUS_ERROR:
155 return LTTNG_LIVE_ITERATOR_STATUS_ERROR;
f79c2d7a 156 }
f93afbf9
FD
157
158 bt_common_abort();
f79c2d7a
FD
159}
160
161static inline
162enum ctf_msg_iter_medium_status viewer_status_to_ctf_msg_iter_medium_status(
163 enum lttng_live_viewer_status viewer_status)
164{
165 switch (viewer_status) {
166 case LTTNG_LIVE_VIEWER_STATUS_OK:
167 return CTF_MSG_ITER_MEDIUM_STATUS_OK;
168 case LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED:
169 return CTF_MSG_ITER_MEDIUM_STATUS_AGAIN;
170 case LTTNG_LIVE_VIEWER_STATUS_ERROR:
171 return CTF_MSG_ITER_MEDIUM_STATUS_ERROR;
f79c2d7a 172 }
f93afbf9
FD
173
174 bt_common_abort();
f79c2d7a
FD
175}
176
b197ca37
FD
177static inline
178void viewer_connection_close_socket(
179 struct live_viewer_connection *viewer_connection)
180{
181 bt_self_component_class *self_comp_class =
182 viewer_connection->self_comp_class;
183 bt_self_component *self_comp =
184 viewer_connection->self_comp;
185 int ret = bt_socket_close(viewer_connection->control_sock);
186 if (ret == -1) {
187 BT_COMP_OR_COMP_CLASS_LOGW_ERRNO(
188 self_comp, self_comp_class,
189 "Error closing viewer connection socket: ", ".");
190 }
191
192 viewer_connection->control_sock = BT_INVALID_SOCKET;
193}
194
f79c2d7a
FD
195/*
196 * This function receives a message from the Relay daemon.
197 * If it received the entire message, it returns _OK,
198 * If it's interrupted, it returns _INTERRUPTED,
199 * otherwise, it returns _ERROR.
200 */
14f28187 201static
f79c2d7a
FD
202enum lttng_live_viewer_status lttng_live_recv(
203 struct live_viewer_connection *viewer_connection,
4c66436f 204 void *buf, size_t len)
7cdc2bab 205{
f79c2d7a
FD
206 ssize_t received;
207 bt_self_component_class *self_comp_class =
208 viewer_connection->self_comp_class;
209 bt_self_component *self_comp =
210 viewer_connection->self_comp;
211 size_t total_received = 0, to_receive = len;
14f28187
FD
212 struct lttng_live_msg_iter *lttng_live_msg_iter =
213 viewer_connection->lttng_live_msg_iter;
f79c2d7a 214 enum lttng_live_viewer_status status;
1cb3cdd7 215 BT_SOCKET sock = viewer_connection->control_sock;
7cdc2bab 216
f79c2d7a
FD
217 /*
218 * Receive a message from the Relay.
219 */
7cdc2bab 220 do {
f79c2d7a
FD
221 received = bt_socket_recv(sock, buf + total_received, to_receive, 0);
222 if (received == BT_SOCKET_ERROR) {
223 if (bt_socket_interrupted()) {
224 if (lttng_live_graph_is_canceled(lttng_live_msg_iter)) {
225 /*
226 * This interruption was due to a
227 * SIGINT and the graph is being torn
228 * down.
229 */
230 status = LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED;
231 lttng_live_msg_iter->was_interrupted = true;
232 goto end;
233 } else {
234 /*
235 * A signal was received, but the graph
236 * is not being torn down. Carry on.
237 */
238 continue;
239 }
4c66436f 240 } else {
f79c2d7a 241 /*
b197ca37
FD
242 * For any other types of socket error, close
243 * the socket and return an error.
f79c2d7a
FD
244 */
245 LTTNG_LIVE_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE_ERRNO(
246 self_comp, self_comp_class,
247 "Error receiving from Relay", ".");
b197ca37
FD
248
249 viewer_connection_close_socket(viewer_connection);
f79c2d7a
FD
250 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
251 goto end;
4c66436f 252 }
f79c2d7a
FD
253 } else if (received == 0) {
254 /*
255 * The recv() call returned 0. This means the
256 * connection was orderly shutdown from the other peer.
257 * If that happens when we are trying to receive
258 * a message from it, it means something when wrong.
b197ca37 259 * Close the socket and return an error.
f79c2d7a 260 */
f79c2d7a
FD
261 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
262 self_comp_class, "Remote side has closed connection");
b197ca37
FD
263 viewer_connection_close_socket(viewer_connection);
264 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
f79c2d7a 265 goto end;
4c66436f 266 }
710d900e 267
f79c2d7a
FD
268 BT_ASSERT(received <= to_receive);
269 total_received += received;
270 to_receive -= received;
710d900e 271
f79c2d7a
FD
272 } while (to_receive > 0);
273
274 BT_ASSERT(total_received == len);
275 status = LTTNG_LIVE_VIEWER_STATUS_OK;
276
277end:
278 return status;
7cdc2bab
MD
279}
280
f79c2d7a
FD
281/*
282 * This function sends a message to the Relay daemon.
283 * If it send the message, it returns _OK,
284 * If it's interrupted, it returns _INTERRUPTED,
285 * otherwise, it returns _ERROR.
286 */
14f28187 287static
f79c2d7a
FD
288enum lttng_live_viewer_status lttng_live_send(
289 struct live_viewer_connection *viewer_connection,
4c66436f 290 const void *buf, size_t len)
7cdc2bab 291{
f79c2d7a
FD
292 enum lttng_live_viewer_status status;
293 bt_self_component_class *self_comp_class =
294 viewer_connection->self_comp_class;
295 bt_self_component *self_comp =
296 viewer_connection->self_comp;
14f28187
FD
297 struct lttng_live_msg_iter *lttng_live_msg_iter =
298 viewer_connection->lttng_live_msg_iter;
1cb3cdd7 299 BT_SOCKET sock = viewer_connection->control_sock;
f79c2d7a
FD
300 size_t to_send = len;
301 ssize_t total_sent = 0;
302
303 do {
304 ssize_t sent = bt_socket_send_nosigpipe(sock, buf + total_sent,
305 to_send);
306 if (sent == BT_SOCKET_ERROR) {
307 if (bt_socket_interrupted()) {
308 if (lttng_live_graph_is_canceled(lttng_live_msg_iter)) {
309 /*
310 * This interruption was a SIGINT and
311 * the graph is being teared down.
312 */
313 status = LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED;
314 lttng_live_msg_iter->was_interrupted = true;
315 goto end;
316 } else {
317 /*
318 * A signal was received, but the graph
319 * is not being teared down. Carry on.
320 */
321 continue;
322 }
4c66436f 323 } else {
f79c2d7a 324 /*
b197ca37
FD
325 * For any other types of socket error, close
326 * the socket and return an error.
f79c2d7a
FD
327 */
328 LTTNG_LIVE_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE_ERRNO(
329 self_comp, self_comp_class,
330 "Error sending to Relay", ".");
b197ca37
FD
331
332 viewer_connection_close_socket(viewer_connection);
f79c2d7a
FD
333 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
334 goto end;
4c66436f 335 }
4c66436f 336 }
f79c2d7a
FD
337
338 BT_ASSERT(sent <= to_send);
339 total_sent += sent;
340 to_send -= sent;
341
342 } while (to_send > 0);
343
344 BT_ASSERT(total_sent == len);
345 status = LTTNG_LIVE_VIEWER_STATUS_OK;
346
347end:
348 return status;
7cdc2bab
MD
349}
350
14f28187
FD
351static
352int parse_url(struct live_viewer_connection *viewer_connection)
7cdc2bab 353{
94b828f3 354 char error_buf[256] = { 0 };
1419db2b
FD
355 bt_self_component *self_comp = viewer_connection->self_comp;
356 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
94b828f3
MD
357 struct bt_common_lttng_live_url_parts lttng_live_url_parts = { 0 };
358 int ret = -1;
7cdc2bab 359 const char *path = viewer_connection->url->str;
7cdc2bab
MD
360
361 if (!path) {
362 goto end;
363 }
7cdc2bab 364
0f1979c3
FD
365 lttng_live_url_parts = bt_common_parse_lttng_live_url(path, error_buf,
366 sizeof(error_buf));
94b828f3 367 if (!lttng_live_url_parts.proto) {
1419db2b
FD
368 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
369 self_comp_class,"Invalid LTTng live URL format: %s",
370 error_buf);
7cdc2bab
MD
371 goto end;
372 }
ecb4ba8a
FD
373 viewer_connection->proto = lttng_live_url_parts.proto;
374 lttng_live_url_parts.proto = NULL;
7cdc2bab 375
0f1979c3 376 viewer_connection->relay_hostname = lttng_live_url_parts.hostname;
94b828f3
MD
377 lttng_live_url_parts.hostname = NULL;
378
379 if (lttng_live_url_parts.port >= 0) {
380 viewer_connection->port = lttng_live_url_parts.port;
381 } else {
7cdc2bab
MD
382 viewer_connection->port = LTTNG_DEFAULT_NETWORK_VIEWER_PORT;
383 }
384
0f1979c3 385 viewer_connection->target_hostname = lttng_live_url_parts.target_hostname;
94b828f3
MD
386 lttng_live_url_parts.target_hostname = NULL;
387
388 if (lttng_live_url_parts.session_name) {
0f1979c3 389 viewer_connection->session_name = lttng_live_url_parts.session_name;
94b828f3 390 lttng_live_url_parts.session_name = NULL;
7cdc2bab
MD
391 }
392
7cdc2bab
MD
393 ret = 0;
394
395end:
94b828f3 396 bt_common_destroy_lttng_live_url_parts(&lttng_live_url_parts);
7cdc2bab
MD
397 return ret;
398}
399
14f28187 400static
f79c2d7a
FD
401enum lttng_live_viewer_status lttng_live_handshake(
402 struct live_viewer_connection *viewer_connection)
7cdc2bab
MD
403{
404 struct lttng_viewer_cmd cmd;
405 struct lttng_viewer_connect connect;
f79c2d7a 406 enum lttng_live_viewer_status status;
1419db2b
FD
407 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
408 bt_self_component *self_comp = viewer_connection->self_comp;
bdcbd52e
JR
409 const size_t cmd_buf_len = sizeof(cmd) + sizeof(connect);
410 char cmd_buf[cmd_buf_len];
7cdc2bab 411
ecb4ba8a 412 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
f93afbf9
FD
413 "Handshaking with the relay daemon: cmd=%s, major-version=%u, minor-version=%u",
414 lttng_viewer_command_string(LTTNG_VIEWER_CONNECT), LTTNG_LIVE_MAJOR,
415 LTTNG_LIVE_MINOR);
ecb4ba8a 416
7cdc2bab
MD
417 cmd.cmd = htobe32(LTTNG_VIEWER_CONNECT);
418 cmd.data_size = htobe64((uint64_t) sizeof(connect));
419 cmd.cmd_version = htobe32(0);
420
421 connect.viewer_session_id = -1ULL; /* will be set on recv */
422 connect.major = htobe32(LTTNG_LIVE_MAJOR);
423 connect.minor = htobe32(LTTNG_LIVE_MINOR);
424 connect.type = htobe32(LTTNG_VIEWER_CLIENT_COMMAND);
425
bdcbd52e
JR
426 /*
427 * Merge the cmd and connection request to prevent a write-write
428 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
429 * second write to be performed quickly in presence of Nagle's algorithm
430 */
431 memcpy(cmd_buf, &cmd, sizeof(cmd));
432 memcpy(cmd_buf + sizeof(cmd), &connect, sizeof(connect));
7cdc2bab 433
f79c2d7a
FD
434 status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
435 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
436 viewer_handle_send_status(self_comp, self_comp_class,
437 status, "viewer connect command");
438 goto end;
7cdc2bab 439 }
f79c2d7a
FD
440
441 status = lttng_live_recv(viewer_connection, &connect, sizeof(connect));
442 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
443 viewer_handle_recv_status(self_comp, self_comp_class,
444 status, "viewer connect reply");
445 goto end;
7cdc2bab 446 }
7cdc2bab 447
ecb4ba8a
FD
448 BT_COMP_OR_COMP_CLASS_LOGI(self_comp, self_comp_class,
449 "Received viewer session ID : %" PRIu64,
450 (uint64_t) be64toh(connect.viewer_session_id));
451 BT_COMP_OR_COMP_CLASS_LOGI(self_comp, self_comp_class,
452 "Relayd version : %u.%u", be32toh(connect.major),
453 be32toh(connect.minor));
7cdc2bab
MD
454
455 if (LTTNG_LIVE_MAJOR != be32toh(connect.major)) {
1419db2b
FD
456 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
457 self_comp_class, "Incompatible lttng-relayd protocol");
f79c2d7a
FD
458 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
459 goto end;
7cdc2bab
MD
460 }
461 /* Use the smallest protocol version implemented. */
462 if (LTTNG_LIVE_MINOR > be32toh(connect.minor)) {
463 viewer_connection->minor = be32toh(connect.minor);
464 } else {
465 viewer_connection->minor = LTTNG_LIVE_MINOR;
466 }
467 viewer_connection->major = LTTNG_LIVE_MAJOR;
7cdc2bab 468
f79c2d7a
FD
469 status = LTTNG_LIVE_VIEWER_STATUS_OK;
470
471 goto end;
472
473end:
474 return status;
7cdc2bab
MD
475}
476
14f28187 477static
f79c2d7a 478enum lttng_live_viewer_status lttng_live_connect_viewer(
36e94ad6 479 struct live_viewer_connection *viewer_connection)
7cdc2bab
MD
480{
481 struct hostent *host;
482 struct sockaddr_in server_addr;
f79c2d7a 483 enum lttng_live_viewer_status status;
1419db2b
FD
484 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
485 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab
MD
486
487 if (parse_url(viewer_connection)) {
1419db2b
FD
488 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
489 self_comp_class, "Failed to parse URL");
f79c2d7a 490 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
7cdc2bab
MD
491 goto error;
492 }
493
ecb4ba8a
FD
494 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
495 "Connecting to hostname : %s, port : %d, "
496 "target hostname : %s, session name : %s, proto : %s",
497 viewer_connection->relay_hostname->str,
498 viewer_connection->port,
499 !viewer_connection->target_hostname ?
500 "<none>" : viewer_connection->target_hostname->str,
501 !viewer_connection->session_name ?
502 "<none>" : viewer_connection->session_name->str,
503 viewer_connection->proto->str);
504
94b828f3 505 host = gethostbyname(viewer_connection->relay_hostname->str);
7cdc2bab 506 if (!host) {
1419db2b
FD
507 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
508 self_comp_class, "Cannot lookup hostname: hostname=\"%s\"",
94b828f3 509 viewer_connection->relay_hostname->str);
f79c2d7a 510 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
7cdc2bab
MD
511 goto error;
512 }
513
1cb3cdd7 514 if ((viewer_connection->control_sock = socket(AF_INET, SOCK_STREAM, 0)) == BT_INVALID_SOCKET) {
1419db2b
FD
515 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
516 self_comp_class, "Socket creation failed: %s", bt_socket_errormsg());
f79c2d7a 517 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
7cdc2bab
MD
518 goto error;
519 }
520
521 server_addr.sin_family = AF_INET;
522 server_addr.sin_port = htons(viewer_connection->port);
523 server_addr.sin_addr = *((struct in_addr *) host->h_addr);
524 memset(&(server_addr.sin_zero), 0, 8);
525
526 if (connect(viewer_connection->control_sock, (struct sockaddr *) &server_addr,
1cb3cdd7 527 sizeof(struct sockaddr)) == BT_SOCKET_ERROR) {
1419db2b
FD
528 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
529 self_comp_class, "Connection failed: %s",
530 bt_socket_errormsg());
f79c2d7a 531 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
7cdc2bab
MD
532 goto error;
533 }
f79c2d7a
FD
534
535 status = lttng_live_handshake(viewer_connection);
536
537 /*
538 * Only print error and append cause in case of error. not in case of
539 * interruption.
540 */
541 if (status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b
FD
542 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
543 self_comp_class, "Viewer handshake failed");
7cdc2bab 544 goto error;
f79c2d7a
FD
545 } else if (status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
546 goto end;
7cdc2bab
MD
547 }
548
f79c2d7a 549 goto end;
7cdc2bab
MD
550
551error:
1cb3cdd7
MJ
552 if (viewer_connection->control_sock != BT_INVALID_SOCKET) {
553 if (bt_socket_close(viewer_connection->control_sock) == BT_SOCKET_ERROR) {
ecb4ba8a
FD
554 BT_COMP_OR_COMP_CLASS_LOGW(self_comp, self_comp_class,
555 "Error closing socket: %s.", bt_socket_errormsg());
7cdc2bab
MD
556 }
557 }
1cb3cdd7 558 viewer_connection->control_sock = BT_INVALID_SOCKET;
f79c2d7a
FD
559end:
560 return status;
7cdc2bab
MD
561}
562
14f28187
FD
563static
564void lttng_live_disconnect_viewer(
565 struct live_viewer_connection *viewer_connection)
7cdc2bab 566{
ecb4ba8a
FD
567 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
568 bt_self_component *self_comp = viewer_connection->self_comp;
569
1cb3cdd7 570 if (viewer_connection->control_sock == BT_INVALID_SOCKET) {
7cdc2bab
MD
571 return;
572 }
1cb3cdd7 573 if (bt_socket_close(viewer_connection->control_sock) == BT_SOCKET_ERROR) {
ecb4ba8a
FD
574 BT_COMP_OR_COMP_CLASS_LOGW(self_comp, self_comp_class,
575 "Error closing socket: %s", bt_socket_errormsg());
1cb3cdd7 576 viewer_connection->control_sock = BT_INVALID_SOCKET;
7cdc2bab
MD
577 }
578}
579
7cdc2bab 580static
14f28187 581int list_update_session(bt_value *results,
7cdc2bab 582 const struct lttng_viewer_session *session,
c01594de 583 bool *_found, struct live_viewer_connection *viewer_connection)
7cdc2bab 584{
1419db2b
FD
585 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
586 bt_self_component *self_comp = viewer_connection->self_comp;
f80e9ec1
FD
587 int ret = 0;
588 uint64_t i, len;
b19ff26f
PP
589 bt_value *map = NULL;
590 bt_value *hostname = NULL;
591 bt_value *session_name = NULL;
592 bt_value *btval = NULL;
7cdc2bab
MD
593 bool found = false;
594
393729a6 595 len = bt_value_array_get_length(results);
7cdc2bab
MD
596 for (i = 0; i < len; i++) {
597 const char *hostname_str = NULL;
598 const char *session_name_str = NULL;
599
f80e9ec1 600 map = bt_value_array_borrow_element_by_index(results, i);
14f28187 601 hostname = bt_value_map_borrow_entry_value(map, "target-hostname");
7cdc2bab 602 if (!hostname) {
1419db2b
FD
603 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
604 self_comp_class,
605 "Error borrowing \"target-hostname\" entry.");
14f28187 606 ret = -1;
7cdc2bab
MD
607 goto end;
608 }
14f28187 609 session_name = bt_value_map_borrow_entry_value(map, "session-name");
7cdc2bab 610 if (!session_name) {
1419db2b
FD
611 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
612 self_comp_class,
613 "Error borrowing \"session-name\" entry.");
14f28187 614 ret = -1;
7cdc2bab
MD
615 goto end;
616 }
601b0d3c
PP
617 hostname_str = bt_value_string_get(hostname);
618 session_name_str = bt_value_string_get(session_name);
7cdc2bab 619
2242b43d
PP
620 if (strcmp(session->hostname, hostname_str) == 0
621 && strcmp(session->session_name, session_name_str) == 0) {
7cdc2bab
MD
622 int64_t val;
623 uint32_t streams = be32toh(session->streams);
624 uint32_t clients = be32toh(session->clients);
625
626 found = true;
627
14f28187 628 btval = bt_value_map_borrow_entry_value(map, "stream-count");
7cdc2bab 629 if (!btval) {
1419db2b
FD
630 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
631 self_comp, self_comp_class,
632 "Error borrowing \"stream-count\" entry.");
14f28187 633 ret = -1;
7cdc2bab
MD
634 goto end;
635 }
a91cb83e 636 val = bt_value_integer_unsigned_get(btval);
7cdc2bab
MD
637 /* sum */
638 val += streams;
a91cb83e 639 bt_value_integer_unsigned_set(btval, val);
7cdc2bab 640
14f28187 641 btval = bt_value_map_borrow_entry_value(map, "client-count");
7cdc2bab 642 if (!btval) {
1419db2b
FD
643 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
644 self_comp, self_comp_class,
645 "Error borrowing \"client-count\" entry.");
14f28187 646 ret = -1;
7cdc2bab
MD
647 goto end;
648 }
a91cb83e 649 val = bt_value_integer_unsigned_get(btval);
7cdc2bab 650 /* max */
91d81473 651 val = bt_max_t(int64_t, clients, val);
a91cb83e 652 bt_value_integer_unsigned_set(btval, val);
7cdc2bab
MD
653 }
654
7cdc2bab
MD
655 if (found) {
656 break;
657 }
658 }
659end:
7cdc2bab
MD
660 *_found = found;
661 return ret;
662}
663
664static
14f28187 665int list_append_session(bt_value *results,
7cdc2bab 666 GString *base_url,
c01594de
PP
667 const struct lttng_viewer_session *session,
668 struct live_viewer_connection *viewer_connection)
7cdc2bab 669{
14f28187 670 int ret = 0;
1419db2b 671 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
d24d5663
PP
672 bt_value_map_insert_entry_status insert_status;
673 bt_value_array_append_element_status append_status;
b19ff26f 674 bt_value *map = NULL;
7cdc2bab
MD
675 GString *url = NULL;
676 bool found = false;
677
678 /*
679 * If the session already exists, add the stream count to it,
680 * and do max of client counts.
681 */
c01594de 682 ret = list_update_session(results, session, &found, viewer_connection);
14f28187 683 if (ret || found) {
7cdc2bab
MD
684 goto end;
685 }
686
14f28187 687 map = bt_value_map_create();
7cdc2bab 688 if (!map) {
1419db2b
FD
689 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
690 "Error creating map value.");
14f28187 691 ret = -1;
7cdc2bab
MD
692 goto end;
693 }
694
695 if (base_url->len < 1) {
1419db2b
FD
696 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
697 "Error: base_url length smaller than 1.");
14f28187 698 ret = -1;
7cdc2bab
MD
699 goto end;
700 }
701 /*
702 * key = "url",
703 * value = <string>,
704 */
705 url = g_string_new(base_url->str);
706 g_string_append(url, "/host/");
707 g_string_append(url, session->hostname);
708 g_string_append_c(url, '/');
709 g_string_append(url, session->session_name);
710
d24d5663
PP
711 insert_status = bt_value_map_insert_string_entry(map, "url", url->str);
712 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
713 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
714 "Error inserting \"url\" entry.");
14f28187 715 ret = -1;
7cdc2bab
MD
716 goto end;
717 }
718
719 /*
720 * key = "target-hostname",
721 * value = <string>,
722 */
d24d5663 723 insert_status = bt_value_map_insert_string_entry(map, "target-hostname",
7cdc2bab 724 session->hostname);
d24d5663 725 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
726 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
727 "Error inserting \"target-hostname\" entry.");
14f28187 728 ret = -1;
7cdc2bab
MD
729 goto end;
730 }
731
732 /*
733 * key = "session-name",
734 * value = <string>,
735 */
d24d5663 736 insert_status = bt_value_map_insert_string_entry(map, "session-name",
7cdc2bab 737 session->session_name);
d24d5663 738 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
739 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
740 "Error inserting \"session-name\" entry.");
14f28187 741 ret = -1;
7cdc2bab
MD
742 goto end;
743 }
744
745 /*
746 * key = "timer-us",
747 * value = <integer>,
748 */
749 {
750 uint32_t live_timer = be32toh(session->live_timer);
751
a91cb83e 752 insert_status = bt_value_map_insert_unsigned_integer_entry(
fdd3a2da 753 map, "timer-us", live_timer);
d24d5663 754 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
755 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
756 "Error inserting \"timer-us\" entry.");
14f28187 757 ret = -1;
7cdc2bab
MD
758 goto end;
759 }
760 }
761
762 /*
763 * key = "stream-count",
764 * value = <integer>,
765 */
766 {
767 uint32_t streams = be32toh(session->streams);
768
a91cb83e 769 insert_status = bt_value_map_insert_unsigned_integer_entry(map,
fdd3a2da 770 "stream-count", streams);
d24d5663 771 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
772 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
773 "Error inserting \"stream-count\" entry.");
14f28187 774 ret = -1;
7cdc2bab
MD
775 goto end;
776 }
777 }
778
7cdc2bab
MD
779 /*
780 * key = "client-count",
781 * value = <integer>,
782 */
783 {
784 uint32_t clients = be32toh(session->clients);
785
a91cb83e 786 insert_status = bt_value_map_insert_unsigned_integer_entry(map,
fdd3a2da 787 "client-count", clients);
d24d5663 788 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
1419db2b
FD
789 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
790 "Error inserting \"client-count\" entry.");
14f28187 791 ret = -1;
7cdc2bab
MD
792 goto end;
793 }
794 }
795
d24d5663
PP
796 append_status = bt_value_array_append_element(results, map);
797 if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) {
1419db2b
FD
798 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
799 "Error appending map to results.");
14f28187
FD
800 ret = -1;
801 }
802
7cdc2bab
MD
803end:
804 if (url) {
14f28187 805 g_string_free(url, true);
7cdc2bab 806 }
c5b9b441 807 BT_VALUE_PUT_REF_AND_RESET(map);
7cdc2bab
MD
808 return ret;
809}
810
811/*
812 * Data structure returned:
813 *
814 * {
815 * <array> = {
816 * [n] = {
817 * <map> = {
818 * {
819 * key = "url",
820 * value = <string>,
821 * },
822 * {
823 * key = "target-hostname",
824 * value = <string>,
825 * },
826 * {
827 * key = "session-name",
828 * value = <string>,
829 * },
830 * {
831 * key = "timer-us",
832 * value = <integer>,
833 * },
834 * {
835 * key = "stream-count",
836 * value = <integer>,
837 * },
838 * {
839 * key = "client-count",
840 * value = <integer>,
841 * },
842 * },
843 * }
844 * }
845 */
846
847BT_HIDDEN
d24d5663 848bt_component_class_query_method_status live_viewer_connection_list_sessions(
14f28187
FD
849 struct live_viewer_connection *viewer_connection,
850 const bt_value **user_result)
7cdc2bab 851{
1419db2b 852 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
d24d5663
PP
853 bt_component_class_query_method_status status =
854 BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
14f28187 855 bt_value *result = NULL;
f79c2d7a 856 enum lttng_live_viewer_status viewer_status;
7cdc2bab
MD
857 struct lttng_viewer_cmd cmd;
858 struct lttng_viewer_list_sessions list;
859 uint32_t i, sessions_count;
7cdc2bab 860
14f28187
FD
861 result = bt_value_array_create();
862 if (!result) {
1419db2b
FD
863 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
864 "Error creating array");
d24d5663 865 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
7cdc2bab
MD
866 goto error;
867 }
868
f93afbf9
FD
869 BT_LOGD("Requesting list of sessions: cmd=%s",
870 lttng_viewer_command_string(LTTNG_VIEWER_LIST_SESSIONS));
871
7cdc2bab
MD
872 cmd.cmd = htobe32(LTTNG_VIEWER_LIST_SESSIONS);
873 cmd.data_size = htobe64((uint64_t) 0);
874 cmd.cmd_version = htobe32(0);
875
f79c2d7a
FD
876 viewer_status = lttng_live_send(viewer_connection, &cmd, sizeof(cmd));
877 if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b 878 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
f79c2d7a 879 "Error sending list sessions command");
d24d5663 880 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
7cdc2bab 881 goto error;
f79c2d7a
FD
882 } else if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
883 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
884 goto error;
7cdc2bab 885 }
7cdc2bab 886
f79c2d7a
FD
887 viewer_status = lttng_live_recv(viewer_connection, &list, sizeof(list));
888 if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b 889 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
f79c2d7a 890 "Error receiving session list");
d24d5663 891 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
7cdc2bab 892 goto error;
f79c2d7a
FD
893 } else if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
894 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
7cdc2bab
MD
895 goto error;
896 }
7cdc2bab
MD
897
898 sessions_count = be32toh(list.sessions_count);
899 for (i = 0; i < sessions_count; i++) {
900 struct lttng_viewer_session lsession;
901
f79c2d7a 902 viewer_status = lttng_live_recv(viewer_connection, &lsession,
14f28187 903 sizeof(lsession));
f79c2d7a 904 if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b 905 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
f79c2d7a 906 "Error receiving session:");
d24d5663 907 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
7cdc2bab 908 goto error;
f79c2d7a
FD
909 } else if (viewer_status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
910 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
7cdc2bab
MD
911 goto error;
912 }
f79c2d7a 913
7cdc2bab
MD
914 lsession.hostname[LTTNG_VIEWER_HOST_NAME_MAX - 1] = '\0';
915 lsession.session_name[LTTNG_VIEWER_NAME_MAX - 1] = '\0';
14f28187 916 if (list_append_session(result, viewer_connection->url,
c01594de 917 &lsession, viewer_connection)) {
1419db2b
FD
918 BT_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp_class,
919 "Error appending session");
d24d5663 920 status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
7cdc2bab
MD
921 goto error;
922 }
923 }
14f28187
FD
924
925 *user_result = result;
7cdc2bab
MD
926 goto end;
927error:
14f28187 928 BT_VALUE_PUT_REF_AND_RESET(result);
7cdc2bab 929end:
14f28187 930 return status;
7cdc2bab
MD
931}
932
933static
f79c2d7a
FD
934enum lttng_live_viewer_status lttng_live_query_session_ids(
935 struct lttng_live_msg_iter *lttng_live_msg_iter)
7cdc2bab
MD
936{
937 struct lttng_viewer_cmd cmd;
938 struct lttng_viewer_list_sessions list;
939 struct lttng_viewer_session lsession;
940 uint32_t i, sessions_count;
7cdc2bab 941 uint64_t session_id;
f79c2d7a 942 enum lttng_live_viewer_status status;
14f28187 943 struct live_viewer_connection *viewer_connection =
1419db2b
FD
944 lttng_live_msg_iter->viewer_connection;
945 bt_self_component *self_comp = viewer_connection->self_comp;
f79c2d7a
FD
946 bt_self_component_class *self_comp_class =
947 viewer_connection->self_comp_class;
7cdc2bab 948
f93afbf9
FD
949 BT_COMP_LOGD("Asking the relay daemon for the list of sessions: cmd=%s",
950 lttng_viewer_command_string(LTTNG_VIEWER_LIST_SESSIONS));
ecb4ba8a 951
7cdc2bab
MD
952 cmd.cmd = htobe32(LTTNG_VIEWER_LIST_SESSIONS);
953 cmd.data_size = htobe64((uint64_t) 0);
954 cmd.cmd_version = htobe32(0);
955
f79c2d7a
FD
956 status = lttng_live_send(viewer_connection, &cmd, sizeof(cmd));
957 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
958 viewer_handle_send_status(self_comp, self_comp_class,
959 status, "list sessions command");
960 goto end;
7cdc2bab 961 }
7cdc2bab 962
f79c2d7a
FD
963 status = lttng_live_recv(viewer_connection, &list, sizeof(list));
964 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
965 viewer_handle_recv_status(self_comp, self_comp_class,
966 status, "session list reply");
967 goto end;
7cdc2bab 968 }
7cdc2bab
MD
969
970 sessions_count = be32toh(list.sessions_count);
971 for (i = 0; i < sessions_count; i++) {
f79c2d7a
FD
972 status = lttng_live_recv(viewer_connection, &lsession,
973 sizeof(lsession));
974 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
975 viewer_handle_recv_status(self_comp, self_comp_class,
976 status, "session reply");
977 goto end;
7cdc2bab 978 }
7cdc2bab
MD
979 lsession.hostname[LTTNG_VIEWER_HOST_NAME_MAX - 1] = '\0';
980 lsession.session_name[LTTNG_VIEWER_NAME_MAX - 1] = '\0';
981 session_id = be64toh(lsession.id);
982
ecb4ba8a
FD
983 BT_COMP_LOGI("Adding session to internal list: "
984 "session-id=%" PRIu64 ", hostname=\"%s\", session-name=\"%s\"",
06994c71
MD
985 session_id, lsession.hostname, lsession.session_name);
986
7cdc2bab 987 if ((strncmp(lsession.session_name,
94b828f3 988 viewer_connection->session_name->str,
1cb3cdd7 989 LTTNG_VIEWER_NAME_MAX) == 0) && (strncmp(lsession.hostname,
94b828f3 990 viewer_connection->target_hostname->str,
1cb3cdd7 991 LTTNG_VIEWER_HOST_NAME_MAX) == 0)) {
ecb4ba8a 992
14f28187 993 if (lttng_live_add_session(lttng_live_msg_iter, session_id,
06994c71
MD
994 lsession.hostname,
995 lsession.session_name)) {
1419db2b
FD
996 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
997 "Failed to add live session");
f79c2d7a
FD
998 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
999 goto end;
7cdc2bab
MD
1000 }
1001 }
1002 }
1003
f79c2d7a 1004 status = LTTNG_LIVE_VIEWER_STATUS_OK;
7cdc2bab 1005
f79c2d7a
FD
1006end:
1007 return status;
7cdc2bab
MD
1008}
1009
1010BT_HIDDEN
f79c2d7a 1011enum lttng_live_viewer_status lttng_live_create_viewer_session(
14f28187 1012 struct lttng_live_msg_iter *lttng_live_msg_iter)
7cdc2bab
MD
1013{
1014 struct lttng_viewer_cmd cmd;
1015 struct lttng_viewer_create_session_response resp;
f79c2d7a 1016 enum lttng_live_viewer_status status;
14f28187 1017 struct live_viewer_connection *viewer_connection =
1419db2b
FD
1018 lttng_live_msg_iter->viewer_connection;
1019 bt_self_component *self_comp = viewer_connection->self_comp;
f79c2d7a
FD
1020 bt_self_component_class *self_comp_class =
1021 viewer_connection->self_comp_class;
7cdc2bab 1022
ecb4ba8a 1023 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
f93afbf9
FD
1024 "Creating a viewer session: cmd=%s",
1025 lttng_viewer_command_string(LTTNG_VIEWER_CREATE_SESSION));
ecb4ba8a 1026
7cdc2bab
MD
1027 cmd.cmd = htobe32(LTTNG_VIEWER_CREATE_SESSION);
1028 cmd.data_size = htobe64((uint64_t) 0);
1029 cmd.cmd_version = htobe32(0);
1030
f79c2d7a
FD
1031 status = lttng_live_send(viewer_connection, &cmd, sizeof(cmd));
1032 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1033 viewer_handle_send_status(self_comp, self_comp_class,
1034 status, "create session command");
1035 goto end;
7cdc2bab 1036 }
7cdc2bab 1037
f79c2d7a
FD
1038 status = lttng_live_recv(viewer_connection, &resp, sizeof(resp));
1039 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1040 viewer_handle_recv_status(self_comp, self_comp_class,
1041 status, "create session reply");
1042 goto end;
7cdc2bab 1043 }
7cdc2bab
MD
1044
1045 if (be32toh(resp.status) != LTTNG_VIEWER_CREATE_SESSION_OK) {
1419db2b
FD
1046 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1047 "Error creating viewer session");
f79c2d7a
FD
1048 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1049 goto end;
7cdc2bab 1050 }
f79c2d7a
FD
1051
1052 status = lttng_live_query_session_ids(lttng_live_msg_iter);
1053 if (status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b
FD
1054 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1055 "Failed to query live viewer session ids");
f79c2d7a
FD
1056 goto end;
1057 } else if (status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
1058 goto end;
7cdc2bab
MD
1059 }
1060
f79c2d7a
FD
1061end:
1062 return status;
7cdc2bab
MD
1063}
1064
1065static
f79c2d7a 1066enum lttng_live_viewer_status receive_streams(struct lttng_live_session *session,
851de941
SM
1067 uint32_t stream_count,
1068 bt_self_message_iterator *self_msg_iter)
7cdc2bab 1069{
7cdc2bab 1070 uint32_t i;
14f28187 1071 struct lttng_live_msg_iter *lttng_live_msg_iter =
0f1979c3 1072 session->lttng_live_msg_iter;
f79c2d7a 1073 enum lttng_live_viewer_status status;
14f28187 1074 struct live_viewer_connection *viewer_connection =
0f1979c3 1075 lttng_live_msg_iter->viewer_connection;
1419db2b 1076 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab 1077
f93afbf9 1078 BT_COMP_LOGI("Getting %" PRIu32 " new streams", stream_count);
7cdc2bab
MD
1079 for (i = 0; i < stream_count; i++) {
1080 struct lttng_viewer_stream stream;
1081 struct lttng_live_stream_iterator *live_stream;
1082 uint64_t stream_id;
1083 uint64_t ctf_trace_id;
1084
f79c2d7a
FD
1085 status = lttng_live_recv(viewer_connection, &stream,
1086 sizeof(stream));
1087 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1088 viewer_handle_recv_status(self_comp, NULL,
1089 status, "stream reply");
1090 goto end;
7cdc2bab 1091 }
7cdc2bab
MD
1092 stream.path_name[LTTNG_VIEWER_PATH_MAX - 1] = '\0';
1093 stream.channel_name[LTTNG_VIEWER_NAME_MAX - 1] = '\0';
1094 stream_id = be64toh(stream.id);
1095 ctf_trace_id = be64toh(stream.ctf_trace_id);
1096
1097 if (stream.metadata_flag) {
2ece7dd0 1098 BT_COMP_LOGI(" metadata stream %" PRIu64 " : %s/%s",
0f1979c3 1099 stream_id, stream.path_name, stream.channel_name);
7cdc2bab 1100 if (lttng_live_metadata_create_stream(session,
06994c71
MD
1101 ctf_trace_id, stream_id,
1102 stream.path_name)) {
1419db2b
FD
1103 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1104 "Error creating metadata stream");
f79c2d7a
FD
1105 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1106 goto end;
7cdc2bab 1107 }
d6e69534 1108 session->lazy_stream_msg_init = true;
7cdc2bab 1109 } else {
2ece7dd0 1110 BT_COMP_LOGI(" stream %" PRIu64 " : %s/%s",
0f1979c3 1111 stream_id, stream.path_name, stream.channel_name);
7cdc2bab 1112 live_stream = lttng_live_stream_iterator_create(session,
851de941 1113 ctf_trace_id, stream_id, self_msg_iter);
7cdc2bab 1114 if (!live_stream) {
1419db2b
FD
1115 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1116 "Error creating stream");
f79c2d7a
FD
1117 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1118 goto end;
7cdc2bab
MD
1119 }
1120 }
1121 }
f79c2d7a 1122 status = LTTNG_LIVE_VIEWER_STATUS_OK;
7cdc2bab 1123
f79c2d7a
FD
1124end:
1125 return status;
7cdc2bab
MD
1126}
1127
1128BT_HIDDEN
36e94ad6 1129enum lttng_live_viewer_status lttng_live_session_attach(
851de941
SM
1130 struct lttng_live_session *session,
1131 bt_self_message_iterator *self_msg_iter)
7cdc2bab
MD
1132{
1133 struct lttng_viewer_cmd cmd;
f79c2d7a 1134 enum lttng_live_viewer_status status;
7cdc2bab
MD
1135 struct lttng_viewer_attach_session_request rq;
1136 struct lttng_viewer_attach_session_response rp;
0f1979c3
FD
1137 struct lttng_live_msg_iter *lttng_live_msg_iter =
1138 session->lttng_live_msg_iter;
14f28187 1139 struct live_viewer_connection *viewer_connection =
0f1979c3 1140 lttng_live_msg_iter->viewer_connection;
1419db2b 1141 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab
MD
1142 uint64_t session_id = session->id;
1143 uint32_t streams_count;
bdcbd52e
JR
1144 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1145 char cmd_buf[cmd_buf_len];
7cdc2bab 1146
f93afbf9
FD
1147 BT_COMP_LOGD("Attaching to session: cmd=%s, session-id=%" PRIu64
1148 ", seek=%s",
1149 lttng_viewer_command_string(LTTNG_VIEWER_ATTACH_SESSION),
1150 session_id,
1151 lttng_viewer_seek_string(LTTNG_VIEWER_SEEK_LAST));
ecb4ba8a 1152
7cdc2bab
MD
1153 cmd.cmd = htobe32(LTTNG_VIEWER_ATTACH_SESSION);
1154 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1155 cmd.cmd_version = htobe32(0);
1156
1157 memset(&rq, 0, sizeof(rq));
1158 rq.session_id = htobe64(session_id);
1159 // TODO: add cmd line parameter to select seek beginning
1160 // rq.seek = htobe32(LTTNG_VIEWER_SEEK_BEGINNING);
1161 rq.seek = htobe32(LTTNG_VIEWER_SEEK_LAST);
1162
bdcbd52e
JR
1163 /*
1164 * Merge the cmd and connection request to prevent a write-write
1165 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1166 * second write to be performed quickly in presence of Nagle's algorithm.
1167 */
1168 memcpy(cmd_buf, &cmd, sizeof(cmd));
1169 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f79c2d7a
FD
1170 status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1171 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1172 viewer_handle_send_status(self_comp, NULL,
1173 status, "attach session command");
1174 goto end;
7cdc2bab 1175 }
7cdc2bab 1176
f79c2d7a
FD
1177 status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1178 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1179 viewer_handle_recv_status(self_comp, NULL,
1180 status, "attach session reply");
1181 goto end;
7cdc2bab 1182 }
7cdc2bab
MD
1183
1184 streams_count = be32toh(rp.streams_count);
1185 switch(be32toh(rp.status)) {
1186 case LTTNG_VIEWER_ATTACH_OK:
1187 break;
1188 case LTTNG_VIEWER_ATTACH_UNK:
1419db2b
FD
1189 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1190 "Session id %" PRIu64 " is unknown", session_id);
f79c2d7a
FD
1191 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1192 goto end;
7cdc2bab 1193 case LTTNG_VIEWER_ATTACH_ALREADY:
1419db2b
FD
1194 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1195 "There is already a viewer attached to this session");
f79c2d7a
FD
1196 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1197 goto end;
7cdc2bab 1198 case LTTNG_VIEWER_ATTACH_NOT_LIVE:
1419db2b 1199 BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Not a live session");
f79c2d7a
FD
1200 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1201 goto end;
7cdc2bab 1202 case LTTNG_VIEWER_ATTACH_SEEK_ERR:
1419db2b 1203 BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Wrong seek parameter");
f79c2d7a
FD
1204 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1205 goto end;
7cdc2bab 1206 default:
1419db2b
FD
1207 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1208 "Unknown attach return code %u", be32toh(rp.status));
f79c2d7a
FD
1209 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1210 goto end;
7cdc2bab
MD
1211 }
1212
1213 /* We receive the initial list of streams. */
f79c2d7a
FD
1214 status = receive_streams(session, streams_count, self_msg_iter);
1215 switch (status) {
1216 case LTTNG_LIVE_VIEWER_STATUS_OK:
1217 break;
1218 case LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED:
1219 goto end;
1220 case LTTNG_LIVE_VIEWER_STATUS_ERROR:
1419db2b 1221 BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Error receiving streams");
f79c2d7a
FD
1222 goto end;
1223 default:
1224 bt_common_abort();
7cdc2bab
MD
1225 }
1226
1227 session->attached = true;
1228 session->new_streams_needed = false;
1229
eee8e741 1230end:
f79c2d7a 1231 return status;
7cdc2bab
MD
1232}
1233
1234BT_HIDDEN
36e94ad6 1235enum lttng_live_viewer_status lttng_live_session_detach(
f79c2d7a 1236 struct lttng_live_session *session)
7cdc2bab
MD
1237{
1238 struct lttng_viewer_cmd cmd;
f79c2d7a 1239 enum lttng_live_viewer_status status;
7cdc2bab
MD
1240 struct lttng_viewer_detach_session_request rq;
1241 struct lttng_viewer_detach_session_response rp;
0f1979c3
FD
1242 struct lttng_live_msg_iter *lttng_live_msg_iter =
1243 session->lttng_live_msg_iter;
f79c2d7a 1244 bt_self_component *self_comp = session->self_comp;
14f28187 1245 struct live_viewer_connection *viewer_connection =
0f1979c3 1246 lttng_live_msg_iter->viewer_connection;
7cdc2bab 1247 uint64_t session_id = session->id;
bdcbd52e
JR
1248 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1249 char cmd_buf[cmd_buf_len];
7cdc2bab 1250
b197ca37
FD
1251 /*
1252 * The session might already be detached and the viewer socket might
1253 * already been closed. This happens when calling this function when
1254 * tearing down the graph after an error.
1255 */
1256 if (!session->attached || viewer_connection->control_sock == BT_INVALID_SOCKET) {
7cdc2bab
MD
1257 return 0;
1258 }
1259
f93afbf9
FD
1260 BT_COMP_LOGD("Detaching from session: cmd=%s, session-id=%" PRIu64,
1261 lttng_viewer_command_string(LTTNG_VIEWER_DETACH_SESSION),
1262 session_id);
1263
7cdc2bab
MD
1264 cmd.cmd = htobe32(LTTNG_VIEWER_DETACH_SESSION);
1265 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1266 cmd.cmd_version = htobe32(0);
1267
1268 memset(&rq, 0, sizeof(rq));
1269 rq.session_id = htobe64(session_id);
1270
bdcbd52e
JR
1271 /*
1272 * Merge the cmd and connection request to prevent a write-write
1273 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1274 * second write to be performed quickly in presence of Nagle's algorithm.
1275 */
1276 memcpy(cmd_buf, &cmd, sizeof(cmd));
1277 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f79c2d7a
FD
1278 status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1279 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1280 viewer_handle_send_status(self_comp, NULL,
1281 status, "detach session command");
1282 goto end;
7cdc2bab 1283 }
7cdc2bab 1284
f79c2d7a
FD
1285 status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1286 if (status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1287 viewer_handle_recv_status(self_comp, NULL,
1288 status, "detach session reply");
1289 goto end;
7cdc2bab 1290 }
7cdc2bab
MD
1291
1292 switch(be32toh(rp.status)) {
1293 case LTTNG_VIEWER_DETACH_SESSION_OK:
1294 break;
1295 case LTTNG_VIEWER_DETACH_SESSION_UNK:
2ece7dd0 1296 BT_COMP_LOGW("Session id %" PRIu64 " is unknown", session_id);
f79c2d7a
FD
1297 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1298 goto end;
7cdc2bab 1299 case LTTNG_VIEWER_DETACH_SESSION_ERR:
2ece7dd0 1300 BT_COMP_LOGW("Error detaching session id %" PRIu64 "", session_id);
f79c2d7a
FD
1301 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1302 goto end;
7cdc2bab 1303 default:
2ece7dd0 1304 BT_COMP_LOGE("Unknown detach return code %u", be32toh(rp.status));
f79c2d7a
FD
1305 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1306 goto end;
7cdc2bab
MD
1307 }
1308
1309 session->attached = false;
1310
f79c2d7a 1311 status = LTTNG_LIVE_VIEWER_STATUS_OK;
7cdc2bab 1312
f79c2d7a
FD
1313end:
1314 return status;
7cdc2bab
MD
1315}
1316
1317BT_HIDDEN
c28512ab
FD
1318enum lttng_live_get_one_metadata_status lttng_live_get_one_metadata_packet(
1319 struct lttng_live_trace *trace, FILE *fp, size_t *reply_len)
7cdc2bab
MD
1320{
1321 uint64_t len = 0;
f79c2d7a
FD
1322 enum lttng_live_get_one_metadata_status status;
1323 enum lttng_live_viewer_status viewer_status;
7cdc2bab
MD
1324 struct lttng_viewer_cmd cmd;
1325 struct lttng_viewer_get_metadata rq;
1326 struct lttng_viewer_metadata_packet rp;
b7370030 1327 gchar *data = NULL;
0e73b4c2 1328 ssize_t writelen;
7cdc2bab 1329 struct lttng_live_session *session = trace->session;
0f1979c3
FD
1330 struct lttng_live_msg_iter *lttng_live_msg_iter =
1331 session->lttng_live_msg_iter;
7cdc2bab 1332 struct lttng_live_metadata *metadata = trace->metadata;
14f28187 1333 struct live_viewer_connection *viewer_connection =
0f1979c3 1334 lttng_live_msg_iter->viewer_connection;
1419db2b 1335 bt_self_component *self_comp = viewer_connection->self_comp;
bdcbd52e
JR
1336 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1337 char cmd_buf[cmd_buf_len];
7cdc2bab 1338
f93afbf9
FD
1339 BT_COMP_LOGD("Requesting new metadata for trace:"
1340 "cmd=%s, trace-id=%" PRIu64 ", metadata-stream-id=%" PRIu64,
1341 lttng_viewer_command_string(LTTNG_VIEWER_GET_METADATA),
ecb4ba8a
FD
1342 trace->id, metadata->stream_id);
1343
7cdc2bab
MD
1344 rq.stream_id = htobe64(metadata->stream_id);
1345 cmd.cmd = htobe32(LTTNG_VIEWER_GET_METADATA);
1346 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1347 cmd.cmd_version = htobe32(0);
1348
bdcbd52e
JR
1349 /*
1350 * Merge the cmd and connection request to prevent a write-write
1351 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1352 * second write to be performed quickly in presence of Nagle's algorithm.
1353 */
1354 memcpy(cmd_buf, &cmd, sizeof(cmd));
1355 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f79c2d7a
FD
1356 viewer_status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1357 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1358 viewer_handle_send_status(self_comp, NULL,
1359 viewer_status, "get metadata command");
1360 status = (enum lttng_live_get_one_metadata_status) viewer_status;
1361 goto end;
7cdc2bab 1362 }
7cdc2bab 1363
f79c2d7a
FD
1364 viewer_status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1365 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1366 viewer_handle_recv_status(self_comp, NULL,
1367 viewer_status, "get metadata reply");
1368 status = (enum lttng_live_get_one_metadata_status) viewer_status;
1369 goto end;
7cdc2bab 1370 }
7cdc2bab
MD
1371
1372 switch (be32toh(rp.status)) {
1373 case LTTNG_VIEWER_METADATA_OK:
1419db2b 1374 BT_COMP_LOGD("Received get_metadata response: ok");
7cdc2bab
MD
1375 break;
1376 case LTTNG_VIEWER_NO_NEW_METADATA:
c28512ab 1377 BT_COMP_LOGD("Received get_metadata response: no new");
f79c2d7a 1378 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_END;
7cdc2bab
MD
1379 goto end;
1380 case LTTNG_VIEWER_METADATA_ERR:
c28512ab
FD
1381 /*
1382 * The Relayd cannot find this stream id. Maybe its
1383 * gone already. This can happen in short lived UST app
1384 * in a per-pid session.
1385 */
1386 BT_COMP_LOGD("Received get_metadata response: error");
f79c2d7a 1387 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_CLOSED;
c28512ab 1388 goto end;
7cdc2bab 1389 default:
1419db2b
FD
1390 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1391 "Received get_metadata response: unknown");
f79c2d7a 1392 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR;
b7370030 1393 goto end;
7cdc2bab
MD
1394 }
1395
1396 len = be64toh(rp.len);
2ece7dd0 1397 BT_COMP_LOGD("Writing %" PRIu64" bytes to metadata", len);
7cdc2bab 1398 if (len <= 0) {
1419db2b
FD
1399 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1400 "Erroneous response length");
f79c2d7a 1401 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR;
b7370030 1402 goto end;
7cdc2bab
MD
1403 }
1404
b7370030 1405 data = g_new0(gchar, len);
7cdc2bab 1406 if (!data) {
1419db2b
FD
1407 BT_COMP_LOGE_APPEND_CAUSE_ERRNO(self_comp,
1408 "Failed to allocate data buffer", ".");
f79c2d7a 1409 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR;
b7370030 1410 goto end;
7cdc2bab 1411 }
f79c2d7a
FD
1412
1413 viewer_status = lttng_live_recv(viewer_connection, data, len);
1414 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1415 viewer_handle_recv_status(self_comp, NULL,
1416 viewer_status, "get metadata packet");
1417 status = (enum lttng_live_get_one_metadata_status) viewer_status;
b7370030 1418 goto end;
7cdc2bab 1419 }
7cdc2bab 1420
f79c2d7a
FD
1421 /*
1422 * Write the metadata to the file handle.
1423 */
0e73b4c2
FD
1424 writelen = fwrite(data, sizeof(uint8_t), len, fp);
1425 if (writelen != len) {
1419db2b
FD
1426 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1427 "Writing in the metadata file stream");
f79c2d7a 1428 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR;
b7370030 1429 goto end;
7cdc2bab 1430 }
0e73b4c2 1431
c28512ab 1432 *reply_len = len;
f79c2d7a 1433 status = LTTNG_LIVE_GET_ONE_METADATA_STATUS_OK;
c28512ab 1434
c28512ab 1435end:
b7370030 1436 g_free(data);
f79c2d7a 1437 return status;
7cdc2bab
MD
1438}
1439
1440/*
1441 * Assign the fields from a lttng_viewer_index to a packet_index.
1442 */
1443static
1444void lttng_index_to_packet_index(struct lttng_viewer_index *lindex,
1445 struct packet_index *pindex)
1446{
f6ccaed9
PP
1447 BT_ASSERT(lindex);
1448 BT_ASSERT(pindex);
7cdc2bab
MD
1449
1450 pindex->offset = be64toh(lindex->offset);
1451 pindex->packet_size = be64toh(lindex->packet_size);
1452 pindex->content_size = be64toh(lindex->content_size);
1453 pindex->ts_cycles.timestamp_begin = be64toh(lindex->timestamp_begin);
1454 pindex->ts_cycles.timestamp_end = be64toh(lindex->timestamp_end);
1455 pindex->events_discarded = be64toh(lindex->events_discarded);
1456}
1457
36e94ad6
FD
1458static
1459void lttng_live_need_new_streams(struct lttng_live_msg_iter *lttng_live_msg_iter)
1460{
1461 uint64_t session_idx;
f93afbf9
FD
1462 struct live_viewer_connection *viewer_connection =
1463 lttng_live_msg_iter->viewer_connection;
36e94ad6
FD
1464
1465 for (session_idx = 0; session_idx < lttng_live_msg_iter->sessions->len;
1466 session_idx++) {
1467 struct lttng_live_session *session =
f93afbf9
FD
1468 g_ptr_array_index(lttng_live_msg_iter->sessions, session_idx);
1469 BT_COMP_LOGD("Marking session as needing new streams: "
1470 "session-id=%" PRIu64, session->id);
36e94ad6
FD
1471 session->new_streams_needed = true;
1472 }
1473}
1474
7cdc2bab 1475BT_HIDDEN
14f28187
FD
1476enum lttng_live_iterator_status lttng_live_get_next_index(
1477 struct lttng_live_msg_iter *lttng_live_msg_iter,
7cdc2bab
MD
1478 struct lttng_live_stream_iterator *stream,
1479 struct packet_index *index)
1480{
1481 struct lttng_viewer_cmd cmd;
1482 struct lttng_viewer_get_next_index rq;
f79c2d7a 1483 enum lttng_live_viewer_status viewer_status;
7cdc2bab 1484 struct lttng_viewer_index rp;
f79c2d7a 1485 enum lttng_live_iterator_status status;
14f28187 1486 struct live_viewer_connection *viewer_connection =
1419db2b
FD
1487 lttng_live_msg_iter->viewer_connection;
1488 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab 1489 struct lttng_live_trace *trace = stream->trace;
bdcbd52e
JR
1490 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1491 char cmd_buf[cmd_buf_len];
f79c2d7a 1492 uint32_t flags, rp_status;
7cdc2bab 1493
f93afbf9
FD
1494 BT_COMP_LOGD("Requesting next index for stream: cmd=%s, "
1495 "viewer-stream-id=%" PRIu64,
1496 lttng_viewer_command_string(LTTNG_VIEWER_GET_NEXT_INDEX),
1497 stream->viewer_stream_id);
7cdc2bab
MD
1498 cmd.cmd = htobe32(LTTNG_VIEWER_GET_NEXT_INDEX);
1499 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1500 cmd.cmd_version = htobe32(0);
1501
1502 memset(&rq, 0, sizeof(rq));
1503 rq.stream_id = htobe64(stream->viewer_stream_id);
1504
bdcbd52e
JR
1505 /*
1506 * Merge the cmd and connection request to prevent a write-write
1507 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1508 * second write to be performed quickly in presence of Nagle's algorithm.
1509 */
1510 memcpy(cmd_buf, &cmd, sizeof(cmd));
1511 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f93afbf9 1512
f79c2d7a
FD
1513 viewer_status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1514 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1515 viewer_handle_send_status(self_comp, NULL,
1516 viewer_status, "get next index command");
7cdc2bab
MD
1517 goto error;
1518 }
7cdc2bab 1519
f79c2d7a
FD
1520 viewer_status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1521 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1522 viewer_handle_recv_status(self_comp, NULL,
1523 viewer_status, "get next index reply");
7cdc2bab
MD
1524 goto error;
1525 }
7cdc2bab
MD
1526
1527 flags = be32toh(rp.flags);
f79c2d7a 1528 rp_status = be32toh(rp.status);
7cdc2bab 1529
f93afbf9
FD
1530 BT_COMP_LOGD("Received response from relay daemon: cmd=%s, response=%s",
1531 lttng_viewer_command_string(LTTNG_VIEWER_GET_NEXT_INDEX),
1532 lttng_viewer_next_index_return_code_string(rp_status));
f79c2d7a 1533 switch (rp_status) {
7cdc2bab
MD
1534 case LTTNG_VIEWER_INDEX_INACTIVE:
1535 {
1536 uint64_t ctf_stream_class_id;
1537
7cdc2bab
MD
1538 memset(index, 0, sizeof(struct packet_index));
1539 index->ts_cycles.timestamp_end = be64toh(rp.timestamp_end);
14f28187 1540 stream->current_inactivity_ts = index->ts_cycles.timestamp_end;
7cdc2bab 1541 ctf_stream_class_id = be64toh(rp.stream_id);
1a258819
FD
1542 if (stream->ctf_stream_class_id.is_set) {
1543 BT_ASSERT(stream->ctf_stream_class_id.value==
7cdc2bab
MD
1544 ctf_stream_class_id);
1545 } else {
1a258819
FD
1546 stream->ctf_stream_class_id.value = ctf_stream_class_id;
1547 stream->ctf_stream_class_id.is_set = true;
7cdc2bab 1548 }
34533ae0 1549 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_QUIESCENT);
f79c2d7a 1550 status = LTTNG_LIVE_ITERATOR_STATUS_OK;
7cdc2bab
MD
1551 break;
1552 }
1553 case LTTNG_VIEWER_INDEX_OK:
1554 {
1555 uint64_t ctf_stream_class_id;
1556
7cdc2bab
MD
1557 lttng_index_to_packet_index(&rp, index);
1558 ctf_stream_class_id = be64toh(rp.stream_id);
1a258819
FD
1559 if (stream->ctf_stream_class_id.is_set) {
1560 BT_ASSERT(stream->ctf_stream_class_id.value==
7cdc2bab
MD
1561 ctf_stream_class_id);
1562 } else {
1a258819
FD
1563 stream->ctf_stream_class_id.value = ctf_stream_class_id;
1564 stream->ctf_stream_class_id.is_set = true;
7cdc2bab
MD
1565 }
1566
34533ae0 1567 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_ACTIVE_DATA);
7cdc2bab
MD
1568
1569 if (flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
f93afbf9
FD
1570 BT_COMP_LOGD("Marking trace as needing new metadata: "
1571 "response=%s, response-flag=NEW_METADATA, trace-id=%" PRIu64,
1572 lttng_viewer_next_index_return_code_string(rp_status),
1573 trace->id);
76bbaebc 1574 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NEEDED;
7cdc2bab
MD
1575 }
1576 if (flags & LTTNG_VIEWER_FLAG_NEW_STREAM) {
f93afbf9
FD
1577 BT_COMP_LOGD("Marking all sessions as possibly needing new streams: "
1578 "response=%s, response-flag=NEW_STREAM",
1579 lttng_viewer_next_index_return_code_string(rp_status));
14f28187 1580 lttng_live_need_new_streams(lttng_live_msg_iter);
7cdc2bab 1581 }
f79c2d7a 1582 status = LTTNG_LIVE_ITERATOR_STATUS_OK;
7cdc2bab
MD
1583 break;
1584 }
1585 case LTTNG_VIEWER_INDEX_RETRY:
7cdc2bab 1586 memset(index, 0, sizeof(struct packet_index));
34533ae0 1587 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_ACTIVE_NO_DATA);
f79c2d7a 1588 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
7cdc2bab
MD
1589 goto end;
1590 case LTTNG_VIEWER_INDEX_HUP:
7cdc2bab
MD
1591 memset(index, 0, sizeof(struct packet_index));
1592 index->offset = EOF;
34533ae0 1593 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_EOF);
4a39caef 1594 stream->has_stream_hung_up = true;
f79c2d7a 1595 status = LTTNG_LIVE_ITERATOR_STATUS_END;
7cdc2bab
MD
1596 break;
1597 case LTTNG_VIEWER_INDEX_ERR:
7cdc2bab 1598 memset(index, 0, sizeof(struct packet_index));
34533ae0 1599 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_ACTIVE_NO_DATA);
f79c2d7a
FD
1600 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
1601 goto end;
7cdc2bab 1602 default:
1419db2b 1603 BT_COMP_LOGD("Received get_next_index response: unknown value");
7cdc2bab 1604 memset(index, 0, sizeof(struct packet_index));
34533ae0 1605 lttng_live_stream_iterator_set_state(stream, LTTNG_LIVE_STREAM_ACTIVE_NO_DATA);
f79c2d7a
FD
1606 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
1607 goto end;
7cdc2bab 1608 }
f79c2d7a 1609 goto end;
7cdc2bab
MD
1610
1611error:
f79c2d7a
FD
1612 status = viewer_status_to_live_iterator_status(viewer_status);
1613end:
1614 return status;
7cdc2bab
MD
1615}
1616
1617BT_HIDDEN
18a1979b 1618enum ctf_msg_iter_medium_status lttng_live_get_stream_bytes(
14f28187
FD
1619 struct lttng_live_msg_iter *lttng_live_msg_iter,
1620 struct lttng_live_stream_iterator *stream, uint8_t *buf,
1621 uint64_t offset, uint64_t req_len, uint64_t *recv_len)
7cdc2bab 1622{
f79c2d7a
FD
1623 enum ctf_msg_iter_medium_status status;
1624 enum lttng_live_viewer_status viewer_status;
0f1979c3 1625 struct lttng_viewer_trace_packet rp;
7cdc2bab
MD
1626 struct lttng_viewer_cmd cmd;
1627 struct lttng_viewer_get_packet rq;
14f28187 1628 struct live_viewer_connection *viewer_connection =
1419db2b
FD
1629 lttng_live_msg_iter->viewer_connection;
1630 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab 1631 struct lttng_live_trace *trace = stream->trace;
bdcbd52e
JR
1632 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1633 char cmd_buf[cmd_buf_len];
f79c2d7a 1634 uint32_t flags, rp_status;
7cdc2bab 1635
f93afbf9
FD
1636 BT_COMP_LOGD("Requesting data from stream: cmd=%s, "
1637 "offset=%" PRIu64 ", request-len=%" PRIu64,
1638 lttng_viewer_command_string(LTTNG_VIEWER_GET_PACKET),
7cdc2bab 1639 offset, req_len);
f93afbf9 1640
7cdc2bab
MD
1641 cmd.cmd = htobe32(LTTNG_VIEWER_GET_PACKET);
1642 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1643 cmd.cmd_version = htobe32(0);
1644
1645 memset(&rq, 0, sizeof(rq));
1646 rq.stream_id = htobe64(stream->viewer_stream_id);
1647 rq.offset = htobe64(offset);
1648 rq.len = htobe32(req_len);
1649
bdcbd52e
JR
1650 /*
1651 * Merge the cmd and connection request to prevent a write-write
1652 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1653 * second write to be performed quickly in presence of Nagle's algorithm.
1654 */
1655 memcpy(cmd_buf, &cmd, sizeof(cmd));
1656 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f93afbf9 1657
f79c2d7a
FD
1658 viewer_status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1659 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1660 viewer_handle_send_status(self_comp, NULL,
1661 viewer_status, "get data packet command");
535fb48a 1662 goto error_convert_status;
7cdc2bab 1663 }
7cdc2bab 1664
f79c2d7a
FD
1665 viewer_status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1666 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1667 viewer_handle_recv_status(self_comp, NULL,
1668 viewer_status, "get data packet reply");
535fb48a 1669 goto error_convert_status;
7cdc2bab
MD
1670 }
1671
1672 flags = be32toh(rp.flags);
f79c2d7a 1673 rp_status = be32toh(rp.status);
7cdc2bab 1674
f93afbf9
FD
1675 BT_COMP_LOGD("Received response from relay daemon: cmd=%s, response=%s",
1676 lttng_viewer_command_string(LTTNG_VIEWER_GET_PACKET),
1677 lttng_viewer_get_packet_return_code_string(rp_status));
f79c2d7a 1678 switch (rp_status) {
7cdc2bab
MD
1679 case LTTNG_VIEWER_GET_PACKET_OK:
1680 req_len = be32toh(rp.len);
f93afbf9
FD
1681 BT_COMP_LOGD("Got packet from relay daemon: response=%s, packet-len=%" PRIu64 "",
1682 lttng_viewer_get_packet_return_code_string(rp_status),
1683 req_len);
f79c2d7a 1684 status = CTF_MSG_ITER_MEDIUM_STATUS_OK;
7cdc2bab
MD
1685 break;
1686 case LTTNG_VIEWER_GET_PACKET_RETRY:
1687 /* Unimplemented by relay daemon */
f79c2d7a 1688 status = CTF_MSG_ITER_MEDIUM_STATUS_AGAIN;
7cdc2bab
MD
1689 goto end;
1690 case LTTNG_VIEWER_GET_PACKET_ERR:
1691 if (flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
f93afbf9
FD
1692 BT_COMP_LOGD("Marking trace as needing new metadata: "
1693 "response=%s, response-flag=NEW_METADATA, trace-id=%" PRIu64,
1694 lttng_viewer_next_index_return_code_string(rp_status),
1695 trace->id);
76bbaebc 1696 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NEEDED;
7cdc2bab
MD
1697 }
1698 if (flags & LTTNG_VIEWER_FLAG_NEW_STREAM) {
f93afbf9
FD
1699 BT_COMP_LOGD("Marking all sessions as possibly needing new streams: "
1700 "response=%s, response-flag=NEW_STREAM",
1701 lttng_viewer_next_index_return_code_string(rp_status));
14f28187 1702 lttng_live_need_new_streams(lttng_live_msg_iter);
7cdc2bab
MD
1703 }
1704 if (flags & (LTTNG_VIEWER_FLAG_NEW_METADATA
1705 | LTTNG_VIEWER_FLAG_NEW_STREAM)) {
f79c2d7a 1706 status = CTF_MSG_ITER_MEDIUM_STATUS_AGAIN;
f93afbf9
FD
1707 BT_COMP_LOGD("Reply with any one flags set means we should retry: response=%s",
1708 lttng_viewer_get_packet_return_code_string(rp_status));
7cdc2bab
MD
1709 goto end;
1710 }
1419db2b
FD
1711 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1712 "Received get_data_packet response: error");
f79c2d7a
FD
1713 status = CTF_MSG_ITER_MEDIUM_STATUS_ERROR;
1714 goto end;
7cdc2bab 1715 case LTTNG_VIEWER_GET_PACKET_EOF:
f79c2d7a 1716 status = CTF_MSG_ITER_MEDIUM_STATUS_EOF;
7cdc2bab
MD
1717 goto end;
1718 default:
1419db2b 1719 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
535fb48a 1720 "Received get_data_packet response: unknown (%d)", rp_status);
f79c2d7a 1721 status = CTF_MSG_ITER_MEDIUM_STATUS_ERROR;
535fb48a 1722 goto end;
7cdc2bab
MD
1723 }
1724
1725 if (req_len == 0) {
f79c2d7a 1726 status = CTF_MSG_ITER_MEDIUM_STATUS_ERROR;
535fb48a 1727 goto end;
7cdc2bab
MD
1728 }
1729
f79c2d7a
FD
1730 viewer_status = lttng_live_recv(viewer_connection, buf, req_len);
1731 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1732 viewer_handle_recv_status(self_comp, NULL,
1733 viewer_status, "get data packet");
535fb48a 1734 goto error_convert_status;
7cdc2bab 1735 }
f79c2d7a 1736 *recv_len = req_len;
7cdc2bab 1737
f79c2d7a
FD
1738 status = CTF_MSG_ITER_MEDIUM_STATUS_OK;
1739 goto end;
f79c2d7a 1740
535fb48a 1741error_convert_status:
f79c2d7a
FD
1742 status = viewer_status_to_ctf_msg_iter_medium_status(viewer_status);
1743end:
1744 return status;
7cdc2bab
MD
1745}
1746
1747/*
1748 * Request new streams for a session.
1749 */
1750BT_HIDDEN
36e94ad6 1751enum lttng_live_iterator_status lttng_live_session_get_new_streams(
851de941
SM
1752 struct lttng_live_session *session,
1753 bt_self_message_iterator *self_msg_iter)
7cdc2bab 1754{
14f28187
FD
1755 enum lttng_live_iterator_status status =
1756 LTTNG_LIVE_ITERATOR_STATUS_OK;
7cdc2bab
MD
1757 struct lttng_viewer_cmd cmd;
1758 struct lttng_viewer_new_streams_request rq;
1759 struct lttng_viewer_new_streams_response rp;
14f28187
FD
1760 struct lttng_live_msg_iter *lttng_live_msg_iter =
1761 session->lttng_live_msg_iter;
f79c2d7a 1762 enum lttng_live_viewer_status viewer_status;
14f28187
FD
1763 struct live_viewer_connection *viewer_connection =
1764 lttng_live_msg_iter->viewer_connection;
1419db2b 1765 bt_self_component *self_comp = viewer_connection->self_comp;
7cdc2bab 1766 uint32_t streams_count;
bdcbd52e
JR
1767 const size_t cmd_buf_len = sizeof(cmd) + sizeof(rq);
1768 char cmd_buf[cmd_buf_len];
7cdc2bab
MD
1769
1770 if (!session->new_streams_needed) {
f79c2d7a
FD
1771 status = LTTNG_LIVE_ITERATOR_STATUS_OK;
1772 goto end;
7cdc2bab
MD
1773 }
1774
0c4e4aa8 1775 BT_COMP_LOGD("Requesting new streams for session: cmd=%s, "
f93afbf9
FD
1776 "session-id=%" PRIu64,
1777 lttng_viewer_command_string(LTTNG_VIEWER_GET_NEW_STREAMS),
1778 session->id);
ecb4ba8a 1779
7cdc2bab
MD
1780 cmd.cmd = htobe32(LTTNG_VIEWER_GET_NEW_STREAMS);
1781 cmd.data_size = htobe64((uint64_t) sizeof(rq));
1782 cmd.cmd_version = htobe32(0);
1783
1784 memset(&rq, 0, sizeof(rq));
1785 rq.session_id = htobe64(session->id);
1786
bdcbd52e
JR
1787 /*
1788 * Merge the cmd and connection request to prevent a write-write
1789 * sequence on the TCP socket. Otherwise, a delayed ACK will prevent the
1790 * second write to be performed quickly in presence of Nagle's algorithm.
1791 */
1792 memcpy(cmd_buf, &cmd, sizeof(cmd));
1793 memcpy(cmd_buf + sizeof(cmd), &rq, sizeof(rq));
f93afbf9 1794
f79c2d7a
FD
1795 viewer_status = lttng_live_send(viewer_connection, &cmd_buf, cmd_buf_len);
1796 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1797 viewer_handle_send_status(self_comp, NULL,
1798 viewer_status, "get new streams command");
1799 status = viewer_status_to_live_iterator_status(viewer_status);
1800 goto end;
7cdc2bab 1801 }
7cdc2bab 1802
f79c2d7a
FD
1803 viewer_status = lttng_live_recv(viewer_connection, &rp, sizeof(rp));
1804 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1805 viewer_handle_recv_status(self_comp, NULL,
1806 viewer_status, "get new streams reply");
1807 status = viewer_status_to_live_iterator_status(viewer_status);
1808 goto end;
7cdc2bab 1809 }
7cdc2bab
MD
1810
1811 streams_count = be32toh(rp.streams_count);
1812
1813 switch(be32toh(rp.status)) {
1814 case LTTNG_VIEWER_NEW_STREAMS_OK:
1815 session->new_streams_needed = false;
1816 break;
1817 case LTTNG_VIEWER_NEW_STREAMS_NO_NEW:
1818 session->new_streams_needed = false;
1819 goto end;
1820 case LTTNG_VIEWER_NEW_STREAMS_HUP:
1821 session->new_streams_needed = false;
1822 session->closed = true;
14f28187 1823 status = LTTNG_LIVE_ITERATOR_STATUS_END;
7cdc2bab
MD
1824 goto end;
1825 case LTTNG_VIEWER_NEW_STREAMS_ERR:
1419db2b 1826 BT_COMP_LOGD("Received get_new_streams response: error");
f79c2d7a
FD
1827 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
1828 goto end;
7cdc2bab 1829 default:
1419db2b
FD
1830 BT_COMP_LOGE_APPEND_CAUSE(self_comp,
1831 "Received get_new_streams response: Unknown:"
1832 "return code %u", be32toh(rp.status));
f79c2d7a
FD
1833 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
1834 goto end;
7cdc2bab
MD
1835 }
1836
f79c2d7a
FD
1837 viewer_status = receive_streams(session, streams_count, self_msg_iter);
1838 if (viewer_status != LTTNG_LIVE_VIEWER_STATUS_OK) {
1839 viewer_handle_recv_status(self_comp, NULL,
1840 viewer_status, "new streams");
1841 status = viewer_status_to_live_iterator_status(viewer_status);
1842 goto end;
7cdc2bab 1843 }
7cdc2bab 1844
f79c2d7a
FD
1845 status = LTTNG_LIVE_ITERATOR_STATUS_OK;
1846end:
7cdc2bab
MD
1847 return status;
1848}
1849
1850BT_HIDDEN
f79c2d7a 1851enum lttng_live_viewer_status live_viewer_connection_create(
1419db2b
FD
1852 bt_self_component *self_comp,
1853 bt_self_component_class *self_comp_class,
f79c2d7a
FD
1854 bt_logging_level log_level,
1855 const char *url, bool in_query,
1856 struct lttng_live_msg_iter *lttng_live_msg_iter,
1857 struct live_viewer_connection **viewer)
7cdc2bab 1858{
14f28187 1859 struct live_viewer_connection *viewer_connection;
f79c2d7a 1860 enum lttng_live_viewer_status status;
7cdc2bab 1861
14f28187 1862 viewer_connection = g_new0(struct live_viewer_connection, 1);
7cdc2bab 1863
550004b4 1864 if (bt_socket_init(log_level) != 0) {
1419db2b
FD
1865 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
1866 self_comp_class, "Failed to init socket");
f79c2d7a 1867 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
1cb3cdd7
MJ
1868 goto error;
1869 }
1870
550004b4
PP
1871 viewer_connection->log_level = log_level;
1872
1419db2b
FD
1873 viewer_connection->self_comp = self_comp;
1874 viewer_connection->self_comp_class = self_comp_class;
550004b4 1875
1cb3cdd7 1876 viewer_connection->control_sock = BT_INVALID_SOCKET;
7cdc2bab 1877 viewer_connection->port = -1;
14f28187
FD
1878 viewer_connection->in_query = in_query;
1879 viewer_connection->lttng_live_msg_iter = lttng_live_msg_iter;
7cdc2bab
MD
1880 viewer_connection->url = g_string_new(url);
1881 if (!viewer_connection->url) {
1419db2b
FD
1882 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
1883 self_comp_class, "Failed to allocate URL buffer");
f79c2d7a 1884 status = LTTNG_LIVE_VIEWER_STATUS_ERROR;
7cdc2bab
MD
1885 goto error;
1886 }
1887
ecb4ba8a
FD
1888 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
1889 "Establishing connection to url \"%s\"...", url);
f79c2d7a
FD
1890 status = lttng_live_connect_viewer(viewer_connection);
1891 /*
1892 * Only print error and append cause in case of error. not in case of
1893 * interruption.
1894 */
1895 if (status == LTTNG_LIVE_VIEWER_STATUS_ERROR) {
1419db2b
FD
1896 BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp,
1897 self_comp_class, "Failed to establish connection: "
1898 "url=\"%s\"", url);
1899 goto error;
f79c2d7a
FD
1900 } else if (status == LTTNG_LIVE_VIEWER_STATUS_INTERRUPTED) {
1901 goto error;
7cdc2bab 1902 }
ecb4ba8a
FD
1903 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
1904 "Connection to url \"%s\" is established", url);
f79c2d7a
FD
1905
1906 *viewer = viewer_connection;
1907 status = LTTNG_LIVE_VIEWER_STATUS_OK;
1908 goto end;
7cdc2bab 1909
7cdc2bab 1910error:
2f767475
PP
1911 if (viewer_connection) {
1912 live_viewer_connection_destroy(viewer_connection);
1913 }
f79c2d7a
FD
1914end:
1915 return status;
7cdc2bab
MD
1916}
1917
1918BT_HIDDEN
14f28187
FD
1919void live_viewer_connection_destroy(
1920 struct live_viewer_connection *viewer_connection)
7cdc2bab 1921{
ecb4ba8a
FD
1922 bt_self_component *self_comp = viewer_connection->self_comp;
1923 bt_self_component_class *self_comp_class = viewer_connection->self_comp_class;
b9e6ec43
FD
1924
1925 if (!viewer_connection) {
1926 goto end;
1927 }
1928
ecb4ba8a
FD
1929 BT_COMP_OR_COMP_CLASS_LOGD(self_comp, self_comp_class,
1930 "Closing connection to relay:"
1931 "relay-url=\"%s\"", viewer_connection->url->str);
1932
7cdc2bab 1933 lttng_live_disconnect_viewer(viewer_connection);
b9e6ec43 1934
2f767475
PP
1935 if (viewer_connection->url) {
1936 g_string_free(viewer_connection->url, true);
1937 }
b9e6ec43 1938
94b828f3 1939 if (viewer_connection->relay_hostname) {
14f28187 1940 g_string_free(viewer_connection->relay_hostname, true);
94b828f3 1941 }
b9e6ec43 1942
94b828f3 1943 if (viewer_connection->target_hostname) {
14f28187 1944 g_string_free(viewer_connection->target_hostname, true);
94b828f3 1945 }
b9e6ec43 1946
94b828f3 1947 if (viewer_connection->session_name) {
14f28187 1948 g_string_free(viewer_connection->session_name, true);
94b828f3 1949 }
b9e6ec43 1950
ecb4ba8a
FD
1951 if (viewer_connection->proto) {
1952 g_string_free(viewer_connection->proto, true);
1953 }
1954
7cdc2bab 1955 g_free(viewer_connection);
1cb3cdd7
MJ
1956
1957 bt_socket_fini();
b9e6ec43
FD
1958
1959end:
1960 return;
7cdc2bab 1961}
This page took 0.181279 seconds and 4 git commands to generate.