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