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