1# pylint: disable=C0111
2
3import logging
4import socket
5import pika.compat
6
7LOGGER = logging.getLogger(__name__)
8
9_SUPPORTED_TCP_OPTIONS = {}
10
11try:
12    _SUPPORTED_TCP_OPTIONS['TCP_USER_TIMEOUT'] = socket.TCP_USER_TIMEOUT
13except AttributeError:
14    if pika.compat.LINUX_VERSION and pika.compat.LINUX_VERSION >= (2, 6, 37):
15        # this is not the timeout value, but the number corresponding
16        # to the constant in tcp.h
17        # https://github.com/torvalds/linux/blob/master/include/uapi/linux/tcp.h#
18        # #define TCP_USER_TIMEOUT	18	/* How long for loss retry before timeout */
19        _SUPPORTED_TCP_OPTIONS['TCP_USER_TIMEOUT'] = 18
20
21try:
22    _SUPPORTED_TCP_OPTIONS['TCP_KEEPIDLE'] = socket.TCP_KEEPIDLE
23    _SUPPORTED_TCP_OPTIONS['TCP_KEEPCNT'] = socket.TCP_KEEPCNT
24    _SUPPORTED_TCP_OPTIONS['TCP_KEEPINTVL'] = socket.TCP_KEEPINTVL
25except AttributeError:
26    pass
27
28
29def socket_requires_keepalive(tcp_options):
30    return ('TCP_KEEPIDLE' in tcp_options or
31            'TCP_KEEPCNT' in tcp_options or
32            'TCP_KEEPINTVL' in tcp_options)
33
34
35def set_sock_opts(tcp_options, sock):
36    if not tcp_options:
37        return
38
39    if socket_requires_keepalive(tcp_options):
40        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
41
42    for key, value in tcp_options.items():
43        option = _SUPPORTED_TCP_OPTIONS.get(key)
44        if option:
45            sock.setsockopt(pika.compat.SOL_TCP, option, value)
46        else:
47            LOGGER.warning('Unsupported TCP option %s:%s', key, value)
48