nicer output of the time spent in a syscall
[lttngtop.git] / src / network-live.c
1 /*
2 * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <netinet/in.h>
27 #include <netdb.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <inttypes.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36
37 #include "lttng-viewer-abi.h"
38 #include "network-live.h"
39 #include "liblttng-live.h"
40
41 #include <babeltrace/babeltrace.h>
42 #include <babeltrace/ctf/events.h>
43 #include <babeltrace/ctf/callbacks.h>
44 #include <babeltrace/ctf/iterator.h>
45
46 /* for packet_index */
47 #include <babeltrace/ctf/types.h>
48
49 #include <babeltrace/ctf/metadata.h>
50 #include <babeltrace/ctf-text/types.h>
51 #include <babeltrace/ctf/events-internal.h>
52 #include <lib/babeltrace/ctf/ctf-index.h>
53
54 /*
55 * hostname parameter needs to hold NAME_MAX chars.
56 */
57 static
58 int parse_url(const char *path, struct lttng_live_ctx *ctx)
59 {
60 char remain[3][NAME_MAX];
61 int ret = -1, proto, proto_offset = 0;
62 size_t path_len = strlen(path);
63
64 /*
65 * Since sscanf API does not allow easily checking string length
66 * against a size defined by a macro. Test it beforehand on the
67 * input. We know the output is always <= than the input length.
68 */
69 if (path_len > NAME_MAX) {
70 goto end;
71 }
72 ret = sscanf(path, "net%d://", &proto);
73 if (ret < 1) {
74 proto = 4;
75 /* net:// */
76 proto_offset = strlen("net://");
77 } else {
78 /* net4:// or net6:// */
79 proto_offset = strlen("netX://");
80 }
81 if (proto_offset > path_len) {
82 goto end;
83 }
84 /* TODO : parse for IPv6 as well */
85 /* Parse the hostname or IP */
86 ret = sscanf(&path[proto_offset], "%[a-zA-Z.0-9%-]%s",
87 ctx->relay_hostname, remain[0]);
88 if (ret == 2) {
89 /* Optional port number */
90 switch (remain[0][0]) {
91 case ':':
92 ret = sscanf(remain[0], ":%d%s", &ctx->port, remain[1]);
93 /* Optional session ID with port number */
94 if (ret == 2) {
95 ret = sscanf(remain[1], "/%s", remain[2]);
96 /* Accept 0 or 1 (optional) */
97 if (ret < 0) {
98 goto end;
99 }
100 }
101 break;
102 case '/':
103 /* Optional session ID */
104 ret = sscanf(remain[0], "/%s", remain[2]);
105 /* Accept 0 or 1 (optional) */
106 if (ret < 0) {
107 goto end;
108 }
109 break;
110 default:
111 fprintf(stderr, "[error] wrong delimitor : %c\n",
112 remain[0][0]);
113 ret = -1;
114 goto end;
115 }
116 }
117
118 if (ctx->port < 0)
119 ctx->port = LTTNG_DEFAULT_NETWORK_VIEWER_PORT;
120
121 if (strlen(remain[2]) == 0) {
122 printf_verbose("Connecting to hostname : %s, port : %d, "
123 "proto : IPv%d\n",
124 ctx->relay_hostname, ctx->port, proto);
125 ret = 0;
126 goto end;
127 }
128 ret = sscanf(remain[2], "host/%[a-zA-Z.0-9%-]/%s",
129 ctx->traced_hostname, ctx->session_name);
130 if (ret != 2) {
131 fprintf(stderr, "[error] Format : "
132 "net://<hostname>/host/<traced_hostname>/<session_name>\n");
133 goto end;
134 }
135
136 printf_verbose("Connecting to hostname : %s, port : %d, "
137 "traced hostname : %s, session name : %s, "
138 "proto : IPv%d\n",
139 ctx->relay_hostname, ctx->port, ctx->traced_hostname,
140 ctx->session_name, proto);
141 ret = 0;
142
143 end:
144 return ret;
145 }
146
147 static int lttng_live_open_trace_read(const char *path)
148 {
149 int ret = 0;
150 struct lttng_live_ctx *ctx;
151
152 ctx = g_new0(struct lttng_live_ctx, 1);
153 ctx->session = g_new0(struct lttng_live_session, 1);
154
155 /* We need a pointer to the context from the packet_seek function. */
156 ctx->session->ctx = ctx;
157
158 /* HT to store the CTF traces. */
159 ctx->session->ctf_traces = g_hash_table_new(g_direct_hash,
160 g_direct_equal);
161 ctx->port = -1;
162 ctx->session_ids = g_array_new(FALSE, TRUE, sizeof(uint64_t));
163
164 ret = parse_url(path, ctx);
165 if (ret < 0) {
166 goto end_free;
167 }
168
169 ret = lttng_live_connect_viewer(ctx);
170 if (ret < 0) {
171 fprintf(stderr, "[error] Connection failed\n");
172 goto end_free;
173 }
174 printf_verbose("LTTng-live connected to relayd\n");
175
176 ret = lttng_live_establish_connection(ctx);
177 if (ret < 0) {
178 goto end_free;
179 }
180 printf_verbose("Listing sessions\n");
181 ret = lttng_live_list_sessions(ctx, path);
182 if (ret < 0) {
183 fprintf(stderr, "[error] List error\n");
184 goto end_free;
185 }
186
187 if (ctx->session_ids->len > 0)
188 lttng_live_read(ctx);
189
190 end_free:
191 g_hash_table_destroy(ctx->session->ctf_traces);
192 g_free(ctx->session);
193 g_free(ctx->session->streams);
194 g_free(ctx);
195 return ret;
196 }
197
198 static
199 struct bt_trace_descriptor *lttng_live_open_trace(const char *path, int flags,
200 void (*packet_seek)(struct bt_stream_pos *pos, size_t index,
201 int whence), FILE *metadata_fp)
202 {
203 struct ctf_text_stream_pos *pos;
204
205 switch (flags & O_ACCMODE) {
206 case O_RDONLY:
207 /* OK */
208 break;
209 case O_RDWR:
210 fprintf(stderr, "[error] lttng live plugin cannot be used as output plugin.\n");
211 goto error;
212 default:
213 fprintf(stderr, "[error] Incorrect open flags.\n");
214 goto error;
215 }
216
217 pos = g_new0(struct ctf_text_stream_pos, 1);
218 pos->parent.rw_table = NULL;
219 pos->parent.event_cb = NULL;
220 pos->parent.trace = &pos->trace_descriptor;
221 lttng_live_open_trace_read(path);
222 return &pos->trace_descriptor;
223
224 error:
225 return NULL;
226 }
227
228 static
229 int lttng_live_close_trace(struct bt_trace_descriptor *td)
230 {
231 struct ctf_text_stream_pos *pos =
232 container_of(td, struct ctf_text_stream_pos,
233 trace_descriptor);
234 free(pos);
235 return 0;
236 }
237
238 static
239 struct bt_format lttng_live_format = {
240 .open_trace = lttng_live_open_trace,
241 .close_trace = lttng_live_close_trace,
242 };
243
244 static
245 void __attribute__((constructor)) lttng_live_init(void)
246 {
247 int ret;
248
249 lttng_live_format.name = g_quark_from_static_string("lttng-live");
250 ret = bt_register_format(&lttng_live_format);
251 assert(!ret);
252 }
253
254 static
255 void __attribute__((destructor)) lttng_live_exit(void)
256 {
257 bt_unregister_format(&lttng_live_format);
258 }
This page took 0.034047 seconds and 4 git commands to generate.