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.
26 #include <sys/types.h>
33 #include <common/common.h>
37 #define MSEC_PER_SEC 1000
38 #define NSEC_PER_MSEC 1000000
39 #define RECONNECT_DELAY 200 /* ms */
42 * INET protocol operations.
44 static const struct lttcomm_proto_ops inet_ops
= {
45 .bind
= lttcomm_bind_inet_sock
,
46 .close
= lttcomm_close_inet_sock
,
47 .connect
= lttcomm_connect_inet_sock
,
48 .accept
= lttcomm_accept_inet_sock
,
49 .listen
= lttcomm_listen_inet_sock
,
50 .recvmsg
= lttcomm_recvmsg_inet_sock
,
51 .sendmsg
= lttcomm_sendmsg_inet_sock
,
54 unsigned long lttcomm_inet_tcp_timeout
;
57 * Creates an PF_INET socket.
60 int lttcomm_create_inet_sock(struct lttcomm_sock
*sock
, int type
, int proto
)
63 unsigned long timeout
;
65 /* Create server socket */
66 if ((sock
->fd
= socket(PF_INET
, type
, proto
)) < 0) {
67 PERROR("socket inet");
71 sock
->ops
= &inet_ops
;
74 * Set socket option to reuse the address.
76 ret
= setsockopt(sock
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(int));
78 PERROR("setsockopt inet");
81 timeout
= lttcomm_get_network_timeout();
83 ret
= lttcomm_setsockopt_rcv_timeout(sock
->fd
, timeout
);
87 ret
= lttcomm_setsockopt_snd_timeout(sock
->fd
, timeout
);
100 * Bind socket and return.
103 int lttcomm_bind_inet_sock(struct lttcomm_sock
*sock
)
107 ret
= bind(sock
->fd
, &sock
->sockaddr
.addr
.sin
,
108 sizeof(sock
->sockaddr
.addr
.sin
));
117 int connect_no_timeout(struct lttcomm_sock
*sock
)
119 return connect(sock
->fd
, (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
,
120 sizeof(sock
->sockaddr
.addr
.sin
));
124 * Return time_a - time_b in milliseconds.
127 unsigned long time_diff_ms(struct timespec
*time_a
,
128 struct timespec
*time_b
)
132 unsigned long result_ms
;
134 sec_diff
= time_a
->tv_sec
- time_b
->tv_sec
;
135 nsec_diff
= time_a
->tv_nsec
- time_b
->tv_nsec
;
137 result_ms
= sec_diff
* MSEC_PER_SEC
;
138 result_ms
+= nsec_diff
/ NSEC_PER_MSEC
;
143 int connect_with_timeout(struct lttcomm_sock
*sock
)
145 unsigned long timeout
= lttcomm_get_network_timeout();
146 int ret
, flags
, connect_ret
;
147 struct timespec orig_time
, cur_time
;
149 ret
= fcntl(sock
->fd
, F_GETFL
, 0);
156 /* Set socket to nonblock */
157 ret
= fcntl(sock
->fd
, F_SETFL
, flags
| O_NONBLOCK
);
163 ret
= clock_gettime(CLOCK_MONOTONIC
, &orig_time
);
165 PERROR("clock_gettime");
169 connect_ret
= connect(sock
->fd
,
170 (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
,
171 sizeof(sock
->sockaddr
.addr
.sin
));
172 if (connect_ret
== -1 && errno
!= EAGAIN
173 && errno
!= EWOULDBLOCK
174 && errno
!= EINPROGRESS
) {
176 } else if (!connect_ret
) {
177 /* Connect succeeded */
182 * Perform poll loop following EINPROGRESS recommendation from
183 * connect(2) man page.
189 fds
.events
= POLLOUT
;
191 ret
= poll(&fds
, 1, RECONNECT_DELAY
);
194 } else if (ret
> 0) {
196 socklen_t optval_len
= sizeof(optval
);
198 if (!(fds
.revents
& POLLOUT
)) {
199 /* Either hup or error */
204 ret
= getsockopt(sock
->fd
, SOL_SOCKET
,
205 SO_ERROR
, &optval
, &optval_len
);
216 /* ret == 0: timeout */
217 ret
= clock_gettime(CLOCK_MONOTONIC
, &cur_time
);
219 PERROR("clock_gettime");
223 } while (time_diff_ms(&cur_time
, &orig_time
) < timeout
);
230 /* Restore initial flags */
231 ret
= fcntl(sock
->fd
, F_SETFL
, flags
);
234 /* Continue anyway */
241 * Connect PF_INET socket.
244 int lttcomm_connect_inet_sock(struct lttcomm_sock
*sock
)
248 if (lttcomm_get_network_timeout()) {
249 ret
= connect_with_timeout(sock
);
251 ret
= connect_no_timeout(sock
);
261 closeret
= close(sock
->fd
);
263 PERROR("close inet");
270 * Do an accept(2) on the sock and return the new lttcomm socket. The socket
271 * MUST be bind(2) before.
274 struct lttcomm_sock
*lttcomm_accept_inet_sock(struct lttcomm_sock
*sock
)
278 struct lttcomm_sock
*new_sock
;
279 unsigned long timeout
;
281 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
283 * accept(2) does not exist for UDP so simply return the passed socket.
289 new_sock
= lttcomm_alloc_sock(sock
->proto
);
290 if (new_sock
== NULL
) {
294 len
= sizeof(new_sock
->sockaddr
.addr
.sin
);
297 new_fd
= accept(sock
->fd
, (struct sockaddr
*) &new_sock
->sockaddr
.addr
.sin
,
300 PERROR("accept inet");
303 timeout
= lttcomm_get_network_timeout();
307 ret
= lttcomm_setsockopt_rcv_timeout(new_fd
, timeout
);
311 ret
= lttcomm_setsockopt_snd_timeout(new_fd
, timeout
);
317 new_sock
->fd
= new_fd
;
318 new_sock
->ops
= &inet_ops
;
324 if (close(new_fd
) < 0) {
325 PERROR("accept inet close fd");
334 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
337 int lttcomm_listen_inet_sock(struct lttcomm_sock
*sock
, int backlog
)
341 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
342 /* listen(2) does not exist for UDP so simply return success. */
347 /* Default listen backlog */
349 backlog
= LTTNG_SESSIOND_COMM_MAX_LISTEN
;
352 ret
= listen(sock
->fd
, backlog
);
354 PERROR("listen inet");
362 * Receive data of size len in put that data into the buf param. Using recvmsg
365 * Return the size of received data.
368 ssize_t
lttcomm_recvmsg_inet_sock(struct lttcomm_sock
*sock
, void *buf
,
369 size_t len
, int flags
)
376 memset(&msg
, 0, sizeof(msg
));
378 iov
[0].iov_base
= buf
;
379 iov
[0].iov_len
= len
;
383 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
;
384 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin
);
387 len_last
= iov
[0].iov_len
;
388 ret
= recvmsg(sock
->fd
, &msg
, flags
);
390 iov
[0].iov_base
+= ret
;
391 iov
[0].iov_len
-= ret
;
392 assert(ret
<= len_last
);
394 } while ((ret
> 0 && ret
< len_last
) || (ret
< 0 && errno
== EINTR
));
396 PERROR("recvmsg inet");
397 } else if (ret
> 0) {
400 /* Else ret = 0 meaning an orderly shutdown. */
406 * Send buf data of size len. Using sendmsg API.
408 * Return the size of sent data.
411 ssize_t
lttcomm_sendmsg_inet_sock(struct lttcomm_sock
*sock
, void *buf
,
412 size_t len
, int flags
)
418 memset(&msg
, 0, sizeof(msg
));
420 iov
[0].iov_base
= buf
;
421 iov
[0].iov_len
= len
;
425 switch (sock
->proto
) {
426 case LTTCOMM_SOCK_UDP
:
427 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
;
428 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin
);
435 ret
= sendmsg(sock
->fd
, &msg
, flags
);
436 } while (ret
< 0 && errno
== EINTR
);
439 * Only warn about EPIPE when quiet mode is deactivated.
440 * We consider EPIPE as expected.
442 if (errno
!= EPIPE
|| !lttng_opt_quiet
) {
443 PERROR("sendmsg inet");
451 * Shutdown cleanly and close.
454 int lttcomm_close_inet_sock(struct lttcomm_sock
*sock
)
458 /* Don't try to close an invalid marked socket */
459 if (sock
->fd
== -1) {
463 ret
= close(sock
->fd
);
465 PERROR("close inet");
475 * Return value read from /proc or else 0 if value is not found.
477 static unsigned long read_proc_value(const char *path
)
482 unsigned long val
= 0;
485 fd
= open(path
, O_RDONLY
);
490 size_ret
= lttng_read(fd
, buf
, sizeof(buf
));
492 * Allow reading a file smaller than buf, but keep space for
495 if (size_ret
< 0 || size_ret
>= sizeof(buf
)) {
496 PERROR("read proc failed");
499 buf
[size_ret
] = '\0';
502 r_val
= strtol(buf
, NULL
, 10);
503 if (errno
!= 0 || r_val
< -1L) {
515 PERROR("close /proc value");
522 void lttcomm_inet_init(void)
524 unsigned long syn_retries
, fin_timeout
, syn_timeout
, env
;
526 env
= lttcomm_get_network_timeout();
528 lttcomm_inet_tcp_timeout
= env
;
532 /* Assign default value and see if we can change it. */
533 lttcomm_inet_tcp_timeout
= DEFAULT_INET_TCP_TIMEOUT
;
535 syn_retries
= read_proc_value(LTTCOMM_INET_PROC_SYN_RETRIES_PATH
);
536 fin_timeout
= read_proc_value(LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH
);
538 syn_timeout
= syn_retries
* LTTCOMM_INET_SYN_TIMEOUT_FACTOR
;
541 * Get the maximum between the two possible timeout value and use that to
542 * get the maximum with the default timeout.
544 lttcomm_inet_tcp_timeout
= max_t(unsigned long,
545 max_t(unsigned long, syn_timeout
, fin_timeout
),
546 lttcomm_inet_tcp_timeout
);
549 DBG("TCP inet operation timeout set to %lu sec", lttcomm_inet_tcp_timeout
);