Commit | Line | Data |
---|---|---|
1b368955 | 1 | /* |
9d16b343 | 2 | * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com> |
1b368955 | 3 | * |
9d16b343 | 4 | * SPDX-License-Identifier: GPL-2.0-only |
1b368955 | 5 | * |
1b368955 JD |
6 | */ |
7 | ||
1b368955 | 8 | #include <assert.h> |
1b368955 JD |
9 | #include <stdio.h> |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
12 | #include <unistd.h> | |
389fbf04 | 13 | #include <common/compat/time.h> |
1b368955 JD |
14 | #include <sys/types.h> |
15 | #include <inttypes.h> | |
16 | #include <stdlib.h> | |
17 | #include <sys/socket.h> | |
18 | #include <netinet/in.h> | |
19 | #include <netdb.h> | |
20 | #include <fcntl.h> | |
21 | #include <sys/mman.h> | |
22 | #include <sys/stat.h> | |
23 | ||
24 | #include <tap/tap.h> | |
25 | #include <lttng/lttng.h> | |
e207fe73 | 26 | #include <lttng/ust-sigbus.h> |
1b368955 JD |
27 | |
28 | #include <urcu/list.h> | |
1b368955 JD |
29 | #include <common/common.h> |
30 | ||
2f8f53af | 31 | #include <bin/lttng-relayd/lttng-viewer-abi.h> |
50adc264 | 32 | #include <common/index/ctf-index.h> |
1b368955 | 33 | |
edf4b93e | 34 | #include <common/compat/errno.h> |
f263b7fd JD |
35 | #include <common/compat/endian.h> |
36 | ||
1b368955 JD |
37 | #define SESSION1 "test1" |
38 | #define RELAYD_URL "net://localhost" | |
39 | #define LIVE_TIMER 2000000 | |
40 | ||
41 | /* Number of TAP tests in this file */ | |
e22ba966 | 42 | #define NUM_TESTS 11 |
1b368955 JD |
43 | #define mmap_size 524288 |
44 | ||
e207fe73 | 45 | DEFINE_LTTNG_UST_SIGBUS_STATE(); |
46 | ||
1b368955 JD |
47 | static int control_sock; |
48 | struct live_session *session; | |
49 | ||
50 | static int first_packet_offset; | |
51 | static int first_packet_len; | |
7409dd34 | 52 | static int first_packet_stream_id = -1; |
1b368955 JD |
53 | |
54 | struct viewer_stream { | |
55 | uint64_t id; | |
56 | uint64_t ctf_trace_id; | |
57 | void *mmap_base; | |
58 | int fd; | |
59 | int metadata_flag; | |
60 | int first_read; | |
61 | char path[PATH_MAX]; | |
62 | }; | |
63 | ||
64 | struct live_session { | |
65 | struct viewer_stream *streams; | |
66 | uint64_t live_timer_interval; | |
67 | uint64_t stream_count; | |
68 | }; | |
69 | ||
10236918 MD |
70 | static |
71 | ssize_t lttng_live_recv(int fd, void *buf, size_t len) | |
72 | { | |
73 | ssize_t ret; | |
74 | size_t copied = 0, to_copy = len; | |
75 | ||
76 | do { | |
77 | ret = recv(fd, buf + copied, to_copy, 0); | |
78 | if (ret > 0) { | |
79 | assert(ret <= to_copy); | |
80 | copied += ret; | |
81 | to_copy -= ret; | |
82 | } | |
83 | } while ((ret > 0 && to_copy > 0) | |
84 | || (ret < 0 && errno == EINTR)); | |
85 | if (ret > 0) | |
86 | ret = copied; | |
87 | /* ret = 0 means orderly shutdown, ret < 0 is error. */ | |
88 | return ret; | |
89 | } | |
90 | ||
91 | static | |
92 | ssize_t lttng_live_send(int fd, const void *buf, size_t len) | |
93 | { | |
94 | ssize_t ret; | |
95 | ||
96 | do { | |
97 | ret = send(fd, buf, len, MSG_NOSIGNAL); | |
98 | } while (ret < 0 && errno == EINTR); | |
99 | return ret; | |
100 | } | |
101 | ||
1b368955 | 102 | static |
b53d4e59 | 103 | int connect_viewer(const char *hostname) |
1b368955 JD |
104 | { |
105 | struct hostent *host; | |
106 | struct sockaddr_in server_addr; | |
107 | int ret; | |
108 | ||
109 | host = gethostbyname(hostname); | |
110 | if (!host) { | |
111 | ret = -1; | |
112 | goto end; | |
113 | } | |
114 | ||
115 | if ((control_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { | |
6f04ed72 | 116 | PERROR("Socket"); |
1b368955 JD |
117 | ret = -1; |
118 | goto end; | |
119 | } | |
120 | ||
121 | server_addr.sin_family = AF_INET; | |
122 | server_addr.sin_port = htons(5344); | |
123 | server_addr.sin_addr = *((struct in_addr *) host->h_addr); | |
124 | bzero(&(server_addr.sin_zero), 8); | |
125 | ||
126 | if (connect(control_sock, (struct sockaddr *) &server_addr, | |
127 | sizeof(struct sockaddr)) == -1) { | |
6f04ed72 | 128 | PERROR("Connect"); |
1b368955 JD |
129 | ret = -1; |
130 | goto end; | |
131 | } | |
132 | ||
133 | server_addr.sin_family = AF_INET; | |
134 | server_addr.sin_port = htons(5345); | |
135 | server_addr.sin_addr = *((struct in_addr *) host->h_addr); | |
136 | bzero(&(server_addr.sin_zero), 8); | |
137 | ||
138 | ret = 0; | |
139 | ||
140 | end: | |
141 | return ret; | |
142 | } | |
143 | ||
8f92cd08 | 144 | static |
1b368955 JD |
145 | int establish_connection(void) |
146 | { | |
147 | struct lttng_viewer_cmd cmd; | |
148 | struct lttng_viewer_connect connect; | |
10236918 | 149 | ssize_t ret_len; |
1b368955 | 150 | |
c4e361a4 | 151 | cmd.cmd = htobe32(LTTNG_VIEWER_CONNECT); |
2dc797f3 JD |
152 | cmd.data_size = htobe64(sizeof(connect)); |
153 | cmd.cmd_version = htobe32(0); | |
1b368955 | 154 | |
dcf5c25e | 155 | memset(&connect, 0, sizeof(connect)); |
1b368955 JD |
156 | connect.major = htobe32(VERSION_MAJOR); |
157 | connect.minor = htobe32(VERSION_MINOR); | |
c4e361a4 | 158 | connect.type = htobe32(LTTNG_VIEWER_CLIENT_COMMAND); |
1b368955 | 159 | |
10236918 MD |
160 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
161 | if (ret_len < 0) { | |
7409dd34 | 162 | diag("Error sending cmd"); |
1b368955 JD |
163 | goto error; |
164 | } | |
10236918 MD |
165 | ret_len = lttng_live_send(control_sock, &connect, sizeof(connect)); |
166 | if (ret_len < 0) { | |
7409dd34 | 167 | diag("Error sending version"); |
1b368955 JD |
168 | goto error; |
169 | } | |
170 | ||
10236918 MD |
171 | ret_len = lttng_live_recv(control_sock, &connect, sizeof(connect)); |
172 | if (ret_len == 0) { | |
7409dd34 | 173 | diag("[error] Remote side has closed connection"); |
10236918 MD |
174 | goto error; |
175 | } | |
176 | if (ret_len < 0) { | |
7409dd34 | 177 | diag("Error receiving version"); |
1b368955 JD |
178 | goto error; |
179 | } | |
10236918 | 180 | return 0; |
1b368955 JD |
181 | |
182 | error: | |
10236918 | 183 | return -1; |
1b368955 JD |
184 | } |
185 | ||
186 | /* | |
187 | * Returns the number of sessions, should be 1 during the unit test. | |
188 | */ | |
8f92cd08 | 189 | static |
7409dd34 | 190 | int list_sessions(uint64_t *session_id) |
1b368955 JD |
191 | { |
192 | struct lttng_viewer_cmd cmd; | |
193 | struct lttng_viewer_list_sessions list; | |
194 | struct lttng_viewer_session lsession; | |
10236918 MD |
195 | int i; |
196 | ssize_t ret_len; | |
1b368955 JD |
197 | int first_session = 0; |
198 | ||
c4e361a4 | 199 | cmd.cmd = htobe32(LTTNG_VIEWER_LIST_SESSIONS); |
2dc797f3 JD |
200 | cmd.data_size = htobe64(0); |
201 | cmd.cmd_version = htobe32(0); | |
1b368955 | 202 | |
10236918 MD |
203 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
204 | if (ret_len < 0) { | |
7409dd34 | 205 | diag("Error sending cmd"); |
1b368955 JD |
206 | goto error; |
207 | } | |
208 | ||
10236918 MD |
209 | ret_len = lttng_live_recv(control_sock, &list, sizeof(list)); |
210 | if (ret_len == 0) { | |
7409dd34 | 211 | diag("[error] Remote side has closed connection"); |
10236918 MD |
212 | goto error; |
213 | } | |
214 | if (ret_len < 0) { | |
7409dd34 | 215 | diag("Error receiving session list"); |
1b368955 JD |
216 | goto error; |
217 | } | |
218 | ||
219 | for (i = 0; i < be32toh(list.sessions_count); i++) { | |
10236918 MD |
220 | ret_len = lttng_live_recv(control_sock, &lsession, sizeof(lsession)); |
221 | if (ret_len < 0) { | |
7409dd34 | 222 | diag("Error receiving session"); |
1b368955 JD |
223 | goto error; |
224 | } | |
225 | if (lsession.streams > 0 && first_session <= 0) { | |
226 | first_session = be64toh(lsession.id); | |
227 | *session_id = first_session; | |
228 | } | |
229 | } | |
230 | ||
10236918 | 231 | return be32toh(list.sessions_count); |
1b368955 JD |
232 | |
233 | error: | |
10236918 | 234 | return -1; |
1b368955 JD |
235 | } |
236 | ||
8f92cd08 | 237 | static |
10236918 | 238 | int create_viewer_session(void) |
25b50f8f JD |
239 | { |
240 | struct lttng_viewer_cmd cmd; | |
241 | struct lttng_viewer_create_session_response resp; | |
25b50f8f JD |
242 | ssize_t ret_len; |
243 | ||
244 | cmd.cmd = htobe32(LTTNG_VIEWER_CREATE_SESSION); | |
2dc797f3 JD |
245 | cmd.data_size = htobe64(0); |
246 | cmd.cmd_version = htobe32(0); | |
25b50f8f | 247 | |
10236918 | 248 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
25b50f8f | 249 | if (ret_len < 0) { |
7409dd34 | 250 | diag("[error] Error sending cmd"); |
25b50f8f JD |
251 | goto error; |
252 | } | |
253 | assert(ret_len == sizeof(cmd)); | |
254 | ||
10236918 MD |
255 | ret_len = lttng_live_recv(control_sock, &resp, sizeof(resp)); |
256 | if (ret_len == 0) { | |
7409dd34 | 257 | diag("[error] Remote side has closed connection"); |
10236918 MD |
258 | goto error; |
259 | } | |
25b50f8f | 260 | if (ret_len < 0) { |
7409dd34 | 261 | diag("[error] Error receiving create session reply"); |
25b50f8f JD |
262 | goto error; |
263 | } | |
264 | assert(ret_len == sizeof(resp)); | |
265 | ||
266 | if (be32toh(resp.status) != LTTNG_VIEWER_CREATE_SESSION_OK) { | |
7409dd34 | 267 | diag("[error] Error creating viewer session"); |
25b50f8f JD |
268 | goto error; |
269 | } | |
10236918 | 270 | return 0; |
25b50f8f JD |
271 | |
272 | error: | |
10236918 | 273 | return -1; |
25b50f8f JD |
274 | } |
275 | ||
8f92cd08 | 276 | static |
7409dd34 | 277 | int attach_session(uint64_t id) |
1b368955 JD |
278 | { |
279 | struct lttng_viewer_cmd cmd; | |
280 | struct lttng_viewer_attach_session_request rq; | |
281 | struct lttng_viewer_attach_session_response rp; | |
282 | struct lttng_viewer_stream stream; | |
10236918 MD |
283 | int i; |
284 | ssize_t ret_len; | |
1b368955 JD |
285 | |
286 | session = zmalloc(sizeof(struct live_session)); | |
287 | if (!session) { | |
1b368955 JD |
288 | goto error; |
289 | } | |
290 | ||
c4e361a4 | 291 | cmd.cmd = htobe32(LTTNG_VIEWER_ATTACH_SESSION); |
2dc797f3 JD |
292 | cmd.data_size = htobe64(sizeof(rq)); |
293 | cmd.cmd_version = htobe32(0); | |
1b368955 | 294 | |
dcf5c25e | 295 | memset(&rq, 0, sizeof(rq)); |
1b368955 | 296 | rq.session_id = htobe64(id); |
c4e361a4 | 297 | rq.seek = htobe32(LTTNG_VIEWER_SEEK_BEGINNING); |
1b368955 | 298 | |
10236918 MD |
299 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
300 | if (ret_len < 0) { | |
7409dd34 | 301 | diag("Error sending cmd LTTNG_VIEWER_ATTACH_SESSION"); |
1b368955 JD |
302 | goto error; |
303 | } | |
10236918 MD |
304 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
305 | if (ret_len < 0) { | |
7409dd34 | 306 | diag("Error sending attach request"); |
1b368955 JD |
307 | goto error; |
308 | } | |
309 | ||
10236918 MD |
310 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
311 | if (ret_len == 0) { | |
7409dd34 | 312 | diag("[error] Remote side has closed connection"); |
10236918 MD |
313 | goto error; |
314 | } | |
315 | if (ret_len < 0) { | |
7409dd34 | 316 | diag("Error receiving attach response"); |
1b368955 JD |
317 | goto error; |
318 | } | |
c4e361a4 | 319 | if (be32toh(rp.status) != LTTNG_VIEWER_ATTACH_OK) { |
10236918 | 320 | goto error; |
1b368955 JD |
321 | } |
322 | ||
323 | session->stream_count = be32toh(rp.streams_count); | |
7409dd34 JG |
324 | if (session->stream_count == 0) { |
325 | diag("Got session stream count == 0"); | |
326 | goto error; | |
327 | } | |
1b368955 JD |
328 | session->streams = zmalloc(session->stream_count * |
329 | sizeof(struct viewer_stream)); | |
330 | if (!session->streams) { | |
1b368955 JD |
331 | goto error; |
332 | } | |
333 | ||
334 | for (i = 0; i < be32toh(rp.streams_count); i++) { | |
10236918 MD |
335 | ret_len = lttng_live_recv(control_sock, &stream, sizeof(stream)); |
336 | if (ret_len == 0) { | |
7409dd34 | 337 | diag("[error] Remote side has closed connection"); |
10236918 MD |
338 | goto error; |
339 | } | |
340 | if (ret_len < 0) { | |
7409dd34 | 341 | diag("Error receiving stream"); |
1b368955 JD |
342 | goto error; |
343 | } | |
344 | session->streams[i].id = be64toh(stream.id); | |
345 | ||
346 | session->streams[i].ctf_trace_id = be64toh(stream.ctf_trace_id); | |
347 | session->streams[i].first_read = 1; | |
7409dd34 JG |
348 | session->streams[i].mmap_base = mmap(NULL, mmap_size, |
349 | PROT_READ | PROT_WRITE, | |
1b368955 JD |
350 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
351 | if (session->streams[i].mmap_base == MAP_FAILED) { | |
7409dd34 | 352 | diag("mmap error"); |
1b368955 JD |
353 | goto error; |
354 | } | |
355 | ||
356 | if (be32toh(stream.metadata_flag)) { | |
357 | session->streams[i].metadata_flag = 1; | |
358 | } | |
359 | } | |
10236918 | 360 | return session->stream_count; |
1b368955 | 361 | |
1b368955 | 362 | error: |
10236918 | 363 | return -1; |
1b368955 JD |
364 | } |
365 | ||
8f92cd08 | 366 | static |
1b368955 JD |
367 | int get_metadata(void) |
368 | { | |
369 | struct lttng_viewer_cmd cmd; | |
370 | struct lttng_viewer_get_metadata rq; | |
371 | struct lttng_viewer_metadata_packet rp; | |
10236918 | 372 | ssize_t ret_len; |
1b368955 JD |
373 | int ret; |
374 | uint64_t i; | |
375 | char *data = NULL; | |
376 | uint64_t len = 0; | |
377 | int metadata_stream_id = -1; | |
378 | ||
c4e361a4 | 379 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_METADATA); |
2dc797f3 JD |
380 | cmd.data_size = htobe64(sizeof(rq)); |
381 | cmd.cmd_version = htobe32(0); | |
1b368955 JD |
382 | |
383 | for (i = 0; i < session->stream_count; i++) { | |
384 | if (session->streams[i].metadata_flag) { | |
385 | metadata_stream_id = i; | |
386 | break; | |
387 | } | |
388 | } | |
389 | ||
390 | if (metadata_stream_id < 0) { | |
7409dd34 | 391 | diag("No metadata stream found"); |
1b368955 JD |
392 | goto error; |
393 | } | |
394 | ||
395 | rq.stream_id = htobe64(session->streams[metadata_stream_id].id); | |
396 | ||
a648b489 | 397 | retry: |
10236918 MD |
398 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
399 | if (ret_len < 0) { | |
7409dd34 | 400 | diag("Error sending cmd"); |
1b368955 JD |
401 | goto error; |
402 | } | |
10236918 MD |
403 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
404 | if (ret_len < 0) { | |
7409dd34 | 405 | diag("Error sending get_metadata request"); |
1b368955 JD |
406 | goto error; |
407 | } | |
10236918 MD |
408 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
409 | if (ret_len == 0) { | |
7409dd34 | 410 | diag("[error] Remote side has closed connection"); |
10236918 MD |
411 | goto error; |
412 | } | |
413 | if (ret_len < 0) { | |
7409dd34 | 414 | diag("Error receiving metadata response"); |
1b368955 JD |
415 | goto error; |
416 | } | |
417 | switch (be32toh(rp.status)) { | |
7409dd34 JG |
418 | case LTTNG_VIEWER_METADATA_OK: |
419 | break; | |
420 | case LTTNG_VIEWER_NO_NEW_METADATA: | |
421 | diag("Got LTTNG_VIEWER_NO_NEW_METADATA:"); | |
a648b489 JR |
422 | usleep(50); |
423 | goto retry; | |
7409dd34 JG |
424 | case LTTNG_VIEWER_METADATA_ERR: |
425 | diag("Got LTTNG_VIEWER_METADATA_ERR:"); | |
426 | goto error; | |
427 | default: | |
428 | diag("Got unknown status during LTTNG_VIEWER_GET_METADATA"); | |
429 | goto error; | |
1b368955 JD |
430 | } |
431 | ||
432 | len = be64toh(rp.len); | |
433 | if (len <= 0) { | |
10236918 | 434 | goto error; |
1b368955 JD |
435 | } |
436 | ||
437 | data = zmalloc(len); | |
438 | if (!data) { | |
6f04ed72 | 439 | PERROR("relay data zmalloc"); |
1b368955 JD |
440 | goto error; |
441 | } | |
10236918 MD |
442 | ret_len = lttng_live_recv(control_sock, data, len); |
443 | if (ret_len == 0) { | |
7409dd34 | 444 | diag("[error] Remote side has closed connection"); |
10236918 MD |
445 | goto error_free_data; |
446 | } | |
447 | if (ret_len < 0) { | |
7409dd34 | 448 | diag("Error receiving trace packet"); |
10236918 | 449 | goto error_free_data; |
1b368955 JD |
450 | } |
451 | free(data); | |
10236918 | 452 | ret = len; |
a648b489 | 453 | |
1b368955 | 454 | return ret; |
10236918 MD |
455 | |
456 | error_free_data: | |
457 | free(data); | |
458 | error: | |
459 | return -1; | |
1b368955 JD |
460 | } |
461 | ||
8f92cd08 | 462 | static |
1b368955 JD |
463 | int get_next_index(void) |
464 | { | |
465 | struct lttng_viewer_cmd cmd; | |
466 | struct lttng_viewer_get_next_index rq; | |
467 | struct lttng_viewer_index rp; | |
10236918 | 468 | ssize_t ret_len; |
1b368955 JD |
469 | int id; |
470 | ||
c4e361a4 | 471 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_NEXT_INDEX); |
2dc797f3 JD |
472 | cmd.data_size = htobe64(sizeof(rq)); |
473 | cmd.cmd_version = htobe32(0); | |
1b368955 JD |
474 | |
475 | for (id = 0; id < session->stream_count; id++) { | |
476 | if (session->streams[id].metadata_flag) { | |
477 | continue; | |
478 | } | |
10236918 | 479 | memset(&rq, 0, sizeof(rq)); |
1b368955 JD |
480 | rq.stream_id = htobe64(session->streams[id].id); |
481 | ||
482 | retry: | |
10236918 MD |
483 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
484 | if (ret_len < 0) { | |
7409dd34 | 485 | diag("Error sending cmd"); |
1b368955 JD |
486 | goto error; |
487 | } | |
10236918 MD |
488 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
489 | if (ret_len < 0) { | |
7409dd34 | 490 | diag("Error sending get_next_index request"); |
1b368955 JD |
491 | goto error; |
492 | } | |
10236918 MD |
493 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
494 | if (ret_len == 0) { | |
7409dd34 | 495 | diag("[error] Remote side has closed connection"); |
10236918 MD |
496 | goto error; |
497 | } | |
498 | if (ret_len < 0) { | |
7409dd34 | 499 | diag("Error receiving index response"); |
1b368955 JD |
500 | goto error; |
501 | } | |
502 | ||
503 | rp.flags = be32toh(rp.flags); | |
504 | ||
505 | switch (be32toh(rp.status)) { | |
7409dd34 JG |
506 | case LTTNG_VIEWER_INDEX_INACTIVE: |
507 | /* Skip this stream. */ | |
508 | diag("Got LTTNG_VIEWER_INDEX_INACTIVE"); | |
509 | continue; | |
510 | case LTTNG_VIEWER_INDEX_OK: | |
511 | break; | |
512 | case LTTNG_VIEWER_INDEX_RETRY: | |
513 | sleep(1); | |
514 | goto retry; | |
515 | case LTTNG_VIEWER_INDEX_HUP: | |
516 | diag("Got LTTNG_VIEWER_INDEX_HUP"); | |
517 | session->streams[id].id = -1ULL; | |
518 | session->streams[id].fd = -1; | |
519 | goto error; | |
520 | case LTTNG_VIEWER_INDEX_ERR: | |
521 | diag("Got LTTNG_VIEWER_INDEX_ERR"); | |
522 | goto error; | |
523 | default: | |
524 | diag("Unknown reply status during LTTNG_VIEWER_GET_NEXT_INDEX (%d)", be32toh(rp.status)); | |
525 | goto error; | |
1b368955 | 526 | } |
7409dd34 JG |
527 | if (first_packet_stream_id < 0) { |
528 | /* | |
529 | * Initialize the first packet stream id. That is, | |
530 | * the first active stream encoutered. | |
531 | */ | |
1b368955 JD |
532 | first_packet_offset = be64toh(rp.offset); |
533 | first_packet_len = be64toh(rp.packet_size) / CHAR_BIT; | |
534 | first_packet_stream_id = id; | |
7409dd34 JG |
535 | diag("Got first packet index with offset %d and len %d", |
536 | first_packet_offset, first_packet_len); | |
1b368955 JD |
537 | } |
538 | } | |
10236918 | 539 | return 0; |
1b368955 JD |
540 | |
541 | error: | |
10236918 | 542 | return -1; |
1b368955 JD |
543 | } |
544 | ||
545 | static | |
546 | int get_data_packet(int id, uint64_t offset, | |
547 | uint64_t len) | |
548 | { | |
549 | struct lttng_viewer_cmd cmd; | |
550 | struct lttng_viewer_get_packet rq; | |
551 | struct lttng_viewer_trace_packet rp; | |
10236918 | 552 | ssize_t ret_len; |
1b368955 | 553 | |
c4e361a4 | 554 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_PACKET); |
2dc797f3 JD |
555 | cmd.data_size = htobe64(sizeof(rq)); |
556 | cmd.cmd_version = htobe32(0); | |
1b368955 | 557 | |
10236918 | 558 | memset(&rq, 0, sizeof(rq)); |
1b368955 JD |
559 | rq.stream_id = htobe64(session->streams[id].id); |
560 | /* Already in big endian. */ | |
561 | rq.offset = offset; | |
562 | rq.len = htobe32(len); | |
563 | ||
10236918 MD |
564 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
565 | if (ret_len < 0) { | |
7409dd34 | 566 | diag("Error sending cmd"); |
1b368955 JD |
567 | goto error; |
568 | } | |
10236918 MD |
569 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
570 | if (ret_len < 0) { | |
7409dd34 | 571 | diag("Error sending get_data_packet request"); |
1b368955 JD |
572 | goto error; |
573 | } | |
10236918 MD |
574 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
575 | if (ret_len == 0) { | |
7409dd34 | 576 | diag("[error] Remote side has closed connection"); |
10236918 MD |
577 | goto error; |
578 | } | |
579 | if (ret_len < 0) { | |
7409dd34 | 580 | diag("Error receiving data response"); |
1b368955 JD |
581 | goto error; |
582 | } | |
583 | rp.flags = be32toh(rp.flags); | |
584 | ||
585 | switch (be32toh(rp.status)) { | |
c4e361a4 | 586 | case LTTNG_VIEWER_GET_PACKET_OK: |
10236918 | 587 | len = be32toh(rp.len); |
7409dd34 JG |
588 | if (len == 0) { |
589 | diag("Got LTTNG_VIEWER_GET_PACKET_OK, but len == 0"); | |
590 | goto error; | |
591 | } | |
1b368955 | 592 | break; |
c4e361a4 | 593 | case LTTNG_VIEWER_GET_PACKET_RETRY: |
7409dd34 | 594 | diag("Got LTTNG_VIEWER_GET_PACKET_RETRY:"); |
10236918 | 595 | goto error; |
c4e361a4 | 596 | case LTTNG_VIEWER_GET_PACKET_ERR: |
1b368955 | 597 | if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) { |
7409dd34 | 598 | diag("Got LTTNG_VIEWER_GET_PACKET_ERR with NEW_METADATA flag"); |
1b368955 JD |
599 | goto end; |
600 | } | |
7409dd34 | 601 | diag("Got LTTNG_VIEWER_GET_PACKET_ERR:"); |
10236918 | 602 | goto error; |
1b368955 | 603 | default: |
7409dd34 | 604 | diag("Got unknown status code during LTTNG_VIEWER_GET_PACKET"); |
10236918 | 605 | goto error; |
1b368955 JD |
606 | } |
607 | ||
608 | if (len > mmap_size) { | |
7409dd34 | 609 | diag("mmap_size not big enough"); |
1b368955 JD |
610 | goto error; |
611 | } | |
612 | ||
10236918 MD |
613 | ret_len = lttng_live_recv(control_sock, session->streams[id].mmap_base, len); |
614 | if (ret_len == 0) { | |
7409dd34 | 615 | diag("[error] Remote side has closed connection"); |
10236918 MD |
616 | goto error; |
617 | } | |
618 | if (ret_len < 0) { | |
7409dd34 | 619 | diag("Error receiving trace packet"); |
1b368955 JD |
620 | goto error; |
621 | } | |
1b368955 | 622 | end: |
10236918 | 623 | return 0; |
1b368955 | 624 | error: |
10236918 | 625 | return -1; |
1b368955 JD |
626 | } |
627 | ||
8f92cd08 | 628 | static |
e22ba966 JD |
629 | int detach_viewer_session(uint64_t id) |
630 | { | |
631 | struct lttng_viewer_cmd cmd; | |
632 | struct lttng_viewer_detach_session_response resp; | |
633 | struct lttng_viewer_detach_session_request rq; | |
634 | int ret; | |
635 | ssize_t ret_len; | |
636 | ||
637 | cmd.cmd = htobe32(LTTNG_VIEWER_DETACH_SESSION); | |
2dc797f3 JD |
638 | cmd.data_size = htobe64(sizeof(rq)); |
639 | cmd.cmd_version = htobe32(0); | |
e22ba966 JD |
640 | |
641 | memset(&rq, 0, sizeof(rq)); | |
642 | rq.session_id = htobe64(id); | |
643 | ||
644 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); | |
645 | if (ret_len < 0) { | |
646 | fprintf(stderr, "[error] Error sending cmd\n"); | |
647 | ret = ret_len; | |
648 | goto error; | |
649 | } | |
650 | ||
651 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); | |
652 | if (ret_len < 0) { | |
653 | fprintf(stderr, "Error sending attach request\n"); | |
654 | ret = ret_len; | |
655 | goto error; | |
656 | } | |
657 | ||
658 | ret_len = lttng_live_recv(control_sock, &resp, sizeof(resp)); | |
659 | if (ret_len < 0) { | |
660 | fprintf(stderr, "[error] Error receiving detach session reply\n"); | |
661 | ret = ret_len; | |
662 | goto error; | |
663 | } | |
664 | ||
665 | if (be32toh(resp.status) != LTTNG_VIEWER_DETACH_SESSION_OK) { | |
666 | fprintf(stderr, "[error] Error detaching viewer session\n"); | |
667 | ret = -1; | |
668 | goto error; | |
669 | } | |
670 | ret = 0; | |
671 | ||
672 | error: | |
673 | return ret; | |
674 | } | |
675 | ||
1b368955 JD |
676 | int main(int argc, char **argv) |
677 | { | |
678 | int ret; | |
7409dd34 | 679 | uint64_t session_id; |
1b368955 JD |
680 | |
681 | plan_tests(NUM_TESTS); | |
682 | ||
683 | diag("Live unit tests"); | |
684 | ||
685 | ret = connect_viewer("localhost"); | |
686 | ok(ret == 0, "Connect viewer to relayd"); | |
687 | ||
688 | ret = establish_connection(); | |
689 | ok(ret == 0, "Established connection and version check with %d.%d", | |
690 | VERSION_MAJOR, VERSION_MINOR); | |
691 | ||
692 | ret = list_sessions(&session_id); | |
693 | ok(ret > 0, "List sessions : %d session(s)", ret); | |
8674c9bf JG |
694 | if (ret < 0) { |
695 | goto end; | |
696 | } | |
1b368955 | 697 | |
25b50f8f JD |
698 | ret = create_viewer_session(); |
699 | ok(ret == 0, "Create viewer session"); | |
700 | ||
1b368955 | 701 | ret = attach_session(session_id); |
7409dd34 | 702 | ok(ret > 0, "Attach to session, %d stream(s) received", ret); |
1b368955 JD |
703 | |
704 | ret = get_metadata(); | |
705 | ok(ret > 0, "Get metadata, received %d bytes", ret); | |
706 | ||
707 | ret = get_next_index(); | |
708 | ok(ret == 0, "Get one index per stream"); | |
709 | ||
710 | ret = get_data_packet(first_packet_stream_id, first_packet_offset, | |
711 | first_packet_len); | |
10236918 | 712 | ok(ret == 0, |
1b368955 JD |
713 | "Get one data packet for stream %d, offset %d, len %d", |
714 | first_packet_stream_id, first_packet_offset, | |
715 | first_packet_len); | |
716 | ||
e22ba966 JD |
717 | ret = detach_viewer_session(session_id); |
718 | ok(ret == 0, "Detach viewer session"); | |
719 | ||
720 | ret = list_sessions(&session_id); | |
721 | ok(ret > 0, "List sessions : %d session(s)", ret); | |
722 | ||
723 | ret = attach_session(session_id); | |
724 | ok(ret > 0, "Attach to session, %d streams received", ret); | |
8674c9bf | 725 | end: |
1b368955 JD |
726 | return exit_status(); |
727 | } |