2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
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
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.
25 #include <sys/types.h>
29 #include <common/compat/time.h>
32 #include <common/common.h>
33 #include <common/time.h>
37 #define RECONNECT_DELAY 200 /* ms */
40 * INET protocol operations.
42 static const struct lttcomm_proto_ops inet6_ops
= {
43 .bind
= lttcomm_bind_inet6_sock
,
44 .close
= lttcomm_close_inet6_sock
,
45 .connect
= lttcomm_connect_inet6_sock
,
46 .accept
= lttcomm_accept_inet6_sock
,
47 .listen
= lttcomm_listen_inet6_sock
,
48 .recvmsg
= lttcomm_recvmsg_inet6_sock
,
49 .sendmsg
= lttcomm_sendmsg_inet6_sock
,
53 * Creates an PF_INET socket.
56 int lttcomm_create_inet6_sock(struct lttcomm_sock
*sock
, int type
, int proto
)
59 unsigned long timeout
;
61 /* Create server socket */
62 if ((sock
->fd
= socket(PF_INET6
, type
, proto
)) < 0) {
63 PERROR("socket inet6");
67 sock
->ops
= &inet6_ops
;
70 * Set socket option to reuse the address.
72 ret
= setsockopt(sock
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(int));
74 PERROR("setsockopt inet6");
77 timeout
= lttcomm_get_network_timeout();
79 ret
= lttcomm_setsockopt_rcv_timeout(sock
->fd
, timeout
);
83 ret
= lttcomm_setsockopt_snd_timeout(sock
->fd
, timeout
);
96 * Bind socket and return.
99 int lttcomm_bind_inet6_sock(struct lttcomm_sock
*sock
)
101 return bind(sock
->fd
,
102 (const struct sockaddr
*) ALIGNED_CONST_PTR(
103 sock
->sockaddr
.addr
.sin6
),
104 sizeof(sock
->sockaddr
.addr
.sin6
));
108 int connect_no_timeout(struct lttcomm_sock
*sock
)
110 return connect(sock
->fd
,
111 (const struct sockaddr
*) ALIGNED_CONST_PTR(
112 sock
->sockaddr
.addr
.sin6
),
113 sizeof(sock
->sockaddr
.addr
.sin6
));
117 int connect_with_timeout(struct lttcomm_sock
*sock
)
119 unsigned long timeout
= lttcomm_get_network_timeout();
120 int ret
, flags
, connect_ret
;
121 struct timespec orig_time
, cur_time
;
122 unsigned long diff_ms
;
124 ret
= fcntl(sock
->fd
, F_GETFL
, 0);
131 /* Set socket to nonblock */
132 ret
= fcntl(sock
->fd
, F_SETFL
, flags
| O_NONBLOCK
);
138 ret
= lttng_clock_gettime(CLOCK_MONOTONIC
, &orig_time
);
140 PERROR("clock_gettime");
144 connect_ret
= connect(sock
->fd
,
145 (const struct sockaddr
*) ALIGNED_CONST_PTR(
146 sock
->sockaddr
.addr
.sin6
),
147 sizeof(sock
->sockaddr
.addr
.sin6
));
148 if (connect_ret
== -1 && errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&&
149 errno
!= EINPROGRESS
) {
151 } else if (!connect_ret
) {
152 /* Connect succeeded */
156 DBG("Asynchronous connect for sock %d, performing polling with"
157 " timeout: %lums", sock
->fd
, timeout
);
160 * Perform poll loop following EINPROGRESS recommendation from
161 * connect(2) man page.
167 fds
.events
= POLLOUT
;
169 ret
= poll(&fds
, 1, RECONNECT_DELAY
);
172 } else if (ret
> 0) {
174 socklen_t optval_len
= sizeof(optval
);
176 if (!(fds
.revents
& POLLOUT
)) {
177 /* Either hup or error */
182 ret
= getsockopt(sock
->fd
, SOL_SOCKET
,
183 SO_ERROR
, &optval
, &optval_len
);
185 PERROR("getsockopt");
192 /* Get actual connect() errno from opt_val */
197 /* ret == 0: timeout */
198 ret
= lttng_clock_gettime(CLOCK_MONOTONIC
, &cur_time
);
200 PERROR("clock_gettime");
204 if (timespec_to_ms(timespec_abs_diff(cur_time
, orig_time
), &diff_ms
) < 0) {
205 ERR("timespec_to_ms input overflows milliseconds output");
209 } while (diff_ms
< timeout
);
216 /* Restore initial flags */
217 ret
= fcntl(sock
->fd
, F_SETFL
, flags
);
220 /* Continue anyway */
227 * Connect PF_INET socket.
230 int lttcomm_connect_inet6_sock(struct lttcomm_sock
*sock
)
234 if (lttcomm_get_network_timeout()) {
235 ret
= connect_with_timeout(sock
);
237 ret
= connect_no_timeout(sock
);
240 PERROR("connect inet6");
247 closeret
= close(sock
->fd
);
249 PERROR("close inet6");
256 * Do an accept(2) on the sock and return the new lttcomm socket. The socket
257 * MUST be bind(2) before.
260 struct lttcomm_sock
*lttcomm_accept_inet6_sock(struct lttcomm_sock
*sock
)
264 struct lttcomm_sock
*new_sock
;
265 struct sockaddr_in6 new_addr
= {};
267 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
269 * accept(2) does not exist for UDP so simply return the passed socket.
275 new_sock
= lttcomm_alloc_sock(sock
->proto
);
276 if (new_sock
== NULL
) {
280 len
= sizeof(new_addr
);
283 new_fd
= accept(sock
->fd
, (struct sockaddr
*) &new_addr
, &len
);
285 PERROR("accept inet6");
288 new_sock
->sockaddr
.addr
.sin6
= new_addr
;
289 new_sock
->fd
= new_fd
;
290 new_sock
->ops
= &inet6_ops
;
301 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
304 int lttcomm_listen_inet6_sock(struct lttcomm_sock
*sock
, int backlog
)
308 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
309 /* listen(2) does not exist for UDP so simply return success. */
314 /* Default listen backlog */
316 backlog
= LTTNG_SESSIOND_COMM_MAX_LISTEN
;
319 ret
= listen(sock
->fd
, backlog
);
321 PERROR("listen inet6");
329 * Receive data of size len in put that data into the buf param. Using recvmsg
332 * Return the size of received data.
335 ssize_t
lttcomm_recvmsg_inet6_sock(struct lttcomm_sock
*sock
, void *buf
,
336 size_t len
, int flags
)
342 struct sockaddr_in6 addr
= sock
->sockaddr
.addr
.sin6
;
344 memset(&msg
, 0, sizeof(msg
));
346 iov
[0].iov_base
= buf
;
347 iov
[0].iov_len
= len
;
351 msg
.msg_name
= (struct sockaddr
*) &addr
;
352 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin6
);
355 len_last
= iov
[0].iov_len
;
356 ret
= recvmsg(sock
->fd
, &msg
, flags
);
358 if (flags
& MSG_DONTWAIT
) {
361 iov
[0].iov_base
+= ret
;
362 iov
[0].iov_len
-= ret
;
363 assert(ret
<= len_last
);
365 } while ((ret
> 0 && ret
< len_last
) || (ret
< 0 && errno
== EINTR
));
367 PERROR("recvmsg inet");
368 } else if (ret
> 0) {
371 /* Else ret = 0 meaning an orderly shutdown. */
377 * Send buf data of size len. Using sendmsg API.
379 * Return the size of sent data.
382 ssize_t
lttcomm_sendmsg_inet6_sock(struct lttcomm_sock
*sock
, const void *buf
,
383 size_t len
, int flags
)
389 memset(&msg
, 0, sizeof(msg
));
391 iov
[0].iov_base
= (void *) buf
;
392 iov
[0].iov_len
= len
;
396 switch (sock
->proto
) {
397 case LTTCOMM_SOCK_UDP
:
399 struct sockaddr_in6 addr
= sock
->sockaddr
.addr
.sin6
;
401 msg
.msg_name
= (struct sockaddr
*) &addr
;
402 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin6
);
410 ret
= sendmsg(sock
->fd
, &msg
, flags
);
411 } while (ret
< 0 && errno
== EINTR
);
414 * Only warn about EPIPE when quiet mode is deactivated.
415 * We consider EPIPE as expected.
417 if (errno
!= EPIPE
|| !lttng_opt_quiet
) {
418 PERROR("sendmsg inet6");
426 * Shutdown cleanly and close.
429 int lttcomm_close_inet6_sock(struct lttcomm_sock
*sock
)
433 /* Don't try to close an invalid marked socket */
434 if (sock
->fd
== -1) {
438 ret
= close(sock
->fd
);
440 PERROR("close inet6");